diff --git a/cmd/jwks-server/Makefile b/cmd/auth-server/Makefile similarity index 82% rename from cmd/jwks-server/Makefile rename to cmd/auth-server/Makefile index 5f4381f..b071e89 100644 --- a/cmd/jwks-server/Makefile +++ b/cmd/auth-server/Makefile @@ -1,5 +1,5 @@ # Define variables -KO_DOCKER_REPO := ghcr.io/carverauto/jwks-server +KO_DOCKER_REPO := ghcr.io/carverauto/auth-server VERSION := v0.0.01 # Default target @@ -7,7 +7,7 @@ all: build # Build the binary locally build: - go build -o jwks-server . + go build -o auth-server . # Build and push the container image using ko ko-build: diff --git a/cmd/jwks-server/jwt/jwks.json b/cmd/auth-server/jwt/jwks.json similarity index 100% rename from cmd/jwks-server/jwt/jwks.json rename to cmd/auth-server/jwt/jwks.json diff --git a/cmd/jwks-server/jwt/jwtKeys.go b/cmd/auth-server/jwt/jwtKeys.go similarity index 100% rename from cmd/jwks-server/jwt/jwtKeys.go rename to cmd/auth-server/jwt/jwtKeys.go diff --git a/cmd/auth-server/main.go b/cmd/auth-server/main.go new file mode 100644 index 0000000..a94e208 --- /dev/null +++ b/cmd/auth-server/main.go @@ -0,0 +1,35 @@ +package main + +import ( + "encoding/json" + "os" + + "gofr.dev/pkg/gofr" + "gofr.dev/pkg/gofr/http/response" +) + +const ( + rulesPath = "/app/config/rules.json" +) + +func main() { + app := gofr.New() + + app.GET("/rules.json", RulesHandler) + + app.Run() +} + +func RulesHandler(c *gofr.Context) (interface{}, error) { + data, err := os.ReadFile(rulesPath) + if err != nil { + return nil, err + } + + var jsonObj interface{} + if err := json.Unmarshal(data, &jsonObj); err != nil { + return nil, err + } + + return response.Raw{Data: jsonObj}, nil +} diff --git a/cmd/jwks-server/main.go b/cmd/jwks-server/main.go deleted file mode 100644 index aae9589..0000000 --- a/cmd/jwks-server/main.go +++ /dev/null @@ -1,46 +0,0 @@ -// File: main.go - -package main - -import ( - "gofr.dev/pkg/gofr" -) - -func main() { - // Initialize gofr application - app := gofr.New() - - // Register the JWKS route - app.GET("/jwks.json", JWKSHandler) - - // Run the application - app.Run() -} - -type JWK struct { - E string `json:"e"` - Kid string `json:"kid"` - Kty string `json:"kty"` - N string `json:"n"` -} - -type JWKS struct { - Keys []JWK `json:"keys"` -} - -func JWKSHandler(c *gofr.Context) (interface{}, error) { - // Create the JWKS data - jwks := JWKS{ - Keys: []JWK{ - { - E: "AQAB", - Kid: "eventrunner-jwt", - Kty: "RSA", - N: "viVXLTzUz5zrrTRFe59lc5JfjonbmnBxgGVD2RHG-FQXdKp-5xnuH5C9ZLujcew8jYoeFw6o7ab7PMONzru5UcjxadKXaC1uTId_chCDVVVSD80IlYtzgchhMBTpqZJY5hd6GybODwJj0ulcfpXmw43dF5CRC9uLbLuSvkVsELgcioUJnaMTZjisY9R5ApeUOLSAZGOacdlVBBZfQb8pVjBqJQQmcyzooLZdXq-hNvutnI15sPQLcoBXXat_n8lfrI2Jr_mlG_rcvAdhZXUGeu1NeWdJuaHFoHcbV-PeSnr0mAGZxFEdM6nFywqmjtiU3EXhDmqfrB7hMiWdbAueRQ", - }, - }, - } - - // Return the JWKS data; gofr will marshal it to JSON - return jwks, nil -} diff --git a/k8s/auth-server/base/auth-server-configmaps.yaml b/k8s/auth-server/base/auth-server-configmaps.yaml new file mode 100644 index 0000000..f467f1a --- /dev/null +++ b/k8s/auth-server/base/auth-server-configmaps.yaml @@ -0,0 +1,105 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: oathkeeper-rules-data + namespace: eventrunner +data: + rules.json: | + [ + { + "id": "api-health-check", + "upstream": { + "preserve_host": true, + "url": "http://eventrunner-api.eventrunner.svc.cluster.local:8200" + }, + "match": { + "url": "/api/v1/health", + "methods": ["GET"] + }, + "authenticators": [ + { + "handler": "anonymous", + "config": { + "subject": "guest" + } + } + ], + "authorizer": { + "handler": "allow" + }, + "mutators": [ + { + "handler": "noop" + } + ] + }, + { + "id": "auth-check", + "upstream": { + "preserve_host": true, + "url": "http://eventrunner-api.eventrunner.svc.cluster.local:8200" + }, + "match": { + "url": "/judge", + "methods": ["GET"] + }, + "authenticators": [ + { + "handler": "anonymous", + "config": { + "subject": "anonymous" + } + } + ], + "authorizer": { + "handler": "allow" + }, + "mutators": [ + { + "handler": "header", + "config": { + "headers": { + "X-User": "anonymous", + "X-Tenant-ID": "default", + "X-Request-Id": "{{ print .RequestID }}" + } + } + } + ] + }, + { + "id": "protected-endpoints", + "upstream": { + "preserve_host": true, + "url": "http://eventrunner-api.eventrunner.svc.cluster.local:8200" + }, + "match": { + "url": "/api/v1/<.*>", + "methods": ["GET", "POST", "PUT", "DELETE", "PATCH"] + }, + "authenticators": [ + { + "handler": "jwt", + "config": { + "jwks_urls": ["https://affectionate-brattain-fl0yahcycw.projects.oryapis.com/.well-known/jwks.json"], + "trusted_issuers": ["https://affectionate-brattain-fl0yahcycw.projects.oryapis.com"] + } + } + ], + "authorizer": { + "handler": "allow" + }, + "mutators": [ + { + "handler": "header", + "config": { + "headers": { + "X-User": "{{ print .Subject }}", + "X-Tenant-ID": "{{ print .Extra.tenant_id }}", + "X-Request-Id": "{{ print .RequestID }}" + } + } + } + ] + } + ] \ No newline at end of file diff --git a/k8s/auth-server/base/auth-server.yaml b/k8s/auth-server/base/auth-server.yaml new file mode 100644 index 0000000..acaf501 --- /dev/null +++ b/k8s/auth-server/base/auth-server.yaml @@ -0,0 +1,34 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: auth-server + namespace: eventrunner +spec: + replicas: 1 + selector: + matchLabels: + app: auth-server + template: + metadata: + labels: + app: auth-server + spec: + containers: + - name: auth-server + image: ghcr.io/carverauto/auth-server:v0.0.06 + imagePullPolicy: Always + ports: + - containerPort: 8000 + volumeMounts: + - name: rules-volume + mountPath: /app/config/rules.json + subPath: rules.json + volumes: + - name: rules-volume + configMap: + name: oathkeeper-rules-data + items: + - key: rules.json + path: rules.json + imagePullSecrets: + - name: ghcr-io-cred \ No newline at end of file diff --git a/k8s/auth-server/base/kustomization.yaml b/k8s/auth-server/base/kustomization.yaml new file mode 100644 index 0000000..1e7363f --- /dev/null +++ b/k8s/auth-server/base/kustomization.yaml @@ -0,0 +1,4 @@ +resources: + - auth-server-configmaps.yaml + - auth-server.yaml + - service.yaml \ No newline at end of file diff --git a/k8s/auth-server/base/service.yaml b/k8s/auth-server/base/service.yaml new file mode 100644 index 0000000..232c423 --- /dev/null +++ b/k8s/auth-server/base/service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: auth-server + namespace: eventrunner +spec: + selector: + app: auth-server + ports: + - protocol: TCP + port: 80 + targetPort: 8000 + type: ClusterIP \ No newline at end of file diff --git a/k8s/er-api/base/db_secret.yaml b/k8s/er-api/base/db_secret.yaml deleted file mode 100644 index ec7a00d..0000000 --- a/k8s/er-api/base/db_secret.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: db-credentials - namespace: eventrunner -type: Opaque -data: - DB_PASSWORD: base64encodedpassword= \ No newline at end of file diff --git a/k8s/er/base/kustomization.yaml b/k8s/er/base/kustomization.yaml deleted file mode 100644 index ba40e8c..0000000 --- a/k8s/er/base/kustomization.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resources: - - eventrunner.yaml - - configmap.yaml diff --git a/k8s/er-api/base/configmap.yaml b/k8s/eventrunner-api/base/configmap.yaml similarity index 84% rename from k8s/er-api/base/configmap.yaml rename to k8s/eventrunner-api/base/configmap.yaml index 26c135d..8c52d36 100644 --- a/k8s/er-api/base/configmap.yaml +++ b/k8s/eventrunner-api/base/configmap.yaml @@ -15,7 +15,7 @@ data: DB_NAME=eventrunner DB_PORT=2001 DB_DIALECT=mongo - DB_URL=mongodb://mongodb.svc.cluster.local:27017 + DB_URL=mongodb://er-mongodb.svc.cluster.local:27017 .staging.env: | LOG_LEVEL=DEBUG APP_NAME=eventrunner @@ -27,4 +27,4 @@ data: DB_NAME=eventrunner DB_PORT=2001 DB_DIALECT=mongo - DB_URL=mongodb://mongodb.svc.cluster.local:27017 \ No newline at end of file + DB_URL=mongodb://er-mongodb.svc.cluster.local:27017 \ No newline at end of file diff --git a/k8s/er-api/base/eventrunner.yaml b/k8s/eventrunner-api/base/eventrunner.yaml similarity index 100% rename from k8s/er-api/base/eventrunner.yaml rename to k8s/eventrunner-api/base/eventrunner.yaml diff --git a/k8s/eventrunner-api/base/ingress.yaml b/k8s/eventrunner-api/base/ingress.yaml new file mode 100644 index 0000000..4afba29 --- /dev/null +++ b/k8s/eventrunner-api/base/ingress.yaml @@ -0,0 +1,29 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: eventrunner-api + namespace: eventrunner + annotations: + cert-manager.io/cluster-issuer: threadr-issuer + nginx.ingress.kubernetes.io/auth-url: "http://oathkeeper-proxy.default.svc.cluster.local:4455/judge" + nginx.ingress.kubernetes.io/auth-response-headers: "X-User,X-Tenant-ID,X-Request-Id" + nginx.ingress.kubernetes.io/auth-preserve-uri: "true" + nginx.ingress.kubernetes.io/auth-always-set-cookie: "true" + nginx.ingress.kubernetes.io/ssl-redirect: "true" +spec: + ingressClassName: nginx + tls: + - hosts: + - api.tunnel.threadr.ai + secretName: eventrunner-api-tls + rules: + - host: api.tunnel.threadr.ai + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: eventrunner-api + port: + number: 8200 \ No newline at end of file diff --git a/k8s/eventrunner-api/base/kustomization.yaml b/k8s/eventrunner-api/base/kustomization.yaml new file mode 100644 index 0000000..3b95b27 --- /dev/null +++ b/k8s/eventrunner-api/base/kustomization.yaml @@ -0,0 +1,7 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +namespace: eventrunner +resources: + - eventrunner.yaml + - configmap.yaml + - service.yaml + - ingress.yaml diff --git a/k8s/eventrunner-api/base/service.yaml b/k8s/eventrunner-api/base/service.yaml new file mode 100644 index 0000000..6a62451 --- /dev/null +++ b/k8s/eventrunner-api/base/service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: eventrunner-api + namespace: eventrunner +spec: + selector: + app: eventrunner-api + ports: + - protocol: TCP + port: 8200 + targetPort: 8200 + type: ClusterIP \ No newline at end of file diff --git a/k8s/er/base/configmap.yaml b/k8s/eventrunner/base/configmap.yaml similarity index 100% rename from k8s/er/base/configmap.yaml rename to k8s/eventrunner/base/configmap.yaml diff --git a/k8s/er/base/eventrunner.yaml b/k8s/eventrunner/base/eventrunner.yaml similarity index 100% rename from k8s/er/base/eventrunner.yaml rename to k8s/eventrunner/base/eventrunner.yaml diff --git a/k8s/er-api/base/kustomization.yaml b/k8s/eventrunner/base/kustomization.yaml similarity index 100% rename from k8s/er-api/base/kustomization.yaml rename to k8s/eventrunner/base/kustomization.yaml diff --git a/k8s/jwks-server/base/jwks-server.yaml b/k8s/jwks-server/base/jwks-server.yaml deleted file mode 100644 index dab4e66..0000000 --- a/k8s/jwks-server/base/jwks-server.yaml +++ /dev/null @@ -1,35 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: jwks-server - namespace: eventrunner -spec: - replicas: 1 - selector: - matchLabels: - app: jwks-server - template: - metadata: - labels: - app: jwks-server - spec: - serviceAccountName: eventrunner-account - imagePullSecrets: - - name: ghcr-io-cred - containers: - - name: jwks-server - image: ghcr.io/carverauto/jwks-server:v0.0.01 - imagePullPolicy: Always - volumeMounts: - - name: config - mountPath: /app/configs - volumes: - - name: config - configMap: - name: eventrunner-config - - name: nats-creds - secret: - secretName: nats-creds - items: - - key: nats.creds - path: nats.creds \ No newline at end of file diff --git a/k8s/jwks-server/base/kustomization.yaml b/k8s/jwks-server/base/kustomization.yaml deleted file mode 100644 index 5973557..0000000 --- a/k8s/jwks-server/base/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: - - jwks-server.yaml \ No newline at end of file diff --git a/k8s/ory/oathkeeper/access-rules-configmap.yaml b/k8s/ory/oathkeeper/access-rules-configmap.yaml deleted file mode 100644 index 27201ce..0000000 --- a/k8s/ory/oathkeeper/access-rules-configmap.yaml +++ /dev/null @@ -1,52 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: oathkeeper-access-rules -data: - access-rules.json: | - [ - { - "id": "health-readiness", - "match": { - "url": "http://127.0.0.1:4456/health/*", - "methods": [ - "GET" - ] - }, - "authenticators": [ - { - "handler": "anonymous" - } - ], - "authorizer": { - "handler": "allow" - }, - "mutators": [ - { - "handler": "noop" - } - ] - }, - { - "id": "default", - "match": { - "url": "http://127.0.0.1:4456/*", - "methods": [ - "GET" - ] - }, - "authenticators": [ - { - "handler": "anonymous" - } - ], - "authorizer": { - "handler": "allow" - }, - "mutators": [ - { - "handler": "noop" - } - ] - } - ] \ No newline at end of file diff --git a/k8s/ory/oathkeeper/access-rules.json b/k8s/ory/oathkeeper/access-rules.json deleted file mode 100644 index e1eeefb..0000000 --- a/k8s/ory/oathkeeper/access-rules.json +++ /dev/null @@ -1,46 +0,0 @@ -[ - { - "id": "health-readiness", - "match": { - "url": "http://127.0.0.1:4456/health/*", - "methods": [ - "GET" - ] - }, - "authenticators": [ - { - "handler": "anonymous" - } - ], - "authorizer": { - "handler": "allow" - }, - "mutators": [ - { - "handler": "noop" - } - ] - }, - { - "id": "default", - "match": { - "url": "http://127.0.0.1:4456/*", - "methods": [ - "GET" - ] - }, - "authenticators": [ - { - "handler": "anonymous" - } - ], - "authorizer": { - "handler": "allow" - }, - "mutators": [ - { - "handler": "noop" - } - ] - } -] \ No newline at end of file diff --git a/k8s/ory/oathkeeper/nginx-auth-config.yaml b/k8s/ory/oathkeeper/nginx-auth-config.yaml new file mode 100644 index 0000000..1c0bff9 --- /dev/null +++ b/k8s/ory/oathkeeper/nginx-auth-config.yaml @@ -0,0 +1,52 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: oathkeeper-config + namespace: default +data: + config.yaml: | + serve: + proxy: + port: 4455 + cors: + enabled: true + allowed_origins: + - "*" + allowed_methods: + - POST + - GET + - PUT + - PATCH + - DELETE + allowed_headers: + - Authorization + - Content-Type + exposed_headers: + - X-User + - X-Tenant-ID + allow_credentials: true + debug: true + api: + port: 4456 + + access_rules: + repositories: + - file:///etc/rules/access-rules.json + matching_strategy: "regexp" + + authenticators: + jwt: + enabled: true + config: + jwks_urls: + - https://affectionate-brattain-fl0yahcycw.projects.oryapis.com/.well-known/jwks.json + + authorizers: + allow: + enabled: true + + mutators: + header: + enabled: true + noop: + enabled: true \ No newline at end of file diff --git a/k8s/ory/oathkeeper/oathkeeper-values.yaml b/k8s/ory/oathkeeper/oathkeeper-values.yaml index bf2a6ca..230e641 100644 --- a/k8s/ory/oathkeeper/oathkeeper-values.yaml +++ b/k8s/ory/oathkeeper/oathkeeper-values.yaml @@ -5,6 +5,23 @@ oathkeeper: port: 4455 cors: enabled: true + allowed_origins: + - "*" + allowed_methods: + - POST + - GET + - PUT + - PATCH + - DELETE + allowed_headers: + - Authorization + - Content-Type + exposed_headers: + - X-User + - X-Tenant-ID + - X-Request-Id + allow_credentials: true + debug: true api: port: 4456 cors: @@ -12,8 +29,8 @@ oathkeeper: access_rules: repositories: - - inline://WwogIHsKICAgICJpZCI6ICJoZWFsdGgtcmVhZGluZXNzIiwKICAgICJtYXRjaCI6IHsKICAgICAgInVybCI6ICJodHRwOi8vMTI3LjAuMC4xOjQ0NTYvaGVhbHRoLyoiLAogICAgICAibWV0aG9kcyI6IFsKICAgICAgICAiR0VUIgogICAgICBdCiAgICB9LAogICAgImF1dGhlbnRpY2F0b3JzIjogWwogICAgICB7CiAgICAgICAgImhhbmRsZXIiOiAiYW5vbnltb3VzIgogICAgICB9CiAgICBdLAogICAgImF1dGhvcml6ZXIiOiB7CiAgICAgICJoYW5kbGVyIjogImFsbG93IgogICAgfSwKICAgICJtdXRhdG9ycyI6IFsKICAgICAgewogICAgICAgICJoYW5kbGVyIjogIm5vb3AiCiAgICAgIH0KICAgIF0KICB9LAogIHsKICAgICJpZCI6ICJkZWZhdWx0IiwKICAgICJtYXRjaCI6IHsKICAgICAgInVybCI6ICJodHRwOi8vMTI3LjAuMC4xOjQ0NTYvKiIsCiAgICAgICJtZXRob2RzIjogWwogICAgICAgICJHRVQiCiAgICAgIF0KICAgIH0sCiAgICAiYXV0aGVudGljYXRvcnMiOiBbCiAgICAgIHsKICAgICAgICAiaGFuZGxlciI6ICJhbm9ueW1vdXMiCiAgICAgIH0KICAgIF0sCiAgICAiYXV0aG9yaXplciI6IHsKICAgICAgImhhbmRsZXIiOiAiYWxsb3ciCiAgICB9LAogICAgIm11dGF0b3JzIjogWwogICAgICB7CiAgICAgICAgImhhbmRsZXIiOiAibm9vcCIKICAgICAgfQogICAgXQogIH0KXQ== - matching_strategy: glob # Changed to glob + - "http://auth-server.eventrunner.svc.cluster.local/rules.json" + matching_strategy: glob authenticators: anonymous: @@ -26,7 +43,7 @@ oathkeeper: enabled: true config: jwks_urls: - - file:///etc/jwks/jwks.json + - "https://affectionate-brattain-fl0yahcycw.projects.oryapis.com/.well-known/jwks.json" authorizers: allow: @@ -35,35 +52,21 @@ oathkeeper: mutators: noop: enabled: true - id_token: - enabled: true + header: config: - issuer_url: "https://affectionate-brattain-fl0yahcycw.projects.oryapis.com" - jwks_url: file:///etc/jwks/jwks.json - ttl: "15m" + headers: {} # This is important - we're enabling header mutator with empty default config + enabled: true + + log: + level: debug + format: json deployment: replicas: 1 pod: - volumes: - - name: jwks - secret: - secretName: oathkeeper-jwks - items: - - key: jwks.json - path: jwks.json - - name: custom-rules - configMap: - name: oathkeeper-access-rules containers: - name: oathkeeper image: oryd/oathkeeper:v0.40.7 - volumeMounts: - - name: jwks - mountPath: /etc/jwks/jwks.json - subPath: jwks.json - - name: custom-rules - mountPath: /etc/rules readinessProbe: httpGet: path: /health/ready @@ -79,6 +82,4 @@ oathkeeper: failureThreshold: 3 periodSeconds: 10 initialDelaySeconds: 5 - timeoutSeconds: 1 - - # Rest of your config... + timeoutSeconds: 1 \ No newline at end of file diff --git a/pkg/api/handlers/jwks.go b/pkg/api/handlers/jwks.go deleted file mode 100644 index 5ac8282..0000000 --- a/pkg/api/handlers/jwks.go +++ /dev/null @@ -1 +0,0 @@ -package handlers diff --git a/pkg/eventrunner/app_interface.go b/pkg/eventrunner/app_interface.go index 2c5587b..28b1d4e 100644 --- a/pkg/eventrunner/app_interface.go +++ b/pkg/eventrunner/app_interface.go @@ -1,6 +1,8 @@ package eventrunner import ( + "context" + "gofr.dev/pkg/gofr" "gofr.dev/pkg/gofr/container" "gofr.dev/pkg/gofr/logging" @@ -13,8 +15,8 @@ type AppWrapper struct { app *gofr.App } -func (a *AppWrapper) AddMongo(mongoClient container.MongoProvider) { - a.app.AddMongo(mongoClient) +func (a *AppWrapper) AddMongo(ctx context.Context, mongoClient container.MongoProvider) error { + return a.app.AddMongo(ctx, mongoClient) } func NewAppWrapper(app *gofr.App) *AppWrapper { @@ -37,12 +39,12 @@ func (a *AppWrapper) Metrics() metrics.Manager { return a.app.Metrics() } -func (a *AppWrapper) AddPubSub(pubsubClient container.PubSubProvider) { - a.app.AddPubSub(pubsubClient) +func (a *AppWrapper) AddPubSub(ctx context.Context, pubsubClient container.PubSubProvider) error { + return a.app.AddPubSub(ctx, pubsubClient) } -func (a *AppWrapper) AddCassandra(cassandraClient container.CassandraProvider) { - a.app.AddCassandra(cassandraClient) +func (a *AppWrapper) AddCassandra(ctx context.Context, cassandraClient container.CassandraProvider) error { + return a.app.AddCassandra(ctx, cassandraClient) } func (a *AppWrapper) Migrate(migrationsMap map[int64]migration.Migrate) {