diff --git a/Makefile b/Makefile index 5ed4be07..242d7231 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,12 @@ install: manifests kustomize uninstall: manifests kustomize $(KUSTOMIZE) build install | kubectl delete -f - +# Install CertManager to the Kubernetes cluster +.PHONY: cert-manager +cert-manager: + kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.4.0/cert-manager.yaml + kubectl -n cert-manager wait --timeout=300s --for=condition=Available deployments --all + # Deploy controller in the configured Kubernetes cluster in ~/.kube/config deploy: manifests kustomize cd deploy/base && $(KUSTOMIZE) edit set image authorino=$(AUTHORINO_IMAGE) && $(KUSTOMIZE) edit set namespace $(AUTHORINO_NAMESPACE) && $(KUSTOMIZE) edit set replicas authorino-controller-manager=$(AUTHORINO_REPLICAS) @@ -181,12 +187,12 @@ local-push: kind # Builds the image, pushes to the local cluster and deployes Authorino. # Sets the imagePullPolicy to 'IfNotPresent' so it doesn't try to pull the image again (just pushed into the server registry) .PHONY: deploy -local-deploy: docker-build local-push deploy +local-deploy: deploy kubectl -n $(AUTHORINO_NAMESPACE) patch deployment authorino-controller-manager -p '{"spec": {"template": {"spec":{"containers":[{"name": "manager", "imagePullPolicy":"IfNotPresent"}]}}}}' # Set up a test/dev local Kubernetes server loaded up with a freshly built Authorino image plus dependencies .PHONY: local-setup -local-setup: local-cluster-up install namespace local-deploy example-apps +local-setup: docker-build local-cluster-up local-push cert-manager install namespace local-deploy example-apps kubectl -n $(AUTHORINO_NAMESPACE) wait --timeout=300s --for=condition=Available deployments --all @{ \ echo "Now you can export the envoy service by doing:"; \ diff --git a/deploy/base/certmanager/issuer.yaml b/deploy/base/certmanager/issuer.yaml new file mode 100644 index 00000000..c0e2fc5a --- /dev/null +++ b/deploy/base/certmanager/issuer.yaml @@ -0,0 +1,32 @@ +# The following manifest contains a self-signed issuer CR +# More document can be found at https://docs.cert-manager.io +# WARNING: Targets CertManager 1.4.0 check https://docs.cert-manager.io/en/latest/tasks/upgrading/index.html for breaking changes +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: selfsigned-issuer + namespace: system +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: ca-cert + namespace: system +spec: + commonName: "*.$(AUTHORINO_NAMESPACE).svc" + issuerRef: + kind: Issuer + name: selfsigned-issuer + secretName: authorino-ca-cert # this secret will not be prefixed, since it's not managed by kustomize + isCA: true +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: ca-issuer + namespace: system +spec: + ca: + secretName: authorino-ca-cert diff --git a/deploy/base/certmanager/kustomization.yaml b/deploy/base/certmanager/kustomization.yaml index bebea5a5..e61c366d 100644 --- a/deploy/base/certmanager/kustomization.yaml +++ b/deploy/base/certmanager/kustomization.yaml @@ -1,5 +1,7 @@ resources: -- certificate.yaml +- issuer.yaml +- oidc-server-cert.yaml +# - webhook-server-cert.yaml configurations: - kustomizeconfig.yaml diff --git a/deploy/base/certmanager/oidc-server-cert.yaml b/deploy/base/certmanager/oidc-server-cert.yaml new file mode 100644 index 00000000..44027a36 --- /dev/null +++ b/deploy/base/certmanager/oidc-server-cert.yaml @@ -0,0 +1,16 @@ +# The following manifest contains a certificate CR for Authorino OIDC server (OpenID Connect config and JWKS for the Festival Wristbands) +# More document can be found at https://docs.cert-manager.io +# WARNING: Targets CertManager 1.4.0 check https://docs.cert-manager.io/en/latest/tasks/upgrading/index.html for breaking changes +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: oidc-server-cert + namespace: system +spec: + dnsNames: + - $(OIDC_SERVICE_NAME).$(AUTHORINO_NAMESPACE).svc + - $(OIDC_SERVICE_NAME).$(AUTHORINO_NAMESPACE).svc.cluster.local + issuerRef: + kind: Issuer + name: ca-issuer + secretName: authorino-oidc-server-cert # this secret will not be prefixed, since it's not managed by kustomize diff --git a/deploy/base/certmanager/certificate.yaml b/deploy/base/certmanager/webhook-server-cert.yaml similarity index 59% rename from deploy/base/certmanager/certificate.yaml rename to deploy/base/certmanager/webhook-server-cert.yaml index 58db114f..075b498d 100644 --- a/deploy/base/certmanager/certificate.yaml +++ b/deploy/base/certmanager/webhook-server-cert.yaml @@ -1,16 +1,7 @@ -# The following manifests contain a self-signed issuer CR and a certificate CR. +# The following manifest contains a certificate CR for the webhook server # More document can be found at https://docs.cert-manager.io -# WARNING: Targets CertManager 0.11 check https://docs.cert-manager.io/en/latest/tasks/upgrading/index.html for -# breaking changes -apiVersion: cert-manager.io/v1alpha2 -kind: Issuer -metadata: - name: selfsigned-issuer - namespace: system -spec: - selfSigned: {} ---- -apiVersion: cert-manager.io/v1alpha2 +# WARNING: Targets CertManager 1.4.0 check https://docs.cert-manager.io/en/latest/tasks/upgrading/index.html for breaking changes +apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml diff --git a/deploy/base/kustomization.yaml b/deploy/base/kustomization.yaml index ef1d7204..f58096b6 100644 --- a/deploy/base/kustomization.yaml +++ b/deploy/base/kustomization.yaml @@ -5,12 +5,12 @@ kind: Kustomization resources: - manager.yaml -- wristband_service.yaml +- oidc_service.yaml - leader_election_role.yaml - leader_election_role_binding.yaml - auth_proxy_service.yaml +- certmanager #- webhook -#- certmanager #- prometheus #- scorecard @@ -26,6 +26,7 @@ commonLabels: patchesStrategicMerge: - patches/manager_auth_proxy_patch.yaml +- patches/oidc_server_cert_patch.yaml #- patches/manager_webhook_patch.yaml #- patches/webhookcainjection_patch.yaml @@ -37,3 +38,19 @@ images: replicas: - count: 1 name: authorino-controller-manager + +vars: +- fieldref: + fieldPath: metadata.namespace + name: AUTHORINO_NAMESPACE + objref: + apiVersion: v1 + kind: Service + name: authorization +- fieldref: + fieldPath: metadata.name + name: OIDC_SERVICE_NAME + objref: + apiVersion: v1 + kind: Service + name: oidc diff --git a/deploy/base/wristband_service.yaml b/deploy/base/oidc_service.yaml similarity index 76% rename from deploy/base/wristband_service.yaml rename to deploy/base/oidc_service.yaml index 4bb69ed8..c248b81e 100644 --- a/deploy/base/wristband_service.yaml +++ b/deploy/base/oidc_service.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: Service metadata: - name: wristband + name: oidc labels: app: authorino spec: @@ -9,6 +9,6 @@ spec: app: authorino control-plane: controller-manager ports: - - name: oidc - port: 8003 + - name: https + port: 8083 protocol: TCP diff --git a/deploy/base/patches/oidc_server_cert_patch.yaml b/deploy/base/patches/oidc_server_cert_patch.yaml new file mode 100644 index 00000000..54d12992 --- /dev/null +++ b/deploy/base/patches/oidc_server_cert_patch.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + volumeMounts: + - name: oidc-cert + mountPath: /etc/ssl/certs/tls.crt + subPath: tls.crt + readOnly: true + - name: oidc-cert + mountPath: /etc/ssl/private/tls.key + subPath: tls.key + readOnly: true + volumes: + - name: oidc-cert + secret: + defaultMode: 420 + secretName: authorino-oidc-server-cert diff --git a/docs/architecture.md b/docs/architecture.md index 86270ea0..6755bd18 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -77,7 +77,7 @@ spec: # Festival Wristband (only if you want JWTs issued by Authorino at the end of the auth pipeline) wristband: - issuer: http://authorino.svc.cluster.local:8003/namespace/my-api-protection + issuer: https://authorino-oidc.authorino.svc.cluster.local:8083/namespace/my-api-protection customClaims: - name: foo value: bar @@ -314,7 +314,7 @@ spec: in: authorization_header keySelector: APIKEY wristband: - issuer: http://authorino.svc.cluster.local:8003/my-namespace/talker-api-protection + issuer: https://authorino-oidc.authorino.svc:8083/my-namespace/talker-api-protection customClaims: - name: aud value: internal @@ -331,8 +331,8 @@ spec: The signing key names listed in `signingKeyRefs` must match the names of Kubernetes `Secret` resources created in the same namespace, where each secret contains a `key.pem` entry that holds the value of the private key that will be used to sign the wristbands issued, formatted as [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail). The first key in this list will be used to sign the wristbands, while the others are kept to support key rotation. -For each protected API configured for the Festival Wristband issuing, Authorino exposes the following OpenID Connect Discovery well-known endpoints: +For each protected API configured for the Festival Wristband issuing, Authorino exposes the following OpenID Connect Discovery well-known endpoints (available for requests within the cluster): - **OpenID Connect configuration:**
- http://authorino.svc.cluster.local:8003/{namespace}/{api-protection-name}/.well-known/openid-configuration + https://authorino-oidc.authorino.svc:8083/{namespace}/{api-protection-name}/.well-known/openid-configuration - **JSON Web Key Set (JWKS) well-known endpoint:**
- http://authorino.svc.cluster.local:8003/{namespace}/{api-protection-name}/.well-known/openid-connect/certs + https://authorino-oidc.authorino.svc:8083/{namespace}/{api-protection-name}/.well-known/openid-connect/certs diff --git a/examples/README.md b/examples/README.md index 02226485..54dc42de 100644 --- a/examples/README.md +++ b/examples/README.md @@ -566,7 +566,7 @@ The payload of the wristband (decoded) shall look like the following: "born": "2021-05-13T15:42:41Z", # custom claim (dynamic value) "exp": 1620921395, "iat": 1620921095, - "iss": "http://authorino-authorization:8003/authorino/talker-api-protection", + "iss": "https://authorino-oidc.authorino.svc:8083/authorino/talker-api-protection", "sub": "84d3f3a06f5569e06a050516363f0a65c1789d3433bb4fed5d48801997d5c30e" # SHA256 of the resolved identity in the initial request (based on API key auth) } ``` @@ -574,11 +574,11 @@ The payload of the wristband (decoded) shall look like the following: To discover the OpenID Connect configuration and JSON Web Key Set (JWKS) to verify and validate wristbands issued on requests to this protected API: ``` -kubectl -n authorino port-forward service/authorino-authorization 8003:8003 +kubectl -n authorino port-forward service/authorino-oidc 8083:8083 ``` OpenID Connect configuration well-known endpoint:
-http://localhost:8003/authorino/talker-api-protection/.well-known/openid-configuration +http://localhost:8083/authorino/talker-api-protection/.well-known/openid-configuration JSON Web Key Set (JWKS) well-known endpoint:
-http://localhost:8003/authorino/talker-api-protection/.well-known/openid-connect/certs +http://localhost:8083/authorino/talker-api-protection/.well-known/openid-connect/certs diff --git a/examples/wristband.yaml b/examples/wristband.yaml index 5180bf4d..85cc9b5f 100644 --- a/examples/wristband.yaml +++ b/examples/wristband.yaml @@ -15,9 +15,9 @@ spec: keySelector: APIKEY - name: wristband oidc: - endpoint: http://authorino-wristband:8003/authorino/talker-api-protection + endpoint: https://authorino-oidc.authorino.svc:8083/authorino/talker-api-protection wristband: - issuer: http://authorino-wristband:8003/authorino/talker-api-protection + issuer: https://authorino-oidc.authorino.svc:8083/authorino/talker-api-protection customClaims: - name: aud value: internal diff --git a/main.go b/main.go index 1e9580d8..7eecf36f 100644 --- a/main.go +++ b/main.go @@ -53,7 +53,8 @@ var ( watchNamespace = common.FetchEnv("WATCH_NAMESPACE", "") authorinoWatchedSecretLabel = common.FetchEnv("AUTHORINO_SECRET_LABEL_KEY", defaultAuthorinoWatchedSecretLabel) extAuthGRPCPort = common.FetchEnv("EXT_AUTH_GRPC_PORT", "50051") - oidcHTTPPort = common.FetchEnv("OIDC_HTTP_PORT", "8003") + oidcHTTPPort = common.FetchEnv("OIDC_HTTP_PORT", "8083") + oidcCAPath = common.FetchEnv("OIDC_CA_PATH", "/etc/ssl") ) func init() { @@ -206,12 +207,10 @@ func startOIDCServer(serviceCache cache.Cache) { logger.Info("starting oidc service", "port", oidcHTTPPort) go func() { - if err := http.Serve(lis, nil); err != nil { + if err := http.ServeTLS(lis, nil, oidcCAPath+"/certs/tls.crt", oidcCAPath+"/private/tls.key"); err != nil { logger.Error(err, "failed to start oidc service") os.Exit(1) } - - // TODO: ServeTLS }() } }