Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-pages.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Bizon <grzesiek.bizon@gmail.com>2020-01-16 18:33:30 +0300
committerGrzegorz Bizon <grzesiek.bizon@gmail.com>2020-01-28 13:33:17 +0300
commit0509d6b4aa276d0a61592f5ad9d464f13c8e458f (patch)
tree1e554394fa6b79c6479590e2284cee9c0f798b5a
parent4317f67bea77be4cfce36a7454e15f888a2d9ea2 (diff)
Add initial implementation of serverless proxy
-rw-r--r--internal/serving/serverless/cluster.go38
-rw-r--r--internal/serving/serverless/director.go17
-rw-r--r--internal/serving/serverless/serverless.go10
-rw-r--r--internal/serving/serverless/serverless_test.go50
-rw-r--r--internal/serving/serverless/transport.go3
5 files changed, 103 insertions, 15 deletions
diff --git a/internal/serving/serverless/cluster.go b/internal/serving/serverless/cluster.go
index d8eb6696..3912fc73 100644
--- a/internal/serving/serverless/cluster.go
+++ b/internal/serving/serverless/cluster.go
@@ -1,5 +1,43 @@
package serverless
+import (
+ "crypto/tls"
+ "crypto/x509"
+)
+
// Cluster represent a Knative cluster that we want to proxy requests to
type Cluster struct {
+ Address string
+ Hostname string
+ Port string
+ Config *Config
+}
+
+// Config holds configuration for a cluster, especially definition of
+// certificates we use to perform mTLS handshake
+type Config struct {
+ RootCerts *x509.CertPool
+ Certificate tls.Certificate
+}
+
+// NewClusterConfig creates a new cluster configuration from cert / key pair
+func NewClusterConfig(clientCert, clientKey string) (*Config, error) {
+ cert, err := tls.X509KeyPair([]byte(clientCert), []byte(clientKey))
+ if err != nil {
+ return nil, err
+ }
+
+ caCertPool := x509.NewCertPool()
+ caCertPool.AppendCertsFromPEM([]byte(clientCert))
+
+ return &Config{RootCerts: caCertPool, Certificate: cert}, nil
+}
+
+// TLSConfig builds a new tls.Config and returns a pointer to it
+func (c Cluster) TLSConfig() *tls.Config {
+ return &tls.Config{
+ Certificates: []tls.Certificate{c.Config.Certificate},
+ RootCAs: c.Config.RootCerts,
+ ServerName: c.Hostname,
+ }
}
diff --git a/internal/serving/serverless/director.go b/internal/serving/serverless/director.go
index 83398c0e..83d792c3 100644
--- a/internal/serving/serverless/director.go
+++ b/internal/serving/serverless/director.go
@@ -1,15 +1,18 @@
package serverless
-import "net/http"
+import (
+ "net/http"
+ "strings"
+)
// NewDirectorFunc returns a director function capable of configuring a proxy
// request
func NewDirectorFunc(cluster Cluster) func(*http.Request) {
- return func(r *http.Request) {
- // request.Host = domain
- // request.URL.Host = domain
- // request.URL.Scheme = "https"
- // request.Header.Set("User-Agent", "ReverseProxy PoC")
- // request.Header.Set("X-Forwarded ...")
+ return func(request *http.Request) {
+ request.Host = cluster.Address
+ request.URL.Host = strings.Join([]string{cluster.Address, cluster.Port}, ":")
+ request.URL.Scheme = "https"
+ request.Header.Set("User-Agent", "GitLab Pages Daemon")
+ request.Header.Set("X-Forwarded-For", "123") // TODO
}
}
diff --git a/internal/serving/serverless/serverless.go b/internal/serving/serverless/serverless.go
index 96a3a996..77150996 100644
--- a/internal/serving/serverless/serverless.go
+++ b/internal/serving/serverless/serverless.go
@@ -1,7 +1,6 @@
package serverless
import (
- "net/http"
"net/http/httputil"
"gitlab.com/gitlab-org/gitlab-pages/internal/httperrors"
@@ -26,15 +25,12 @@ func New(cluster Cluster) serving.Serving {
// ServeFileHTTP handle an incoming request and proxies it to Knative cluster
func (s *Serverless) ServeFileHTTP(h serving.Handler) bool {
- return false
+ s.proxy.ServeHTTP(h.Writer, h.Request)
+
+ return true
}
// ServeNotFoundHTTP responds with 404
func (s *Serverless) ServeNotFoundHTTP(h serving.Handler) {
httperrors.Serve404(h.Writer)
}
-
-func (s *Serverless) director() func(request *http.Request) {
- return func(request *http.Request) {
- }
-}
diff --git a/internal/serving/serverless/serverless_test.go b/internal/serving/serverless/serverless_test.go
new file mode 100644
index 00000000..169f3de5
--- /dev/null
+++ b/internal/serving/serverless/serverless_test.go
@@ -0,0 +1,50 @@
+package serverless
+
+import (
+ "crypto/tls"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ "gitlab.com/gitlab-org/gitlab-pages/internal/fixture"
+ "gitlab.com/gitlab-org/gitlab-pages/internal/serving"
+)
+
+func TestServeFileHTTP(t *testing.T) {
+ config, err := NewClusterConfig(fixture.Certificate, fixture.Key)
+ require.NoError(t, err)
+
+ cluster := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ assert.Equal(t, "GitLab Pages Daemon", r.Header.Get("User-Agent"))
+ }))
+
+ cluster.TLS = &tls.Config{
+ Certificates: []tls.Certificate{config.Certificate},
+ RootCAs: config.RootCerts,
+ }
+
+ cluster.StartTLS()
+ defer cluster.Close()
+
+ clusterURL, err := url.Parse(cluster.URL)
+ require.NoError(t, err)
+
+ serverless := New(Cluster{
+ Address: clusterURL.Hostname(),
+ Hostname: "knative.gitlab-example.com",
+ Port: clusterURL.Port(),
+ Config: config,
+ })
+
+ t.Run("when proxying simple request to a cluster", func(t *testing.T) {
+ writer := httptest.NewRecorder()
+ request := httptest.NewRequest("GET", "http://example.gitlab.com", nil)
+ handler := serving.Handler{Writer: writer, Request: request}
+
+ assert.True(t, serverless.ServeFileHTTP(handler))
+ })
+}
diff --git a/internal/serving/serverless/transport.go b/internal/serving/serverless/transport.go
index 7cd3e03d..8d195688 100644
--- a/internal/serving/serverless/transport.go
+++ b/internal/serving/serverless/transport.go
@@ -31,10 +31,11 @@ func NewTransport(cluster Cluster) *Transport {
}
return &Transport{
+ cluster: cluster,
transport: &http.Transport{
DialContext: dialContext,
TLSHandshakeTimeout: 5 * time.Second,
- // TODO TLSClientConfig: newTLSConfig(),
+ TLSClientConfig: cluster.TLSConfig(),
},
}
}