diff --git a/components/operator/api/formance.com/v1beta1/gateway_types.go b/components/operator/api/formance.com/v1beta1/gateway_types.go index ad8823b507..4f335658fd 100644 --- a/components/operator/api/formance.com/v1beta1/gateway_types.go +++ b/components/operator/api/formance.com/v1beta1/gateway_types.go @@ -60,9 +60,6 @@ type GatewayStatus struct { // Detected http apis. See [GatewayHTTPAPI](#gatewayhttpapi) //+optional SyncHTTPAPIs []string `json:"syncHTTPAPIs"` - // +kubebuilder:default:=false - // Indicates if a [Auth](#auth) module has been detected. - AuthEnabled bool `json:"authEnabled"` } //+kubebuilder:object:root=true @@ -70,7 +67,6 @@ type GatewayStatus struct { //+kubebuilder:resource:scope=Cluster //+kubebuilder:printcolumn:name="Stack",type=string,JSONPath=".spec.stack",description="Stack" //+kubebuilder:printcolumn:name="HTTP APIs",type=string,JSONPath=".status.syncHTTPAPIs",description="Synchronized http apis" -//+kubebuilder:printcolumn:name="Auth enabled",type=string,JSONPath=".status.authEnabled",description="Is authentication enabled" //+kubebuilder:printcolumn:name="Ready",type=string,JSONPath=".status.ready",description="Is ready" //+kubebuilder:printcolumn:name="Info",type=string,JSONPath=".status.info",description="Info" //+kubebuilder:metadata:labels=formance.com/kind=module diff --git a/components/operator/config/crd/bases/formance.com_gateways.yaml b/components/operator/config/crd/bases/formance.com_gateways.yaml index 53564169c1..e44cccb0ec 100644 --- a/components/operator/config/crd/bases/formance.com_gateways.yaml +++ b/components/operator/config/crd/bases/formance.com_gateways.yaml @@ -25,10 +25,6 @@ spec: jsonPath: .status.syncHTTPAPIs name: HTTP APIs type: string - - description: Is authentication enabled - jsonPath: .status.authEnabled - name: Auth enabled - type: string - description: Is ready jsonPath: .status.ready name: Ready @@ -119,10 +115,6 @@ spec: type: object status: properties: - authEnabled: - default: false - description: Indicates if a [Auth](#auth) module has been detected. - type: boolean conditions: items: description: "Condition contains details for one aspect of the current @@ -202,8 +194,6 @@ spec: items: type: string type: array - required: - - authEnabled type: object type: object served: true diff --git a/components/operator/docs/09-Configuration reference/02-Custom Resource Definitions.md b/components/operator/docs/09-Configuration reference/02-Custom Resource Definitions.md index 4589256071..77e3507616 100644 --- a/components/operator/docs/09-Configuration reference/02-Custom Resource Definitions.md +++ b/components/operator/docs/09-Configuration reference/02-Custom Resource Definitions.md @@ -731,7 +731,6 @@ Gateway is the Schema for the gateways API | `ready` _boolean_ | Ready indicates if the resource is seen as completely reconciled | | | | `info` _string_ | Info can contain any additional like reconciliation errors | | | | `syncHTTPAPIs` _string array_ | Detected http apis. See [GatewayHTTPAPI](#gatewayhttpapi) | | | -| `authEnabled` _boolean_ | Indicates if a [Auth](#auth) module has been detected. | false | | #### Ledger diff --git a/components/operator/helm/crds/templates/crds/apiextensions.k8s.io_v1_customresourcedefinition_gateways.formance.com.yaml b/components/operator/helm/crds/templates/crds/apiextensions.k8s.io_v1_customresourcedefinition_gateways.formance.com.yaml index 779fc73826..6211aa3243 100644 --- a/components/operator/helm/crds/templates/crds/apiextensions.k8s.io_v1_customresourcedefinition_gateways.formance.com.yaml +++ b/components/operator/helm/crds/templates/crds/apiextensions.k8s.io_v1_customresourcedefinition_gateways.formance.com.yaml @@ -25,10 +25,6 @@ spec: jsonPath: .status.syncHTTPAPIs name: HTTP APIs type: string - - description: Is authentication enabled - jsonPath: .status.authEnabled - name: Auth enabled - type: string - description: Is ready jsonPath: .status.ready name: Ready @@ -119,10 +115,6 @@ spec: type: object status: properties: - authEnabled: - default: false - description: Indicates if a [Auth](#auth) module has been detected. - type: boolean conditions: items: description: "Condition contains details for one aspect of the current @@ -202,8 +194,6 @@ spec: items: type: string type: array - required: - - authEnabled type: object type: object served: true diff --git a/components/operator/internal/resources/gateways/Caddyfile.gotpl b/components/operator/internal/resources/gateways/Caddyfile.gotpl index 0aafdef33a..9316309bd5 100644 --- a/components/operator/internal/resources/gateways/Caddyfile.gotpl +++ b/components/operator/internal/resources/gateways/Caddyfile.gotpl @@ -7,20 +7,6 @@ } } {{- $values := . }} -{{- if .Auth }} -(auth) { - auth { - issuer {{ .Auth.Issuer }} - - read_key_set_max_retries 10 - - {{- if .Auth.EnableScopes }} - check_scopes yes - service {args[0]} - {{- end }} - } -} -{{- end }} {{- if .EnableAudit }} (audit) { audit { @@ -58,9 +44,6 @@ # those directives are evaluated matters. So the jwtauth directive must be # ordered. # c.f. https://caddyserver.com/docs/caddyfile/directives#directive-order - {{- if .Auth }} - order auth before basicauth - {{- end }} order versions after metrics {{- if .EnableAudit }} order audit after encode @@ -92,9 +75,6 @@ {{- end }} uri strip_prefix /api/{{ $service.Name }} import cors - {{- if and (not $rule.Secured) $values.Auth }} - import auth {{ $service.Name }} - {{- end }} reverse_proxy {{ $service.Name }}:8080 { header_up Host {upstream_hostport} } diff --git a/components/operator/internal/resources/gateways/caddyfile.go b/components/operator/internal/resources/gateways/caddyfile.go index f3eec1d4ee..6ccc4bc9ab 100644 --- a/components/operator/internal/resources/gateways/caddyfile.go +++ b/components/operator/internal/resources/gateways/caddyfile.go @@ -1,8 +1,6 @@ package gateways import ( - "fmt" - "github.com/formancehq/operator/api/formance.com/v1beta1" "github.com/formancehq/operator/internal/core" "github.com/formancehq/operator/internal/resources/caddy" @@ -10,7 +8,7 @@ import ( ) func CreateCaddyfile(ctx core.Context, stack *v1beta1.Stack, - gateway *v1beta1.Gateway, httpAPIs []*v1beta1.GatewayHTTPAPI, auth *v1beta1.Auth, broker *v1beta1.Broker) (string, error) { + gateway *v1beta1.Gateway, httpAPIs []*v1beta1.GatewayHTTPAPI, broker *v1beta1.Broker) (string, error) { data := map[string]any{ "Services": collectionutils.Map(httpAPIs, func(from *v1beta1.GatewayHTTPAPI) v1beta1.GatewayHTTPAPISpec { @@ -23,12 +21,6 @@ func CreateCaddyfile(ctx core.Context, stack *v1beta1.Stack, "Version": gateway.Spec.Version, }, } - if auth != nil { - data["Auth"] = map[string]any{ - "Issuer": fmt.Sprintf("%s/api/auth", URL(gateway)), - "EnableScopes": auth.Spec.EnableScopes, - } - } // TODO(gfyrag): Check if search is enabled if stack.Spec.EnableAudit && broker != nil { diff --git a/components/operator/internal/resources/gateways/configuration.go b/components/operator/internal/resources/gateways/configuration.go index d5bc6741aa..1173df6ab5 100644 --- a/components/operator/internal/resources/gateways/configuration.go +++ b/components/operator/internal/resources/gateways/configuration.go @@ -8,9 +8,9 @@ import ( ) func createConfigMap(ctx core.Context, stack *v1beta1.Stack, - gateway *v1beta1.Gateway, httpAPIs []*v1beta1.GatewayHTTPAPI, auth *v1beta1.Auth, broker *v1beta1.Broker) (*v1.ConfigMap, error) { + gateway *v1beta1.Gateway, httpAPIs []*v1beta1.GatewayHTTPAPI, broker *v1beta1.Broker) (*v1.ConfigMap, error) { - caddyfile, err := CreateCaddyfile(ctx, stack, gateway, httpAPIs, auth, broker) + caddyfile, err := CreateCaddyfile(ctx, stack, gateway, httpAPIs, broker) if err != nil { return nil, err } diff --git a/components/operator/internal/resources/gateways/init.go b/components/operator/internal/resources/gateways/init.go index ca18c7aabf..1294463e60 100644 --- a/components/operator/internal/resources/gateways/init.go +++ b/components/operator/internal/resources/gateways/init.go @@ -48,15 +48,6 @@ func Reconcile(ctx Context, stack *v1beta1.Stack, gateway *v1beta1.Gateway, vers return httpAPIs[i].Spec.Name < httpAPIs[j].Spec.Name }) - auth := &v1beta1.Auth{} - ok, err := GetIfExists(ctx, stack.Name, auth) - if err != nil { - return err - } - if !ok { - auth = nil - } - var broker *v1beta1.Broker if t, err := brokertopics.Find(ctx, stack, "gateway"); err != nil { return err @@ -69,7 +60,7 @@ func Reconcile(ctx Context, stack *v1beta1.Stack, gateway *v1beta1.Gateway, vers } } - configMap, err := createConfigMap(ctx, stack, gateway, httpAPIs, auth, broker) + configMap, err := createConfigMap(ctx, stack, gateway, httpAPIs, broker) if err != nil { return err } @@ -89,7 +80,6 @@ func Reconcile(ctx Context, stack *v1beta1.Stack, gateway *v1beta1.Gateway, vers gateway.Status.SyncHTTPAPIs = Map(httpAPIs, func(from *v1beta1.GatewayHTTPAPI) string { return from.Spec.Name }) - gateway.Status.AuthEnabled = auth != nil return nil } diff --git a/components/operator/internal/tests/gateway_controller_test.go b/components/operator/internal/tests/gateway_controller_test.go index 574b56e805..80da85c60e 100644 --- a/components/operator/internal/tests/gateway_controller_test.go +++ b/components/operator/internal/tests/gateway_controller_test.go @@ -182,40 +182,6 @@ var _ = Describe("GatewayController", func() { MatchGoldenFile("gateway-controller", "configmap-with-ledger-and-another-service.yaml")) }) }) - Context("Then creating a Auth object", func() { - var ( - databaseSettings *v1beta1.Settings - auth *v1beta1.Auth - ) - BeforeEach(func() { - auth = &v1beta1.Auth{ - ObjectMeta: RandObjectMeta(), - Spec: v1beta1.AuthSpec{ - StackDependency: v1beta1.StackDependency{ - Stack: stack.Name, - }, - }, - } - databaseSettings = settings.New(uuid.NewString(), "postgres.*.uri", "postgresql://localhost", stack.Name) - - Expect(Create(databaseSettings)).To(Succeed()) - Expect(Create(auth)).To(Succeed()) - }) - AfterEach(func() { - Expect(Delete(auth)).To(Succeed()) - Expect(Delete(databaseSettings)).To(Succeed()) - }) - It("Should redeploy the gateway with auth configuration", func() { - Eventually(func(g Gomega) []string { - g.Expect(LoadResource("", gateway.Name, gateway)) - return gateway.Status.SyncHTTPAPIs - }).Should(ContainElements("ledger", "auth")) - cm := &corev1.ConfigMap{} - Expect(LoadResource(stack.Name, "gateway", cm)).To(Succeed()) - Expect(cm.Data["Caddyfile"]).To( - MatchGoldenFile("gateway-controller", "configmap-with-ledger-and-auth.yaml")) - }) - }) Context("With audit enabled", func() { var ( brokerNatsDSNSettings *v1beta1.Settings diff --git a/components/operator/internal/tests/testdata/resources/gateway-controller/configmap-with-ledger-and-auth.yaml b/components/operator/internal/tests/testdata/resources/gateway-controller/configmap-with-ledger-and-auth.yaml deleted file mode 100644 index c6ecbd1f66..0000000000 --- a/components/operator/internal/tests/testdata/resources/gateway-controller/configmap-with-ledger-and-auth.yaml +++ /dev/null @@ -1,71 +0,0 @@ -(cors) { - header { - Access-Control-Allow-Methods "GET,OPTIONS,PUT,POST,DELETE,HEAD,PATCH" - Access-Control-Allow-Headers content-type - Access-Control-Max-Age 100 - Access-Control-Allow-Origin * - } -} -(auth) { - auth { - issuer https://example.net/api/auth - - read_key_set_max_retries 10 - } -} - -{ - - servers { - metrics - } - admin :3080 - - # Many directives manipulate the HTTP handler chain and the order in which - # those directives are evaluated matters. So the jwtauth directive must be - # ordered. - # c.f. https://caddyserver.com/docs/caddyfile/directives#directive-order - order auth before basicauth - order versions after metrics -} - -:8080 { - log { - output stdout - } - handle /api/auth* { - uri strip_prefix /api/auth - import cors - reverse_proxy auth:8080 { - header_up Host {upstream_hostport} - } - } - handle /api/ledger* { - uri strip_prefix /api/ledger - import cors - import auth ledger - reverse_proxy ledger:8080 { - header_up Host {upstream_hostport} - } - } - - handle /versions { - versions { - region "us-west-1" - env "staging" - endpoints { - auth { - http://auth:8080/_info http://auth:8080/_healthcheck - } - ledger { - http://ledger:8080/_info http://ledger:8080/ - } - } - } - } - - # Respond 404 if service does not exists - handle /api/* { - respond "Not Found" 404 - } -} \ No newline at end of file diff --git a/ee/gateway/go.mod b/ee/gateway/go.mod index 212de42fe1..3732462d17 100644 --- a/ee/gateway/go.mod +++ b/ee/gateway/go.mod @@ -11,15 +11,14 @@ require ( github.com/ThreeDotsLabs/watermill-nats/v2 v2.0.2 github.com/caddyserver/caddy/v2 v2.7.5 github.com/golang-jwt/jwt/v5 v5.2.1 - github.com/hashicorp/go-retryablehttp v0.7.7 github.com/nats-io/nats.go v1.37.0 github.com/xdg-go/scram v1.1.2 - github.com/zitadel/oidc/v2 v2.12.0 go.uber.org/zap v1.27.0 golang.org/x/sync v0.8.0 ) require ( + cloud.google.com/go/compute/metadata v0.3.0 // indirect cloud.google.com/go/kms v1.15.7 // indirect github.com/ThreeDotsLabs/watermill-http/v2 v2.3.0 // indirect github.com/ajg/form v1.5.1 // indirect @@ -51,11 +50,7 @@ require ( github.com/google/go-tpm v0.9.0 // indirect github.com/google/go-tspi v0.3.0 // indirect github.com/googleapis/gax-go/v2 v2.12.3 // indirect - github.com/gorilla/mux v1.8.0 // indirect - github.com/gorilla/schema v1.2.0 // indirect - github.com/gorilla/securecookie v1.1.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/jcmturner/aescts/v2 v2.0.0 // indirect @@ -67,14 +62,11 @@ require ( github.com/lib/pq v1.10.9 // indirect github.com/lithammer/shortuuid/v3 v3.0.7 // indirect github.com/mastercactapus/proxyprotocol v0.0.4 // indirect - github.com/muhlemmer/gu v0.3.1 // indirect - github.com/muhlemmer/httpforwarded v0.1.0 // indirect github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/rs/cors v1.10.1 // indirect github.com/smallstep/go-attestation v0.4.4-0.20230627102604-cf579e53cbd2 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect github.com/uptrace/bun v1.2.1 // indirect @@ -95,7 +87,6 @@ require ( go.uber.org/dig v1.18.0 // indirect go.uber.org/fx v1.22.2 // indirect go.uber.org/mock v0.4.0 // indirect - golang.org/x/oauth2 v0.20.0 // indirect google.golang.org/api v0.171.0 // indirect google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect diff --git a/ee/gateway/go.sum b/ee/gateway/go.sum index 657f854f35..811e115033 100644 --- a/ee/gateway/go.sum +++ b/ee/gateway/go.sum @@ -1,5 +1,4 @@ cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= -cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= @@ -212,8 +211,6 @@ github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -253,11 +250,6 @@ github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/ github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.4.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc= -github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= -github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/groob/finalizer v0.0.0-20170707115354-4c2ed49aabda/go.mod h1:MyndkAZd5rUMdNogn35MWXBX1UiBigrU8eTj8DoAC2c= @@ -266,14 +258,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= -github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= -github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -353,8 +339,6 @@ github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh6 github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= -github.com/jeremija/gosubmit v0.2.7 h1:At0OhGCFGPXyjPYAsCchoBUhE099pcBXmsb4iZqROIc= -github.com/jeremija/gosubmit v0.2.7/go.mod h1:Ui+HS073lCFREXBbdfrJzMB57OI/bdxTiLtrDHHhFPI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= @@ -432,10 +416,6 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= -github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM= -github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM= -github.com/muhlemmer/httpforwarded v0.1.0 h1:x4DLrzXdliq8mprgUMR0olDvHGkou5BJsK/vWUetyzY= -github.com/muhlemmer/httpforwarded v0.1.0/go.mod h1:yo9czKedo2pdZhoXe+yDkGVbU0TJ0q9oQ90BVoDEtw0= github.com/nats-io/jwt/v2 v2.5.8 h1:uvdSzwWiEGWGXf+0Q+70qv6AQdvcvxrv9hPM0RiPamE= github.com/nats-io/jwt/v2 v2.5.8/go.mod h1:ZdWS1nZa6WMZfFwwgpEaqBV8EPGVgOTDHN/wTbz0Y5A= github.com/nats-io/nats-server/v2 v2.10.18 h1:tRdZmBuWKVAFYtayqlBB2BuCHNGAQPvoQIXOKwU3WSM= @@ -491,8 +471,6 @@ github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqn github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= -github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= @@ -612,8 +590,6 @@ github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvv github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -github.com/zitadel/oidc/v2 v2.12.0 h1:4aMTAy99/4pqNwrawEyJqhRb3yY3PtcDxnoDSryhpn4= -github.com/zitadel/oidc/v2 v2.12.0/go.mod h1:LrRav74IiThHGapQgCHZOUNtnqJG0tcZKHro/91rtLw= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.mozilla.org/pkcs7 v0.0.0-20210730143726-725912489c62/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= diff --git a/ee/gateway/pkg/plugins/auth.go b/ee/gateway/pkg/plugins/auth.go deleted file mode 100644 index 16f8e532fd..0000000000 --- a/ee/gateway/pkg/plugins/auth.go +++ /dev/null @@ -1,197 +0,0 @@ -package plugins - -import ( - "context" - "fmt" - "net/http" - "os" - "strconv" - "strings" - - "github.com/formancehq/stack/libs/go-libs/collectionutils" - - "github.com/caddyserver/caddy/v2" - "github.com/caddyserver/caddy/v2/caddyconfig" - "github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile" - "github.com/caddyserver/caddy/v2/modules/caddyhttp" - "github.com/caddyserver/caddy/v2/modules/caddyhttp/caddyauth" - "github.com/hashicorp/go-retryablehttp" - "github.com/zitadel/oidc/v2/pkg/client/rp" - "github.com/zitadel/oidc/v2/pkg/oidc" - "github.com/zitadel/oidc/v2/pkg/op" - "go.uber.org/zap" -) - -func init() { - caddy.RegisterModule(JWTAuth{}) - httpcaddyfile.RegisterHandlerDirective("auth", parseAuthCaddyfile) -} - -type JWTAuth struct { - logger *zap.Logger `json:"-"` - httpClient *http.Client `json:"-"` - accessTokenVerifier op.AccessTokenVerifier `json:"-"` - - Issuer string `json:"issuer,omitempty"` - ReadKeySetMaxRetries int `json:"read_key_set_max_retries,omitempty"` - CheckScopes bool `json:"check_scopes,omitempty"` - Service string `json:"service"` -} - -func (JWTAuth) CaddyModule() caddy.ModuleInfo { - return caddy.ModuleInfo{ - ID: "http.authentication.providers.jwt", - New: func() caddy.Module { return new(JWTAuth) }, - } -} - -// Provision implements caddy.Provisioner interface. -func (ja *JWTAuth) Provision(ctx caddy.Context) error { - ja.logger = ctx.Logger(ja) - ja.httpClient = newOtlpHttpClient(ja.ReadKeySetMaxRetries) - - // We can't provision the access token verifier here because the auth - // components is not started yet. He will not be started until the - // gateway is started, which will be the case after this provision call. - ja.accessTokenVerifier = nil - return nil -} - -func parseAuthCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) { - var ja JWTAuth - - for h.Next() { - for h.NextBlock(0) { - opt := h.Val() - switch opt { - case "issuer": - if !h.AllArgs(&ja.Issuer) { - return nil, h.Errf("invalid issuer") - } - case "read_key_set_max_retries": - var readKeySetMaxRetries string - if !h.AllArgs(&readKeySetMaxRetries) { - return nil, h.Errf("invalid read_key_set_max_retries") - } - - var err error - ja.ReadKeySetMaxRetries, err = strconv.Atoi(readKeySetMaxRetries) - if err != nil { - return nil, h.Errf("invalid read_key_set_max_retries") - } - case "check_scopes": - var checkScopes string - if !h.AllArgs(&checkScopes) { - return nil, h.Errf("invalid check_scopes") - } - checkScopes = strings.ToLower(checkScopes) - ja.CheckScopes = checkScopes == "true" || checkScopes == "1" || checkScopes == "yes" - case "service": - var service string - if !h.AllArgs(&service) { - return nil, h.Errf("invalid service") - } - ja.Service = service - default: - return nil, h.Errf("unrecognized option: %s", opt) - } - } - } - - return caddyauth.Authentication{ - ProvidersRaw: caddy.ModuleMap{ - "jwt": caddyconfig.JSON(ja, nil), - }, - }, nil -} - -// Authenticate validates the JWT in the request and returns the user, if valid. -func (ja *JWTAuth) Authenticate(w http.ResponseWriter, r *http.Request) (caddyauth.User, bool, error) { - authHeader := r.Header.Get("authorization") - if authHeader == "" { - ja.logger.Error("no authorization header") - return caddyauth.User{}, false, fmt.Errorf("no authorization header") - } - - if !strings.HasPrefix(authHeader, strings.ToLower(oidc.PrefixBearer)) && - !strings.HasPrefix(authHeader, oidc.PrefixBearer) { - ja.logger.Error("malformed authorization header") - return caddyauth.User{}, false, fmt.Errorf("malformed authorization header") - } - - token := strings.TrimPrefix(authHeader, strings.ToLower(oidc.PrefixBearer)) - token = strings.TrimPrefix(token, oidc.PrefixBearer) - - accessTokenVerifier, err := ja.getAccessTokenVerifier(r.Context()) - if err != nil { - ja.logger.Error("unable to create access token verifier", zap.Error(err)) - return caddyauth.User{}, false, fmt.Errorf("unable to create access token verifier: %w", err) - } - - claims, err := op.VerifyAccessToken[*oidc.AccessTokenClaims](r.Context(), token, accessTokenVerifier) - if err != nil { - ja.logger.Error("unable to verify access token", zap.Error(err)) - return caddyauth.User{}, false, fmt.Errorf("unable to verify access token: %w", err) - } - - if ja.CheckScopes { - scope := claims.Scopes - - allowed := true - switch r.Method { - case http.MethodOptions, http.MethodGet, http.MethodHead, http.MethodTrace: - allowed = allowed && (collectionutils.Contains(scope, ja.Service+":read") || collectionutils.Contains(scope, ja.Service+":write")) - default: - allowed = allowed && collectionutils.Contains(scope, ja.Service+":write") - } - - if !allowed { - ja.logger.Info("not enough scopes") - return caddyauth.User{}, false, fmt.Errorf("missing access, found scopes: '%s' need %s:read|write", strings.Join(scope, ", "), ja.Service) - } - } - - return caddyauth.User{}, true, nil -} - -//------------------------------------------------------------------------------ -// Helpers -//------------------------------------------------------------------------------ - -func (ja *JWTAuth) getAccessTokenVerifier(ctx context.Context) (op.AccessTokenVerifier, error) { - if ja.accessTokenVerifier == nil { - //discoveryConfiguration, err := client.Discover(ja.Issuer, ja.httpClient) - //if err != nil { - // return nil, err - //} - - // todo: ugly quick fix - authServicePort := "8080" - if fromEnv := os.Getenv("AUTH_SERVICE_PORT"); fromEnv != "" { - authServicePort = fromEnv - } - keySet := rp.NewRemoteKeySet(ja.httpClient, fmt.Sprintf("http://auth:%s/keys", authServicePort)) - - ja.accessTokenVerifier = op.NewAccessTokenVerifier( - os.Getenv("STACK_PUBLIC_URL")+"/api/auth", - keySet, - ) - } - - return ja.accessTokenVerifier, nil -} - -func newOtlpHttpClient(maxRetries int) *http.Client { - retryClient := retryablehttp.NewClient() - retryClient.RetryMax = maxRetries - return retryClient.StandardClient() -} - -//------------------------------------------------------------------------------ - -// Interface Guards -var ( - _ caddy.Provisioner = (*JWTAuth)(nil) - _ caddy.Module = (*JWTAuth)(nil) - _ caddyauth.Authenticator = (*JWTAuth)(nil) -)