From 591f293c8bcf464ed62701321d3f27de31ceb621 Mon Sep 17 00:00:00 2001 From: mo khan Date: Wed, 28 May 2025 12:14:11 -0600 Subject: refactor: parse headers injected by envoy --- pkg/authz/id_token.go | 38 ++++++++++++++++++++++++++------------ pkg/authz/id_token_test.go | 1 + 2 files changed, 27 insertions(+), 12 deletions(-) (limited to 'pkg') diff --git a/pkg/authz/id_token.go b/pkg/authz/id_token.go index ccc96de..3271af8 100644 --- a/pkg/authz/id_token.go +++ b/pkg/authz/id_token.go @@ -5,21 +5,35 @@ import ( "encoding/json" "errors" "strings" - "time" ) +type CustomClaims struct { + Name string `json:"name"` + Nickname string `json:"nickname"` + Email string `json:"email"` + ProfileURL string `json:"profile"` + Picture string `json:"picture"` + Groups []string `json:"groups_direct"` +} + type IDToken struct { - // Audience []string `json:"aud"` - Email string `json:"email"` - EmailVerified bool `json:"email_verified"` - ExpiredAt int64 `json:"exp"` - IssuedAt int64 `json:"iat"` - Issuer string `json:"iss"` - Name string `json:"name"` - Nickname string `json:"nickname"` - Picture string `json:"picture"` - Subject string `json:"sub"` - UpdatedAt time.Time `json:"updated_at"` + Issuer string `json:"iss"` + Subject string `json:"sub"` + Audience any `json:"aud"` + Expiry any `json:"exp"` + IssuedAt any `json:"iat"` + NotBefore any `json:"nbf"` + Nonce string `json:"nonce"` + AtHash string `json:"at_hash"` + ClaimNames map[string]string `json:"_claim_names"` + ClaimSources map[string]ClaimSource `json:"_claim_sources"` + + CustomClaims +} + +type ClaimSource struct { + Endpoint string `json:"endpoint"` + AccessToken string `json:"access_token"` } func NewIDToken(raw string) (*IDToken, error) { diff --git a/pkg/authz/id_token_test.go b/pkg/authz/id_token_test.go index 22aabc4..054c48b 100644 --- a/pkg/authz/id_token_test.go +++ b/pkg/authz/id_token_test.go @@ -15,6 +15,7 @@ func TestIDToken(t *testing.T) { t.Run("when the token is valid", func(t *testing.T) { user := mockoidc.DefaultUser() _, rawIDToken := idp.CreateTokensFor(user) + t.Logf("id_token: %v\n", rawIDToken) token, err := NewIDToken(rawIDToken) require.NoError(t, err) -- cgit v1.2.3 From 5b6ed074bfb9c99d24d17dd9ba720d69fadf91b1 Mon Sep 17 00:00:00 2001 From: mo khan Date: Wed, 28 May 2025 12:34:58 -0600 Subject: refactor: delete jwt verification code --- app/init.go | 22 ---------------------- app/middleware/from_cookie.go | 15 --------------- app/middleware/from_custom_header.go | 9 --------- app/middleware/init.go | 2 +- app/middleware/raw_token.go | 7 ------- app/middleware/token_parser.go | 3 --- app/middleware/user.go | 23 +++++++++++++++-------- app/middleware/user_parser.go | 16 ---------------- app/middleware/user_parser_test.go | 36 ------------------------------------ app/middleware/user_test.go | 2 ++ bin/envoy.sh | 2 +- pkg/web/cookie.go | 35 ----------------------------------- pkg/web/cookie_test.go | 33 --------------------------------- pkg/web/oidc.go | 27 --------------------------- 14 files changed, 19 insertions(+), 213 deletions(-) delete mode 100644 app/middleware/from_cookie.go delete mode 100644 app/middleware/from_custom_header.go delete mode 100644 app/middleware/raw_token.go delete mode 100644 app/middleware/token_parser.go delete mode 100644 app/middleware/user_parser.go delete mode 100644 app/middleware/user_parser_test.go delete mode 100644 pkg/web/cookie.go delete mode 100644 pkg/web/cookie_test.go delete mode 100644 pkg/web/oidc.go (limited to 'pkg') diff --git a/app/init.go b/app/init.go index 935c962..5057fe4 100644 --- a/app/init.go +++ b/app/init.go @@ -1,24 +1,20 @@ package app import ( - "context" "net/http" "os" - "github.com/coreos/go-oidc/v3/oidc" "github.com/rs/zerolog" "github.com/xlgmokha/x/pkg/env" "github.com/xlgmokha/x/pkg/ioc" "github.com/xlgmokha/x/pkg/log" "github.com/xlgmokha/x/pkg/mapper" "gitlab.com/gitlab-org/software-supply-chain-security/authorization/authzd.git/pkg/rpc" - "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/cfg" "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/controllers/dashboard" "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/controllers/sparkles" "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/db" "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/domain" "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/web" - "golang.org/x/oauth2" ) func init() { @@ -28,9 +24,6 @@ func init() { ioc.RegisterSingleton[domain.Repository[*domain.Sparkle]](ioc.Default, func() domain.Repository[*domain.Sparkle] { return db.NewRepository[*domain.Sparkle]() }) - ioc.RegisterSingleton[domain.Repository[*domain.User]](ioc.Default, func() domain.Repository[*domain.User] { - return db.NewRepository[*domain.User]() - }) ioc.RegisterSingleton[*http.ServeMux](ioc.Default, func() *http.ServeMux { return http.NewServeMux() }) @@ -47,21 +40,6 @@ func init() { }, } }) - ioc.RegisterSingleton[*oidc.Provider](ioc.Default, func() *oidc.Provider { - ctx := context.WithValue( - context.Background(), - oauth2.HTTPClient, - ioc.MustResolve[*http.Client](ioc.Default), - ) - return web.NewOIDCProvider(ctx, cfg.OIDCIssuer, func(err error) { - ioc.MustResolve[*zerolog.Logger](ioc.Default).Err(err).Send() - }) - }) - ioc.Register[*oidc.Config](ioc.Default, func() *oidc.Config { - return &oidc.Config{ - ClientID: cfg.OAuthClientID, - } - }) ioc.Register[rpc.Ability](ioc.Default, func() rpc.Ability { return rpc.NewAbilityProtobufClient( env.Fetch("AUTHZD_HOST", ""), diff --git a/app/middleware/from_cookie.go b/app/middleware/from_cookie.go deleted file mode 100644 index 316d6e4..0000000 --- a/app/middleware/from_cookie.go +++ /dev/null @@ -1,15 +0,0 @@ -package middleware - -import "net/http" - -func FromCookie(name string) TokenParser { - return func(r *http.Request) RawToken { - cookies := r.CookiesNamed(name) - - if len(cookies) != 1 { - return "" - } - - return RawToken(cookies[0].Value) - } -} diff --git a/app/middleware/from_custom_header.go b/app/middleware/from_custom_header.go deleted file mode 100644 index f385911..0000000 --- a/app/middleware/from_custom_header.go +++ /dev/null @@ -1,9 +0,0 @@ -package middleware - -import "net/http" - -func FromCustomHeader(name string) TokenParser { - return func(r *http.Request) RawToken { - return RawToken(r.Header.Get(name)) - } -} diff --git a/app/middleware/init.go b/app/middleware/init.go index 5bf84f6..23c524d 100644 --- a/app/middleware/init.go +++ b/app/middleware/init.go @@ -13,7 +13,7 @@ func init() { subject := h.Get("x-jwt-claim-sub") if x.IsPresent(subject) { return &domain.User{ - ID: domain.ID(subject), + ID: domain.ID(h.Get("x-jwt-claim-sub")), Username: h.Get("x-jwt-claim-username"), ProfileURL: h.Get("x-jwt-claim-profile-url"), Picture: h.Get("x-jwt-claim-picture-url"), diff --git a/app/middleware/raw_token.go b/app/middleware/raw_token.go deleted file mode 100644 index f7aa264..0000000 --- a/app/middleware/raw_token.go +++ /dev/null @@ -1,7 +0,0 @@ -package middleware - -type RawToken string - -func (r RawToken) String() string { - return string(r) -} diff --git a/app/middleware/token_parser.go b/app/middleware/token_parser.go deleted file mode 100644 index 1a92760..0000000 --- a/app/middleware/token_parser.go +++ /dev/null @@ -1,3 +0,0 @@ -package middleware - -type TokenParser RequestParser[RawToken] diff --git a/app/middleware/user.go b/app/middleware/user.go index 90bf6aa..2b2dd17 100644 --- a/app/middleware/user.go +++ b/app/middleware/user.go @@ -3,20 +3,27 @@ package middleware import ( "net/http" - "github.com/xlgmokha/x/pkg/x" + "github.com/xlgmokha/x/pkg/log" + "github.com/xlgmokha/x/pkg/mapper" "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/cfg" + "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/domain" ) func User() func(http.Handler) http.Handler { - parser := UserParser() return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - user := parser(r) - if x.IsPresent(user) { - next.ServeHTTP(w, r.WithContext(cfg.CurrentUser.With(r.Context(), user))) - } else { - next.ServeHTTP(w, r) - } + log.WithFields(r.Context(), log.Fields{ + "payload": r.Header.Get("x-jwt-payload"), + "photo": r.Header.Get("x-jwt-claim-picture-url"), + "profile": r.Header.Get("x-jwt-claim-profile-url"), + "sub": r.Header.Get("x-jwt-claim-sub"), + "username": r.Header.Get("x-jwt-claim-username"), + }) + + next.ServeHTTP(w, r.WithContext(cfg.CurrentUser.With( + r.Context(), + mapper.MapFrom[http.Header, *domain.User](r.Header), + ))) }) } } diff --git a/app/middleware/user_parser.go b/app/middleware/user_parser.go deleted file mode 100644 index dfa0cce..0000000 --- a/app/middleware/user_parser.go +++ /dev/null @@ -1,16 +0,0 @@ -package middleware - -import ( - "net/http" - - "github.com/xlgmokha/x/pkg/log" - "github.com/xlgmokha/x/pkg/mapper" - "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/domain" -) - -func UserParser() RequestParser[*domain.User] { - return func(r *http.Request) *domain.User { - log.WithFields(r.Context(), log.Fields{"header": r.Header}) - return mapper.MapFrom[http.Header, *domain.User](r.Header) - } -} diff --git a/app/middleware/user_parser_test.go b/app/middleware/user_parser_test.go deleted file mode 100644 index 2127a10..0000000 --- a/app/middleware/user_parser_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package middleware - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/xlgmokha/x/pkg/test" - "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/domain" -) - -func TestUserParser(t *testing.T) { - parser := UserParser() - - t.Run("when x-jwt-claim-* headers are not provided", func(t *testing.T) { - t.Run("forwards the request without a current user attached to the request", func(t *testing.T) { - assert.Nil(t, parser(test.Request("GET", "/"))) - }) - }) - - t.Run("when x-jwt-claim-* headers are provided", func(t *testing.T) { - r := test.Request("GET", "/", - test.WithRequestHeader("x-jwt-claim-sub", "1"), - test.WithRequestHeader("x-jwt-claim-username", "root"), - test.WithRequestHeader("x-jwt-claim-profile-url", "https://gitlab.com/tanuki"), - test.WithRequestHeader("x-jwt-claim-picture-url", "https://example.com/profile.png"), - ) - - result := parser(r) - require.NotNil(t, result) - assert.Equal(t, domain.ID("1"), result.ID) - assert.Equal(t, "root", result.Username) - assert.Equal(t, "https://gitlab.com/tanuki", result.ProfileURL) - assert.Equal(t, "https://example.com/profile.png", result.Picture) - }) -} diff --git a/app/middleware/user_test.go b/app/middleware/user_test.go index c5fa7ed..66ca121 100644 --- a/app/middleware/user_test.go +++ b/app/middleware/user_test.go @@ -29,6 +29,8 @@ func TestUser(t *testing.T) { t.Run("when x-jwt-claim-* headers are provided", func(t *testing.T) { server := middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + require.True(t, IsLoggedIn(r)) + user := cfg.CurrentUser.From(r.Context()) require.NotNil(t, user) diff --git a/bin/envoy.sh b/bin/envoy.sh index 692167c..219228f 100755 --- a/bin/envoy.sh +++ b/bin/envoy.sh @@ -33,4 +33,4 @@ fi envoy \ --config-yaml "$yaml" \ --log-level warn \ - --component-log-level admin:warn,connection:warn,ext_authz:info,grpc:info,health_checker:warn,http:warn,http2:warn,jwt:warn,oauth2:warn,router:warn,secret:warn,upstream:warn + --component-log-level admin:warn,connection:warn,ext_authz:info,grpc:info,health_checker:warn,http:warn,http2:warn,jwt:trace,oauth2:warn,router:warn,secret:warn,upstream:warn diff --git a/pkg/web/cookie.go b/pkg/web/cookie.go deleted file mode 100644 index 11cc807..0000000 --- a/pkg/web/cookie.go +++ /dev/null @@ -1,35 +0,0 @@ -package web - -import ( - "net/http" - - "github.com/xlgmokha/x/pkg/cookie" - "github.com/xlgmokha/x/pkg/x" -) - -func NewCookie(name, value string, options ...x.Option[*http.Cookie]) *http.Cookie { - return x.New[*http.Cookie](x.Prepend[x.Option[*http.Cookie]]( - options, - cookie.WithName(name), - cookie.WithValue(value), - cookie.WithPath("/"), - cookie.WithHttpOnly(true), - cookie.WithSecure(true), - )...) -} - -func ExpireCookie(w http.ResponseWriter, name string) error { - return WriteCookie(w, cookie.Reset(name, - cookie.WithPath("/"), - cookie.WithHttpOnly(true), - cookie.WithSecure(true), - )) -} - -func WriteCookie(w http.ResponseWriter, c *http.Cookie) error { - if err := c.Valid(); err != nil { - return err - } - cookie.Write(w, c) - return nil -} diff --git a/pkg/web/cookie_test.go b/pkg/web/cookie_test.go deleted file mode 100644 index 1a3bfb0..0000000 --- a/pkg/web/cookie_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package web - -import ( - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestNewCookie(t *testing.T) { - cookie := NewCookie("name", "value") - assert.True(t, cookie.HttpOnly) - assert.True(t, cookie.Secure) -} - -func TestExpireCookie(t *testing.T) { - w := httptest.NewRecorder() - - ExpireCookie(w, "example") - - result, err := http.ParseSetCookie(w.Header().Get("Set-Cookie")) - require.NoError(t, err) - - assert.Empty(t, result.Value) - assert.Equal(t, -1, result.MaxAge) - assert.Equal(t, time.Unix(0, 0).Unix(), result.Expires.Unix()) - assert.True(t, result.HttpOnly) - assert.True(t, result.Secure) - assert.Zero(t, result.SameSite) -} diff --git a/pkg/web/oidc.go b/pkg/web/oidc.go deleted file mode 100644 index 707a1b5..0000000 --- a/pkg/web/oidc.go +++ /dev/null @@ -1,27 +0,0 @@ -package web - -import ( - "context" - - "github.com/coreos/go-oidc/v3/oidc" -) - -func NewOIDCProvider(ctx context.Context, issuer string, report func(error)) *oidc.Provider { - provider, err := oidc.NewProvider(ctx, issuer) - if err == nil { - return provider - } - - report(err) - - config := &oidc.ProviderConfig{ - IssuerURL: issuer, - AuthURL: issuer + "/oauth/authorize", - TokenURL: issuer + "/oauth/token", - DeviceAuthURL: "", - UserInfoURL: issuer + "/oauth/userinfo", - JWKSURL: issuer + "/oauth/disovery/keys", - Algorithms: []string{"RS256"}, - } - return config.NewProvider(ctx) -} -- cgit v1.2.3 From e9546b40c8befabda26c1598c124a6ee2a8d2b8f Mon Sep 17 00:00:00 2001 From: mo khan Date: Wed, 28 May 2025 14:26:19 -0600 Subject: refactor: always provide a user in the request context --- app/controllers/dashboard/controller.go | 6 ++---- app/controllers/dashboard/controller_test.go | 3 ++- app/controllers/sparkles/controller_test.go | 3 ++- app/domain/entity.go | 6 ++++++ app/domain/user.go | 6 +----- app/middleware/init.go | 15 +++++---------- app/middleware/is_logged_in.go | 3 ++- app/middleware/request_parser.go | 9 --------- app/middleware/require_user_test.go | 3 ++- app/middleware/user.go | 11 ++++++----- app/middleware/user_test.go | 14 +++++++------- bin/envoy.sh | 2 +- etc/envoy/envoy.yaml | 23 +++++++---------------- pkg/authz/check_service.go | 1 + 14 files changed, 44 insertions(+), 61 deletions(-) delete mode 100644 app/middleware/request_parser.go (limited to 'pkg') diff --git a/app/controllers/dashboard/controller.go b/app/controllers/dashboard/controller.go index 04a7ed1..d279930 100644 --- a/app/controllers/dashboard/controller.go +++ b/app/controllers/dashboard/controller.go @@ -41,14 +41,12 @@ func (c *Controller) Show(w http.ResponseWriter, r *http.Request) { } func (c *Controller) Navigation(w http.ResponseWriter, r *http.Request) { - currentUser := cfg.CurrentUser.From(r.Context()) - w.WriteHeader(http.StatusOK) w.Header().Add("Content-Type", "text/html") dto := &NavigationDTO{ - CurrentUser: currentUser, - IsLoggedIn: currentUser != nil, + CurrentUser: cfg.CurrentUser.From(r.Context()), + IsLoggedIn: middleware.IsLoggedIn(r), } if err := views.Render(w, "dashboard/nav", dto); err != nil { pls.LogError(r.Context(), err) diff --git a/app/controllers/dashboard/controller_test.go b/app/controllers/dashboard/controller_test.go index c717a74..ddbfd34 100644 --- a/app/controllers/dashboard/controller_test.go +++ b/app/controllers/dashboard/controller_test.go @@ -28,7 +28,7 @@ func TestController(t *testing.T) { }) t.Run("when authenticated", func(t *testing.T) { - ctx := cfg.CurrentUser.With(t.Context(), &domain.User{}) + ctx := cfg.CurrentUser.With(t.Context(), &domain.User{ID: domain.ID("1")}) r, w := test.RequestResponse("GET", "/dashboard", test.WithContext(ctx)) mux.ServeHTTP(w, r) @@ -55,6 +55,7 @@ func TestController(t *testing.T) { t.Run("when authenticated", func(t *testing.T) { ctx := cfg.CurrentUser.With(t.Context(), &domain.User{ + ID: domain.ID("1"), Username: "root", }) r, w := test.RequestResponse("GET", "/dashboard/nav", test.WithContext(ctx)) diff --git a/app/controllers/sparkles/controller_test.go b/app/controllers/sparkles/controller_test.go index 8a1717d..0619b99 100644 --- a/app/controllers/sparkles/controller_test.go +++ b/app/controllers/sparkles/controller_test.go @@ -44,9 +44,10 @@ func TestSparkles(t *testing.T) { t.Run("POST /sparkles", func(t *testing.T) { t.Run("when a user is logged in", func(t *testing.T) { - currentUser := &domain.User{} + currentUser := domain.NewUser(domain.WithID[*domain.User](domain.ID("1"))) t.Run("saves a new sparkle", func(t *testing.T) { + repository := db.NewRepository[*domain.Sparkle]() mux := http.NewServeMux() controller := New(repository) diff --git a/app/domain/entity.go b/app/domain/entity.go index 0377c51..b2c2166 100644 --- a/app/domain/entity.go +++ b/app/domain/entity.go @@ -1,6 +1,12 @@ package domain +import "github.com/xlgmokha/x/pkg/x" + type Entity interface { Identifiable Validate() error } + +func New[T Entity](options ...x.Configure[T]) T { + return x.New[T](x.Map[x.Configure[T], x.Option[T]](options, x.With[T])...) +} diff --git a/app/domain/user.go b/app/domain/user.go index a6adfa8..52cd780 100644 --- a/app/domain/user.go +++ b/app/domain/user.go @@ -10,11 +10,7 @@ type User struct { } func NewUser(options ...x.Configure[*User]) *User { - user := &User{} - for _, option := range options { - option(user) - } - return user + return New[*User](options...) } func (u *User) GetID() ID { diff --git a/app/middleware/init.go b/app/middleware/init.go index 23c524d..4ff10c4 100644 --- a/app/middleware/init.go +++ b/app/middleware/init.go @@ -4,21 +4,16 @@ import ( "net/http" "github.com/xlgmokha/x/pkg/mapper" - "github.com/xlgmokha/x/pkg/x" "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/domain" ) func init() { mapper.Register(func(h http.Header) *domain.User { - subject := h.Get("x-jwt-claim-sub") - if x.IsPresent(subject) { - return &domain.User{ - ID: domain.ID(h.Get("x-jwt-claim-sub")), - Username: h.Get("x-jwt-claim-username"), - ProfileURL: h.Get("x-jwt-claim-profile-url"), - Picture: h.Get("x-jwt-claim-picture-url"), - } + return &domain.User{ + ID: domain.ID(h.Get("x-id-jwt-claim-sub")), + Username: h.Get("x-id-jwt-claim-username"), + ProfileURL: h.Get("x-id-jwt-claim-profile-url"), + Picture: h.Get("x-id-jwt-claim-picture-url"), } - return nil }) } diff --git a/app/middleware/is_logged_in.go b/app/middleware/is_logged_in.go index e2f0445..f70a03b 100644 --- a/app/middleware/is_logged_in.go +++ b/app/middleware/is_logged_in.go @@ -8,5 +8,6 @@ import ( ) var IsLoggedIn x.Predicate[*http.Request] = x.Predicate[*http.Request](func(r *http.Request) bool { - return x.IsPresent(cfg.CurrentUser.From(r.Context())) + user := cfg.CurrentUser.From(r.Context()) + return x.IsPresent(user) && x.IsPresent(user.ID) }) diff --git a/app/middleware/request_parser.go b/app/middleware/request_parser.go deleted file mode 100644 index dfc5d3a..0000000 --- a/app/middleware/request_parser.go +++ /dev/null @@ -1,9 +0,0 @@ -package middleware - -import ( - "net/http" - - "github.com/xlgmokha/x/pkg/x" -) - -type RequestParser[T any] x.Mapper[*http.Request, T] diff --git a/app/middleware/require_user_test.go b/app/middleware/require_user_test.go index 07cbf92..20b5f94 100644 --- a/app/middleware/require_user_test.go +++ b/app/middleware/require_user_test.go @@ -28,7 +28,8 @@ func TestRequireUser(t *testing.T) { t.Run("when a user is logged in", func(t *testing.T) { t.Run("forwards the request", func(t *testing.T) { - r, w := test.RequestResponse("GET", "/example", test.WithContextKeyValue(t.Context(), cfg.CurrentUser, &domain.User{})) + user := &domain.User{ID: domain.ID("1")} + r, w := test.RequestResponse("GET", "/example", test.WithContextKeyValue(t.Context(), cfg.CurrentUser, user)) server := middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusTeapot) diff --git a/app/middleware/user.go b/app/middleware/user.go index 2b2dd17..317671e 100644 --- a/app/middleware/user.go +++ b/app/middleware/user.go @@ -13,11 +13,12 @@ func User() func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.WithFields(r.Context(), log.Fields{ - "payload": r.Header.Get("x-jwt-payload"), - "photo": r.Header.Get("x-jwt-claim-picture-url"), - "profile": r.Header.Get("x-jwt-claim-profile-url"), - "sub": r.Header.Get("x-jwt-claim-sub"), - "username": r.Header.Get("x-jwt-claim-username"), + "authorization": r.Header.Get("Authorization"), + "payload": r.Header.Get("x-id-jwt-payload"), + "photo": r.Header.Get("x-id-jwt-claim-picture-url"), + "profile": r.Header.Get("x-id-jwt-claim-profile-url"), + "sub": r.Header.Get("x-id-jwt-claim-sub"), + "username": r.Header.Get("x-id-jwt-claim-username"), }) next.ServeHTTP(w, r.WithContext(cfg.CurrentUser.With( diff --git a/app/middleware/user_test.go b/app/middleware/user_test.go index 66ca121..c778c98 100644 --- a/app/middleware/user_test.go +++ b/app/middleware/user_test.go @@ -14,9 +14,9 @@ import ( func TestUser(t *testing.T) { middleware := User() - t.Run("when x-jwt-claim-* headers are not provided", func(t *testing.T) { + t.Run("when x-id-jwt-claim-* headers are not provided", func(t *testing.T) { server := middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - require.Nil(t, cfg.CurrentUser.From(r.Context())) + require.False(t, IsLoggedIn(r)) w.WriteHeader(http.StatusTeapot) })) @@ -27,7 +27,7 @@ func TestUser(t *testing.T) { assert.Equal(t, http.StatusTeapot, w.Code) }) - t.Run("when x-jwt-claim-* headers are provided", func(t *testing.T) { + t.Run("when x-id-jwt-claim-* headers are provided", func(t *testing.T) { server := middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { require.True(t, IsLoggedIn(r)) @@ -43,10 +43,10 @@ func TestUser(t *testing.T) { })) r, w := test.RequestResponse("GET", "/", - test.WithRequestHeader("x-jwt-claim-sub", "1"), - test.WithRequestHeader("x-jwt-claim-username", "root"), - test.WithRequestHeader("x-jwt-claim-profile-url", "https://gitlab.com/tanuki"), - test.WithRequestHeader("x-jwt-claim-picture-url", "https://example.com/profile.png"), + test.WithRequestHeader("x-id-jwt-claim-sub", "1"), + test.WithRequestHeader("x-id-jwt-claim-username", "root"), + test.WithRequestHeader("x-id-jwt-claim-profile-url", "https://gitlab.com/tanuki"), + test.WithRequestHeader("x-id-jwt-claim-picture-url", "https://example.com/profile.png"), ) server.ServeHTTP(w, r) diff --git a/bin/envoy.sh b/bin/envoy.sh index 219228f..1af16aa 100755 --- a/bin/envoy.sh +++ b/bin/envoy.sh @@ -33,4 +33,4 @@ fi envoy \ --config-yaml "$yaml" \ --log-level warn \ - --component-log-level admin:warn,connection:warn,ext_authz:info,grpc:info,health_checker:warn,http:warn,http2:warn,jwt:trace,oauth2:warn,router:warn,secret:warn,upstream:warn + --component-log-level admin:warn,connection:warn,ext_authz:info,grpc:info,health_checker:warn,http:warn,http2:warn,jwt:trace,oauth2:trace,router:warn,secret:warn,upstream:warn diff --git a/etc/envoy/envoy.yaml b/etc/envoy/envoy.yaml index ef676fb..a7d20be 100644 --- a/etc/envoy/envoy.yaml +++ b/etc/envoy/envoy.yaml @@ -172,24 +172,23 @@ static_resources: typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication providers: - provider1: + id_token_provider: issuer: https://example.com audiences: - OAUTH_CLIENT_ID claim_to_headers: - claim_name: sub - header_name: x-jwt-claim-sub + header_name: x-id-jwt-claim-sub - claim_name: nickname - header_name: x-jwt-claim-username + header_name: x-id-jwt-claim-username - claim_name: profile - header_name: x-jwt-claim-profile-url + header_name: x-id-jwt-claim-profile-url - claim_name: picture - header_name: x-jwt-claim-picture-url + header_name: x-id-jwt-claim-picture-url forward: true - forward_payload_header: x-jwt-payload + forward_payload_header: x-id-jwt-payload from_cookies: - id_token - - bearer_token issuer: https://example.com remote_jwks: http_uri: @@ -197,21 +196,13 @@ static_resources: cluster: oidc timeout: 5s rules: - - match: - path: /health - - match: - prefix: /sparkles - - match: - prefix: /dashboard/nav - match: safe_regex: regex: .*\\.(css|js|png|html|ico)$ - match: path: / - - match: - path: /dashboard requires: - provider_name: provider1 + provider_name: id_token_provider - name: envoy.filters.http.ext_authz typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz diff --git a/pkg/authz/check_service.go b/pkg/authz/check_service.go index 641ba92..9db32d0 100644 --- a/pkg/authz/check_service.go +++ b/pkg/authz/check_service.go @@ -40,6 +40,7 @@ func NewCheckService() *CheckService { } func (svc *CheckService) Check(ctx context.Context, request *auth.CheckRequest) (*auth.CheckResponse, error) { + log.WithFields(ctx, log.Fields{"headers": request.Attributes.Request.Http.Headers}) if svc.isAllowed(ctx, request) { return svc.OK(ctx), nil } -- cgit v1.2.3 From c7fe2ec85cf77ede757675f9f068c85d304d9f61 Mon Sep 17 00:00:00 2001 From: mo khan Date: Wed, 28 May 2025 14:54:14 -0600 Subject: chore: remove logging of sensitive fields --- app/middleware/user.go | 11 +++++------ pkg/authz/check_service.go | 1 - 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'pkg') diff --git a/app/middleware/user.go b/app/middleware/user.go index 317671e..0ffc8cf 100644 --- a/app/middleware/user.go +++ b/app/middleware/user.go @@ -13,12 +13,11 @@ func User() func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.WithFields(r.Context(), log.Fields{ - "authorization": r.Header.Get("Authorization"), - "payload": r.Header.Get("x-id-jwt-payload"), - "photo": r.Header.Get("x-id-jwt-claim-picture-url"), - "profile": r.Header.Get("x-id-jwt-claim-profile-url"), - "sub": r.Header.Get("x-id-jwt-claim-sub"), - "username": r.Header.Get("x-id-jwt-claim-username"), + "payload": r.Header.Get("x-id-jwt-payload"), + "photo": r.Header.Get("x-id-jwt-claim-picture-url"), + "profile": r.Header.Get("x-id-jwt-claim-profile-url"), + "sub": r.Header.Get("x-id-jwt-claim-sub"), + "username": r.Header.Get("x-id-jwt-claim-username"), }) next.ServeHTTP(w, r.WithContext(cfg.CurrentUser.With( diff --git a/pkg/authz/check_service.go b/pkg/authz/check_service.go index 9db32d0..641ba92 100644 --- a/pkg/authz/check_service.go +++ b/pkg/authz/check_service.go @@ -40,7 +40,6 @@ func NewCheckService() *CheckService { } func (svc *CheckService) Check(ctx context.Context, request *auth.CheckRequest) (*auth.CheckResponse, error) { - log.WithFields(ctx, log.Fields{"headers": request.Attributes.Request.Http.Headers}) if svc.isAllowed(ctx, request) { return svc.OK(ctx), nil } -- cgit v1.2.3 From e5bc1eb2b71d46958088f1c62e69e1074e9f8026 Mon Sep 17 00:00:00 2001 From: mo khan Date: Wed, 28 May 2025 17:01:00 -0600 Subject: test: remove logging from test --- pkg/authz/id_token_test.go | 1 - 1 file changed, 1 deletion(-) (limited to 'pkg') diff --git a/pkg/authz/id_token_test.go b/pkg/authz/id_token_test.go index 054c48b..22aabc4 100644 --- a/pkg/authz/id_token_test.go +++ b/pkg/authz/id_token_test.go @@ -15,7 +15,6 @@ func TestIDToken(t *testing.T) { t.Run("when the token is valid", func(t *testing.T) { user := mockoidc.DefaultUser() _, rawIDToken := idp.CreateTokensFor(user) - t.Logf("id_token: %v\n", rawIDToken) token, err := NewIDToken(rawIDToken) require.NoError(t, err) -- cgit v1.2.3