diff --git a/09_ExternalSecrets/external-secrets-values.yaml b/09_ExternalSecrets/external-secrets-values.yaml new file mode 100644 index 0000000..3b71b07 --- /dev/null +++ b/09_ExternalSecrets/external-secrets-values.yaml @@ -0,0 +1,51 @@ +# External Secrets Operator resource configuration +# Based on Goldilocks recommendations (Burstable QoS) + +podSecurityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + seccompProfile: + type: RuntimeDefault + +# Main controller +resources: + requests: + cpu: 15m + memory: 192Mi + limits: + cpu: 50m + memory: 256Mi + +certController: + podSecurityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + seccompProfile: + type: RuntimeDefault + resources: + requests: + cpu: 15m + memory: 192Mi + limits: + cpu: 50m + memory: 256Mi + +webhook: + podSecurityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + seccompProfile: + type: RuntimeDefault + resources: + requests: + cpu: 15m + memory: 128Mi + limits: + cpu: 50m + memory: 256Mi diff --git a/09_ExternalSecrets/justfile b/09_ExternalSecrets/justfile new file mode 100644 index 0000000..82defb0 --- /dev/null +++ b/09_ExternalSecrets/justfile @@ -0,0 +1,65 @@ +set fallback := true + +export EXTERNAL_SECRETS_NAMESPACE := env("EXTERNAL_SECRETS_NAMESPACE", "external-secrets") +export EXTERNAL_SECRETS_CHART_VERSION := env("EXTERNAL_SECRETS_CHART_VERSION", "1.1.0") +export EXTERNAL_SECRETS_REFRESH_INTERVAL := env("EXTERNAL_SECRETS_REFRESH_INTERVAL", "1800") +export K8S_VAULT_NAMESPACE := env("K8S_VAULT_NAMESPACE", "vault") +export VAULT_HOST := env("VAULT_HOST", "") +export VAULT_ADDR := "https://" + VAULT_HOST + +[private] +default: + @just --list --unsorted --list-submodules + +# Add Helm repository +add-helm-repo: + helm repo add external-secrets https://charts.external-secrets.io + helm repo update + +# Remove Helm repository +remove-helm-repo: + helm repo remove external-secrets + +# Install External Secrets +install: + just add-helm-repo + helm upgrade --cleanup-on-fail \ + --install external-secrets external-secrets/external-secrets \ + --version ${EXTERNAL_SECRETS_CHART_VERSION} -n ${EXTERNAL_SECRETS_NAMESPACE} \ + --create-namespace --wait \ + -f external-secrets-values.yaml + + kubectl label namespace ${EXTERNAL_SECRETS_NAMESPACE} \ + pod-security.kubernetes.io/enforce=restricted --overwrite + + just create-external-secrets-role + just create-vault-secret-store + +# Uninstall External Secrets +uninstall: + just delete-vault-secret-store + helm uninstall external-secrets -n ${EXTERNAL_SECRETS_NAMESPACE} --wait + kubectl delete namespace ${EXTERNAL_SECRETS_NAMESPACE} --ignore-not-found + +# Create Vault Secret Store for External Secrets +create-vault-secret-store: + gomplate -f ./vault-secret-store.gomplate.yaml | kubectl apply -f - + +# Delete Vault Secret Store for External Secrets +delete-vault-secret-store: + gomplate -f ./vault-secret-store.gomplate.yaml | kubectl delete --ignore-not-found -f - + +# Create Vault role for External Secrets +create-external-secrets-role root_token='': + #!/bin/bash + set -euo pipefail + export VAULT_TOKEN="{{ root_token }}" + while [ -z "${VAULT_TOKEN}" ]; do + VAULT_TOKEN=$(gum input --prompt="Vault root token: " --password --width=100) + done + vault write auth/kubernetes/role/external-secrets \ + bound_service_account_names=external-secrets \ + bound_service_account_namespaces=${EXTERNAL_SECRETS_NAMESPACE} \ + audience=vault \ + policies=admin \ + ttl=1h diff --git a/09_ExternalSecrets/vault-secret-store.gomplate.yaml b/09_ExternalSecrets/vault-secret-store.gomplate.yaml new file mode 100644 index 0000000..d3d5bb5 --- /dev/null +++ b/09_ExternalSecrets/vault-secret-store.gomplate.yaml @@ -0,0 +1,22 @@ +apiVersion: external-secrets.io/v1 +kind: ClusterSecretStore +metadata: + name: vault-secret-store +spec: + provider: + vault: + server: http://vault.{{ .Env.K8S_VAULT_NAMESPACE }}:8200 + path: secret + version: v2 + auth: + kubernetes: + role: external-secrets + mountPath: kubernetes + serviceAccountRef: + name: external-secrets + namespace: {{ .Env.EXTERNAL_SECRETS_NAMESPACE }} + # Audience must match the audience configured in Vault Kubernetes auth role + # Required for Vault 1.21+ compatibility + audiences: + - vault + refreshInterval: {{ .Env.EXTERNAL_SECRETS_REFRESH_INTERVAL }}