From 6bfc9bd1a7e5b938096d6db3ddf30820b41232f8 Mon Sep 17 00:00:00 2001 From: Thomas Yip Date: Mon, 19 Nov 2018 17:41:36 -0800 Subject: [PATCH 1/2] Added the option to authentical using OKTA lib (which use RS256 alg). * Updated golang to 1.11 (the original docker was on 1.8 and code didn't build on it) * Added instructions to run git-gateway to README.md * Added abstraction to auth.go such that different implementations of auth can be used * Updated example.env --- .gitignore | 1 + Dockerfile | 10 ++- README.md | 38 ++++++++- api/api.go | 12 +-- api/auth.go | 179 +++++++++++++++++++++++++++++++++++++++--- api/bitbucket.go | 38 +-------- api/context.go | 25 ++---- api/github.go | 39 +-------- api/gitlab.go | 38 +-------- api/middleware.go | 2 +- conf/configuration.go | 4 + example.env | 34 +++++++- glide.lock | 111 ++++++++++++++++---------- glide.yaml | 2 + 14 files changed, 342 insertions(+), 191 deletions(-) diff --git a/.gitignore b/.gitignore index ec26daa..cb13f5f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .env +my.env gorm.db vendor/ git-gateway diff --git a/Dockerfile b/Dockerfile index 480c7cb..a7af9ae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,14 @@ -FROM netlify/go-glide:v0.12.3 +FROM golang:1.11.2-alpine3.8 ADD . /go/src/github.com/netlify/git-gateway -RUN useradd -m netlify && cd /go/src/github.com/netlify/git-gateway && make deps build && mv git-gateway /usr/local/bin/ +RUN apk add --update alpine-sdk + +RUN rm -rf /var/cache/apk/* + +RUN go get -u github.com/Masterminds/glide golang.org/x/lint/golint + +RUN adduser -D -u 1000 netlify && cd /go/src/github.com/netlify/git-gateway && make deps build lint && mv git-gateway /usr/local/bin/ USER netlify CMD ["git-gateway"] diff --git a/README.md b/README.md index 44341c1..4e48fce 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ However, for most use cases you won’t want to require all content editors to h Netlify’s Git Gateway lets you setup a gateway to your choice of Git provider's API ( now available with both GitHub and GitLab 🎉 ) that lets tools like Netlify CMS work with content, branches and pull requests on your users’ behalf. -The Git Gateway works with any identity service that can issue JWTs and only allows access when a JSON Web Token with sufficient permissions is present. +The Git Gateway works with some supported identity service that can issue JWTs and only allows access when a JSON Web Token with sufficient permissions is present. To configure the gateway, see our `example.env` file @@ -29,3 +29,39 @@ for GitLab: /repos/:owner/:name/commits/ /repos/:owner/:name/tree/ ``` + +### Trying out `git-gateway` + +The instructions below is a way of testing out `git-gateway`. It assumes you have Docker installed and are familiar with Okta (an IDaaS). If you are using a different stack, please adjust the steps accordingly. + +1. pull down this project +2. generate a `personal access token` on github. (recommended: using a test account and w/ `repo:status` and `public_repo` permission only) + https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/ +3. `cp example.env my.env` +4. update `GITGATEWAY_GITHUB_ACCESS_TOKEN` value in `my.env` accordingly +5. update `GITGATEWAY_GITHUB_REPO` value in `my.env` (it will be where the content being stored, eg, `owner/netlify-cms-storage`.) +6. sign up for a Dev account on Okta: https://developer.okta.com/signup/ +7. create a SPA Application onto the Dev account: + a. fill out the details + b. pick `Either Okta or App` + c. pick `Send ID Token directly to app (Okta Simplified)`` + d. have redirect uri points to the url of your `my-netlify-cms` ip:port + (eg, `http://localhost:8080/admin` etc, see, https://github.com/<< your org >>/my-netlify-cms) + e. make sure `Authorization Servers` is activated + f. go to `Trusted Origins` tab and add the url for your `my-netlify-cms` instance + g. add yourself or a test user +8. update `ISSUER` value in `my.env` accordingly (eg, `https://dev-1234.oktapreview.com/oauth2/default`) +9. update `CLIENT_ID` value in `my.env` accordingly (eg, `32q897q234q324rq42322q`) +10. comment out `GITGATEWAY_ROLES` to disable role checking (authorization is controlled by `Assignments` on Okta) +11. update `GITGATEWAY_API_HOST` to `0.0.0.0` +12. inspect Dockerfile and then build the docker with this command: + `docker build -t netlify/git-gateway:latest .` +13. run `git-gateway` with this command: + `docker run --rm --env-file my.env -p 127.0.0.1:9999:9999 --expose 9999 -ti --name netlify-git-gateway "netlify/git-gateway:latest"` +14. update `config.yml` in your my-netlify-cms repo. + change `backend.name` value to `git-gateway` + change `backend.gateway_url` value to `http://localhost:9999` +15. integrate okta sign-in to your `my-netlify-cms` (eg, https://developer.okta.com/quickstart/#/widget/nodejs/express) +16. start your `my-netlify-cms` instance + +See, Wiki page for additional information. diff --git a/api/api.go b/api/api.go index 99eed03..e537ab4 100644 --- a/api/api.go +++ b/api/api.go @@ -27,6 +27,7 @@ var bearerRegexp = regexp.MustCompile(`^(?:B|b)earer (\S+$)`) type API struct { handler http.Handler db storage.Connection + auth Auth config *conf.GlobalConfiguration version string } @@ -58,7 +59,8 @@ func NewAPI(globalConfig *conf.GlobalConfiguration, db storage.Connection) *API // NewAPIWithVersion creates a new REST API using the specified version func NewAPIWithVersion(ctx context.Context, globalConfig *conf.GlobalConfiguration, db storage.Connection, version string) *API { - api := &API{config: globalConfig, db: db, version: version} + auth := NewAuthWithVersion(ctx, version) + api := &API{config: globalConfig, db: db, auth: *auth, version: version} xffmw, _ := xff.Default() @@ -75,10 +77,10 @@ func NewAPIWithVersion(ctx context.Context, globalConfig *conf.GlobalConfigurati r.Use(api.loadJWSSignatureHeader) r.Use(api.loadInstanceConfig) } - r.With(api.requireAuthentication).Mount("/github", NewGitHubGateway()) - r.With(api.requireAuthentication).Mount("/gitlab", NewGitLabGateway()) - r.With(api.requireAuthentication).Mount("/bitbucket", NewBitBucketGateway()) - r.With(api.requireAuthentication).Get("/settings", api.Settings) + r.With(api.auth.accessControl).Mount("/github", NewGitHubGateway()) + r.With(api.auth.accessControl).Mount("/gitlab", NewGitLabGateway()) + r.With(api.auth.accessControl).Mount("/bitbucket", NewBitBucketGateway()) + r.With(api.auth.accessControl).Get("/settings", api.Settings) }) if globalConfig.MultiInstanceMode { diff --git a/api/auth.go b/api/auth.go index d1b380a..6a7f2c6 100644 --- a/api/auth.go +++ b/api/auth.go @@ -6,21 +6,77 @@ import ( jwt "github.com/dgrijalva/jwt-go" "github.com/sirupsen/logrus" + "github.com/okta/okta-jwt-verifier-golang" ) -// requireAuthentication checks incoming requests for tokens presented using the Authorization header -func (a *API) requireAuthentication(w http.ResponseWriter, r *http.Request) (context.Context, error) { - logrus.Info("Getting auth token") - token, err := a.extractBearerToken(w, r) +type Authenticator interface { + // `authenticate` checks incoming requests for tokens presented using the Authorization header + authenticate(w http.ResponseWriter, r *http.Request) (context.Context, error) + getName() string +} + +type Authorizer interface { + // `authorize` checks incoming requests for roles data in tokens that is parsed and verified by a prior `authenticate` step + authorize(w http.ResponseWriter, r *http.Request) (context.Context, error) + getName() string +} + +type Auth struct { + authenticator Authenticator + authorizer Authorizer + version string +} + +type JWTAuthenticator struct { + name string + auth Auth +} + +type OktaJWTAuthenticator struct { + name string + auth Auth +} + +type RolesAuthorizer struct { + name string + auth Auth +} + +func NewAuthWithVersion(ctx context.Context, version string) *Auth { + config := getConfig(ctx) + auth := &Auth{version: version} + authenticatorName := config.JWT.Authenticator + + if (authenticatorName == "bearer-jwt-token") { + auth.authenticator = &JWTAuthenticator{name: "bearer-jwt-token", auth: *auth} + } else if (authenticatorName == "bearer-okta-jwt-token") { + auth.authenticator = &OktaJWTAuthenticator{name: "bearer-okta-jwt-token", auth: *auth} + } else { + if (authenticatorName != "") { + logrus.Fatal("Authenticator `%v` is not recognized", authenticatorName) + } else { + logrus.Fatal("Authenticator is not defined") + } + } + + auth.authorizer = &RolesAuthorizer{name: "bearer-jwt-token-roles", auth: *auth} + + return auth +} + +// check both authentication and authorization +func (a *Auth) accessControl(w http.ResponseWriter, r *http.Request) (context.Context, error) { + logrus.Infof("Authenticate with: %v", a.authenticator.getName()) + ctx, err := a.authenticator.authenticate(w, r) if err != nil { return nil, err } - logrus.Infof("Parsing JWT claims: %v", token) - return a.parseJWTClaims(token, r) + logrus.Infof("Authorizing with: %v", a.authorizer.getName()) + return a.authorizer.authorize(w, r.WithContext(ctx)) } -func (a *API) extractBearerToken(w http.ResponseWriter, r *http.Request) (string, error) { +func (a *Auth) extractBearerToken(w http.ResponseWriter, r *http.Request) (string, error) { authHeader := r.Header.Get("Authorization") if authHeader == "" { return "", unauthorizedError("This endpoint requires a Bearer token") @@ -34,15 +90,120 @@ func (a *API) extractBearerToken(w http.ResponseWriter, r *http.Request) (string return matches[1], nil } -func (a *API) parseJWTClaims(bearer string, r *http.Request) (context.Context, error) { +func (a *JWTAuthenticator) getName() string { + return a.name +} + +func (a *JWTAuthenticator) authenticate(w http.ResponseWriter, r *http.Request) (context.Context, error) { + logrus.Info("Getting auth token") + token, err := a.auth.extractBearerToken(w, r) + if err != nil { + return nil, err + } + + logrus.Infof("Parsing JWT claims: %v", token) + return a.parseJWTClaims(token, r) +} + +func (a *JWTAuthenticator) parseJWTClaims(bearer string, r *http.Request) (context.Context, error) { config := getConfig(r.Context()) p := jwt.Parser{ValidMethods: []string{jwt.SigningMethodHS256.Name}} token, err := p.ParseWithClaims(bearer, &GatewayClaims{}, func(token *jwt.Token) (interface{}, error) { return []byte(config.JWT.Secret), nil }) + + if err != nil { + return nil, unauthorizedError("Invalid token: %v", err) + } + claims := token.Claims.(GatewayClaims) + return withClaims(r.Context(), &claims), nil +} + +func (a *OktaJWTAuthenticator) getName() string { + return a.name +} + +func (a *OktaJWTAuthenticator) authenticate(w http.ResponseWriter, r *http.Request) (context.Context, error) { + logrus.Info("Getting auth token") + token, err := a.auth.extractBearerToken(w, r) + if err != nil { + return nil, err + } + + logrus.Infof("Parsing JWT claims: %v", token) + return a.parseOktaJWTClaims(token, r) +} + +func (a *OktaJWTAuthenticator) parseOktaJWTClaims(bearer string, r *http.Request) (context.Context, error) { + config := getConfig(r.Context()) + + toValidate := map[string]string{} + toValidate["aud"] = config.JWT.AUD + toValidate["cid"] = config.JWT.CID + + jwtVerifierSetup := jwtverifier.JwtVerifier{ + Issuer: config.JWT.Issuer, + ClaimsToValidate: toValidate, + } + + verifier := jwtVerifierSetup.New() + + token, err := verifier.VerifyAccessToken(bearer) + if err != nil { return nil, unauthorizedError("Invalid token: %v", err) } + logrus.Infof("parseJWTClaims passed") + + claims := GatewayClaims{ + Email: token.Claims["sub"].(string), + AppMetaData: nil, + UserMetaData: nil, + StandardClaims: jwt.StandardClaims{ + Audience: token.Claims["aud"].(string), + ExpiresAt: int64(token.Claims["exp"].(float64)), + Id: token.Claims["jti"].(string), + IssuedAt: int64(token.Claims["iat"].(float64)), + Issuer: token.Claims["iss"].(string), + NotBefore: 0, + Subject: token.Claims["sub"].(string), + }, + } + + return withClaims(r.Context(), &claims), nil +} + +func (a *RolesAuthorizer) getName() string { + return a.name +} + +func (a *RolesAuthorizer) authorize(w http.ResponseWriter, r *http.Request) (context.Context, error) { + ctx := r.Context() + claims := getClaims(ctx) + config := getConfig(ctx) + + logrus.Infof("authenticate url: %v+", r.URL) + logrus.Infof("claims: %v+", claims) + if claims == nil { + return nil, unauthorizedError("Access to endpoint not allowed: no claims found in Bearer token") + } + + if len(config.Roles) == 0 { + return ctx, nil + } + + roles, ok := claims.AppMetaData["roles"] + if ok { + roleStrings, _ := roles.([]interface{}) + for _, data := range roleStrings { + role, _ := data.(string) + for _, adminRole := range config.Roles { + if role == adminRole { + return ctx, nil + } + } + } + } - return withToken(r.Context(), token), nil + return nil, unauthorizedError("Access to endpoint not allowed: your role doesn't allow access") } diff --git a/api/bitbucket.go b/api/bitbucket.go index 68dda4f..1f30dc4 100644 --- a/api/bitbucket.go +++ b/api/bitbucket.go @@ -5,7 +5,6 @@ import ( "compress/gzip" "context" "encoding/json" - "errors" "io" "io/ioutil" "net/http" @@ -118,8 +117,8 @@ func (bb *BitBucketGateway) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - if err := bb.authenticate(w, r); err != nil { - handleError(unauthorizedError(err.Error()), w, r) + if !bitbucketAllowedRegexp.MatchString(r.URL.Path) { + handleError(unauthorizedError("Access to endpoint not allowed: this part of BitBucket's API has been restricted"), w, r) return } @@ -142,39 +141,6 @@ func (bb *BitBucketGateway) ServeHTTP(w http.ResponseWriter, r *http.Request) { bb.proxy.ServeHTTP(w, r.WithContext(ctx)) } -func (bb *BitBucketGateway) authenticate(w http.ResponseWriter, r *http.Request) error { - ctx := r.Context() - claims := getClaims(ctx) - config := getConfig(ctx) - - if claims == nil { - return errors.New("Access to endpoint not allowed: no claims found in Bearer token") - } - - if !bitbucketAllowedRegexp.MatchString(r.URL.Path) { - return errors.New("Access to endpoint not allowed: this part of BitBucket's API has been restricted") - } - - if len(config.Roles) == 0 { - return nil - } - - roles, ok := claims.AppMetaData["roles"] - if ok { - roleStrings, _ := roles.([]interface{}) - for _, data := range roleStrings { - role, _ := data.(string) - for _, adminRole := range config.Roles { - if role == adminRole { - return nil - } - } - } - } - - return errors.New("Access to endpoint not allowed: your role doesn't allow access") -} - func rewriteBitBucketLink(link, endpointAPIURL, proxyAPIURL string) string { return proxyAPIURL + strings.TrimPrefix(link, endpointAPIURL) } diff --git a/api/context.go b/api/context.go index e8d2a8a..ca0abed 100644 --- a/api/context.go +++ b/api/context.go @@ -4,7 +4,6 @@ import ( "context" "net/url" - jwt "github.com/dgrijalva/jwt-go" "github.com/netlify/git-gateway/conf" "github.com/netlify/git-gateway/models" ) @@ -21,7 +20,7 @@ func (c contextKey) String() string { const ( accessTokenKey = contextKey("access_token") - tokenKey = contextKey("jwt") + tokenClaimsKey = contextKey("jwt_claims") requestIDKey = contextKey("request_id") configKey = contextKey("config") instanceIDKey = contextKey("instance_id") @@ -31,27 +30,17 @@ const ( netlifyIDKey = contextKey("netlify_id") ) -// withToken adds the JWT token to the context. -func withToken(ctx context.Context, token *jwt.Token) context.Context { - return context.WithValue(ctx, tokenKey, token) -} - -// getToken reads the JWT token from the context. -func getToken(ctx context.Context) *jwt.Token { - obj := ctx.Value(tokenKey) - if obj == nil { - return nil - } - - return obj.(*jwt.Token) +// withTokenClaims adds the JWT token claims to the context. +func withClaims(ctx context.Context, claims *GatewayClaims) context.Context { + return context.WithValue(ctx, tokenClaimsKey, claims) } func getClaims(ctx context.Context) *GatewayClaims { - token := getToken(ctx) - if token == nil { + claims := ctx.Value(tokenClaimsKey) + if claims == nil { return nil } - return token.Claims.(*GatewayClaims) + return claims.(*GatewayClaims) } func withRequestID(ctx context.Context, id string) context.Context { diff --git a/api/github.go b/api/github.go index 72ff074..47cedb5 100644 --- a/api/github.go +++ b/api/github.go @@ -1,7 +1,6 @@ package api import ( - "errors" "net/http" "net/http/httputil" "net/url" @@ -60,8 +59,8 @@ func (gh *GitHubGateway) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - if err := gh.authenticate(w, r); err != nil { - handleError(unauthorizedError(err.Error()), w, r) + if !allowedRegexp.MatchString(r.URL.Path) { + handleError(unauthorizedError("Access to endpoint not allowed: this part of GitHub's API has been restricted"), w, r) return } @@ -74,40 +73,8 @@ func (gh *GitHubGateway) ServeHTTP(w http.ResponseWriter, r *http.Request) { } ctx = withProxyTarget(ctx, target) ctx = withAccessToken(ctx, config.GitHub.AccessToken) - gh.proxy.ServeHTTP(w, r.WithContext(ctx)) -} - -func (gh *GitHubGateway) authenticate(w http.ResponseWriter, r *http.Request) error { - ctx := r.Context() - claims := getClaims(ctx) - config := getConfig(ctx) - - if claims == nil { - return errors.New("Access to endpoint not allowed: no claims found in Bearer token") - } - if !allowedRegexp.MatchString(r.URL.Path) { - return errors.New("Access to endpoint not allowed: this part of GitHub's API has been restricted") - } - - if len(config.Roles) == 0 { - return nil - } - - roles, ok := claims.AppMetaData["roles"] - if ok { - roleStrings, _ := roles.([]interface{}) - for _, data := range roleStrings { - role, _ := data.(string) - for _, adminRole := range config.Roles { - if role == adminRole { - return nil - } - } - } - } - - return errors.New("Access to endpoint not allowed: your role doesn't allow access") + gh.proxy.ServeHTTP(w, r.WithContext(ctx)) } type GitHubTransport struct{} diff --git a/api/gitlab.go b/api/gitlab.go index 3702eae..7c855a7 100644 --- a/api/gitlab.go +++ b/api/gitlab.go @@ -1,7 +1,6 @@ package api import ( - "errors" "net/http" "net/http/httputil" "net/url" @@ -79,8 +78,8 @@ func (gl *GitLabGateway) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - if err := gl.authenticate(w, r); err != nil { - handleError(unauthorizedError(err.Error()), w, r) + if !gitlabAllowedRegexp.MatchString(r.URL.Path) { + handleError(unauthorizedError("Access to endpoint not allowed: this part of GitLab's API has been restricted"), w, r) return } @@ -99,39 +98,6 @@ func (gl *GitLabGateway) ServeHTTP(w http.ResponseWriter, r *http.Request) { gl.proxy.ServeHTTP(w, r.WithContext(ctx)) } -func (gl *GitLabGateway) authenticate(w http.ResponseWriter, r *http.Request) error { - ctx := r.Context() - claims := getClaims(ctx) - config := getConfig(ctx) - - if claims == nil { - return errors.New("Access to endpoint not allowed: no claims found in Bearer token") - } - - if !gitlabAllowedRegexp.MatchString(r.URL.Path) { - return errors.New("Access to endpoint not allowed: this part of GitLab's API has been restricted") - } - - if len(config.Roles) == 0 { - return nil - } - - roles, ok := claims.AppMetaData["roles"] - if ok { - roleStrings, _ := roles.([]interface{}) - for _, data := range roleStrings { - role, _ := data.(string) - for _, adminRole := range config.Roles { - if role == adminRole { - return nil - } - } - } - } - - return errors.New("Access to endpoint not allowed: your role doesn't allow access") -} - var gitlabLinkRegex = regexp.MustCompile("<(.*?)>") var gitlabLinkRelRegex = regexp.MustCompile("rel=\"(.*?)\"") diff --git a/api/middleware.go b/api/middleware.go index adf9ca5..08cae70 100644 --- a/api/middleware.go +++ b/api/middleware.go @@ -80,7 +80,7 @@ func (a *API) verifyOperatorRequest(w http.ResponseWriter, req *http.Request) (c } func (a *API) extractOperatorRequest(w http.ResponseWriter, req *http.Request) (context.Context, string, error) { - token, err := a.extractBearerToken(w, req) + token, err := a.auth.extractBearerToken(w, req) if err != nil { return nil, token, err } diff --git a/conf/configuration.go b/conf/configuration.go index d162f8a..80495f2 100644 --- a/conf/configuration.go +++ b/conf/configuration.go @@ -46,6 +46,10 @@ type DBConfiguration struct { // JWTConfiguration holds all the JWT related configuration. type JWTConfiguration struct { Secret string `json:"secret" required:"true"` + CID string `envconfig:"CLIENT_ID" json:"client_id,omitempty"` + Issuer string `envconfig:"ISSUER" json:"issuer,omitempty"` + AUD string `envconfig:"AUD" json:"aud,omitempty"` + Authenticator string `envconfig:"AUTHENTICATOR" json:"authenticator,omitempty"` } // GlobalConfiguration holds all the configuration that applies to all instances. diff --git a/example.env b/example.env index 2d6691f..864edda 100644 --- a/example.env +++ b/example.env @@ -1,12 +1,38 @@ -GITGATEWAY_JWT_SECRET="CHANGE-THIS! VERY IMPORTANT!" +# Do not use quote (ie, "") if you start `git-gateway` with docker command: `--env-file` +# DB GITGATEWAY_DB_DRIVER=sqlite3 DATABASE_URL=gorm.db +# Startup Options GITGATEWAY_API_HOST=localhost PORT=9999 -GITGATEWAY_GITHUB_ACCESS_TOKEN="personal-access-token" -GITGATEWAY_GITHUB_REPO="owner/name" +# <> config for JWT Token with HS256 alg +# AUTHENTICATOR=bearer-jwt-token + +# Leave blank for other AUTHENTICATOR +GITGATEWAY_JWT_SECRET="CHANGE-THIS! VERY IMPORTANT!" +# + +# <> config for JWT Token with Okta (RS256) alg +AUTHENTICATOR=bearer-okta-jwt-token + +# REQUIRED for AUTHENTICATOR=bearer-okta-jwt-token +AUD=api://default + +# REQUIRED for AUTHENTICATOR=bearer-okta-jwt-token +ISSUER= +# + +# REQUIRED for both AUTHENTICATOR = {bearer-jwt-token or bearer-okta-jwt-token} +CLIENT_ID= + +# REQUIRED for GITHUB +GITGATEWAY_GITHUB_ACCESS_TOKEN= + +# REQUIRED for GITHUB +GITGATEWAY_GITHUB_REPO=owner/name -GITGATEWAY_ROLES="admin,cms" # leave blank to allow all roles +# Commented out to allow roles +GITGATEWAY_ROLES=admin,cms diff --git a/glide.lock b/glide.lock index 125fb36..7efa71b 100644 --- a/glide.lock +++ b/glide.lock @@ -1,12 +1,12 @@ -hash: 584c9db44ed61e38b043e033cc12c9a6f229a5a91a110b1f4a69bf48f843e0f1 -updated: 2017-08-21T11:29:52.316754668-04:00 +hash: d16d6e38e0df8d4315d0630917bff19bc885c18c3566e74638fa8c2fc59f2541 +updated: 2018-11-16T13:17:46.231317-08:00 imports: - name: cloud.google.com/go - version: 06f11fffc537c4aef126d9fd3a92e2d7968f118f + version: 74b12019e2aa53ec27882158f59192d7cd6d1998 subpackages: - compute/metadata - name: github.com/badoux/checkmail - version: d0a759655d62bcdc95c50a0676f3e9702ed59453 + version: 0755fe2dc241caebab64327c352006712f6a55c4 - name: github.com/davecgh/go-spew version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 subpackages: @@ -14,7 +14,7 @@ imports: - name: github.com/dgrijalva/jwt-go version: d2709f9f1f31ebcda9651b03077758c1f3a0018c - name: github.com/fsnotify/fsnotify - version: 4da3e2cfbabc9f751898f250b49f2439785783a1 + version: ccc981bf80385c528a65fbfdd49bf2d8da22aa23 - name: github.com/go-chi/chi version: b8567b6442e27704bfeb725095091581cbe82a00 subpackages: @@ -22,7 +22,7 @@ imports: - name: github.com/go-sql-driver/mysql version: a0583e0143b1624142adab07e0e97fe106d99561 - name: github.com/golang/protobuf - version: ab9f9a6dab164b7d1246e0e688b0ab7b94d8553e + version: 52132540909e117f2b98b0694383dc0ab1e1deca subpackages: - proto - name: github.com/GoogleCloudPlatform/cloudsql-proxy @@ -30,14 +30,16 @@ imports: subpackages: - logging - proxy/certs + - proxy/dialers/mysql - proxy/dialers/postgres - proxy/proxy - proxy/util - name: github.com/hashicorp/hcl - version: 392dba7d905ed5d04a5794ba89f558b27e2ba1ca + version: 65a6292f0157eff210d03ed1bf6c59b190b8b906 subpackages: - hcl/ast - hcl/parser + - hcl/printer - hcl/scanner - hcl/strconv - hcl/token @@ -45,36 +47,54 @@ imports: - json/scanner - json/token - name: github.com/imdario/mergo - version: 3e95a51e0639b4cf372f2ccf74c86749d747fbdc + version: ca3dcc1022bae9b5510f3c83705b72db1b1a96f9 - name: github.com/inconshreveable/mousetrap version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 - name: github.com/jinzhu/gorm version: 5b8c0dd6b92d9caa8036c31dcb117f2df7cceefa - name: github.com/jinzhu/inflection - version: 1c35d901db3da928c72a72d8458480cc9ade058f + version: 04140366298a54a039076d798123ffa108fff46c - name: github.com/joho/godotenv version: 726cc8b906e3d31c70a9671c90a13716a8d3f50d - name: github.com/kelseyhightower/envconfig version: f611eb38b3875cc3bd991ca91c51d06446afa14c - name: github.com/kr/logfmt version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 +- name: github.com/lestrrat-go/jwx + version: 0d477e6a1f0ec69634840308e3873fe71d928dd0 + subpackages: + - internal/base64 + - internal/option + - jwa + - jwk + - jws + - jws/sign + - jws/verify +- name: github.com/lestrrat-go/pdebug + version: 39f9a71bcabe9432cbdfe4d3d33f41988acd2ce6 - name: github.com/lib/pq - version: e42267488fe361b9dc034be7a6bffef5b195bceb + version: 9eb73efc1fcc404148b56765b0d3f61d9a5ef8ee subpackages: - oid - name: github.com/magiconair/properties - version: be5ece7dd465ab0765a9682137865547526d1dfb + version: c2353362d570a7bfa228149c62842019201cfb71 +- name: github.com/mailru/easyjson + version: 60711f1a8329503b04e1c88535f419d0bb440bff + subpackages: + - buffer + - jlexer + - jwriter - name: github.com/mattn/go-sqlite3 version: 3b3f1d01b2696af5501697c35629048c227586ab - name: github.com/mitchellh/mapstructure - version: d0303fe809921458f417bcf828397a65db30a7e4 + version: 3536a929edddb9a5b34bd6861dc4a9647cb459fe - name: github.com/nats-io/nats version: 61923ed1eaf8398000991fbbee2ef11ab5a5be0d subpackages: - encoders/builtin - util - name: github.com/nats-io/nuid - version: 3cf34f9fca4e88afa9da8eabd75e3326c9941b44 + version: 3024a71c3cbe30667286099921591e6fcc328230 - name: github.com/netlify/mailme version: c4a76ce443c1122ead2518b28cc7ffaf1091cc9a - name: github.com/netlify/netlify-commons @@ -86,16 +106,20 @@ imports: - metrics/transport - nconf - tls +- name: github.com/okta/okta-jwt-verifier-golang + version: 04702def3e1b9b1c6b419c9c3aae1ec184a5d4b2 + subpackages: + - adaptors + - adaptors/lestrratGoJwx + - discovery + - discovery/oidc + - errors - name: github.com/pborman/uuid version: a97ce2ca70fa5a848076093f05e639a89ca34d06 - name: github.com/pelletier/go-toml - version: 4692b8f9babfc93db58cc592ba2689d8736781de + version: aa79e12a973495d00b01f2353330e5275d084731 - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d -- name: github.com/pmezard/go-difflib - version: d8ed2627bdf02c080bf22230dbb337003b7aba2d - subpackages: - - difflib - name: github.com/rs/cors version: 8dd4211afb5d08dbb39a533b9bb9e4b486351df6 - name: github.com/rybit/nats_logrus_hook @@ -107,7 +131,7 @@ imports: - name: github.com/signalfx/gohistogram version: 1ccfd2ff508314074672f4450a917011a2060408 - name: github.com/signalfx/golib - version: cb7680940d605b817db79790c241eed2a00fa6e6 + version: 33764ade36dd90eb1593000ebee93ac1f9d9d419 subpackages: - datapoint - errors @@ -115,25 +139,28 @@ imports: - eventcounter - log - sfxclient + - sfxclient/spanfilter - timekeeper + - trace + - trace/format - name: github.com/sirupsen/logrus version: a3f95b5c423586578a4e099b11a46c2479628cac - name: github.com/spf13/afero - version: 9be650865eab0c12963d8753212f4f9c66cdcf12 + version: d40851caa0d747393da1ffb28f7f9d8b4eeffebd subpackages: - mem - name: github.com/spf13/cast - version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 + version: 8c9545af88b134710ab1cd196795e7f2388358d7 - name: github.com/spf13/cobra - version: 4a7b7e65864c064d48dce82efbbfed2bdc0bf2aa + version: fe5e611709b0c57fa4a89136deaa8e1d4004d053 - name: github.com/spf13/jwalterweatherman - version: 0efa5202c04663c757d84f90f5219c1250baf94f + version: 94f6ae3ed3bceceafa716478c5fbf8d29ca601a1 - name: github.com/spf13/pflag - version: e57e3eeb33f795204c1ca35f56c44f83227c6e66 + version: aea12ed6721610dc6ed40141676d7ab0a1dac9e9 - name: github.com/spf13/viper - version: 25b30aa063fc18e48662b86996252eabdcf2f0c7 + version: ae103d7e593e371c69e832d5eb3347e2b80cbbc9 - name: github.com/streadway/amqp - version: 2cbfe40c9341ad63ba23e53013b3ddc7989d801c + version: 27835f1a64e97101d95306211f03c0620ffa295d - name: github.com/stretchr/testify version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 subpackages: @@ -141,17 +168,16 @@ imports: - require - suite - name: golang.org/x/crypto - version: eb71ad9bd329b5ac0fd0148dd99bd62e8be8e035 + version: 3d3f9f413869b949e48070b5bc593aa22cc2b8f2 subpackages: - bcrypt - - blowfish - name: golang.org/x/net - version: 1c05540f6879653db88113bc4a2b70aec4bd491f + version: adae6a3d119ae4890b46832a2e88a95adc62b8e7 subpackages: - context - context/ctxhttp - name: golang.org/x/oauth2 - version: 9a379c6b3e95a790ffc43293c2a78dee0d7b6e20 + version: f42d05182288abf10faef86d16c0d07b8d40ea2d subpackages: - bitbucket - github @@ -160,23 +186,23 @@ imports: - jws - jwt - name: golang.org/x/sys - version: 07c182904dbd53199946ba614a412c61d3c548f5 + version: 93218def8b18e66adbdab3eca8ec334700329f1f subpackages: - unix - name: golang.org/x/text - version: e56139fd9c5bc7244c76116c68e500765bb6db6b + version: 6f44c5a2ea40ee3593d98cdcc905cc1fdaa660e2 subpackages: - transform - unicode/norm - name: google.golang.org/api - version: ed10e890a8366167a7ce33fac2b12447987bcb1c + version: 83a9d304b1e613fc253e1e2710778642fe81af53 subpackages: - gensupport - googleapi - googleapi/internal/uritemplates - sqladmin/v1beta4 - name: google.golang.org/appengine - version: d9a072cfa7b9736e44311ef77b3e09d804bfa599 + version: 4a4468ece617fc8205e99368fa2200e9d1fad421 subpackages: - internal - internal/app_identity @@ -187,22 +213,21 @@ imports: - internal/remote_api - internal/urlfetch - urlfetch -- name: gopkg.in/alexcesaro/quotedprintable.v3 - version: 2caba252f4dc53eaf6b553000885530023f54623 - name: gopkg.in/gomail.v2 version: 41f3572897373c5538c50a2402db15db079fa4fd - name: gopkg.in/logfmt.v0 version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 - name: gopkg.in/mgo.v2 - version: 3f83fa5005286a7fe593b055f0d7771a7dce4655 + version: 9856a29383ce1c59f308dd1cf0363a79b5bef6b5 subpackages: - bson - - internal/json - - internal/sasl - - internal/scram - txn - name: gopkg.in/stack.v1 - version: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf + version: 2fee6af1a9795aafbe0253a0cfbdf668e1fb8a9a - name: gopkg.in/yaml.v2 - version: eb3733d160e74a9c7e442f435eb3bea458e1d19f -testImports: [] + version: 5420a8b6744d3b0345ab293f6fcba19c978f1183 +testImports: +- name: github.com/pmezard/go-difflib + version: d8ed2627bdf02c080bf22230dbb337003b7aba2d + subpackages: + - difflib diff --git a/glide.yaml b/glide.yaml index 20f99fc..18d20d6 100644 --- a/glide.yaml +++ b/glide.yaml @@ -2,6 +2,8 @@ package: github.com/netlify/git-gateway import: - package: github.com/dgrijalva/jwt-go version: v3.0.0 +- package: github.com/okta/okta-jwt-verifier-golang + version: 04702def3e1b9b1c6b419c9c3aae1ec184a5d4b2 - package: github.com/jinzhu/gorm version: 5b8c0dd6b92d9caa8036c31dcb117f2df7cceefa - package: github.com/pborman/uuid From 2e10cc5b2411c02b6ee0d841fadfd61178e224c3 Mon Sep 17 00:00:00 2001 From: Thomas Yip Date: Wed, 28 Nov 2018 15:37:55 -0800 Subject: [PATCH 2/2] Updated .travis to get it build. * updated to golang 1.11 * worked around open-source fork problem * fixed lint on auth.go and errors.go --- .travis.yml | 10 +++++++++- api/auth.go | 2 +- api/errors.go | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2ffeb70..e1c56f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,11 +11,19 @@ addons: - mongodb-org-server go: - - 1.8 + - 1.11 env: - git-gateway_MONGODB_TEST_CONN_URL=127.0.0.1 +before_install: + # git-gateway consists of multiple Go packages, which refer to each other by + # their absolute GitHub path, e.g. github.com/netlify/git-gateway/api + # That means, by default, if someone forks the repo, Travis won't pass for the + # branch on their own repo. To fix that, we move the directory + - mkdir -p $TRAVIS_BUILD_DIR $GOPATH/src/github.com/netlify + - test ! -d $GOPATH/src/github.com/netlify/git-gateway && mv $TRAVIS_BUILD_DIR $GOPATH/src/github.com/netlify/git-gateway || true + install: make deps script: make all diff --git a/api/auth.go b/api/auth.go index 6a7f2c6..f1d4afb 100644 --- a/api/auth.go +++ b/api/auth.go @@ -53,7 +53,7 @@ func NewAuthWithVersion(ctx context.Context, version string) *Auth { auth.authenticator = &OktaJWTAuthenticator{name: "bearer-okta-jwt-token", auth: *auth} } else { if (authenticatorName != "") { - logrus.Fatal("Authenticator `%v` is not recognized", authenticatorName) + logrus.Fatal("Authenticator `" + authenticatorName + "` is not recognized") } else { logrus.Fatal("Authenticator is not defined") } diff --git a/api/errors.go b/api/errors.go index 98dfe6e..61b33c3 100644 --- a/api/errors.go +++ b/api/errors.go @@ -31,7 +31,7 @@ func (e *OAuthError) WithInternalError(err error) *OAuthError { // WithInternalMessage adds internal message information to the error func (e *OAuthError) WithInternalMessage(fmtString string, args ...interface{}) *OAuthError { - e.InternalMessage = fmt.Sprintf(fmtString, args) + e.InternalMessage = fmt.Sprintf(fmtString, args...) return e } @@ -99,7 +99,7 @@ func (e *HTTPError) WithInternalError(err error) *HTTPError { // WithInternalMessage adds internal message information to the error func (e *HTTPError) WithInternalMessage(fmtString string, args ...interface{}) *HTTPError { - e.InternalMessage = fmt.Sprintf(fmtString, args) + e.InternalMessage = fmt.Sprintf(fmtString, args...) return e }