# Example: Using KubeMirror with ExternalSecrets Operator # # This example demonstrates how to use KubeMirror to distribute secrets from # external secret stores (1Password, Vault, AWS Secrets Manager, etc.) across # multiple namespaces. # # KubeMirror automatically strips ownerReferences from mirrors, so you can use # the standard ExternalSecrets creationPolicy: Owner without conflicts. # # Prerequisites: # 1. ExternalSecrets Operator installed: https://external-secrets.io/ # 2. ClusterSecretStore configured for your secret backend # 3. KubeMirror installed and running # # Apply this manifest: # kubectl apply -f externalsecret-dockerconfig.yaml # # Verify: # kubectl get externalsecret 1p-docker-config -n default # kubectl get secret multi-registry-secret -n default # kubectl get secrets --all-namespaces -l kubemirror.raczylo.com/mirror=true --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: 1p-docker-config namespace: default annotations: description: "Pulls Docker registry credentials from 1Password and mirrors to all namespaces" spec: # Secret backend configuration secretStoreRef: kind: ClusterSecretStore name: 1password-homecluster # Replace with your ClusterSecretStore name # Refresh interval - how often to sync from external store refreshInterval: 24h # Target secret configuration target: # Standard ExternalSecrets setting - KubeMirror automatically strips ownerReferences from mirrors creationPolicy: Owner # Deletion policy - what happens when ExternalSecret is deleted # - Retain: Keep the secret (recommended with KubeMirror) # - Delete: Remove the secret deletionPolicy: Retain # Name of the Kubernetes secret to create name: multi-registry-secret # Template for the secret - includes KubeMirror annotations template: type: kubernetes.io/dockerconfigjson # Metadata to include in the created secret metadata: labels: # REQUIRED: Server-side filtering label for KubeMirror kubemirror.raczylo.com/enabled: "true" # Optional: Additional labels app: registry-credentials managed-by: external-secrets annotations: # REQUIRED: Enable mirroring kubemirror.raczylo.com/sync: "true" # Target namespaces - choose one of: # - Specific namespaces: "app1,app2,app3" # - Pattern matching: "app-*,prod-*" # - All namespaces: "all" # - Labeled namespaces only: "all-labeled" kubemirror.raczylo.com/target-namespaces: "all" # Optional: Add description description: "Docker registry credentials synced from 1Password" # Docker config JSON template using ExternalSecrets templating data: .dockerconfigjson: | { "auths": { "ghcr.io": { "username": "{{ .ghcrUsername | toString }}", "auth": "{{ printf "%s:%s" .ghcrUsername .ghcrPassword | b64enc }}" }, "https://index.docker.io/v1/": { "username": "{{ .dockerUsername | toString }}", "auth": "{{ printf "%s:%s" .dockerUsername .dockerPassword | b64enc }}" } } } # Data mappings - what to fetch from external secret store data: # GitHub Container Registry credentials - remoteRef: key: DockerAuth/ghcrio_username property: username # Optional: if secret has multiple properties secretKey: ghcrUsername - remoteRef: key: DockerAuth/ghcrio_password secretKey: ghcrPassword # Docker Hub credentials - remoteRef: key: DockerAuth/dockerio_username secretKey: dockerUsername - remoteRef: key: DockerAuth/dockerio_password secretKey: dockerPassword --- # Example: Using with all-labeled for opt-in mirroring apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: 1p-database-credentials namespace: shared-resources spec: secretStoreRef: kind: ClusterSecretStore name: 1password-homecluster refreshInterval: 24h target: creationPolicy: Owner # Standard setting - KubeMirror strips ownerReferences deletionPolicy: Retain name: postgres-credentials template: type: Opaque metadata: labels: kubemirror.raczylo.com/enabled: "true" annotations: kubemirror.raczylo.com/sync: "true" # Only mirror to namespaces with allow-mirrors label kubemirror.raczylo.com/target-namespaces: "all-labeled" stringData: # ExternalSecrets templating for connection strings DATABASE_URL: "postgres://{{ .username }}:{{ .password }}@postgres.shared-resources.svc:5432/mydb" DB_USER: "{{ .username }}" DB_PASSWORD: "{{ .password }}" data: - remoteRef: key: Database/postgres_username secretKey: username - remoteRef: key: Database/postgres_password secretKey: password --- # Example namespace with allow-mirrors label (for all-labeled targeting) apiVersion: v1 kind: Namespace metadata: name: production-app labels: # Opt-in to receive mirrored secrets kubemirror.raczylo.com/allow-mirrors: "true" environment: production --- # Alternative ClusterSecretStore examples for different backends # Uncomment and configure based on your secret backend # # AWS Secrets Manager # apiVersion: external-secrets.io/v1beta1 # kind: ClusterSecretStore # metadata: # name: aws-secrets-manager # spec: # provider: # aws: # service: SecretsManager # region: us-west-2 # auth: # jwt: # serviceAccountRef: # name: external-secrets # namespace: external-secrets # # HashiCorp Vault # apiVersion: external-secrets.io/v1beta1 # kind: ClusterSecretStore # metadata: # name: vault-backend # spec: # provider: # vault: # server: "https://vault.example.com" # path: "secret" # version: "v2" # auth: # kubernetes: # mountPath: "kubernetes" # role: "external-secrets" # serviceAccountRef: # name: external-secrets # namespace: external-secrets # # Google Secret Manager # apiVersion: external-secrets.io/v1beta1 # kind: ClusterSecretStore # metadata: # name: google-secret-manager # spec: # provider: # gcpsm: # projectID: "my-project-id" # auth: # workloadIdentity: # clusterLocation: us-central1 # clusterName: my-cluster # serviceAccountRef: # name: external-secrets # namespace: external-secrets