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:
authorAlessio Caiazza <acaiazza@gitlab.com>2020-01-21 12:07:51 +0300
committerAlessio Caiazza <acaiazza@gitlab.com>2020-01-21 12:07:51 +0300
commita04541aaf6e26b556fb0ea4c49d80a1494abef9e (patch)
tree93710b62480618f6ec95913047d3e134115a0fe3 /internal/source
parentb3276944b2933c6e734200d14b5a9232ce1bfc74 (diff)
parente7e50231712abc7c0ea79acdcd9db3b3003c6cad (diff)
Merge branch '274-make-gitlab-client-timeout-jtw-token-expiry-configurable' into 'master'
Make GitLab client timeout / JTW token expiry configurable Closes #274 See merge request gitlab-org/gitlab-pages!219
Diffstat (limited to 'internal/source')
-rw-r--r--internal/source/domains_test.go8
-rw-r--r--internal/source/gitlab/client/client.go26
-rw-r--r--internal/source/gitlab/client/client_test.go128
-rw-r--r--internal/source/gitlab/client/config.go4
4 files changed, 126 insertions, 40 deletions
diff --git a/internal/source/domains_test.go b/internal/source/domains_test.go
index 5fea6ae3..bbdb8c21 100644
--- a/internal/source/domains_test.go
+++ b/internal/source/domains_test.go
@@ -2,6 +2,7 @@ package source
import (
"testing"
+ "time"
"github.com/stretchr/testify/require"
@@ -21,6 +22,13 @@ func (c sourceConfig) GitlabServerURL() string {
func (c sourceConfig) GitlabAPISecret() []byte {
return []byte(c.secret)
}
+func (c sourceConfig) GitlabClientConnectionTimeout() time.Duration {
+ return 10 * time.Second
+}
+
+func (c sourceConfig) GitlabJWTTokenExpiry() time.Duration {
+ return 30 * time.Second
+}
func TestDomainSources(t *testing.T) {
t.Run("when GitLab API URL has been provided", func(t *testing.T) {
diff --git a/internal/source/gitlab/client/client.go b/internal/source/gitlab/client/client.go
index f5ecf355..59776a8f 100644
--- a/internal/source/gitlab/client/client.go
+++ b/internal/source/gitlab/client/client.go
@@ -19,18 +19,15 @@ import (
// Client is a HTTP client to access Pages internal API
type Client struct {
- secretKey []byte
- baseURL *url.URL
- httpClient *http.Client
+ secretKey []byte
+ baseURL *url.URL
+ httpClient *http.Client
+ jwtTokenExpiry time.Duration
}
-// TODO make these values configurable https://gitlab.com/gitlab-org/gitlab-pages/issues/274
-var tokenTimeout = 30 * time.Second
-var connectionTimeout = 10 * time.Second
-
// NewClient initializes and returns new Client baseUrl is
// appConfig.GitLabServer secretKey is appConfig.GitLabAPISecretKey
-func NewClient(baseURL string, secretKey []byte) (*Client, error) {
+func NewClient(baseURL string, secretKey []byte, connectionTimeout, jwtTokenExpiry time.Duration) (*Client, error) {
if len(baseURL) == 0 || len(secretKey) == 0 {
return nil, errors.New("GitLab API URL or API secret has not been provided")
}
@@ -40,6 +37,14 @@ func NewClient(baseURL string, secretKey []byte) (*Client, error) {
return nil, err
}
+ if connectionTimeout == 0 {
+ return nil, errors.New("GitLab HTTP client connection timeout has not been provided")
+ }
+
+ if jwtTokenExpiry == 0 {
+ return nil, errors.New("GitLab JWT token expiry has not been provided")
+ }
+
return &Client{
secretKey: secretKey,
baseURL: url,
@@ -47,12 +52,13 @@ func NewClient(baseURL string, secretKey []byte) (*Client, error) {
Timeout: connectionTimeout,
Transport: httptransport.Transport,
},
+ jwtTokenExpiry: jwtTokenExpiry,
}, nil
}
// NewFromConfig creates a new client from Config struct
func NewFromConfig(config Config) (*Client, error) {
- return NewClient(config.GitlabServerURL(), config.GitlabAPISecret())
+ return NewClient(config.GitlabServerURL(), config.GitlabAPISecret(), config.GitlabClientConnectionTimeout(), config.GitlabJWTTokenExpiry())
}
// Resolve returns a VirtualDomain configuration wrapped into a Lookup for a
@@ -151,7 +157,7 @@ func (gc *Client) request(ctx context.Context, method string, endpoint *url.URL)
func (gc *Client) token() (string, error) {
claims := jwt.StandardClaims{
Issuer: "gitlab-pages",
- ExpiresAt: time.Now().Add(tokenTimeout).Unix(),
+ ExpiresAt: time.Now().UTC().Add(gc.jwtTokenExpiry).Unix(),
}
token, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(gc.secretKey)
diff --git a/internal/source/gitlab/client/client_test.go b/internal/source/gitlab/client/client_test.go
index 247de5c7..bdfbe6b0 100644
--- a/internal/source/gitlab/client/client_test.go
+++ b/internal/source/gitlab/client/client_test.go
@@ -7,6 +7,7 @@ import (
"net/http"
"net/http/httptest"
"testing"
+ "time"
jwt "github.com/dgrijalva/jwt-go"
"github.com/stretchr/testify/require"
@@ -14,34 +15,90 @@ import (
"gitlab.com/gitlab-org/gitlab-pages/internal/fixture"
)
+const (
+ defaultClientConnTimeout = 10 * time.Second
+ defaultJWTTokenExpiry = 30 * time.Second
+)
+
func TestNewValidBaseURL(t *testing.T) {
- _, err := NewClient("https://gitlab.com", secretKey())
+ _, err := NewClient("https://gitlab.com", secretKey(t), defaultClientConnTimeout, defaultJWTTokenExpiry)
require.NoError(t, err)
}
-func TestNewInvalidBaseURL(t *testing.T) {
- t.Run("when API URL is not valid", func(t *testing.T) {
- client, err := NewClient("%", secretKey())
-
- require.Error(t, err)
- require.Nil(t, client)
- })
-
- t.Run("when API URL is empty", func(t *testing.T) {
- client, err := NewClient("", secretKey())
-
- require.Nil(t, client)
- require.EqualError(t, err, "GitLab API URL or API secret has not been provided")
- })
+func TestNewInvalidConfiguration(t *testing.T) {
+ type args struct {
+ baseURL string
+ secretKey []byte
+ connectionTimeout time.Duration
+ jwtTokenExpiry time.Duration
+ }
- t.Run("when API secret is empty", func(t *testing.T) {
- client, err := NewClient("https://gitlab.com", []byte{})
+ tests := []struct {
+ name string
+ args args
+ wantErrMsg string
+ }{
+
+ {
+ name: "invalid_api_url",
+ args: args{
+ baseURL: "%",
+ secretKey: secretKey(t),
+ connectionTimeout: defaultClientConnTimeout,
+ jwtTokenExpiry: defaultJWTTokenExpiry,
+ },
+ wantErrMsg: "parse %: invalid URL escape \"%\"",
+ },
+ {
+ name: "invalid_api_url_empty",
+ args: args{
+ baseURL: "",
+ secretKey: secretKey(t),
+ connectionTimeout: defaultClientConnTimeout,
+ jwtTokenExpiry: defaultJWTTokenExpiry,
+ },
+ wantErrMsg: "GitLab API URL or API secret has not been provided",
+ },
+ {
+ name: "invalid_api_secret_empty",
+ args: args{
+ baseURL: "https://gitlab.com",
+ secretKey: []byte{},
+ connectionTimeout: defaultClientConnTimeout,
+ jwtTokenExpiry: defaultJWTTokenExpiry,
+ },
+ wantErrMsg: "GitLab API URL or API secret has not been provided",
+ },
+ {
+ name: "invalid_http_client_timeout",
+ args: args{
+ baseURL: "https://gitlab.com",
+ secretKey: secretKey(t),
+ connectionTimeout: 0,
+ jwtTokenExpiry: defaultJWTTokenExpiry,
+ },
+ wantErrMsg: "GitLab HTTP client connection timeout has not been provided",
+ },
+ {
+ name: "invalid_jwt_token_expiry",
+ args: args{
+ baseURL: "https://gitlab.com",
+ secretKey: secretKey(t),
+ connectionTimeout: defaultClientConnTimeout,
+ jwtTokenExpiry: 0,
+ },
+ wantErrMsg: "GitLab JWT token expiry has not been provided",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
- require.Nil(t, client)
- require.EqualError(t, err, "GitLab API URL or API secret has not been provided")
- })
+ got, err := NewClient(tt.args.baseURL, tt.args.secretKey, tt.args.connectionTimeout, tt.args.jwtTokenExpiry)
+ require.Nil(t, got)
+ require.EqualError(t, err, tt.wantErrMsg)
+ })
+ }
}
-
func TestLookupForErrorResponses(t *testing.T) {
tests := map[int]string{
http.StatusUnauthorized: "HTTP status: 401",
@@ -60,8 +117,7 @@ func TestLookupForErrorResponses(t *testing.T) {
server := httptest.NewServer(mux)
defer server.Close()
- client, err := NewClient(server.URL, secretKey())
- require.NoError(t, err)
+ client := defaultClient(t, server.URL)
lookup := client.GetLookup(context.Background(), "group.gitlab.io")
@@ -81,8 +137,7 @@ func TestMissingDomain(t *testing.T) {
server := httptest.NewServer(mux)
defer server.Close()
- client, err := NewClient(server.URL, secretKey())
- require.NoError(t, err)
+ client := defaultClient(t, server.URL)
lookup := client.GetLookup(context.Background(), "group.gitlab.io")
@@ -123,8 +178,7 @@ func TestGetVirtualDomainAuthenticatedRequest(t *testing.T) {
server := httptest.NewServer(mux)
defer server.Close()
- client, err := NewClient(server.URL, secretKey())
- require.NoError(t, err)
+ client := defaultClient(t, server.URL)
lookup := client.GetLookup(context.Background(), "group.gitlab.io")
require.NoError(t, lookup.Error)
@@ -143,12 +197,13 @@ func TestGetVirtualDomainAuthenticatedRequest(t *testing.T) {
}
func validateToken(t *testing.T, tokenString string) {
+ t.Helper()
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
- return secretKey(), nil
+ return secretKey(t), nil
})
require.NoError(t, err)
@@ -159,7 +214,20 @@ func validateToken(t *testing.T, tokenString string) {
require.Equal(t, "gitlab-pages", claims["iss"])
}
-func secretKey() []byte {
- secretKey, _ := base64.StdEncoding.DecodeString(fixture.GitLabAPISecretKey)
+func secretKey(t *testing.T) []byte {
+ t.Helper()
+
+ secretKey, err := base64.StdEncoding.DecodeString(fixture.GitLabAPISecretKey)
+ require.NoError(t, err)
+
return secretKey
}
+
+func defaultClient(t *testing.T, url string) *Client {
+ t.Helper()
+
+ client, err := NewClient(url, secretKey(t), defaultClientConnTimeout, defaultJWTTokenExpiry)
+ require.NoError(t, err)
+
+ return client
+}
diff --git a/internal/source/gitlab/client/config.go b/internal/source/gitlab/client/config.go
index 49c13a60..4ed14267 100644
--- a/internal/source/gitlab/client/config.go
+++ b/internal/source/gitlab/client/config.go
@@ -1,8 +1,12 @@
package client
+import "time"
+
// Config represents an interface that is configuration provider for client
// capable of comunicating with GitLab
type Config interface {
GitlabServerURL() string
GitlabAPISecret() []byte
+ GitlabClientConnectionTimeout() time.Duration
+ GitlabJWTTokenExpiry() time.Duration
}