From aa65a30081aadfc9d69ad32769e38aad79d8aa08 Mon Sep 17 00:00:00 2001 From: ZdravkoGyurov <37419999+ZdravkoGyurov@users.noreply.github.com> Date: Fri, 17 May 2024 13:00:46 +0300 Subject: [PATCH] Make IAS adapter internal (#3873) * ias adapter internal * remove tenant auth middleware * refactor jwt middleware * rename jwt middleware file * move chart changes * revert image version --------- Co-authored-by: PetarTodorovv --- .../internal/api/middlewares/auth.go | 84 ------------------- .../api/middlewares/{jwt.go => id_token.go} | 15 ++-- components/ias-adapter/internal/api/server.go | 10 +-- 3 files changed, 9 insertions(+), 100 deletions(-) delete mode 100644 components/ias-adapter/internal/api/middlewares/auth.go rename components/ias-adapter/internal/api/middlewares/{jwt.go => id_token.go} (88%) diff --git a/components/ias-adapter/internal/api/middlewares/auth.go b/components/ias-adapter/internal/api/middlewares/auth.go deleted file mode 100644 index 4b7ed708c4..0000000000 --- a/components/ias-adapter/internal/api/middlewares/auth.go +++ /dev/null @@ -1,84 +0,0 @@ -package middlewares - -import ( - "context" - "crypto/tls" - "encoding/json" - "fmt" - "net/http" - "strings" - - "github.com/gin-gonic/gin" - - "github.com/kyma-incubator/compass/components/ias-adapter/internal/api/internal" - "github.com/kyma-incubator/compass/components/ias-adapter/internal/config" - "github.com/kyma-incubator/compass/components/ias-adapter/internal/errors" - "github.com/kyma-incubator/compass/components/ias-adapter/internal/logger" - "github.com/kyma-incubator/compass/components/ias-adapter/internal/types" -) - -// ClientIdFromCertificateHeader contains the name of the header containing the client id from the certificate -const ClientIdFromCertificateHeader = "Client-Id-From-Certificate" - -type AuthMiddleware struct { - config config.TenantInfo - client *http.Client - certSubject string -} - -func NewAuthMiddleware(ctx context.Context, cfg config.TenantInfo) (AuthMiddleware, error) { - middleware := AuthMiddleware{ - config: cfg, - client: &http.Client{ - Timeout: cfg.RequestTimeout, - Transport: &http.Transport{ - TLSClientConfig: &tls.Config{ - InsecureSkipVerify: cfg.InsecureSkipVerify, - }, - }, - }, - } - if err := middleware.getTenant(ctx); err != nil { - return middleware, errors.Newf("failed to get auth tenant: %w", err) - } - return middleware, nil -} - -func (m *AuthMiddleware) Auth(ctx *gin.Context) { - log := logger.FromContext(ctx) - - tenant := ctx.Request.Header.Get(ClientIdFromCertificateHeader) - if tenant == "" { - log.Error().Msg("Failed to find tenant in context") - internal.RespondWithError(ctx, http.StatusInternalServerError, errors.New("Tenant not found in request")) - return - } - orgUnit := fmt.Sprintf("OU=%s", tenant) - if !strings.Contains(m.certSubject, orgUnit) { - log.Error().Msgf("Tenant %s is not authorized", tenant) - internal.RespondWithError(ctx, http.StatusUnauthorized, errors.New(http.StatusText(http.StatusUnauthorized))) - return - } - - ctx.Next() -} - -func (m *AuthMiddleware) getTenant(ctx context.Context) error { - req, err := http.NewRequestWithContext(ctx, http.MethodGet, m.config.Endpoint, nil) - if err != nil { - return errors.Newf("failed to create request: %w", err) - } - resp, err := m.client.Do(req) - if err != nil { - return errors.Newf("failed to execute GET request: %w", err) - } - defer resp.Body.Close() - - tenantInfo := types.TenantInfo{} - if err := json.NewDecoder(resp.Body).Decode(&tenantInfo); err != nil { - return errors.Newf("failed to decode response: %w", err) - } - - m.certSubject = tenantInfo.CertSubject - return nil -} diff --git a/components/ias-adapter/internal/api/middlewares/jwt.go b/components/ias-adapter/internal/api/middlewares/id_token.go similarity index 88% rename from components/ias-adapter/internal/api/middlewares/jwt.go rename to components/ias-adapter/internal/api/middlewares/id_token.go index cfff0867cf..9df64b6e04 100644 --- a/components/ias-adapter/internal/api/middlewares/jwt.go +++ b/components/ias-adapter/internal/api/middlewares/id_token.go @@ -5,9 +5,8 @@ import ( "net/http" "strings" - "github.com/golang-jwt/jwt/v5" - "github.com/gin-gonic/gin" + "github.com/golang-jwt/jwt/v5" "github.com/kyma-incubator/compass/components/ias-adapter/internal/api/internal" "github.com/kyma-incubator/compass/components/ias-adapter/internal/errors" "github.com/kyma-incubator/compass/components/ias-adapter/internal/jwk" @@ -19,17 +18,17 @@ const ( keyIDHeader = "kid" ) -type JWTMiddleware struct { +type IDTokenMiddleware struct { cache jwk.Cache } -func NewJWTMiddleware(cache jwk.Cache) JWTMiddleware { - return JWTMiddleware{ +func NewIDTokenMiddleware(cache jwk.Cache) IDTokenMiddleware { + return IDTokenMiddleware{ cache: cache, } } -func (m JWTMiddleware) JWT(ctx *gin.Context) { +func (m IDTokenMiddleware) VerifyIDToken(ctx *gin.Context) { log := logger.FromContext(ctx) bearerToken, err := getBearerToken(ctx.Request) @@ -58,11 +57,11 @@ func getBearerToken(r *http.Request) (string, error) { } type jwtClaims struct { - Tenants string `json:"tenant"` + Tenant string `json:"tenant"` jwt.RegisteredClaims } -func (m JWTMiddleware) verifyJWT(ctx context.Context, jwtToken string) (jwtClaims, error) { +func (m IDTokenMiddleware) verifyJWT(ctx context.Context, jwtToken string) (jwtClaims, error) { claims := jwtClaims{} token, err := jwt.ParseWithClaims(jwtToken, &claims, func(token *jwt.Token) (any, error) { keyID, ok := token.Header[keyIDHeader] diff --git a/components/ias-adapter/internal/api/server.go b/components/ias-adapter/internal/api/server.go index 91ebff63c5..a16e074322 100644 --- a/components/ias-adapter/internal/api/server.go +++ b/components/ias-adapter/internal/api/server.go @@ -41,14 +41,8 @@ func NewServer(ctx context.Context, cfg config.Config, services Services) (*http if err != nil { return nil, errors.Newf("failed to create jwk cache: %w", err) } - jwtMiddleware := middlewares.NewJWTMiddleware(jwkCache) - tenantMappingRouter.Use(jwtMiddleware.JWT) - authMiddleware, err := middlewares.NewAuthMiddleware(ctx, cfg.TenantInfo) - if err != nil { - return nil, errors.Newf("failed to create auth middleware: %w", err) - } - routerGroup.Use(authMiddleware.Auth) - tenantMappingRouter.Use(authMiddleware.Auth) + idTokenMiddleware := middlewares.NewIDTokenMiddleware(jwkCache) + tenantMappingRouter.Use(idTokenMiddleware.VerifyIDToken) tenantMappingsHandler := handlers.TenantMappingsHandler{ Service: services.TenantMappingsService, AsyncProcessor: services.AsyncProcessor,