From 0691541c376779438ac36921e6af2a8fbc2ae190 Mon Sep 17 00:00:00 2001 From: ctyano Date: Wed, 3 Apr 2024 23:59:49 +0900 Subject: [PATCH] Added athenz-oauth2 --- kubernetes/athenz-oauth2/.gitignore | 8 + kubernetes/athenz-oauth2/Makefile | 162 ++++++++++ kubernetes/athenz-oauth2/README.md | 39 +++ kubernetes/athenz-oauth2/kustomize/.gitignore | 1 + .../kustomize/athenz-sia/athenz-sia.env | 175 +++++++++++ .../athenz-oauth2/kustomize/deployment.yaml | 203 +++++++++++++ .../athenz-oauth2/kustomize/envoy/ca_sds.yaml | 13 + .../athenz-oauth2/kustomize/envoy/config.yaml | 282 ++++++++++++++++++ .../kustomize/envoy/identity_sds.yaml | 15 + .../kustomize/envoy/role_sds.yaml | 15 + .../kustomize/kustomization.yaml | 52 ++++ .../athenz-oauth2/kustomize/namespace.yaml | 5 + .../athenz-oauth2/kustomize/service.yaml | 18 ++ .../kustomize/serviceaccount.yaml | 7 + 14 files changed, 995 insertions(+) create mode 100644 kubernetes/athenz-oauth2/.gitignore create mode 100644 kubernetes/athenz-oauth2/Makefile create mode 100644 kubernetes/athenz-oauth2/README.md create mode 100644 kubernetes/athenz-oauth2/kustomize/.gitignore create mode 100644 kubernetes/athenz-oauth2/kustomize/athenz-sia/athenz-sia.env create mode 100644 kubernetes/athenz-oauth2/kustomize/deployment.yaml create mode 100644 kubernetes/athenz-oauth2/kustomize/envoy/ca_sds.yaml create mode 100644 kubernetes/athenz-oauth2/kustomize/envoy/config.yaml create mode 100644 kubernetes/athenz-oauth2/kustomize/envoy/identity_sds.yaml create mode 100644 kubernetes/athenz-oauth2/kustomize/envoy/role_sds.yaml create mode 100644 kubernetes/athenz-oauth2/kustomize/kustomization.yaml create mode 100644 kubernetes/athenz-oauth2/kustomize/namespace.yaml create mode 100644 kubernetes/athenz-oauth2/kustomize/service.yaml create mode 100644 kubernetes/athenz-oauth2/kustomize/serviceaccount.yaml diff --git a/kubernetes/athenz-oauth2/.gitignore b/kubernetes/athenz-oauth2/.gitignore new file mode 100644 index 0000000..1cf8cdb --- /dev/null +++ b/kubernetes/athenz-oauth2/.gitignore @@ -0,0 +1,8 @@ +*.pem +*.jks +*.pkcs12 +*.srl +*.jar +.ntoken +athenz.conf +admin diff --git a/kubernetes/athenz-oauth2/Makefile b/kubernetes/athenz-oauth2/Makefile new file mode 100644 index 0000000..a248001 --- /dev/null +++ b/kubernetes/athenz-oauth2/Makefile @@ -0,0 +1,162 @@ +ifeq ($(DOCKER_REGISTRY),) +DOCKER_REGISTRY=ghcr.io/ctyano/ +endif + +clean-athenz-oauth2: + kubectl delete -k kustomize + +register-athenz-oauth2: + kubectl -n athenz exec deployment/athenz-cli -it -- \ + curl \ + -sv \ + -d"{\"name\":\"$$(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^PROVIDER_SERVICE | sed -e 's/PROVIDER_SERVICE=\(.*\)\.\(.*\)/\1/g')\",\"adminUsers\":[\"user.athenz_admin\"]}" \ + -H"Content-Type: application/json" \ + --key /var/run/athenz/athenz_admin.private.pem \ + --cert /var/run/athenz/athenz_admin.cert.pem \ + "https://athenz-zms-server.athenz:4443/zms/v1/domain" + kubectl -n athenz exec deployment/athenz-cli -it -- \ + zms-cli \ + -z https://athenz-zms-server.athenz:4443/zms/v1 \ + -key /var/run/athenz/athenz_admin.private.pem \ + -cert /var/run/athenz/athenz_admin.cert.pem \ + -d \ + sys.auth \ + set-domain-template \ + instance_provider \ + provider="$$(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^PROVIDER_SERVICE | sed -e 's/PROVIDER_SERVICE=\(.*\)/\1/g')" \ + dnssuffix="$$(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^DNS_SUFFIX | sed -e 's/DNS_SUFFIX=\(.*\)/\1/g')" + kubectl -n athenz exec deployment/athenz-cli -it -- \ + zms-cli \ + -z https://athenz-zms-server.athenz:4443/zms/v1 \ + -key /var/run/athenz/athenz_admin.private.pem \ + -cert /var/run/athenz/athenz_admin.cert.pem \ + -d \ + $$(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^PROVIDER_SERVICE | sed -e 's/PROVIDER_SERVICE=\(.*\)\.\(.*\)/\1/g') \ + add-service \ + $$(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^SERVICEACCOUNT | sed -e 's/SERVICEACCOUNT=\(.*\)/\1/g') \ + 0 \ + $$(cat kustomize/keys/oauth2.public.pem | base64 | tr -d '\r\n' | tr '\+\=\/' '\.\-\_') ||: + kubectl -n athenz exec deployment/athenz-cli -it -- \ + zms-cli \ + -z https://athenz-zms-server.athenz:4443/zms/v1 \ + -key /var/run/athenz/athenz_admin.private.pem \ + -cert /var/run/athenz/athenz_admin.cert.pem \ + -d \ + $$(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^PROVIDER_SERVICE | sed -e 's/PROVIDER_SERVICE=\(.*\)\.\(.*\)/\1/g') \ + set-domain-template \ + identity_provisioning \ + instanceprovider="sys.auth.zts" \ + service="$$(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^SERVICEACCOUNT | sed -e 's/SERVICEACCOUNT=\(.*\)/\1/g')" + kubectl -n athenz exec deployment/athenz-cli -it -- \ + zms-cli \ + -z https://athenz-zms-server.athenz:4443/zms/v1 \ + -key /var/run/athenz/athenz_admin.private.pem \ + -cert /var/run/athenz/athenz_admin.cert.pem \ + -d \ + $$(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^PROVIDER_SERVICE | sed -e 's/PROVIDER_SERVICE=\(.*\)\.\(.*\)/\1/g') \ + set-domain-template \ + identity_provisioning \ + instanceprovider="$$(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^PROVIDER_SERVICE | sed -e 's/PROVIDER_SERVICE=\(.*\)/\1/g')" \ + service="$$(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^SERVICEACCOUNT | sed -e 's/SERVICEACCOUNT=\(.*\)/\1/g')" + kubectl -n athenz exec deployment/athenz-cli -it -- \ + zms-cli \ + -z https://athenz-zms-server.athenz:4443/zms/v1 \ + -key /var/run/athenz/athenz_admin.private.pem \ + -cert /var/run/athenz/athenz_admin.cert.pem \ + -d $$(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^PROVIDER_SERVICE | sed -e 's/PROVIDER_SERVICE=\(.*\)\.\(.*\)/\1/g') \ + add-group-role \ + envoyclients ||: + kubectl -n athenz exec deployment/athenz-cli -it -- \ + zms-cli \ + -z https://athenz-zms-server.athenz:4443/zms/v1 \ + -key /var/run/athenz/athenz_admin.private.pem \ + -cert /var/run/athenz/athenz_admin.cert.pem \ + -d $$(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^PROVIDER_SERVICE | sed -e 's/PROVIDER_SERVICE=\(.*\)\.\(.*\)/\1/g') \ + add-policy \ + envoyclients \ + grant get to envoyclients on /extauthz* ||: + kubectl -n athenz exec deployment/athenz-cli -it -- \ + zms-cli \ + -z https://athenz-zms-server.athenz:4443/zms/v1 \ + -key /var/run/athenz/athenz_admin.private.pem \ + -cert /var/run/athenz/athenz_admin.cert.pem \ + -d $$(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^PROVIDER_SERVICE | sed -e 's/PROVIDER_SERVICE=\(.*\)\.\(.*\)/\1/g') \ + show-domain + +check-register-athenz-oauth2: + SLEEP_SECONDS=5; \ +WAITING_THRESHOLD=60; \ +i=0; \ +while true; do \ + printf "\n***** Waiting for athenz($$(( $$i * $${SLEEP_SECONDS} ))s/$${WAITING_THRESHOLD}s) *****\n"; \ + kubectl -n athenz exec deployment/athenz-cli -it -- \ + curl \ + -sf \ + -H"Content-type: application/json" \ + -H"X-Auth-Request-Preferred-Username: user.athenz_admin" \ + "https://athenz-zts-server.athenz:4443/zts/v1/domain/$$(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^PROVIDER_SERVICE | sed -e 's/PROVIDER_SERVICE=\(.*\)\.\(.*\)/\1/g')/service/$$(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^SERVICEACCOUNT | sed -e 's/SERVICEACCOUNT=\(.*\)/\1/g')" \ + && break \ + || echo "Waiting for ZTS to sync with ZMS..."; \ + sleep $${SLEEP_SECONDS}; \ + i=$$(( i + 1 )); \ + if [ $$i -eq $$(( $${WAITING_THRESHOLD} / $${SLEEP_SECONDS} )) ]; then \ + printf "\n\n** Waiting ($$(( $$i * $${SLEEP_SECONDS} ))s) reached to threshold($${WAITING_THRESHOLD}s) **\n\n"; \ + kubectl -n athenz get all | grep -E "pod/.*0/1" | sed -e 's/^\(pod\/[^ ]*\) *0\/1.*/\1/g' | xargs -I%% kubectl -n athenz logs %% --all-containers=true ||:; \ + kubectl -n athenz get all | grep -E "pod/.*0/1" | sed -e 's/^\(pod\/[^ ]*\) *0\/1.*/\1/g' | xargs -I%% kubectl -n athenz describe %% ||:; \ + kubectl -n athenz get all; \ + exit 1; \ + fi; \ +done + kubectl -n athenz get all + @echo "" + @echo "**************************************" + @echo "** Athenz Authorizer is functioning *" + @echo "**************************************" + @echo "" + +kustomize-edit-athenz-oauth2-image: + if [ "$(DOCKER_REGISTRY)" != "ghcr.io/ctyano/" ]; then \ + ( \ + cd kustomize \ + && kustomize edit set image ghcr.io/ctyano/athenz-cli:latest=$(DOCKER_REGISTRY)athenz-cli:latest \ + && kustomize edit set image ghcr.io/ctyano/k8s-athenz-sia:latest=$(DOCKER_REGISTRY)k8s-athenz-sia:latest \ + ) \ + fi + +deploy-athenz-oauth2: kustomize-edit-athenz-oauth2-image + kubectl apply -k kustomize + +test-athenz-oauth2: + SLEEP_SECONDS=5; \ +WAITING_THRESHOLD=60; \ +i=0; \ +while true; do \ + printf "\n***** Waiting for athenz($$(( $$i * $${SLEEP_SECONDS} ))s/$${WAITING_THRESHOLD}s) *****\n"; \ + ( \ + test $$(( $$(kubectl -n athenz get all | grep oauth2 | grep -E "0/1" | wc -l) )) -eq 0 \ + && \ + kubectl -n athenz exec deployment/oauth2-deployment -it -c sia -- \ + ls \ + -alF \ + /var/run/athenz/tls.key \ + /var/run/athenz/tls.crt \ + /var/run/athenz/ca.crt \ + ) \ + && break \ + || echo "Waiting for Identity Provisioning..."; \ + sleep $${SLEEP_SECONDS}; \ + i=$$(( i + 1 )); \ + if [ $$i -eq $$(( $${WAITING_THRESHOLD} / $${SLEEP_SECONDS} )) ]; then \ + printf "\n\n** Waiting ($$(( $$i * $${SLEEP_SECONDS} ))s) reached to threshold($${WAITING_THRESHOLD}s) **\n\n"; \ + kubectl -n athenz get all | grep -E "pod/oauth2-" | sed -e 's/^\(pod\/[^ ]*\) *[0-9]\/[0-9].*/\1/g' | xargs -I%% kubectl -n athenz logs %% --all-containers=true ||:; \ + kubectl -n athenz get all | grep -E "pod/oauth2-" | sed -e 's/^\(pod\/[^ ]*\) *[0-9]\/[0-9].*/\1/g' | xargs -I%% kubectl -n athenz describe %% ||:; \ + kubectl -n athenz get all; \ + exit 1; \ + fi; \ +done + kubectl -n athenz get all + @echo "" + @echo "**************************************" + @echo "* Authorizer provisioning successful *" + @echo "**************************************" + @echo "" diff --git a/kubernetes/athenz-oauth2/README.md b/kubernetes/athenz-oauth2/README.md new file mode 100644 index 0000000..5b7fd84 --- /dev/null +++ b/kubernetes/athenz-oauth2/README.md @@ -0,0 +1,39 @@ +# athenz-oauth2 + +## Configuration + +Files below must be configured for each use cases accordingly + +1. [athenz-oauth2.env](kustomize/athenz-oauth2/athenz-oauth2.env) +1. [athenz-sia.env](kustomize/athenz-sia/athenz-sia.env) +1. [config.yaml](kustomize/athenz-oauth2/policy/config.yaml) + +## Deployment + +``` +kubectl -n athenz apply -k kustomize +``` + +## Registering Authorizer Service to Athenz + +``` +make register-athenz-oauth2 +``` + +confirm registration with: + +``` +kubectl -n athenz exec deployment/athenz-cli -it -- \ + zms-cli \ + -z https://athenz-zms-server.athenz:4443/zms/v1 \ + -key /var/run/athenz/athenz_admin.private.pem \ + -cert /var/run/athenz/athenz_admin.cert.pem \ + -d $(cat kustomize/athenz-sia/athenz-sia.env | grep -E ^PROVIDER_SERVICE | sed -e 's/PROVIDER_SERVICE=\(.*\)\.\(.*\)/\1/g') \ + show-domain +``` + +## Debugging + +``` +kubectl -n athenz exec -it deployment/oauth2-deployment -c athenz-cli -- /bin/sh -c "curl -sv --resolve oauth2.athenz.svc.cluster.local:443:127.0.0.1 https://oauth2.athenz.svc.cluster.local/echoserver | jq -r .request" +``` diff --git a/kubernetes/athenz-oauth2/kustomize/.gitignore b/kubernetes/athenz-oauth2/kustomize/.gitignore new file mode 100644 index 0000000..4a424df --- /dev/null +++ b/kubernetes/athenz-oauth2/kustomize/.gitignore @@ -0,0 +1 @@ +secret.yaml diff --git a/kubernetes/athenz-oauth2/kustomize/athenz-sia/athenz-sia.env b/kubernetes/athenz-oauth2/kustomize/athenz-sia/athenz-sia.env new file mode 100644 index 0000000..6a09c0c --- /dev/null +++ b/kubernetes/athenz-oauth2/kustomize/athenz-sia/athenz-sia.env @@ -0,0 +1,175 @@ +# +# Booting mode of SIA +# must be one of "init" or "refresh" +# "init": SIA will exit after a single credential retrieval +# "refresh": SIA will run as a continuous process to retrieve credentials periodically and also runs as an HTTP server to provide credentials and metrics +# +MODE=init +# +# Athenz ZTS URL for SIA to request for X.509 certificate +# https://:/zts/v1 +# +ENDPOINT=https://athenz-zts-server.athenz:4443/zts/v1 +# +# Athenz Service name for the cloud provider +# . (e.g. "cloud-provider-top-level-domain.cluster-name.oauth2-service") +# +PROVIDER_SERVICE=athenz.identityprovider +# +# Suffix restriction for SANs(Subject Alternative Names) DNS field in X.509 certificate +# Subject Alternative Names: +# "DNS: ." +# "DNS: .instanceid.athenz." +# Note: must meat the suffix registered in Athenz (e.g. ".athenz.cloud") +# +DNS_SUFFIX=svc.cluster.local +# +# Refresh interval for SIA to request to ZTS periodically in containers to get X.509 identity certificate +# Note: This only applies for refresh mode +# +REFRESH_INTERVAL=30s +# +# Delay interval for SIA to boot +# This may be useful when you want to prevent large number of SIA to make requests to ZTS concurrently in a short period +# +DELAY_JITTER_SECONDS=0 +# +# File paths to store Athenz X.509 certificate key file +# +KEY_FILE=/var/run/athenz/tls.key +# +# File paths to store Athenz X.509 certificate file +# +CERT_FILE=/var/run/athenz/tls.crt +# +# File paths to store Athenz X.509 ca certificate file that can verify CERT_FILE +# +CA_CERT_FILE=/var/run/athenz/ca.crt +# +# Directory to store the log files +# +LOG_DIR=/dev/null +# +# Log level to print logs +# Available values are: TRACE, DEBUG, INFO, WARNING, ERROR, FATAL or PANIC +# +LOG_LEVEL=DEBUG +# +# Set "read" or "read+write" for storing backup of X.509 certificate to Kubernetes Secret +# Set "write" or "read+write" for reading backup of X.509 certificate from Kubernetes Secret +# Set "" for disabling Kubernetes Secret backup +# "write" or "read+write" must be run uniquely for each secret to prevent conflict +# +BACKUP="" +# +# Kubernetes TLS Secret to backup and load X.509 certificate files +# +CERT_SECRET=oauth2-tls +# +# Cloud users Athenz Domain to map to SIA +# +# if is not "", Athenz Domain would be: +# "" +# must end with "." +# must start with "." +# Example: +# ATHENZ_PREFIX="some-tld.foo." +# ATHENZ_DOMAIN="cluster-bar" +# ATHENZ_SUFFIX=".baz" +# +# if is "", Athenz Domain would be: +# "" +# is Kubernetes Namespace set by default +# must end with "." +# must start with "." +# Example: +# ATHENZ_PREFIX="some-tld.foo." +# NAMESPACE="namespace-bar" +# ATHENZ_SUFFIX=".baz" +# +# NAMESPACE may be extracted from metadata.namespace in Kubernetes manifests +# +NAMESPACE= +ATHENZ_DOMAIN= +ATHENZ_PREFIX= +ATHENZ_SUFFIX= +# +# Kubernetes Service Account as same name as Athenz Service +# +# SERVICEACCOUNT may be extracted from spec.serviceAccountName in Kubernetes Pod manifests +# +SERVICEACCOUNT=oauth2 +# +# File path for Kubernetes Service Account Token +# +SA_TOKEN_FILE=/var/run/secrets/kubernetes.io/bound-serviceaccount/token +# +# Kubernetes Pod IP +# +# POD_IP may be extracted from status.podIP in Kubernetes manifests +# +POD_IP= +# +# Kubernetes Pod UID +# +# POD_UID may be extracted from metadata.uid in Kubernetes manifests +# +POD_UID= +# +# CA certificate to verify ZTS server certificate +# +SERVER_CA_CERT=/etc/ssl/certs/ca-certificates.crt +# +# Comma separated Athenz Roles to retrieve role certificates (if empty, role certificate retrieval will be skipped) +# :role.,:role.... +# +TARGET_DOMAIN_ROLES= +# +# Directory path to store Athenz X.509 role certificate files +# +ROLECERT_DIR= +# +# Directory path to store Athenz role token files +# +TOKEN_DIR= +# +# Token type for Athenz role tokens +# +TOKEN_TYPE=roletoken+accesstoken +# +# Refresh interval for SIA to request to ZTS periodically in containers to get role tokens +# +TOKEN_REFRESH_INTERVAL=30s +# +# Server address to listen as token provider sidecar (e.g. :8180) +# +TOKEN_SERVER_ADDR=:8180 +# +# Server address to listen as metrics exporter sidecar (e.g. :9999) +# +METRICS_SERVER_ADDR=:9999 +# +# Delete Instance ID at container shutdown +# +DELETE_INSTANCE_ID=true +# +# Comma separated Athenz Domains to retrieve policies (if empty, Athenz Policy retrieval will be skipped) +# ,... +# +AUTHORIZATION_POLICY_DOMAINS=athenz +# +# Server address to listen as authorization sidecar (e.g. :8280) +# +AUTHORIZATION_SERVER_ADDR=:8280 +# +# Refresh interval for SIA to request to ZTS periodically in containers to get policies +# +POLICY_REFRESH_INTERVAL=30s +# +# Refresh interval for SIA to request to ZTS periodically in containers to get public keys +# +PUBLICKEY_REFRESH_INTERVAL=30s +# +# Cache interval for SIA to authorize requests without comparing with roles and policies +# +AUTHORIZATION_CACHE_INTERVAL=30s diff --git a/kubernetes/athenz-oauth2/kustomize/deployment.yaml b/kubernetes/athenz-oauth2/kustomize/deployment.yaml new file mode 100644 index 0000000..a34a28f --- /dev/null +++ b/kubernetes/athenz-oauth2/kustomize/deployment.yaml @@ -0,0 +1,203 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: oauth2-deployment + labels: + app: oauth2-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: oauth2-deployment + template: + metadata: + labels: + app: oauth2-deployment + spec: + serviceAccountName: athenz-sia + securityContext: + fsGroup: 1000 + volumes: + - name: attestation-data + projected: + sources: + - serviceAccountToken: + audience: https://kubernetes.default.svc + expirationSeconds: 3600 + path: token + - name: athenz-tls-certs + emptyDir: {} + - name: envoy + configMap: + name: oauth2-envoy + - name: policy + configMap: + name: oauth2-policy + - name: config + configMap: + name: oauth2-config + - name: athenz-cacert + configMap: + name: athenz-cacert + items: + - key: ca.cert.pem + path: ca-certificates.crt + - name: athenz-admin-keys + secret: + secretName: athenz-admin-keys + defaultMode: 0555 + items: + - key: athenz_admin.cert.pem + path: athenz_admin.cert.pem + - key: athenz_admin.private.pem + path: athenz_admin.private.pem + initContainers: + # TODO: sia-wait should be implemented in sia-init in future + - name: sia-wait + image: &sia-image ghcr.io/ctyano/k8s-athenz-sia:latest + imagePullPolicy: &sia-imagePullPolicy IfNotPresent + resources: &sia-resources + limits: + cpu: 50m + memory: 64Mi + command: + - sh + - -c + args: + - | + while true; do nc -vzw3 athenz-zts-server.athenz.svc.cluster.local 4443 && nc -vzw3 identityprovider.athenz.svc.cluster.local 443 && break; done + - name: sia-init + image: *sia-image + imagePullPolicy: *sia-imagePullPolicy + resources: *sia-resources + args: &sia-args + - --mode=init + - --delay-jitter-seconds=5 + envFrom: &sia-envFrom + - configMapRef: + name: oauth2-sia + env: &sia-env + - name: NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: SERVICEACCOUNT + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.serviceAccountName + - name: POD_UID + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.uid + - name: POD_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + volumeMounts: &sia-volumeMounts + - name: attestation-data + mountPath: /var/run/secrets/kubernetes.io/bound-serviceaccount + readOnly: true + - name: athenz-tls-certs + mountPath: /var/run/athenz + - name: athenz-cacert + mountPath: /etc/ssl/certs + containers: + - name: sia + image: *sia-image + imagePullPolicy: *sia-imagePullPolicy + args: + - --mode=refresh + - --token-server-addr=:8180 + - --authorization-server-addr=:8280 + - --metrics-server-addr=:9999 + envFrom: *sia-envFrom + env: *sia-env + ports: + - name: token-sidecar + containerPort: 8180 + protocol: TCP + - name: authorization + containerPort: 8280 + protocol: TCP + - name: exporter + containerPort: 9999 + protocol: TCP + resources: *sia-resources + volumeMounts: *sia-volumeMounts + - name: athenz-cli + image: ghcr.io/ctyano/athenz-cli:latest + imagePullPolicy: IfNotPresent + env: + - name: TZ + value: Asia/Tokyo + - name: ZMS + value: https://athenz-zms-server.athenz:4443/zms/v1 + - name: ZTS + value: https://athenz-zts-server.athenz:4443/zts/v1 + resources: + limits: + memory: 1Gi + cpu: 1 + requests: + memory: 256Mi + cpu: 50m + volumeMounts: + - name: athenz-admin-keys + mountPath: /var/run/athenz + readOnly: true + - name: athenz-cacert + mountPath: /etc/ssl/certs/ca-certificates.crt + subPath: ca-certificates.crt + readOnly: true + - name: envoy + image: docker.io/envoyproxy/envoy:v1.29-latest + # Envoy crashes in Raspberry Pi 4 + #image: docker.io/thegrandpkizzle/envoy:1.26.1 + imagePullPolicy: IfNotPresent + ports: + - name: https + containerPort: 443 + protocol: TCP + - name: mtls + containerPort: 4443 + protocol: TCP + - name: http + containerPort: 8080 + protocol: TCP + command: + - /usr/local/bin/envoy + args: + - -c + - /etc/envoy/config.yaml + - -l + - debug + resources: &envoy-resources + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 50m + memory: 64Mi + volumeMounts: + - name: envoy + mountPath: /etc/envoy + readOnly: true + - name: athenz-tls-certs + mountPath: /var/run/athenz + readOnly: true + - name: echoserver + image: docker.io/ealen/echo-server:latest + imagePullPolicy: IfNotPresent + ports: + - name: echoserver + containerPort: 3000 + protocol: TCP + env: + - name: PORT + value: "3000" + resources: *envoy-resources diff --git a/kubernetes/athenz-oauth2/kustomize/envoy/ca_sds.yaml b/kubernetes/athenz-oauth2/kustomize/envoy/ca_sds.yaml new file mode 100644 index 0000000..2af98e2 --- /dev/null +++ b/kubernetes/athenz-oauth2/kustomize/envoy/ca_sds.yaml @@ -0,0 +1,13 @@ +--- +# SDS Configuration to watch X.509 Certificate changes +# This example shows how to set up xDS connection by sourcing SDS configuration from the filesystem. +# The certificate and key files are watched with inotify and reloaded automatically without restart. +# See: https://www.envoyproxy.io/docs/envoy/latest/configuration/security/secret.html?highlight=inotify#example-three-certificate-rotation-for-xds-grpc-connection +resources: + - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret" + name: ca_sds + validation_context: + trusted_ca: + filename: /var/run/athenz/ca.crt + watched_directory: + path: /var/run/athenz diff --git a/kubernetes/athenz-oauth2/kustomize/envoy/config.yaml b/kubernetes/athenz-oauth2/kustomize/envoy/config.yaml new file mode 100644 index 0000000..c4f8dc5 --- /dev/null +++ b/kubernetes/athenz-oauth2/kustomize/envoy/config.yaml @@ -0,0 +1,282 @@ +# athenz-oauth2 +--- +admin: + access_log: + - name: access_log_file + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + path: "/dev/stdout" + address: + socket_address: + address: 127.0.0.1 + port_value: 9901 +node: + id: envoy-0 + cluster: envoy-cluster +static_resources: + listeners: + - name: localhost_listener + address: + socket_address: + protocol: TCP + address: ::FFFF:127.0.0.1 + ipv4_compat: true + port_value: 8080 + filter_chains: &localhost_filter_chains + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + codec_type: auto + stat_prefix: localhost_proxy_prefix + access_log: &access_log + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + route_config: &localhost_route_config + name: localhost_proxy_route + virtual_hosts: + - name: localhost_proxy_hosts + domains: + # Only a single wildcard domain is permitted in route https_proxy_route + - "*" + typed_per_filter_config: + envoy.filters.http.ext_authz: + "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute + check_settings: + context_extensions: + virtual_host: localhost_proxy_hosts + routes: &localhost_routes + - match: + path_separated_prefix: "/status" + direct_response: + status: 200 + body: + inline_string: "This is server ingress proxy." + response_headers_to_add: + - header: + key: x-athenz-method + value: "%REQ(:METHOD)%" + - header: + key: x-athenz-path + value: "%REQ(:PATH)%" + typed_per_filter_config: &filters_disabled + envoy.filters.http.ext_authz.authorization: &ext_authz_authorizationsidecar_disabled + "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute + disabled: true + - match: + path_separated_prefix: "/zms/v1" + route: + cluster: zms + auto_host_rewrite: true + typed_per_filter_config: *filters_disabled + - match: + path_separated_prefix: "/zts/v1" + route: + cluster: zts + auto_host_rewrite: true + typed_per_filter_config: *filters_disabled + - match: + path_separated_prefix: "/oauth2" + route: + cluster: echoserver + prefix_rewrite: "/echoserver" + auto_host_rewrite: true + request_headers_to_add: &request_headers_to_add + - header: + key: x-athenz-sni + value: "%REQUESTED_SERVER_NAME%" + - header: + key: x-athenz-certificate-subject + value: "%DOWNSTREAM_PEER_SUBJECT%" + - header: + key: x-athenz-certificate-issuer + value: "%DOWNSTREAM_PEER_ISSUER%" + - header: + key: x-athenz-certificate-san-uri + value: "%DOWNSTREAM_PEER_URI_SAN%" + - header: + key: x-athenz-certificate-v-start + value: "%DOWNSTREAM_PEER_CERT_V_START%" + - header: + key: x-athenz-certificate-v-end + value: "%DOWNSTREAM_PEER_CERT_V_END%" + - header: + key: x-athenz-certificate + value: "%DOWNSTREAM_PEER_CERT%" + - header: + key: x-athenz-proxy + value: "ingress envoy with extauthz filter" + - match: + prefix: "/echoserver" + route: + cluster: echoserver + request_headers_to_add: *request_headers_to_add + typed_per_filter_config: *filters_disabled + - match: + prefix: "/" + route: + cluster: envoy_admin + typed_per_filter_config: *filters_disabled + http_filters: &localhost_http_filters + # Oauth2 External Authorization + - name: envoy.filters.http.ext_authz.oauth2 + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz + # https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html#extensions-filters-http-ext-authz-v3-httpservice + http_service: + server_uri: + uri: 127.0.0.1:4180 + cluster: oauth2-proxy + timeout: 5s + authorization_request: + headers_to_add: + - key: x-auth-request-redirect + value: https://dexidp/dex/auth + allowed_headers: + patterns: + - safe_regex: + google_re2: {} + regex: ".*" + authorization_response: + allowed_upstream_headers: + patterns: + - prefix: "x-" + with_request_body: + max_request_bytes: 1024 + transport_api_version: V3 + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + - name: mtls_listener + address: + socket_address: + protocol: TCP + address: ::FFFF:0.0.0.0 + ipv4_compat: true + port_value: 4443 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + codec_type: auto + stat_prefix: mtls_proxy_prefix + access_log: *access_log + route_config: *localhost_route_config + http_filters: *localhost_http_filters + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + common_tls_context: &common_tls_context + tls_certificate_sds_secret_configs: &tls_certificate_sds_secret_configs_identity + - name: identity_sds + sds_config: + path_config_source: + path: /etc/envoy/identity_sds.yaml + resource_api_version: V3 + validation_context_sds_secret_config: &validation_context_sds_secret_config_ca + name: ca_sds + sds_config: + path_config_source: + path: /etc/envoy/ca_sds.yaml + resource_api_version: V3 + require_client_certificate: true + - name: https_listener + address: + socket_address: + protocol: TCP + address: ::FFFF:0.0.0.0 + ipv4_compat: true + port_value: 443 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + codec_type: auto + stat_prefix: https_proxy_prefix + access_log: *access_log + route_config: *localhost_route_config + http_filters: *localhost_http_filters + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + common_tls_context: + tls_certificate_sds_secret_configs: *tls_certificate_sds_secret_configs_identity + clusters: + - name: envoy_admin + connect_timeout: 0.25s + type: STATIC # LOGICAL_DNS or STATIC + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: envoy_admin + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 9901 + - name: envoy_localhost + connect_timeout: 0.25s + type: STATIC # LOGICAL_DNS or STATIC + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: envoy_localhost + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 8080 + - name: zms + connect_timeout: 0.25s + type: LOGICAL_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: zms + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: athenz-zms-server.athenz + port_value: 4443 + transport_socket: &transport_socket + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: *common_tls_context + - name: zts + connect_timeout: 0.25s + type: LOGICAL_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: zts + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: athenz-zts-server.athenz + port_value: 4443 + transport_socket: *transport_socket + - name: echoserver + connect_timeout: 0.25s + type: STATIC # LOGICAL_DNS or STATIC + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: echoserver + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 3000 diff --git a/kubernetes/athenz-oauth2/kustomize/envoy/identity_sds.yaml b/kubernetes/athenz-oauth2/kustomize/envoy/identity_sds.yaml new file mode 100644 index 0000000..a9efc5e --- /dev/null +++ b/kubernetes/athenz-oauth2/kustomize/envoy/identity_sds.yaml @@ -0,0 +1,15 @@ +--- +# SDS Configuration to watch X.509 Certificate changes +# This example shows how to set up xDS connection by sourcing SDS configuration from the filesystem. +# The certificate and key files are watched with inotify and reloaded automatically without restart. +# See: https://www.envoyproxy.io/docs/envoy/latest/configuration/security/secret.html?highlight=inotify#example-three-certificate-rotation-for-xds-grpc-connection +resources: + - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret" + name: identity_sds + tls_certificate: + certificate_chain: + filename: /var/run/athenz/tls.crt + private_key: + filename: /var/run/athenz/tls.key + watched_directory: + path: /var/run/athenz diff --git a/kubernetes/athenz-oauth2/kustomize/envoy/role_sds.yaml b/kubernetes/athenz-oauth2/kustomize/envoy/role_sds.yaml new file mode 100644 index 0000000..010042a --- /dev/null +++ b/kubernetes/athenz-oauth2/kustomize/envoy/role_sds.yaml @@ -0,0 +1,15 @@ +--- +# SDS Configuration to watch X.509 Certificate changes +# This example shows how to set up xDS connection by sourcing SDS configuration from the filesystem. +# The certificate and key files are watched with inotify and reloaded automatically without restart. +# See: https://www.envoyproxy.io/docs/envoy/latest/configuration/security/secret.html?highlight=inotify#example-three-certificate-rotation-for-xds-grpc-connection +resources: + - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret" + name: role_sds + tls_certificate: + certificate_chain: + filename: "/var/run/athenz/athenz:role.envoyclients.cert.pem" + private_key: + filename: /var/run/athenz/tls.key + watched_directory: + path: /var/run/athenz diff --git a/kubernetes/athenz-oauth2/kustomize/kustomization.yaml b/kubernetes/athenz-oauth2/kustomize/kustomization.yaml new file mode 100644 index 0000000..74d787a --- /dev/null +++ b/kubernetes/athenz-oauth2/kustomize/kustomization.yaml @@ -0,0 +1,52 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: athenz + +resources: + - deployment.yaml + - namespace.yaml + - service.yaml + - serviceaccount.yaml + +generatorOptions: + disableNameSuffixHash: true + +configMapGenerator: + - name: oauth2-sia + envs: + - athenz-sia/athenz-sia.env + - name: oauth2-envoy + files: + - config.yaml=envoy/config.yaml + - identity_sds.yaml=envoy/identity_sds.yaml + - role_sds.yaml=envoy/role_sds.yaml + - ca_sds.yaml=envoy/ca_sds.yaml +# - name: athenz-cacert +# files: +# - ca.cert.pem=certs/ca.cert.pem + +replacements: + - source: + version: v1 + kind: ConfigMap + name: oauth2-sia + fieldpath: data.SERVICEACCOUNT + targets: + - select: + version: v1 + kind: ServiceAccount + name: oauth2-serviceaccount + fieldPaths: + - metadata.name + options: + create: true + - select: + version: v1 + kind: Deployment + name: oauth2-deployment + fieldPaths: + - spec.template.spec.serviceAccountName + options: + create: true diff --git a/kubernetes/athenz-oauth2/kustomize/namespace.yaml b/kubernetes/athenz-oauth2/kustomize/namespace.yaml new file mode 100644 index 0000000..8df8098 --- /dev/null +++ b/kubernetes/athenz-oauth2/kustomize/namespace.yaml @@ -0,0 +1,5 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: athenz diff --git a/kubernetes/athenz-oauth2/kustomize/service.yaml b/kubernetes/athenz-oauth2/kustomize/service.yaml new file mode 100644 index 0000000..08c33d7 --- /dev/null +++ b/kubernetes/athenz-oauth2/kustomize/service.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: oauth2 + labels: + app: oauth2-service +spec: + type: ClusterIP + selector: + app: oauth2-deployment + ports: + - name: https + port: 443 + targetPort: https + - name: mtls + port: 4443 + targetPort: mtls diff --git a/kubernetes/athenz-oauth2/kustomize/serviceaccount.yaml b/kubernetes/athenz-oauth2/kustomize/serviceaccount.yaml new file mode 100644 index 0000000..146dd0b --- /dev/null +++ b/kubernetes/athenz-oauth2/kustomize/serviceaccount.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: oauth2-serviceaccount + labels: + app: oauth2-serviceaccount