├── CNAME ├── terraform ├── gcp │ ├── secrets │ │ └── .gitkeep │ ├── provider_variables.tf │ ├── provider.tf │ ├── eso_gcp_modules │ │ ├── network │ │ │ ├── variable.tf │ │ │ └── main.tf │ │ └── gke │ │ │ └── variable.tf │ ├── variable.tf │ └── main.tf └── aws │ ├── modules │ └── cluster │ │ ├── provider.tf │ │ ├── variables.tf │ │ └── auth.tf │ ├── main.tf │ ├── provider.tf │ ├── variables.tf │ └── outputs.tf ├── .github ├── FUNDING.yml ├── ci │ └── ct.yaml ├── dependabot.yml ├── workflows │ ├── docs.yml │ ├── ok-to-test.yml │ └── ok-to-test-managed.yml └── issue_template.md ├── deploy ├── charts │ └── external-secrets │ │ ├── ci │ │ └── main-values.yaml │ │ ├── templates │ │ ├── crds │ │ │ └── README.md │ │ ├── webhook-secret.yaml │ │ ├── NOTES.txt │ │ ├── serviceaccount.yaml │ │ ├── webhook-serviceaccount.yaml │ │ ├── cert-controller-serviceaccount.yaml │ │ ├── service.yaml │ │ ├── cert-controller-service.yaml │ │ ├── webhook-service.yaml │ │ ├── validatingwebhook.yaml │ │ └── cert-controller-rbac.yaml │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ └── README.md.gotmpl └── manifests │ ├── helm-values.yaml │ └── README.md ├── docs ├── artifacthub-repo.yml ├── pictures │ ├── cs_logo.png │ ├── godaddy_logo.png │ ├── eso-az-kv-aws-sm.png │ ├── eso-az-kv-azure-kv.png │ ├── screenshot_API_key.png │ ├── screenshot_region.png │ ├── screenshot_user_OCID.png │ ├── diagrams-provider-vault.png │ ├── screenshot_api_keys_iam.png │ ├── screenshot_fingerprint.png │ ├── screenshot_gitlab_token.png │ ├── screenshot_service_url.png │ ├── screenshot_tenancy_OCID.png │ ├── diagrams-resource-mapping.png │ ├── diagrams-high-level-simple.png │ ├── screenshot_api_keys_create.png │ ├── screenshot_api_keys_iam_left.png │ ├── screenshot_gitlab_projectID.png │ ├── diagrams-high-level-ns-detail.png │ ├── diagrams-multi-tenancy-shared.png │ ├── screenshot_ssh_privkey_example.png │ ├── screenshot_api_keys_create_button.png │ ├── screenshot_gitlab_token_created.png │ ├── diagrams-high-level-cluster-detail.png │ ├── diagrams-multi-tenancy-self-service.png │ ├── diagrams-multi-tenancy-managed-store.png │ ├── diagrams-provider-aws-auth-secret-ref.png │ ├── screenshot_api_keys_create_successful.png │ ├── screenshot_docker_config_json_example.png │ ├── screenshot_gitops_final_directory_tree.png │ ├── screenshot_ssl_certificate_p12_example.png │ ├── diagrams-provider-aws-auth-pod-identity.png │ ├── screenshot_json_string_gcp_secret_value.png │ ├── diagrams-provider-aws-auth-service-account.png │ └── diagrams-provider-aws-ssm-parameter-store.png ├── snippets │ ├── gitops │ │ ├── namespace.yaml │ │ ├── crs │ │ │ ├── kustomization.yaml │ │ │ └── clusterSecretStore.yaml │ │ ├── secret-token.yaml │ │ ├── deployment-crds.yaml │ │ ├── deployment-crs.yaml │ │ ├── kustomization.yaml │ │ ├── repositories.yaml │ │ └── deployment.yaml │ ├── gcpsm-pod-wi-secret-store.yaml │ ├── oracle-credentials-secret.yaml │ ├── gitlab-credentials-secret.yaml │ ├── fake-provider-secret.yaml │ ├── azkv-credentials-secret.yaml │ ├── akeyless-credentials-secret.yaml │ ├── ibm-secret-store.yaml │ ├── fake-provider-es.yaml │ ├── gitlab-secret-store.yaml │ ├── oracle-external-secret.yaml │ ├── ibm-external-secret.yaml │ ├── aws-anchore-engine-access-credentials-external-secret.yaml │ ├── fake-provider-store.yaml │ ├── basic-secret-store.yaml │ ├── vault-token-store.yaml │ ├── controller-class-store.yaml │ ├── gcpsm-secret-store.yaml │ ├── gcpsm-data-from-external-secret.yaml │ ├── pkcs12-template-v2-external-secret.yaml │ ├── basic-external-secret.yaml │ ├── gcpsm-wi-secret-store.yaml │ ├── aws-sm-external-secret.yaml │ ├── gcpsm-external-secret.yaml │ ├── aws-parameter-store.yaml │ ├── azkv-secret-store-mi.yaml │ ├── ibm-es-types.yaml │ ├── gcpsm-ssh-auth-externalsecret.yaml │ ├── akeyless-secret-store.yaml │ ├── gitlab-external-secret-json.yaml │ ├── gcpsm-docker-config-externalsecret.yaml │ ├── gitlab-external-secret.yaml │ ├── akeyless-external-secret.yaml │ ├── akeyless-external-secret-json.yaml │ ├── aws-sm-store.yaml │ ├── aws-jenkins-credential-sonarqube-api-token-external-secret.yaml │ ├── vault-ldap-store.yaml │ ├── jwk-template-v2-external-secret.yaml │ ├── vault-jwt-store.yaml │ ├── pkcs12-template-v1-external-secret.yaml │ ├── gcpsm-tls-externalsecret.yaml │ ├── oracle-secret-store.yaml │ ├── aws-jenkins-credential-github-ssh-external-secret.yaml │ ├── vault-jenkins-credential-sonarqube-api-token-external-secret.yaml │ ├── aws-jenkins-credentials-harbor-chart-robot-external-secret.yaml │ ├── multiline-template-v2-external-secret.yaml │ ├── vault-approle-store.yaml │ ├── azkv-secret-store.yaml │ ├── gcpsm-credentials-secret.yaml │ ├── vault-jenkins-credential-harbor-chart-robot-external-secret.yaml │ ├── vault-jenkins-credential-github-ssh-access-external-secret.yaml │ ├── azkv-external-secret.yaml │ ├── multiline-template-v1-external-secret.yaml │ ├── template-v2-from-secret.yaml │ ├── vault-kubernetes-store.yaml │ ├── template-v1-from-secret.yaml │ └── vault-anchore-engine-access-credentials-external-secret.yaml ├── .mkdocs-exclude ├── guides-metrics.md ├── api-secretstore.md ├── guides-introduction.md ├── api-clustersecretstore.md ├── eso-demos.md ├── eso-talks.md ├── guides-using-latest-image.md ├── examples-anchore-engine-credentials.md ├── provider-fake.md ├── guides-controller-class.md ├── guides-all-keys-one-secret.md └── api-externalsecret.md ├── assets ├── CS_logo_1.png ├── round_eso_logo.png └── Godaddylogo_2020.png ├── pkg ├── template │ ├── v2 │ │ ├── _testdata │ │ │ ├── foo-nopass.pfx │ │ │ ├── foo-withpass-1234.pfx │ │ │ ├── foo-disjunct-nopass.pfx │ │ │ ├── foo-multibag-nopass.pfx │ │ │ ├── root-ca.key │ │ │ ├── disjunct-root-ca.key │ │ │ ├── foo.key │ │ │ ├── intermediate-ca.key │ │ │ ├── root-ca.crt │ │ │ ├── disjunct-root-ca.crt │ │ │ ├── intermediate-ca.crt │ │ │ ├── foo.crt │ │ │ ├── intermediate-chain.pem │ │ │ ├── disjunct-chain.pem │ │ │ └── chain.pem │ │ ├── jwk.go │ │ └── pem.go │ └── engine.go └── provider │ ├── aws │ ├── util │ │ ├── errors.go │ │ ├── errors_test.go │ │ └── provider.go │ ├── parameterstore │ │ └── fake │ │ │ └── fake.go │ └── auth │ │ ├── resolver_test.go │ │ ├── fake │ │ └── assumeroler.go │ │ ├── token_fetcher.go │ │ ├── resolver.go │ │ └── token_fetcher_test.go │ ├── alibaba │ └── fake │ │ └── fake.go │ ├── yandex │ └── lockbox │ │ └── client │ │ └── client.go │ ├── oracle │ └── fake │ │ └── fake.go │ ├── akeyless │ └── fake │ │ └── fake.go │ ├── register │ └── register.go │ ├── gitlab │ └── fake │ │ └── fake.go │ └── ibm │ └── fake │ └── fake.go ├── overrides └── main.html ├── e2e ├── k8s │ ├── vault-config │ │ └── vault-policy-es.hcl │ ├── localstack.values.yaml │ └── vault.values.yaml ├── kind.yaml ├── framework │ └── log │ │ └── log.go ├── Dockerfile ├── suite │ ├── import.go │ ├── oracle │ │ └── oracle.go │ ├── azure │ │ ├── azure_secret.go │ │ └── azure_cert.go │ ├── aws │ │ ├── parameterstore │ │ │ └── parameterstore.go │ │ └── secretsmanager │ │ │ └── secretsmanager.go │ ├── alibaba │ │ └── alibaba.go │ ├── akeyless │ │ └── akeyless.go │ └── gitlab │ │ └── gitlab.go ├── e2e_test.go ├── entrypoint.sh └── Makefile ├── Dockerfile ├── tools.go ├── ADOPTERS.md ├── hack ├── api-docs │ ├── requirements.txt │ ├── Dockerfile │ ├── config.json │ ├── pkg.tpl │ ├── members.tpl │ └── generate.sh └── boilerplate.go.txt ├── changelog.json ├── PROJECT ├── apis ├── doc.go ├── externalsecrets │ ├── doc.go │ ├── v1beta1 │ │ ├── externalsecret_conversion.go │ │ ├── doc.go │ │ ├── externalsecret_webhook.go │ │ ├── secretstore_conversion.go │ │ ├── secretstore_fake_types.go │ │ ├── secretstore_webhook.go │ │ ├── secretstore_ibm_types.go │ │ ├── secretstore_gitlab_types.go │ │ ├── secretstore_alibaba_types.go │ │ ├── secretstore_akeyless_types.go │ │ ├── secretstore_yandexlockbox_types.go │ │ ├── secretstore_gcpsm_types.go │ │ └── secretstore_oracle_types.go │ └── v1alpha1 │ │ ├── doc.go │ │ ├── externalsecret_webhook.go │ │ ├── secretstore_webhook.go │ │ ├── secretstore_fake_types.go │ │ ├── secretstore_ibm_types.go │ │ ├── secretstore_gitlab_types.go │ │ ├── secretstore_alibaba_types.go │ │ ├── secretstore_akeyless_types.go │ │ ├── secretstore_yandexlockbox_types.go │ │ ├── secretstore_gcpsm_types.go │ │ └── secretstore_oracle_types.go └── meta │ ├── doc.go │ └── v1 │ ├── doc.go │ └── types.go ├── .editorconfig ├── main.go ├── SECURITY.md ├── .gitignore └── design └── 000-template.md /CNAME: -------------------------------------------------------------------------------- 1 | external-secrets.io 2 | -------------------------------------------------------------------------------- /terraform/gcp/secrets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | open_collective: external-secrets-org 2 | -------------------------------------------------------------------------------- /deploy/charts/external-secrets/ci/main-values.yaml: -------------------------------------------------------------------------------- 1 | image: 2 | tag: main 3 | -------------------------------------------------------------------------------- /docs/artifacthub-repo.yml: -------------------------------------------------------------------------------- 1 | repositoryID: 0be51c62-4e1d-47d5-b586-3662456e2a89 2 | -------------------------------------------------------------------------------- /assets/CS_logo_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/assets/CS_logo_1.png -------------------------------------------------------------------------------- /assets/round_eso_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/assets/round_eso_logo.png -------------------------------------------------------------------------------- /docs/pictures/cs_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/cs_logo.png -------------------------------------------------------------------------------- /assets/Godaddylogo_2020.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/assets/Godaddylogo_2020.png -------------------------------------------------------------------------------- /docs/pictures/godaddy_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/godaddy_logo.png -------------------------------------------------------------------------------- /docs/snippets/gitops/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: external-secrets 5 | -------------------------------------------------------------------------------- /docs/pictures/eso-az-kv-aws-sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/eso-az-kv-aws-sm.png -------------------------------------------------------------------------------- /docs/pictures/eso-az-kv-azure-kv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/eso-az-kv-azure-kv.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_API_key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_API_key.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_region.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_region.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_user_OCID.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_user_OCID.png -------------------------------------------------------------------------------- /terraform/gcp/provider_variables.tf: -------------------------------------------------------------------------------- 1 | variable "credentials_path" { 2 | default = "secrets/gcloud-service-account-key.json" 3 | } 4 | -------------------------------------------------------------------------------- /docs/.mkdocs-exclude: -------------------------------------------------------------------------------- 1 | .mkdocs-exclude 2 | .nojekyll 3 | .placeholder 4 | search/search_index.json 5 | sitemap.xml.gz 6 | sitemap.xml 7 | -------------------------------------------------------------------------------- /docs/pictures/diagrams-provider-vault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/diagrams-provider-vault.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_api_keys_iam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_api_keys_iam.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_fingerprint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_fingerprint.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_gitlab_token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_gitlab_token.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_service_url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_service_url.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_tenancy_OCID.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_tenancy_OCID.png -------------------------------------------------------------------------------- /pkg/template/v2/_testdata/foo-nopass.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/pkg/template/v2/_testdata/foo-nopass.pfx -------------------------------------------------------------------------------- /docs/pictures/diagrams-resource-mapping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/diagrams-resource-mapping.png -------------------------------------------------------------------------------- /deploy/manifests/helm-values.yaml: -------------------------------------------------------------------------------- 1 | fullnameOverride: external-secrets 2 | 3 | resources: 4 | requests: 5 | cpu: 10m 6 | memory: 32Mi 7 | -------------------------------------------------------------------------------- /docs/pictures/diagrams-high-level-simple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/diagrams-high-level-simple.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_api_keys_create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_api_keys_create.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_api_keys_iam_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_api_keys_iam_left.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_gitlab_projectID.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_gitlab_projectID.png -------------------------------------------------------------------------------- /.github/ci/ct.yaml: -------------------------------------------------------------------------------- 1 | chart-dirs: 2 | - deploy/charts 3 | helm-extra-args: "--timeout=5m" 4 | check-version-increment: false 5 | target-branch: main 6 | -------------------------------------------------------------------------------- /docs/pictures/diagrams-high-level-ns-detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/diagrams-high-level-ns-detail.png -------------------------------------------------------------------------------- /docs/pictures/diagrams-multi-tenancy-shared.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/diagrams-multi-tenancy-shared.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_ssh_privkey_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_ssh_privkey_example.png -------------------------------------------------------------------------------- /pkg/template/v2/_testdata/foo-withpass-1234.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/pkg/template/v2/_testdata/foo-withpass-1234.pfx -------------------------------------------------------------------------------- /docs/pictures/screenshot_api_keys_create_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_api_keys_create_button.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_gitlab_token_created.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_gitlab_token_created.png -------------------------------------------------------------------------------- /pkg/template/v2/_testdata/foo-disjunct-nopass.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/pkg/template/v2/_testdata/foo-disjunct-nopass.pfx -------------------------------------------------------------------------------- /pkg/template/v2/_testdata/foo-multibag-nopass.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/pkg/template/v2/_testdata/foo-multibag-nopass.pfx -------------------------------------------------------------------------------- /docs/pictures/diagrams-high-level-cluster-detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/diagrams-high-level-cluster-detail.png -------------------------------------------------------------------------------- /docs/pictures/diagrams-multi-tenancy-self-service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/diagrams-multi-tenancy-self-service.png -------------------------------------------------------------------------------- /docs/pictures/diagrams-multi-tenancy-managed-store.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/diagrams-multi-tenancy-managed-store.png -------------------------------------------------------------------------------- /docs/pictures/diagrams-provider-aws-auth-secret-ref.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/diagrams-provider-aws-auth-secret-ref.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_api_keys_create_successful.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_api_keys_create_successful.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_docker_config_json_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_docker_config_json_example.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_gitops_final_directory_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_gitops_final_directory_tree.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_ssl_certificate_p12_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_ssl_certificate_p12_example.png -------------------------------------------------------------------------------- /docs/snippets/gitops/crs/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - clusterSecretStore.yaml 6 | -------------------------------------------------------------------------------- /pkg/template/v2/_testdata/root-ca.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MC4CAQAwBQYDK2VwBCIEICJ7FAxZXElbLQe/yrvr+ZqYQHKf9oGtzsasBZ8a32nk 3 | -----END PRIVATE KEY----- 4 | -------------------------------------------------------------------------------- /docs/pictures/diagrams-provider-aws-auth-pod-identity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/diagrams-provider-aws-auth-pod-identity.png -------------------------------------------------------------------------------- /docs/pictures/screenshot_json_string_gcp_secret_value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/screenshot_json_string_gcp_secret_value.png -------------------------------------------------------------------------------- /docs/pictures/diagrams-provider-aws-auth-service-account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/diagrams-provider-aws-auth-service-account.png -------------------------------------------------------------------------------- /docs/pictures/diagrams-provider-aws-ssm-parameter-store.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zen/external-secrets/main/docs/pictures/diagrams-provider-aws-ssm-parameter-store.png -------------------------------------------------------------------------------- /pkg/template/v2/_testdata/disjunct-root-ca.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MC4CAQAwBQYDK2VwBCIEIDWjPU0WTbgryudXkq5qduRP5utcq8yEsmYPizQ0J1vW 3 | -----END PRIVATE KEY----- 4 | -------------------------------------------------------------------------------- /docs/snippets/gcpsm-pod-wi-secret-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: example 5 | spec: 6 | provider: 7 | gcpsm: 8 | projectID: pid 9 | -------------------------------------------------------------------------------- /docs/snippets/oracle-credentials-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: oracle-secret 5 | labels: 6 | type: oracle 7 | type: Opaque 8 | stringData: 9 | privateKey: 10 | fingerprint: -------------------------------------------------------------------------------- /docs/snippets/gitlab-credentials-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: gitlab-secret 5 | labels: 6 | type: gitlab 7 | type: Opaque 8 | stringData: 9 | token: "**access token goes here**" 10 | -------------------------------------------------------------------------------- /overrides/main.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block outdated %} 4 | You're not viewing the latest version. 5 | 6 | Click here to go to latest. 7 | 8 | {% endblock %} -------------------------------------------------------------------------------- /terraform/aws/modules/cluster/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = "~> 3.0" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /e2e/k8s/vault-config/vault-policy-es.hcl: -------------------------------------------------------------------------------- 1 | path "secret/+/*" { 2 | capabilities = ["create", "read", "update", "delete", "list"] 3 | } 4 | 5 | path "secret_v1/+/*" { 6 | capabilities = ["create", "read", "update", "delete", "list"] 7 | } 8 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcr.io/distroless/static 2 | ARG TARGETOS 3 | ARG TARGETARCH 4 | COPY bin/external-secrets-${TARGETOS}-${TARGETARCH} /bin/external-secrets 5 | 6 | # Run as UID for nobody 7 | USER 65534 8 | 9 | ENTRYPOINT ["/bin/external-secrets"] 10 | -------------------------------------------------------------------------------- /tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | // +build tools 3 | 4 | package tools 5 | 6 | import ( 7 | _ "github.com/ahmetb/gen-crd-api-reference-docs" 8 | _ "github.com/onsi/ginkgo/v2/ginkgo" 9 | _ "sigs.k8s.io/controller-tools/cmd/controller-gen" 10 | ) 11 | -------------------------------------------------------------------------------- /terraform/aws/main.tf: -------------------------------------------------------------------------------- 1 | module "cluster" { 2 | source = "./modules/cluster" 3 | 4 | cluster_name = var.AWS_CLUSTER_NAME 5 | cluster_region = var.AWS_REGION 6 | irsa_sa_name = var.AWS_SA_NAME 7 | irsa_sa_namespace = var.AWS_SA_NAMESPACE 8 | } 9 | -------------------------------------------------------------------------------- /terraform/aws/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13" 3 | 4 | backend "s3" { 5 | bucket = "eso-e2e-aws-tfstate" 6 | key = "aws-tfstate" 7 | region = "eu-west-1" 8 | } 9 | 10 | required_providers {} 11 | } 12 | -------------------------------------------------------------------------------- /docs/snippets/gitops/secret-token.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: vault-token-global 5 | namespace: external-secrets 6 | stringData: 7 | # This token must be patched by overlays. Not here for security reasons 8 | token: change-me-placeholder 9 | -------------------------------------------------------------------------------- /pkg/template/v2/_testdata/foo.key: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIMuAjEwBeXznOjx3V7viagAznflfL+p64CXkm++xlXhkoAoGCCqGSM49 3 | AwEHoUQDQgAEqnxdeInykx8JZsLi13rZLekoG2cosQ3F+2InVNy7hCQ7soMqdaJs 4 | GQ6LFtovogUFtOOTRWrunblqNWGZsowHbA== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /deploy/charts/external-secrets/templates/crds/README.md: -------------------------------------------------------------------------------- 1 | # CRD Template Directory 2 | CRDs are autogenerated during helm packaging. To install the CRDs set `installCRDS: true` during helm install or upgrade. 3 | 4 | The latest CRDs in the repository are located [here](../../../../crds). 5 | -------------------------------------------------------------------------------- /e2e/k8s/localstack.values.yaml: -------------------------------------------------------------------------------- 1 | image: 2 | tag: "0.12.14" 3 | service: 4 | type: ClusterIP 5 | edgeService: 6 | targetPort: 80 7 | debug: true 8 | extraEnvVars: 9 | - name: EDGE_PORT 10 | value: "80" 11 | - name: SERVICES 12 | value: "secretsmanager,ssm,sts" 13 | -------------------------------------------------------------------------------- /pkg/template/v2/_testdata/intermediate-ca.key: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIIYmlQRczt7PR7VN9jjKf5MGcgKHgohcBbrPbikYVWNqoAoGCCqGSM49 3 | AwEHoUQDQgAE3pHcl+nGXtAI5pnt+t00KFp60MF5wEc3lhH+BUUBPARloH/M+8JY 4 | 46W+DOEuH/giQGGGP+sd/FJ5bMVxHgU6Hw== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /terraform/aws/variables.tf: -------------------------------------------------------------------------------- 1 | variable "AWS_SA_NAME" { 2 | type = string 3 | } 4 | 5 | variable "AWS_SA_NAMESPACE" { 6 | type = string 7 | } 8 | 9 | variable "AWS_REGION" { 10 | type = string 11 | } 12 | 13 | variable "AWS_CLUSTER_NAME" { 14 | type = string 15 | } 16 | -------------------------------------------------------------------------------- /docs/snippets/fake-provider-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: secret-to-be-created 5 | namespace: default 6 | data: 7 | foo_bar: SEVMTE8x # HELLO1 (via data) 8 | foo: ZXhhbXBsZQ== # example (via dataFrom) 9 | other: dGhpbmc= # thing (via dataFrom) 10 | -------------------------------------------------------------------------------- /terraform/aws/outputs.tf: -------------------------------------------------------------------------------- 1 | output "cluster_arn" { 2 | value = module.cluster.cluster_arn 3 | } 4 | 5 | output "cluster_iam_role_arn" { 6 | value = module.cluster.cluster_iam_role_arn 7 | } 8 | 9 | output "aws_auth_configmap_yaml" { 10 | value = module.cluster.aws_auth_configmap_yaml 11 | } 12 | -------------------------------------------------------------------------------- /docs/guides-metrics.md: -------------------------------------------------------------------------------- 1 | # Metrics 2 | 3 | The External Secrets Operator exposes its Prometheus metrics in the `/metrics` path. To enable it, set the `prometheus.enabled` Helm flag to `true`. 4 | 5 | The Operator has the metrics inherited from Kubebuilder plus some custom metrics with the `external_secret` prefix. -------------------------------------------------------------------------------- /docs/api-secretstore.md: -------------------------------------------------------------------------------- 1 | ![SecretStore](./pictures/diagrams-high-level-ns-detail.png) 2 | 3 | 4 | The `SecretStore` is namespaced and specifies how to access the external API. 5 | The SecretStore maps to exactly one instance of an external API. 6 | 7 | ``` yaml 8 | {% include 'full-secret-store.yaml' %} 9 | ``` 10 | -------------------------------------------------------------------------------- /docs/snippets/azkv-credentials-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: azure-secret-sp 5 | type: Opaque 6 | data: 7 | ClientID: bXktc2VydmljZS1wcmluY2lwbGUtY2xpZW50LWlkCg== #service-principal-ID 8 | ClientSecret: bXktc2VydmljZS1wcmluY2lwbGUtY2xpZW50LXNlY3JldAo= #service-principal-secret 9 | -------------------------------------------------------------------------------- /terraform/aws/modules/cluster/variables.tf: -------------------------------------------------------------------------------- 1 | variable "cluster_name" { 2 | type = string 3 | default = "eso-e2e-managed" 4 | } 5 | 6 | variable "irsa_sa_name" { 7 | type = string 8 | } 9 | 10 | variable "irsa_sa_namespace" { 11 | type = string 12 | } 13 | 14 | variable "cluster_region" { 15 | type = string 16 | } 17 | -------------------------------------------------------------------------------- /deploy/charts/external-secrets/templates/webhook-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: {{ include "external-secrets.fullname" . }}-webhook 5 | namespace: {{ .Release.Namespace | quote }} 6 | labels: 7 | {{- include "external-secrets-webhook.labels" . | nindent 4 }} 8 | external-secrets.io/component : webhook 9 | -------------------------------------------------------------------------------- /docs/guides-introduction.md: -------------------------------------------------------------------------------- 1 | # Guides 2 | 3 | The following guides demonstrate use-cases and provide examples of how to use 4 | the API. Please pick one of the following guides: 5 | 6 | * [Getting started](guides-getting-started.md) 7 | * [Advanced Templating](guides-templating.md) 8 | * [Multi-Tenancy Design Considerations](guides-multi-tenancy.md) 9 | -------------------------------------------------------------------------------- /docs/snippets/gitops/deployment-crds.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 3 | kind: Kustomization 4 | metadata: 5 | name: external-secrets-crds 6 | namespace: flux-system 7 | spec: 8 | interval: 10m 9 | path: ./deploy/crds 10 | prune: true 11 | sourceRef: 12 | kind: GitRepository 13 | name: external-secrets 14 | -------------------------------------------------------------------------------- /docs/snippets/akeyless-credentials-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: akeylss-secret-creds 5 | type: Opaque 6 | stringData: 7 | accessId: "p-XXXX" 8 | accessType: # k8s/aws_iam/gcp/azure_ad/api_key 9 | accessTypeParam: # can be one of the following: k8s-conf-name/gcp-audience/azure-obj-id/access-key 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/api-clustersecretstore.md: -------------------------------------------------------------------------------- 1 | ![ClusterSecretStore](./pictures/diagrams-high-level-cluster-detail.png) 2 | 3 | The `ClusterSecretStore` is a cluster scoped SecretStore that can be referenced by all 4 | `ExternalSecrets` from all namespaces. Use it to offer a central gateway to your secret backend. 5 | 6 | ``` yaml 7 | {% include 'full-cluster-secret-store.yaml' %} 8 | ``` 9 | -------------------------------------------------------------------------------- /ADOPTERS.md: -------------------------------------------------------------------------------- 1 | # External Secrets Operator Adopters 2 | 3 | 4 | 5 | - [Polarpoint](https://www.polarpoint.io/) 6 | - [Pento](https://www.pento.io/) 7 | - [Mixpanel](https://mixpanel.com) 8 | - [K8S Website Infra](https://k8s.io/) 9 | 10 | 11 | Countless others that can't disclose that information! :) 12 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "gomod" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: "weekly" 12 | 13 | - package-ecosystem: "docker" 14 | directory: "/" 15 | schedule: 16 | interval: "weekly" 17 | -------------------------------------------------------------------------------- /terraform/gcp/provider.tf: -------------------------------------------------------------------------------- 1 | provider "google" { 2 | project = "external-secrets-operator" 3 | region = "europe-west1" 4 | zone = "europe-west1-b" 5 | credentials = file(var.credentials_path) 6 | } 7 | 8 | provider "google-beta" { 9 | project = "external-secrets-operator" 10 | region = "europe-west1" 11 | zone = "europe-west1-b" 12 | credentials = file(var.credentials_path) 13 | } 14 | -------------------------------------------------------------------------------- /deploy/charts/external-secrets/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | external-secrets has been deployed successfully! 2 | 3 | In order to begin using ExternalSecrets, you will need to set up a SecretStore 4 | or ClusterSecretStore resource (for example, by creating a 'vault' SecretStore). 5 | 6 | More information on the different types of SecretStores and how to configure them 7 | can be found in our Github: {{ .Chart.Home }} 8 | -------------------------------------------------------------------------------- /docs/snippets/ibm-secret-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: secretstore-sample 5 | spec: 6 | provider: 7 | ibm: 8 | serviceUrl: "https://SECRETS_MANAGER_ID.REGION.secrets-manager.appdomain.cloud" 9 | auth: 10 | secretRef: 11 | secretApiKeySecretRef: 12 | name: ibm-secret 13 | key: apiKey 14 | -------------------------------------------------------------------------------- /hack/api-docs/requirements.txt: -------------------------------------------------------------------------------- 1 | Click==8.0.3 2 | htmlmin==0.1.12 3 | Jinja2==3.0.3 4 | jsmin==3.0.1 5 | livereload==2.6.3 6 | Markdown==3.3.6 7 | MarkupSafe==2.0.1 8 | mkdocs==1.2.3 9 | mike==1.1.2 10 | mkdocs-material==8.1.10 11 | mkdocs-minify-plugin==0.5.0 12 | pep562==1.1 13 | Pygments==2.11.2 14 | pymdown-extensions==9.1 15 | PyYAML==6.0 16 | six==1.16.0 17 | tornado==6.1 18 | mkdocs-macros-plugin==0.6.4 19 | -------------------------------------------------------------------------------- /terraform/gcp/eso_gcp_modules/network/variable.tf: -------------------------------------------------------------------------------- 1 | variable "env" { 2 | default = "dev" 3 | } 4 | variable "ip_cidr_range" { 5 | default = "10.69.0.0/16" 6 | } 7 | variable "ip_pod_range" { 8 | default = "10.70.0.0/16" 9 | } 10 | variable "ip_service_range" { 11 | default = "10.71.0.0/16" 12 | } 13 | variable "region" { 14 | default = "europe-west1" 15 | } 16 | variable "project_id" { 17 | type = string 18 | } 19 | -------------------------------------------------------------------------------- /docs/snippets/gitops/deployment-crs.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 3 | kind: Kustomization 4 | metadata: 5 | name: external-secrets-crs 6 | namespace: flux-system 7 | spec: 8 | dependsOn: 9 | - name: external-secrets-crds 10 | interval: 10m 11 | path: ./infrastructure/external-secrets/crs 12 | prune: true 13 | sourceRef: 14 | kind: GitRepository 15 | name: flux-system 16 | -------------------------------------------------------------------------------- /docs/snippets/fake-provider-es.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ExternalSecret 3 | metadata: 4 | name: example 5 | spec: 6 | refreshInterval: 1h 7 | secretStoreRef: 8 | name: fake 9 | kind: ClusterSecretStore 10 | target: 11 | name: secret-to-be-created 12 | data: 13 | - secretKey: foo_bar 14 | remoteRef: 15 | key: /foo/bar 16 | version: v1 17 | dataFrom: 18 | - key: /foo/baz -------------------------------------------------------------------------------- /docs/snippets/gitlab-secret-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: gitlab-secret-store 5 | spec: 6 | provider: 7 | # provider type: gitlab 8 | gitlab: 9 | # url: https://gitlab.mydomain.com/ 10 | auth: 11 | SecretRef: 12 | accessToken: 13 | name: gitlab-secret 14 | key: token 15 | projectID: "**project ID goes here**" -------------------------------------------------------------------------------- /docs/snippets/oracle-external-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ExternalSecret 3 | metadata: 4 | name: example 5 | spec: 6 | refreshInterval: 0.03m 7 | secretStoreRef: 8 | kind: SecretStore 9 | name: example # Must match SecretStore on the cluster 10 | target: 11 | name: secret-to-be-created # Name for the secret on the cluster 12 | creationPolicy: Owner 13 | dataFrom: 14 | - key: the-secret-name 15 | -------------------------------------------------------------------------------- /docs/snippets/ibm-external-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ExternalSecret 3 | metadata: 4 | name: external-secret-sample 5 | spec: 6 | refreshInterval: 1m 7 | secretStoreRef: 8 | name: secretstore-sample 9 | kind: SecretStore 10 | target: 11 | name: secret-to-be-created 12 | creationPolicy: Owner 13 | data: 14 | - secretKey: test 15 | remoteRef: 16 | key: xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 17 | -------------------------------------------------------------------------------- /docs/snippets/aws-anchore-engine-access-credentials-external-secret.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: anchore-access-credentials 6 | namespace: ci 7 | spec: 8 | refreshInterval: 1m 9 | secretStoreRef: 10 | name: cluster-secrets-store 11 | kind: ClusterSecretStore 12 | target: 13 | name: anchore-access-credentials 14 | dataFrom: 15 | - key: service/anchore-engine/engineAccess 16 | -------------------------------------------------------------------------------- /docs/snippets/fake-provider-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ClusterSecretStore 3 | metadata: 4 | name: fake 5 | spec: 6 | provider: 7 | fake: 8 | data: 9 | - key: "/foo/bar" 10 | value: "HELLO1" 11 | version: "v1" 12 | - key: "/foo/bar" 13 | value: "HELLO2" 14 | version: "v2" 15 | - key: "/foo/baz" 16 | valueMap: 17 | foo: example 18 | other: thing 19 | 20 | 21 | -------------------------------------------------------------------------------- /deploy/charts/external-secrets/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "external-secrets.serviceAccountName" . }} 6 | namespace: {{ .Release.Namespace | quote }} 7 | labels: 8 | {{- include "external-secrets.labels" . | nindent 4 }} 9 | {{- with .Values.serviceAccount.annotations }} 10 | annotations: 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | {{- end }} 14 | -------------------------------------------------------------------------------- /docs/eso-demos.md: -------------------------------------------------------------------------------- 1 | # ESO Demos 2 | 3 | A list of demos given by people going through simple setups with ESO. Feel free to let us know if you have a demo that you want to include here! 4 | 5 | ## GCP SM + AWS SM + Azure Key Vault Demo 6 | 7 | This was an old demo going through an old version of ESO. Most of it is still valid, but beware of CRD and breaking change differences. 8 | 9 | [![GCP SM + AWS SM + Azure Key Vault Demo](https://img.youtube.com/vi/L6tn1YdMkF8/0.jpg)](https://www.youtube.com/watch?v=L6tn1YdMkF8) -------------------------------------------------------------------------------- /changelog.json: -------------------------------------------------------------------------------- 1 | { 2 | "categories": [], 3 | "ignore_labels": [], 4 | "sort": "ASC", 5 | "template": "## Changes\n\n${{UNCATEGORIZED}}", 6 | "pr_template": "- ${{TITLE}}", 7 | "empty_template": "- no changes", 8 | "label_extractor": [], 9 | "transformers": [], 10 | "max_tags_to_fetch": 200, 11 | "max_pull_requests": 200, 12 | "max_back_track_time_days": 365, 13 | "exclude_merge_branches": [], 14 | "tag_resolver": { 15 | "method": "semver" 16 | }, 17 | "base_branches": [] 18 | } 19 | -------------------------------------------------------------------------------- /docs/snippets/basic-secret-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: secretstore-sample 5 | spec: 6 | provider: 7 | aws: 8 | service: SecretsManager 9 | region: us-east-1 10 | auth: 11 | secretRef: 12 | accessKeyIDSecretRef: 13 | name: awssm-secret 14 | key: access-key 15 | secretAccessKeySecretRef: 16 | name: awssm-secret 17 | key: secret-access-key 18 | -------------------------------------------------------------------------------- /e2e/kind.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | kubeadmConfigPatches: 4 | - | 5 | kind: ClusterConfiguration 6 | apiServer: 7 | extraArgs: 8 | api-audiences: "sts.amazonaws.com" 9 | service-account-key-file: "/etc/kubernetes/pki/sa.pub" 10 | service-account-signing-key-file: "/etc/kubernetes/pki/sa.key" 11 | service-account-issuer: "https://s3-XXXXXXXXXX.amazonaws.com/XXXXXXXXXXXXXXXXXXXXX" 12 | nodes: 13 | - role: control-plane 14 | - role: worker 15 | - role: worker 16 | -------------------------------------------------------------------------------- /docs/snippets/vault-token-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: vault-backend 5 | namespace: example 6 | spec: 7 | provider: 8 | vault: 9 | server: "https://vault.acme.org" 10 | path: "secret" 11 | version: "v2" 12 | auth: 13 | # points to a secret that contains a vault token 14 | # https://www.vaultproject.io/docs/auth/token 15 | tokenSecretRef: 16 | name: "my-secret" 17 | key: "vault-token" 18 | -------------------------------------------------------------------------------- /pkg/template/v2/_testdata/root-ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBJzCB2qADAgECAhEArvunrLoYXTmwMROkmbAlBTAFBgMrZXAwEjEQMA4GA1UE 3 | AxMHcm9vdC1jYTAeFw0yMjAyMDkxMDI1MzBaFw0zMjAyMDcxMDI1MzBaMBIxEDAO 4 | BgNVBAMTB3Jvb3QtY2EwKjAFBgMrZXADIQDSw5uQ1io+jcKevCH0sl+tGTB6/BQs 5 | Bu84ibw13QoP36NFMEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8C 6 | AQEwHQYDVR0OBBYEFGtn1GnNjmd6cxOhMnVau1L8IkGtMAUGAytlcANBAOHSAS4z 7 | /6ctcvRwlGr9Hyt7vVLROImD2t3rFdDDHLLL1znikK3JZvVbETyMFOMbOMQS33C/ 8 | 4FtLGenZFXySjQw= 9 | -----END CERTIFICATE----- 10 | -------------------------------------------------------------------------------- /deploy/charts/external-secrets/templates/webhook-serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.webhook.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "external-secrets-webhook.serviceAccountName" . }} 6 | namespace: {{ .Release.Namespace | quote }} 7 | labels: 8 | {{- include "external-secrets-webhook.labels" . | nindent 4 }} 9 | {{- with .Values.webhook.serviceAccount.annotations }} 10 | annotations: 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | {{- end }} 14 | -------------------------------------------------------------------------------- /docs/snippets/controller-class-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: controller-custom-example 5 | spec: 6 | #define the controller label to the matching value of the deployment 7 | controller: custom 8 | #configure provider the same way 9 | provider: 10 | vault: 11 | server: "http://vault.default:8200" 12 | path: "secret" 13 | version: "v2" 14 | auth: 15 | kubernetes: 16 | mountPath: "kubernetes" 17 | role: "demo-role" -------------------------------------------------------------------------------- /docs/snippets/gitops/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | # Deploy the Vault access secret 6 | - namespace.yaml 7 | - secret-token.yaml 8 | 9 | # Deploy the repositories 10 | - repositories.yaml 11 | 12 | # Deploy the CRDs 13 | - deployment-crds.yaml 14 | 15 | # Deploy the operator 16 | - deployment.yaml 17 | 18 | # Deploy default Custom Resources from 'crs' directory 19 | # INFO: This depends on the CRDs deployment. Will happen after it 20 | - deployment-crs.yaml 21 | -------------------------------------------------------------------------------- /deploy/charts/external-secrets/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | 25 | # CRD README.md 26 | templates/crds/README.md 27 | -------------------------------------------------------------------------------- /docs/snippets/gcpsm-secret-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: example 5 | spec: 6 | provider: 7 | gcpsm: # gcpsm provider 8 | auth: 9 | secretRef: 10 | secretAccessKeySecretRef: 11 | name: gcpsm-secret # secret name containing SA key 12 | key: secret-access-credentials # key name containing SA key 13 | projectID: myproject # name of Google Cloud project 14 | -------------------------------------------------------------------------------- /deploy/charts/external-secrets/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: external-secrets 3 | description: External secret management for Kubernetes 4 | type: application 5 | version: "0.4.4" 6 | appVersion: "v0.4.4" 7 | kubeVersion: ">= 1.11.0-0" 8 | keywords: 9 | - kubernetes-external-secrets 10 | - secrets 11 | home: https://github.com/external-secrets/external-secrets 12 | icon: https://raw.githubusercontent.com/external-secrets/external-secrets/main/assets/round_eso_logo.png 13 | maintainers: 14 | - name: mcavoyk 15 | email: kellinmcavoy@gmail.com 16 | -------------------------------------------------------------------------------- /docs/snippets/gcpsm-data-from-external-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ExternalSecret 3 | metadata: 4 | name: example 5 | spec: 6 | refreshInterval: 1h # rate SecretManager pulls GCPSM 7 | secretStoreRef: 8 | kind: SecretStore 9 | name: example # name of the SecretStore (or kind specified) 10 | target: 11 | name: secret-to-be-created # name of the k8s Secret to be created 12 | creationPolicy: Owner 13 | dataFrom: 14 | - key: all-keys-example-secret # name of the GCPSM secret 15 | -------------------------------------------------------------------------------- /pkg/template/v2/_testdata/disjunct-root-ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBOTCB7KADAgECAhEA0cArEY0s5JoP8JfqIDv2BTAFBgMrZXAwGzEZMBcGA1UE 3 | AxMQZGlzanVuY3Qtcm9vdC1jYTAeFw0yMjAyMDkxMDI1MzBaFw0zMjAyMDcxMDI1 4 | MzBaMBsxGTAXBgNVBAMTEGRpc2p1bmN0LXJvb3QtY2EwKjAFBgMrZXADIQAJER3w 5 | QFZH1DBmxZm9IkaZ5noangcg/CYNP+GtcyQPL6NFMEMwDgYDVR0PAQH/BAQDAgEG 6 | MBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFMddJG4lWXTN/x9InsiJUTxu 7 | d4+HMAUGAytlcANBABcyLV4om9LPV0TGDf0jiM+JxH1R+ATvAE8FHDtd8L66BrzA 8 | Id656nPz3fz9ZMB9VZr7iGcghXYlTHxu6NkQEgA= 9 | -----END CERTIFICATE----- 10 | -------------------------------------------------------------------------------- /deploy/charts/external-secrets/templates/cert-controller-serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.certController.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "external-secrets-cert-controller.serviceAccountName" . }} 6 | namespace: {{ .Release.Namespace | quote }} 7 | labels: 8 | {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} 9 | {{- with .Values.certController.serviceAccount.annotations }} 10 | annotations: 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | {{- end }} 14 | -------------------------------------------------------------------------------- /docs/snippets/pkcs12-template-v2-external-secret.yaml: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: template 6 | spec: 7 | # ... 8 | target: 9 | template: 10 | type: kubernetes.io/tls 11 | engineVersion: v2 12 | data: 13 | tls.crt: "{{ .mysecret | pkcs12cert }}" 14 | tls.key: "{{ .mysecret | pkcs12key }}" 15 | 16 | # if needed unlock the pkcs12 with the password 17 | tls.crt: "{{ .mysecret | pkcs12certPass "my-password" }}" 18 | 19 | {% endraw %} 20 | -------------------------------------------------------------------------------- /docs/snippets/gitops/crs/clusterSecretStore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ClusterSecretStore 3 | metadata: 4 | name: vault-backend-global 5 | spec: 6 | provider: 7 | vault: 8 | server: "https://vault.your-domain.com" 9 | path: secret 10 | version: v2 11 | auth: 12 | # points to a secret that contains a vault token 13 | # https://www.vaultproject.io/docs/auth/token 14 | tokenSecretRef: 15 | name: "vault-token-global" 16 | key: "token" 17 | namespace: external-secrets 18 | -------------------------------------------------------------------------------- /docs/snippets/gitops/repositories.yaml: -------------------------------------------------------------------------------- 1 | # Reference to Helm repository 2 | apiVersion: source.toolkit.fluxcd.io/v1beta1 3 | kind: HelmRepository 4 | metadata: 5 | name: external-secrets 6 | namespace: flux-system 7 | spec: 8 | interval: 10m 9 | url: https://charts.external-secrets.io 10 | --- 11 | apiVersion: source.toolkit.fluxcd.io/v1beta1 12 | kind: GitRepository 13 | metadata: 14 | name: external-secrets 15 | namespace: flux-system 16 | spec: 17 | interval: 10m 18 | ref: 19 | branch: main 20 | url: http://github.com/external-secrets/external-secrets 21 | -------------------------------------------------------------------------------- /docs/snippets/basic-external-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ExternalSecret 3 | metadata: 4 | name: example 5 | spec: 6 | refreshInterval: 1h 7 | secretStoreRef: 8 | name: secretstore-sample 9 | kind: SecretStore 10 | target: 11 | name: secret-to-be-created 12 | creationPolicy: Owner 13 | data: 14 | - secretKey: secret-key-to-be-managed 15 | remoteRef: 16 | key: provider-key 17 | version: provider-key-version 18 | property: provider-key-property 19 | dataFrom: 20 | - key: remote-key-in-the-provider 21 | -------------------------------------------------------------------------------- /docs/snippets/gcpsm-wi-secret-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ClusterSecretStore 3 | metadata: 4 | name: example 5 | spec: 6 | provider: 7 | gcpsm: 8 | projectID: my-project 9 | auth: 10 | workloadIdentity: 11 | # name of the cluster region 12 | clusterLocation: europe-central2 13 | # name of the GKE cluster 14 | clusterName: example-workload-identity 15 | # reference the sa from above 16 | serviceAccountRef: 17 | name: team-a 18 | namespace: team-a 19 | -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ -------------------------------------------------------------------------------- /docs/snippets/aws-sm-external-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ExternalSecret 3 | metadata: 4 | name: example 5 | spec: 6 | refreshInterval: 1m 7 | secretStoreRef: 8 | name: secretstore-sample 9 | kind: SecretStore 10 | target: 11 | name: secret-to-be-created 12 | creationPolicy: Owner 13 | data: 14 | - secretKey: firstname 15 | remoteRef: 16 | key: my-json-secret 17 | property: name.first # Tom 18 | - secretKey: first_friend 19 | remoteRef: 20 | key: my-json-secret 21 | property: friends.1.first # Roger 22 | -------------------------------------------------------------------------------- /docs/snippets/gcpsm-external-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ExternalSecret 3 | metadata: 4 | name: example 5 | spec: 6 | refreshInterval: 1h # rate SecretManager pulls GCPSM 7 | secretStoreRef: 8 | kind: SecretStore 9 | name: example # name of the SecretStore (or kind specified) 10 | target: 11 | name: secret-to-be-created # name of the k8s Secret to be created 12 | creationPolicy: Owner 13 | data: 14 | - secretKey: dev-secret-test # name of the GCPSM secret key 15 | remoteRef: 16 | key: dev-secret-test 17 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | env: 8 | # Common versions 9 | GO_VERSION: '1.17' 10 | 11 | jobs: 12 | deploy: 13 | runs-on: ubuntu-18.04 14 | steps: 15 | - uses: actions/checkout@v3 16 | with: 17 | fetch-depth: 0 18 | 19 | - name: Setup Go 20 | uses: actions/setup-go@v2 21 | with: 22 | go-version: ${{ env.GO_VERSION }} 23 | 24 | - name: Build Docs 25 | run: make docs.publish 26 | env: 27 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" -------------------------------------------------------------------------------- /docs/snippets/aws-parameter-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: secretstore-sample 5 | spec: 6 | provider: 7 | aws: 8 | service: ParameterStore 9 | # define a specific role to limit access 10 | # to certain secrets 11 | role: iam-role 12 | region: eu-central-1 13 | auth: 14 | secretRef: 15 | accessKeyIDSecretRef: 16 | name: awssm-secret 17 | key: access-key 18 | secretAccessKeySecretRef: 19 | name: awssm-secret 20 | key: secret-access-key 21 | -------------------------------------------------------------------------------- /PROJECT: -------------------------------------------------------------------------------- 1 | domain: io 2 | multigroup: true 3 | repo: github.com/external-secrets/external-secrets 4 | resources: 5 | - group: external-secrets 6 | kind: ClusterSecretStore 7 | version: v1alpha1 8 | - group: external-secrets 9 | kind: SecretStore 10 | version: v1alpha1 11 | - group: external-secrets 12 | kind: ExternalSecret 13 | version: v1alpha1 14 | - group: external-secrets 15 | kind: ClusterSecretStore 16 | version: v1beta1 17 | - group: external-secrets 18 | kind: SecretStore 19 | version: v1beta1 20 | - group: external-secrets 21 | kind: ExternalSecret 22 | version: v1beta1 23 | version: "3" 24 | -------------------------------------------------------------------------------- /docs/snippets/azkv-secret-store-mi.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: example-secret-store 5 | spec: 6 | provider: 7 | # provider type: azure keyvault 8 | azurekv: 9 | authType: ManagedIdentity 10 | # Optionally set the Id of the Managed Identity, if multiple identities are assigned to external-secrets operator 11 | identityId: "" 12 | # URL of your vault instance, see: https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates 13 | vaultUrl: "https://my-keyvault-name.vault.azure.net" 14 | -------------------------------------------------------------------------------- /docs/snippets/ibm-es-types.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ExternalSecret 3 | metadata: 4 | name: ibm-sample 5 | spec: 6 | # [...] 7 | data: 8 | - secretKey: test 9 | remoteRef: 10 | # defaults to type=arbitrary 11 | key: xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 12 | - secretKey: foo 13 | remoteRef: 14 | key: username_password/yyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy 15 | - secretKey: bar 16 | remoteRef: 17 | key: iam_credentials/zzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz 18 | - secretKey: baz 19 | remoteRef: 20 | key: imported_cert/zzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz 21 | -------------------------------------------------------------------------------- /docs/snippets/gcpsm-ssh-auth-externalsecret.yaml: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: ssh-auth-example 6 | spec: 7 | refreshInterval: 1h 8 | secretStoreRef: 9 | name: example 10 | kind: SecretStore 11 | target: 12 | name: secret-to-be-created 13 | template: 14 | type: kubernetes.io/ssh-auth 15 | data: 16 | ssh-privatekey: "{{ .mysecret | toString }}" 17 | name: secret-to-be-created 18 | creationPolicy: Owner 19 | data: 20 | - secretKey: mysecret 21 | remoteRef: 22 | key: ssh-priv-key-example 23 | {% endraw %} 24 | -------------------------------------------------------------------------------- /docs/snippets/akeyless-secret-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: akeyless-secret-store 5 | spec: 6 | provider: 7 | akeyless: 8 | # URL of your akeyless API 9 | akeylessGWApiURL: "https://api.akeyless.io" 10 | authSecretRef: 11 | secretRef: 12 | accessID: 13 | name: akeylss-secret-creds 14 | key: accessId 15 | accessType: 16 | name: akeylss-secret-creds 17 | key: accessType 18 | accessTypeParam: 19 | name: akeylss-secret-creds 20 | key: accessTypeParam 21 | -------------------------------------------------------------------------------- /docs/snippets/gitlab-external-secret-json.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ExternalSecret 3 | metadata: 4 | name: gitlab-external-secret-example 5 | spec: 6 | refreshInterval: 1h 7 | 8 | secretStoreRef: 9 | kind: SecretStore 10 | name: gitlab-secret-store # Must match SecretStore on the cluster 11 | 12 | target: 13 | name: gitlab-secret-to-create # Name for the secret to be created on the cluster 14 | creationPolicy: Owner 15 | 16 | # each secret name in the KV will be used as the secret key in the SECRET k8s target object 17 | dataFrom: 18 | - key: "myJsonVariable" # Key of the variable on Gitlab -------------------------------------------------------------------------------- /docs/snippets/gcpsm-docker-config-externalsecret.yaml: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: dk-cfg-example 6 | spec: 7 | refreshInterval: 1h 8 | secretStoreRef: 9 | name: example 10 | kind: SecretStore 11 | target: 12 | name: secret-to-be-created 13 | template: 14 | type: kubernetes.io/dockerconfigjson 15 | data: 16 | .dockerconfigjson: "{{ .mysecret | toString }}" 17 | name: secret-to-be-created 18 | creationPolicy: Owner 19 | data: 20 | - secretKey: mysecret 21 | remoteRef: 22 | key: docker-config-example 23 | {% endraw %} 24 | -------------------------------------------------------------------------------- /docs/snippets/gitlab-external-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ExternalSecret 3 | metadata: 4 | name: gitlab-external-secret-example 5 | spec: 6 | refreshInterval: 1h 7 | 8 | secretStoreRef: 9 | kind: SecretStore 10 | name: gitlab-secret-store # Must match SecretStore on the cluster 11 | 12 | target: 13 | name: gitlab-secret-to-create # Name for the secret to be created on the cluster 14 | creationPolicy: Owner 15 | 16 | data: 17 | - secretKey: secretKey # Key given to the secret to be created on the cluster 18 | remoteRef: 19 | key: myGitlabVariable # Key of the variable on Gitlab -------------------------------------------------------------------------------- /apis/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | // 16 | // +domain=external-secrets.io 17 | 18 | package apis 19 | -------------------------------------------------------------------------------- /docs/snippets/akeyless-external-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ExternalSecret 3 | metadata: 4 | name: akeyless-external-secret-example 5 | spec: 6 | refreshInterval: 1h 7 | 8 | secretStoreRef: 9 | kind: SecretStore 10 | name: akeyless-secret-store # Must match SecretStore on the cluster 11 | 12 | target: 13 | name: akeyless-secret-to-create # Name for the secret to be created on the cluster 14 | creationPolicy: Owner 15 | 16 | data: 17 | - secretKey: secretKey # Key given to the secret to be created on the cluster 18 | remoteRef: 19 | key: secret-name # Full path of the secret on Akeyless 20 | -------------------------------------------------------------------------------- /pkg/template/v2/_testdata/intermediate-ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBgDCCATKgAwIBAgIRAOzjpCdp42oW5MoccLpRXpAwBQYDK2VwMBIxEDAOBgNV 3 | BAMTB3Jvb3QtY2EwHhcNMjIwMjA5MTAyNTMxWhcNMzIwMjA3MTAyNTMxWjAaMRgw 4 | FgYDVQQDEw9pbnRlcm1lZGlhdGUtY2EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC 5 | AATekdyX6cZe0Ajmme363TQoWnrQwXnARzeWEf4FRQE8BGWgf8z7wljjpb4M4S4f 6 | +CJAYYY/6x38UnlsxXEeBTofo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/ 7 | BAgwBgEB/wIBADAdBgNVHQ4EFgQUIuDzQn9tkFs535jz5X3iXnEzbMQwHwYDVR0j 8 | BBgwFoAUa2fUac2OZ3pzE6EydVq7UvwiQa0wBQYDK2VwA0EA4gntaGs/3ME6q1y9 9 | gO4ntri2qwoC25l3q7q9BiFBmeBmvS6I1w9HCZHtB3JnVC/IYDTCYDNTbpGWEOjl 10 | aCKLCA== 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | 9 | # Go 10 | # https://golang.org/cmd/gofmt/ 11 | [{go.mod,*.go}] 12 | indent_style = tab 13 | 14 | # Shell 15 | # https://google.github.io/styleguide/shell.xml#Indentation 16 | [*.{bash,sh,zsh}] 17 | indent_size = 2 18 | indent_style = space 19 | 20 | # GNU make 21 | # https://www.gnu.org/software/make/manual/html_node/Recipe-Syntax.html 22 | [Makefile] 23 | indent_style = tab 24 | 25 | # YAML 26 | # http://yaml.org/spec/1.2/2009-07-21/spec.html#id2576668 27 | [*.{yaml,yml}] 28 | indent_size = 2 29 | indent_style = space 30 | -------------------------------------------------------------------------------- /apis/externalsecrets/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | // +groupName=external-secrets.io 16 | 17 | package externalsecrets 18 | -------------------------------------------------------------------------------- /apis/meta/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | // Package meta contains meta types for external-secret APIs. 16 | package meta 17 | -------------------------------------------------------------------------------- /docs/snippets/akeyless-external-secret-json.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ExternalSecret 3 | metadata: 4 | name: akeyless-external-secret-example-json 5 | spec: 6 | refreshInterval: 1h 7 | 8 | secretStoreRef: 9 | kind: SecretStore 10 | name: akeyless-secret-store # Must match SecretStore on the cluster 11 | 12 | target: 13 | name: akeyless-secret-to-create-json # Name for the secret to be created on the cluster 14 | creationPolicy: Owner 15 | 16 | # for json formatted secrets: each key in the json will be used as the secret key in the SECRET k8s target object 17 | dataFrom: 18 | - key: secret-name # Full path of the secret on Akeyless 19 | -------------------------------------------------------------------------------- /docs/snippets/aws-sm-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: secretstore-sample 5 | spec: 6 | provider: 7 | aws: 8 | service: SecretsManager 9 | # define a specific role to limit access 10 | # to certain secrets. 11 | # role is a optional field that 12 | # can be omitted for test purposes 13 | role: iam-role 14 | region: eu-central-1 15 | auth: 16 | secretRef: 17 | accessKeyIDSecretRef: 18 | name: awssm-secret 19 | key: access-key 20 | secretAccessKeySecretRef: 21 | name: awssm-secret 22 | key: secret-access-key 23 | -------------------------------------------------------------------------------- /deploy/charts/external-secrets/templates/service.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.prometheus.enabled }} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: {{ include "external-secrets.fullname" . }}-metrics 6 | labels: 7 | {{- include "external-secrets.labels" . | nindent 4 }} 8 | annotations: 9 | prometheus.io/path: "/metrics" 10 | prometheus.io/scrape: "true" 11 | prometheus.io/port: {{ .Values.prometheus.service.port | quote }} 12 | spec: 13 | type: ClusterIP 14 | ports: 15 | - port: {{ .Values.prometheus.service.port }} 16 | protocol: TCP 17 | name: metrics 18 | selector: 19 | {{- include "external-secrets.selectorLabels" . | nindent 4 }} 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /pkg/template/v2/_testdata/foo.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBqjCCAU+gAwIBAgIRAPnGGsBUMbZhmh5QdnYdBmUwCgYIKoZIzj0EAwIwGjEY 3 | MBYGA1UEAxMPaW50ZXJtZWRpYXRlLWNhMB4XDTIyMDIwOTEwMjUzMVoXDTIyMDIx 4 | MDEwMjUzMVowDjEMMAoGA1UEAxMDZm9vMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD 5 | QgAEqnxdeInykx8JZsLi13rZLekoG2cosQ3F+2InVNy7hCQ7soMqdaJsGQ6LFtov 6 | ogUFtOOTRWrunblqNWGZsowHbKOBgTB/MA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUE 7 | FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFLtundVbuKd73OWzo6SY 8 | by0Ajeb2MB8GA1UdIwQYMBaAFCLg80J/bZBbOd+Y8+V94l5xM2zEMA4GA1UdEQQH 9 | MAWCA2ZvbzAKBggqhkjOPQQDAgNJADBGAiEA4K4SbVNqrEtl7RfwBfJFMnWI+X8D 10 | zMPMc4Xqzp2qTxcCIQDsySgtiakypZfWakpB49zJph0kLwGK8xhWvGMUw1N1/w== 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /docs/snippets/aws-jenkins-credential-sonarqube-api-token-external-secret.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: sonarqube-api-token 6 | namespace: ci 7 | spec: 8 | refreshInterval: 1m 9 | secretStoreRef: 10 | name: cluster-secrets-store 11 | kind: ClusterSecretStore 12 | target: 13 | name: sonarqube-api-token 14 | template: 15 | metadata: 16 | labels: 17 | "jenkins.io/credentials-type": "secretText" 18 | annotations: 19 | "jenkins.io/credentials-description": "Sonar API token" 20 | data: 21 | - secretKey: text 22 | remoteRef: 23 | key: service/sonarqube/apiToken 24 | -------------------------------------------------------------------------------- /deploy/manifests/README.md: -------------------------------------------------------------------------------- 1 | # Deployment files 2 | 3 | The 'static deployment manifests' are generated automatically 4 | from the [official helm chart](../charts/external-secrets). 5 | 6 | When a new release of external-secrets is cut, these manifests will be 7 | automatically generated and published as an asset **attached to the GitHub release**. 8 | 9 | ## How can I generate my own manifests? 10 | 11 | If you want to build a copy of your own manifests for testing purposes, you 12 | can do so using Helm and Make. 13 | 14 | To build the manifests, run: 15 | 16 | ```bash 17 | make manifests 18 | ``` 19 | 20 | This will generate the static deployment manifests at 21 | `bin/deploy/manifests/external-secrets.yaml`. 22 | -------------------------------------------------------------------------------- /apis/meta/v1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | // Package meta contains meta types for external-secrets APIs 16 | // +kubebuilder:object:generate=true 17 | package v1 18 | -------------------------------------------------------------------------------- /docs/eso-talks.md: -------------------------------------------------------------------------------- 1 | # ESO Talks 2 | 3 | A list of talks given by people at conferences and events. Feel free to let us know if you are talking about ESO at some place! We would be happy to mention you here! 4 | 5 | ## Kubernetes Community Days UK 6 | 7 | [![Kubernetes Community Days UK](https://img.youtube.com/vi/IsoQWxw3Nk4/0.jpg)](https://www.youtube.com/watch?v=IsoQWxw3Nk4) 8 | 9 | ## CNCF Community Groups Canada 10 | 11 | [![CNCF Community Groups Canada](https://img.youtube.com/vi/CsJgfHQA0SQ/0.jpg)](https://www.youtube.com/watch?v=CsJgfHQA0SQ) 12 | 13 | ## Container Days Hamburg 14 | 15 | [![Container Days Hamburg](https://img.youtube.com/vi/_ZDkHLRYujo/0.jpg)](https://www.youtube.com/watch?v=_ZDkHLRYujo) 16 | 17 | -------------------------------------------------------------------------------- /docs/snippets/vault-ldap-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: vault-backend 5 | namespace: example 6 | spec: 7 | provider: 8 | vault: 9 | server: "https://vault.acme.org" 10 | path: "secret" 11 | version: "v2" 12 | auth: 13 | # VaultLdap authenticates with Vault using the LDAP auth mechanism 14 | # https://www.vaultproject.io/docs/auth/ldap 15 | ldap: 16 | # Path where the LDAP authentication backend is mounted 17 | path: "ldap" 18 | # LDAP username 19 | username: "username" 20 | secretRef: 21 | name: "my-secret" 22 | key: "ldap-password" 23 | -------------------------------------------------------------------------------- /docs/snippets/jwk-template-v2-external-secret.yaml: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: template 6 | spec: 7 | # ... 8 | target: 9 | template: 10 | engineVersion: v2 11 | data: 12 | # .myjwk is a json-encoded JWK string. 13 | # 14 | # this template will produce for jwk_pub a PEM encoded public key: 15 | # -----BEGIN PUBLIC KEY----- 16 | # MIIBI... 17 | # ... 18 | # ...AQAB 19 | # -----END PUBLIC KEY----- 20 | jwk_pub: "{{ .myjwk | jwkPublicKeyPem }}" 21 | # private key is a pem-encoded PKCS#8 private key 22 | jwk_priv: "{{ .myjwk | jwkPrivateKeyPem }}" 23 | 24 | 25 | {% endraw %} 26 | -------------------------------------------------------------------------------- /docs/snippets/vault-jwt-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: vault-backend 5 | namespace: example 6 | spec: 7 | provider: 8 | vault: 9 | server: "https://vault.acme.org" 10 | path: "secret" 11 | version: "v2" 12 | auth: 13 | # VaultJwt authenticates with Vault using the JWT/OIDC auth mechanism 14 | # https://www.vaultproject.io/docs/auth/jwt 15 | jwt: 16 | # Path where the JWT authentication backend is mounted 17 | path: "jwt" 18 | # JWT role configured in a Vault server, optional. 19 | role: "vault-jwt-role" 20 | secretRef: 21 | name: "my-secret" 22 | key: "jwt-token" 23 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2022 ESO Maintainer Team 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package main 17 | 18 | import "github.com/external-secrets/external-secrets/cmd" 19 | 20 | func main() { 21 | cmd.Execute() 22 | } 23 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1beta1/externalsecret_conversion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1beta1 16 | 17 | func (*ExternalSecret) Hub() { 18 | // This empty method defines the Hub convertible interface. 19 | } 20 | -------------------------------------------------------------------------------- /docs/snippets/pkcs12-template-v1-external-secret.yaml: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: template 6 | spec: 7 | refreshInterval: 1h 8 | secretStoreRef: 9 | name: secretstore-sample 10 | kind: SecretStore 11 | target: 12 | name: secret-to-be-created 13 | # this is how the Kind=Secret will look like 14 | template: 15 | type: kubernetes.io/tls 16 | data: 17 | tls.crt: "{{ .mysecret | pkcs12cert | pemCertificate }}" 18 | tls.key: "{{ .mysecret | pkcs12key | pemPrivateKey }}" 19 | 20 | data: 21 | # this is a pkcs12 archive that contains 22 | # a cert and a private key 23 | - secretKey: mysecret 24 | remoteRef: 25 | key: example 26 | {% endraw %} 27 | -------------------------------------------------------------------------------- /deploy/charts/external-secrets/templates/cert-controller-service.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.certController.prometheus.enabled }} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics 6 | labels: 7 | {{- include "external-secrets.labels" . | nindent 4 }} 8 | annotations: 9 | prometheus.io/path: "/metrics" 10 | prometheus.io/scrape: "true" 11 | prometheus.io/port: {{ .Values.certController.prometheus.service.port | quote }} 12 | spec: 13 | type: ClusterIP 14 | ports: 15 | - port: {{ .Values.certController.prometheus.service.port }} 16 | protocol: TCP 17 | name: metrics 18 | selector: 19 | {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 4 }} 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /docs/snippets/gcpsm-tls-externalsecret.yaml: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: template-tls-example 6 | spec: 7 | refreshInterval: 1h 8 | secretStoreRef: 9 | name: example 10 | kind: SecretStore 11 | target: 12 | name: secret-to-be-created 13 | # this is how the Kind=Secret will look like 14 | template: 15 | type: kubernetes.io/tls 16 | data: 17 | tls.crt: "{{ .mysecret | pkcs12cert | pemCertificate }}" 18 | tls.key: "{{ .mysecret | pkcs12key | pemPrivateKey }}" 19 | 20 | data: 21 | # this is a pkcs12 archive that contains 22 | # a cert and a private key 23 | - secretKey: mysecret 24 | remoteRef: 25 | key: ssl-certificate-p12-example 26 | {% endraw %} 27 | -------------------------------------------------------------------------------- /docs/guides-using-latest-image.md: -------------------------------------------------------------------------------- 1 | You can test a feature that was not yet released using the following method, use it at your own discretion: 2 | 3 | 1. Create a `values.yaml` file with the following content: 4 | 5 | ``` 6 | replicaCount: 1 7 | 8 | image: 9 | repository: ghcr.io/external-secrets/external-secrets 10 | pullPolicy: IfNotPresent 11 | # -- The image tag to use. The default is the chart appVersion. 12 | tag: "main" 13 | 14 | # -- If set, install and upgrade CRDs through helm chart. 15 | installCRDs: false 16 | ``` 17 | 18 | 2. Install the crds 19 | ``` 20 | make crds.install 21 | ``` 22 | 23 | 3. Install the external-secrets Helm chart indicating the values file created before: 24 | ``` 25 | helm install external-secrets external-secrets/external-secrets -f values.yaml 26 | ``` -------------------------------------------------------------------------------- /apis/externalsecrets/v1beta1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | // Package v1beta1 contains resources for external-secrets 16 | // +kubebuilder:object:generate=true 17 | // +groupName=external-secrets.io 18 | // +versionName=v1beta1 19 | package v1beta1 20 | -------------------------------------------------------------------------------- /terraform/gcp/variable.tf: -------------------------------------------------------------------------------- 1 | variable "env" { default = "test" } 2 | variable "region" { default = "europe-west1" } 3 | variable "zone" { default = "europe-west1-b" } 4 | variable "horizontal_pod_autoscaling" { default = false } 5 | variable "node_count" { default = 2 } 6 | variable "node_min_count" { default = 2 } 7 | variable "node_max_count" { default = 2 } 8 | variable "initial_node_count" { default = 2 } 9 | variable "max_scale" { default = "10" } 10 | variable "ip_cidr_range" { default = "10.69.0.0/16" } 11 | variable "ip-pod-range" { default = "10.70.0.0/16" } 12 | variable "ip_service_range" { default = "10.71.0.0/16" } 13 | variable "preemptible" { default = true } 14 | variable "GCP_PROJECT_ID" {type = string} 15 | variable "GCP_GSA_NAME" {type = string} 16 | variable "GCP_KSA_NAME" {type = string} 17 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | // Package v1alpha1 contains resources for external-secrets 16 | // +kubebuilder:object:generate=true 17 | // +groupName=external-secrets.io 18 | // +versionName=v1alpha1 19 | package v1alpha1 20 | -------------------------------------------------------------------------------- /docs/snippets/oracle-secret-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: example-instance-principal 5 | spec: 6 | provider: 7 | oracle: 8 | vault: # The vault OCID 9 | region: # The vault region 10 | 11 | --- 12 | 13 | apiVersion: external-secrets.io/v1alpha1 14 | kind: SecretStore 15 | metadata: 16 | name: example-auth 17 | spec: 18 | provider: 19 | oracle: 20 | vault: # The vault OCID 21 | region: # The vault region 22 | auth: 23 | user: # A user OCID 24 | tenancy: # A user's tenancy 25 | secretRef: 26 | privatekey: 27 | name: oracle-secret 28 | key: privateKey 29 | fingerprint: 30 | name: oracle-secret 31 | key: fingerprint 32 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | - [Security Policy](#security-policy) 4 | - [Reporting security problems](#reporting-security-problems) 5 | - [Vulnerability Management Plans](#vulnerability-management-plans) 6 | - [Critical Updates And Security Notices](#critical-updates-and-security-notices) 7 | 8 | 9 | ## Reporting security problems 10 | 11 | **DO NOT CREATE AN ISSUE** to report a security problem. Instead, please 12 | send an email to contact@external-secrets.io 13 | 14 | 15 | ## Vulnerability Management Plans 16 | 17 | ### Critical Updates And Security Notices 18 | 19 | We learn about critical software updates and security threats from these sources 20 | 21 | 1. GitHub Security Alerts 22 | 2. [Dependabot](https://dependabot.com/) Dependency Updates 23 | -------------------------------------------------------------------------------- /e2e/framework/log/log.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package log 15 | 16 | import ( 17 | "github.com/onsi/ginkgo/v2" 18 | ) 19 | 20 | // Logf logs the format string to ginkgo stdout. 21 | func Logf(format string, args ...interface{}) { 22 | ginkgo.GinkgoWriter.Printf(format, args) 23 | } 24 | -------------------------------------------------------------------------------- /docs/snippets/aws-jenkins-credential-github-ssh-external-secret.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: github-ssh-access 6 | namespace: ci 7 | spec: 8 | refreshInterval: 1m 9 | secretStoreRef: 10 | name: cluster-parameter-store 11 | kind: ClusterSecretStore 12 | target: 13 | name: github-ssh-access 14 | template: 15 | metadata: 16 | labels: 17 | "jenkins.io/credentials-type": "basicSSHUserPrivateKey" 18 | annotations: 19 | "jenkins.io/credentials-description": "github-ssh-access key" 20 | data: 21 | - secretKey: username 22 | remoteRef: 23 | key: /service/github/sshUserPrivateKeyUserName 24 | - secretKey: privateKey 25 | remoteRef: 26 | key: /service/github/sshUserPrivateKey 27 | 28 | -------------------------------------------------------------------------------- /docs/snippets/vault-jenkins-credential-sonarqube-api-token-external-secret.yaml: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: sonarqube-api-token 6 | namespace: ci 7 | spec: 8 | refreshInterval: 1m 9 | secretStoreRef: 10 | name: vault-backend 11 | kind: ClusterSecretStore 12 | target: 13 | name: sonarqube-api-token 14 | template: 15 | metadata: 16 | labels: 17 | "jenkins.io/credentials-type": "secretText" 18 | annotations: 19 | "jenkins.io/credentials-description": "sonarqube api token" 20 | data: 21 | text: >- 22 | {{ printf "{{ .password | toString }}" }} 23 | data: 24 | - secretKey: password 25 | remoteRef: 26 | key: jenkins-credentials 27 | property: sonarqube-api-token 28 | {% endraw %} -------------------------------------------------------------------------------- /e2e/k8s/vault.values.yaml: -------------------------------------------------------------------------------- 1 | injector: 2 | enabled: false 3 | server: 4 | extraEnvironmentVars: 5 | VAULT_CACERT: /etc/vault-config/vault-server-ca.pem 6 | VAULT_ADDR: https://127.0.0.1:8200 7 | volumeMounts: 8 | - name: tls-config 9 | mountPath: /etc/vault-config 10 | readOnly: true 11 | volumes: 12 | - name: tls-config 13 | secret: 14 | secretName: vault-tls-config 15 | standalone: 16 | config: | 17 | ui = true 18 | listener "tcp" { 19 | address = "[::]:8200" 20 | cluster_address = "[::]:8201" 21 | tls_cert_file = "/etc/vault-config/server-cert.pem" 22 | tls_key_file = "/etc/vault-config/server-cert-key.pem" 23 | tls_client_ca_file = "/etc/vault-config/vault-client-ca.pem" 24 | } 25 | storage "file" { 26 | path = "/vault/data" 27 | } 28 | -------------------------------------------------------------------------------- /docs/snippets/aws-jenkins-credentials-harbor-chart-robot-external-secret.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: harbor-chart-robot 6 | namespace: ci 7 | spec: 8 | refreshInterval: 1m 9 | secretStoreRef: 10 | name: cluster-secrets-store 11 | kind: ClusterSecretStore 12 | target: 13 | name: harbor-chart-robot 14 | template: 15 | metadata: 16 | labels: 17 | "jenkins.io/credentials-type": "usernamePassword" 18 | annotations: 19 | "jenkins.io/credentials-description": "harbor chart robot access" 20 | data: 21 | - secretKey: password 22 | remoteRef: 23 | key: service/harbor/chartRobot 24 | property: password 25 | - secretKey: username 26 | remoteRef: 27 | key: service/harbor/chartRobot 28 | property: username -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | **Describe the solution you'd like** 2 | Describe the end goal of this proposal. What is this new functionality or the new behaviour (or what problem does it fix)? 3 | 4 | **What is the added value?** 5 | Explain the value that it adds. e.g. "Secret refreshing will make internal secrets up to date with external secrets". 6 | 7 | **Give us examples of the outcome** 8 | 9 | Provide templates if you are proposing changes in the CRD. Provide example workflows or code snippets if they make sense to present. 10 | 11 | **Observations (Constraints, Context, etc):** 12 | 13 | Give here all extra information that could be interesting. Such as Golang version and Kubernetes version if you are reporting a bug/problem. You can also foresee technical constrains like "this could only be implementing using this specific technology or approach, because of this and that". 14 | -------------------------------------------------------------------------------- /docs/snippets/multiline-template-v2-external-secret.yaml: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: template 6 | spec: 7 | # ... 8 | target: 9 | name: secret-to-be-created 10 | # this is how the Kind=Secret will look like 11 | template: 12 | type: kubernetes.io/tls 13 | engineVersion: v2 14 | data: 15 | # multiline string 16 | config: | 17 | datasources: 18 | - name: Graphite 19 | type: graphite 20 | access: proxy 21 | url: http://localhost:8080 22 | password: "{{ .password }}" 23 | user: "{{ .user }}" 24 | 25 | data: 26 | - secretKey: user 27 | remoteRef: 28 | key: /grafana/user 29 | - secretKey: password 30 | remoteRef: 31 | key: /grafana/password 32 | {% endraw %} 33 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1beta1/externalsecret_webhook.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1beta1 16 | 17 | import ( 18 | ctrl "sigs.k8s.io/controller-runtime" 19 | ) 20 | 21 | func (r *ExternalSecret) SetupWebhookWithManager(mgr ctrl.Manager) error { 22 | return ctrl.NewWebhookManagedBy(mgr). 23 | For(r). 24 | Complete() 25 | } 26 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1beta1/secretstore_conversion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1beta1 16 | 17 | func (*SecretStore) Hub() { 18 | // Hub() method to be compliant with the conversion Hub interface 19 | } 20 | 21 | func (*ClusterSecretStore) Hub() { 22 | // Hub() method to be compliant with the conversion Hub interface 23 | } 24 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1alpha1/externalsecret_webhook.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1alpha1 16 | 17 | import ( 18 | ctrl "sigs.k8s.io/controller-runtime" 19 | ) 20 | 21 | func (alpha *ExternalSecret) SetupWebhookWithManager(mgr ctrl.Manager) error { 22 | return ctrl.NewWebhookManagedBy(mgr). 23 | For(alpha). 24 | Complete() 25 | } 26 | -------------------------------------------------------------------------------- /docs/snippets/vault-approle-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: vault-backend 5 | namespace: example 6 | spec: 7 | provider: 8 | vault: 9 | server: "https://vault.acme.org" 10 | path: "secret" 11 | version: "v2" 12 | auth: 13 | # VaultAppRole authenticates with Vault using the 14 | # App Role auth mechanism 15 | # https://www.vaultproject.io/docs/auth/approle 16 | appRole: 17 | # Path where the App Role authentication backend is mounted 18 | path: "approle" 19 | # RoleID configured in the App Role authentication backend 20 | roleId: "db02de05-fa39-4855-059b-67221c5c2f63" 21 | # Reference to a key in a K8 Secret that contains the App Role SecretId 22 | secretRef: 23 | name: "my-secret" 24 | key: "secret-id" 25 | -------------------------------------------------------------------------------- /docs/snippets/azkv-secret-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: example-secret-store 5 | spec: 6 | provider: 7 | # provider type: azure keyvault 8 | azurekv: 9 | # azure tenant ID, see: https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-how-to-find-tenant 10 | tenantId: "d3bc2180-xxxx-xxxx-xxxx-154105743342" 11 | # URL of your vault instance, see: https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates 12 | vaultUrl: "https://my-keyvault-name.vault.azure.net" 13 | authSecretRef: 14 | # points to the secret that contains 15 | # the azure service principal credentials 16 | clientId: 17 | name: azure-secret-sp 18 | key: ClientID 19 | clientSecret: 20 | name: azure-secret-sp 21 | key: ClientSecret 22 | -------------------------------------------------------------------------------- /hack/api-docs/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 The Kubernetes Authors. 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License. 13 | 14 | FROM alpine:3.11 15 | COPY requirements.txt / 16 | RUN apk add -U --no-cache \ 17 | python3 \ 18 | python3-dev \ 19 | musl-dev \ 20 | git \ 21 | openssh \ 22 | git-fast-import \ 23 | bash \ 24 | gcc \ 25 | diffutils \ 26 | && pip3 install -r /requirements.txt 27 | -------------------------------------------------------------------------------- /docs/snippets/gcpsm-credentials-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: gcpsm-secret 5 | labels: 6 | type: gcpsm 7 | type: Opaque 8 | stringData: 9 | secret-access-credentials: |- 10 | { 11 | "type": "service_account", 12 | "project_id": "external-secrets-operator", 13 | "private_key_id": "", 14 | "private_key": "-----BEGIN PRIVATE KEY-----\nA key\n-----END PRIVATE KEY-----\n", 15 | "client_email": "test-service-account@external-secrets-operator.iam.gserviceaccount.com", 16 | "client_id": "client ID", 17 | "auth_uri": "https://accounts.google.com/o/oauth2/auth", 18 | "token_uri": "https://oauth2.googleapis.com/token", 19 | "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", 20 | "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/test-service-account%40external-secrets-operator.iam.gserviceaccount.com" 21 | } 22 | -------------------------------------------------------------------------------- /hack/api-docs/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "hideMemberFields": [ 3 | "TypeMeta" 4 | ], 5 | "hideTypePatterns": [ 6 | "ParseError$", 7 | "List$", 8 | "^StoreProvider$" 9 | ], 10 | "externalPackages": [ 11 | { 12 | "typeMatchPrefix": "^k8s\\.io/apimachinery/pkg/apis/meta/v1\\.Time$", 13 | "docsURLTemplate": "https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#Time" 14 | }, 15 | { 16 | "typeMatchPrefix": "^k8s\\.io/(api|apimachinery/pkg/apis)/", 17 | "docsURLTemplate": "https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#{{lower .TypeIdentifier}}-{{arrIndex .PackageSegments -1}}-{{arrIndex .PackageSegments -2}}" 18 | } 19 | ], 20 | "typeDisplayNamePrefixOverrides": { 21 | "k8s.io/api/": "Kubernetes ", 22 | "k8s.io/apimachinery/pkg/apis/": "Kubernetes " 23 | }, 24 | "markdownDisabled": false 25 | } 26 | -------------------------------------------------------------------------------- /terraform/gcp/eso_gcp_modules/network/main.tf: -------------------------------------------------------------------------------- 1 | resource "google_compute_network" "env-vpc" { 2 | project = var.project_id 3 | name = "${var.env}-vpc" 4 | auto_create_subnetworks = false 5 | } 6 | 7 | resource "google_compute_subnetwork" "env-subnet" { 8 | project = var.project_id 9 | name = "${google_compute_network.env-vpc.name}-subnet" 10 | region = var.region 11 | network = google_compute_network.env-vpc.name 12 | ip_cidr_range = "10.10.0.0/24" 13 | } 14 | 15 | output "vpc-name" { 16 | value = google_compute_network.env-vpc.name 17 | } 18 | output "vpc-id" { 19 | value = google_compute_network.env-vpc.id 20 | } 21 | output "vpc-object" { 22 | value = google_compute_network.env-vpc.self_link 23 | } 24 | output "subnet-name" { 25 | value = google_compute_subnetwork.env-subnet.name 26 | } 27 | output "subnet-ip_cidr_range" { 28 | value = google_compute_subnetwork.env-subnet.ip_cidr_range 29 | } 30 | -------------------------------------------------------------------------------- /terraform/gcp/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "gcs" { 3 | bucket = "eso-infra-state" 4 | prefix = "eso-infra-state/state" 5 | credentials = "secrets/gcloud-service-account-key.json" 6 | } 7 | } 8 | 9 | module "test-network" { 10 | source = "./eso_gcp_modules/network" 11 | env = var.env 12 | region = var.region 13 | ip_cidr_range = var.ip_cidr_range 14 | project_id = var.GCP_PROJECT_ID 15 | } 16 | 17 | module "test-cluster" { 18 | source = "./eso_gcp_modules/gke" 19 | project_id = var.GCP_PROJECT_ID 20 | env = var.env 21 | region = var.region 22 | network = module.test-network.vpc-object 23 | subnetwork = module.test-network.subnet-name 24 | node_count = var.node_count 25 | initial_node_count = var.initial_node_count 26 | preemptible = true 27 | GCP_GSA_NAME = var.GCP_GSA_NAME 28 | GCP_KSA_NAME = var.GCP_KSA_NAME 29 | } 30 | -------------------------------------------------------------------------------- /pkg/provider/aws/util/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package util 16 | 17 | import ( 18 | "errors" 19 | "regexp" 20 | ) 21 | 22 | var regexReqID = regexp.MustCompile(`request id: (\S+)`) 23 | 24 | // SanitizeErr sanitizes the error string 25 | // because the requestID must not be included in the error. 26 | // otherwise the secrets keeps syncing. 27 | func SanitizeErr(err error) error { 28 | return errors.New(string(regexReqID.ReplaceAll([]byte(err.Error()), nil))) 29 | } 30 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1alpha1/secretstore_webhook.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1alpha1 16 | 17 | import ( 18 | ctrl "sigs.k8s.io/controller-runtime" 19 | ) 20 | 21 | func (c *SecretStore) SetupWebhookWithManager(mgr ctrl.Manager) error { 22 | return ctrl.NewWebhookManagedBy(mgr). 23 | For(c). 24 | Complete() 25 | } 26 | 27 | func (c *ClusterSecretStore) SetupWebhookWithManager(mgr ctrl.Manager) error { 28 | return ctrl.NewWebhookManagedBy(mgr). 29 | For(c). 30 | Complete() 31 | } 32 | -------------------------------------------------------------------------------- /deploy/charts/external-secrets/templates/webhook-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "external-secrets.fullname" . }}-webhook 5 | namespace: {{ .Release.Namespace | quote }} 6 | labels: 7 | {{- include "external-secrets-webhook.labels" . | nindent 4 }} 8 | external-secrets.io/component : webhook 9 | {{- if .Values.webhook.prometheus.enabled}} 10 | annotations: 11 | prometheus.io/path: "/metrics" 12 | prometheus.io/scrape: "true" 13 | prometheus.io/port: {{ .Values.prometheus.service.port | quote }} 14 | {{- end }} 15 | spec: 16 | type: ClusterIP 17 | ports: 18 | - port: 443 19 | targetPort: 9443 20 | protocol: TCP 21 | name: webhook 22 | {{- if .Values.webhook.prometheus.enabled}} 23 | - port: {{ .Values.webhook.prometheus.service.port}} 24 | targetPort: {{ .Values.webhook.prometheus.service.port}} 25 | protocol: TCP 26 | name: metrics 27 | {{- end }} 28 | selector: 29 | {{- include "external-secrets-webhook.selectorLabels" . | nindent 4 }} 30 | -------------------------------------------------------------------------------- /docs/snippets/gitops/deployment.yaml: -------------------------------------------------------------------------------- 1 | # How to manage values files. Ref: https://fluxcd.io/docs/guides/helmreleases/#refer-to-values-inside-the-chart 2 | # How to inject values: https://fluxcd.io/docs/guides/helmreleases/#cloud-storage 3 | --- 4 | apiVersion: helm.toolkit.fluxcd.io/v2beta1 5 | kind: HelmRelease 6 | metadata: 7 | name: external-secrets 8 | namespace: flux-system 9 | spec: 10 | # Override Release name to avoid the pattern Namespace-Release 11 | # Ref: https://fluxcd.io/docs/components/helm/api/#helm.toolkit.fluxcd.io/v2beta1.HelmRelease 12 | releaseName: external-secrets 13 | targetNamespace: external-secrets 14 | interval: 10m 15 | chart: 16 | spec: 17 | chart: external-secrets 18 | version: 0.3.9 19 | sourceRef: 20 | kind: HelmRepository 21 | name: external-secrets 22 | namespace: flux-system 23 | values: 24 | installCRDs: false 25 | 26 | # Ref: https://fluxcd.io/docs/components/helm/api/#helm.toolkit.fluxcd.io/v2beta1.Install 27 | install: 28 | createNamespace: true 29 | -------------------------------------------------------------------------------- /docs/snippets/vault-jenkins-credential-harbor-chart-robot-external-secret.yaml: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: harbor-chart-robot 6 | namespace: ci 7 | spec: 8 | refreshInterval: 1m 9 | secretStoreRef: 10 | name: vault-backend 11 | kind: ClusterSecretStore 12 | target: 13 | name: harbor-chart-robot 14 | template: 15 | metadata: 16 | labels: 17 | "jenkins.io/credentials-type": "usernamePassword" 18 | annotations: 19 | "jenkins.io/credentials-description": "harbor chart robot" 20 | data: 21 | username: >- 22 | {{ printf "{{ .username | toString }}" }} 23 | password: >- 24 | {{ printf "{{ .password | toString }}" }} 25 | data: 26 | - secretKey: username 27 | remoteRef: 28 | key: my-kv 29 | property: harbor-chart-robot-username 30 | - secretKey: password 31 | remoteRef: 32 | key: my-kv 33 | property: harbor-chart-robot-token 34 | {% endraw %} -------------------------------------------------------------------------------- /docs/snippets/vault-jenkins-credential-github-ssh-access-external-secret.yaml: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: github-ssh-access 6 | namespace: ci 7 | spec: 8 | refreshInterval: 1m 9 | secretStoreRef: 10 | name: vault-backend 11 | kind: ClusterSecretStore 12 | target: 13 | name: github-ssh-access 14 | template: 15 | metadata: 16 | labels: 17 | "jenkins.io/credentials-type": "basicSSHUserPrivateKey" 18 | annotations: 19 | "jenkins.io/credentials-description": "github-ssh-access key" 20 | data: 21 | username: >- 22 | {{ printf "{{ .username | toString }}" }} 23 | privateKey: >- 24 | {{ printf "{{ .privateKey | toString }}" }} 25 | data: 26 | - secretKey: username 27 | remoteRef: 28 | key: my-kv 29 | property: github-ssh-access-username 30 | - secretKey: privateKey 31 | remoteRef: 32 | key: my-kv 33 | property: github-ssh-access-private-key 34 | {% endraw %} -------------------------------------------------------------------------------- /apis/externalsecrets/v1alpha1/secretstore_fake_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1alpha1 16 | 17 | // FakeProvider configures a fake provider that returns static values. 18 | type FakeProvider struct { 19 | Data []FakeProviderData `json:"data"` 20 | } 21 | 22 | type FakeProviderData struct { 23 | Key string `json:"key"` 24 | Value string `json:"value,omitempty"` 25 | ValueMap map[string]string `json:"valueMap,omitempty"` 26 | Version string `json:"version,omitempty"` 27 | } 28 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1beta1/secretstore_fake_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1beta1 16 | 17 | // FakeProvider configures a fake provider that returns static values. 18 | type FakeProvider struct { 19 | Data []FakeProviderData `json:"data"` 20 | } 21 | 22 | type FakeProviderData struct { 23 | Key string `json:"key"` 24 | Value string `json:"value,omitempty"` 25 | ValueMap map[string]string `json:"valueMap,omitempty"` 26 | Version string `json:"version,omitempty"` 27 | } 28 | -------------------------------------------------------------------------------- /docs/examples-anchore-engine-credentials.md: -------------------------------------------------------------------------------- 1 | # Getting started 2 | 3 | Anchore Engine is an open-source project that provides a centralized service for inspection, analysis, and certification of container images. With Kubernetes, it also brings nice features like preventing unscanned images from being deployed into your clusters 4 | 5 | ## Installing with Helm 6 | 7 | There are several parts of the installation that require credentials these being :- 8 | 9 | ANCHORE_ADMIN_USERNAME 10 | ANCHORE_ADMIN_PASSWORD 11 | ANCHORE_DB_PASSWORD 12 | db-url 13 | db-user 14 | postgres-password 15 | 16 | 17 | Creating the following external secret ensure the credentials are drawn from the backend provider of choice. The example shown here works with Hashicorp Vault and AWS Secrets Manager providers. 18 | 19 | #### Hashicorp Vault 20 | 21 | ``` yaml 22 | {% include 'vault-anchore-engine-access-credentials-external-secret.yaml' %} 23 | ``` 24 | 25 | 26 | #### AWS Secrets Manager 27 | 28 | ``` yaml 29 | {% include 'aws-anchore-engine-access-credentials-external-secret.yaml' %} 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /docs/provider-fake.md: -------------------------------------------------------------------------------- 1 | We provide a `fake` implementation to help with testing. This provider returns static key/value pairs and nothing else. 2 | To use the `fake` provider simply create a `SecretStore` or `ClusterSecretStore` and configure it like in the following example: 3 | 4 | !!! note inline end 5 | The provider returns static data configured in `value` or `valueMap`. You can define a `version`, too. If set the `remoteRef` from an ExternalSecret must match otherwise no value is returned. 6 | 7 | ```yaml 8 | {% include 'fake-provider-store.yaml' %} 9 | ``` 10 | 11 | Please note that `value` is intended for exclusive use with `data` and `valueMap` for `dataFrom`. 12 | Here is an example `ExternalSecret` that displays this behavior: 13 | 14 | !!! warning inline end 15 | This provider supports specifying different `data[].version` configurations. However, `data[].property` is ignored. 16 | 17 | ```yaml 18 | {% include 'fake-provider-es.yaml' %} 19 | ``` 20 | 21 | This results in the following secret: 22 | 23 | 24 | ```yaml 25 | {% include 'fake-provider-secret.yaml' %} 26 | ``` 27 | -------------------------------------------------------------------------------- /docs/snippets/azkv-external-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: ExternalSecret 3 | metadata: 4 | name: example-external-secret 5 | spec: 6 | refreshInterval: 1h 7 | secretStoreRef: 8 | kind: SecretStore 9 | name: example-secret-store 10 | 11 | target: 12 | name: secret-to-be-created 13 | creationPolicy: Owner 14 | 15 | data: 16 | # name of the SECRET in the Azure KV (no prefix is by default a SECRET) 17 | - secretKey: dev-secret-test 18 | remoteRef: 19 | key: dev-secret-test 20 | 21 | # explicit type and name of secret in the Azure KV 22 | - secretKey: dev-another-secret-test 23 | remoteRef: 24 | key: secret/dev-secret-test 25 | 26 | # type/name of certificate in the Azure KV 27 | # raw value will be returned, use templating features for data processing 28 | - secretKey: dev-cert-test 29 | remoteRef: 30 | key: cert/dev-cert-test 31 | 32 | # type/name of the public key in the Azure KV 33 | # the key is returned PEM encoded 34 | - secretKey: dev-key-test 35 | remoteRef: 36 | key: key/dev-key-test 37 | 38 | -------------------------------------------------------------------------------- /docs/snippets/multiline-template-v1-external-secret.yaml: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: template 6 | spec: 7 | refreshInterval: 1h 8 | secretStoreRef: 9 | name: secretstore-sample 10 | kind: SecretStore 11 | target: 12 | name: secret-to-be-created 13 | 14 | # v1 is the default version 15 | engineVersion: v1 16 | 17 | # this is how the Kind=Secret will look like 18 | template: 19 | type: kubernetes.io/tls 20 | data: 21 | # multiline string 22 | config: | 23 | datasources: 24 | - name: Graphite 25 | type: graphite 26 | access: proxy 27 | url: http://localhost:8080 28 | password: "{{ .password | toString }}" # <-- convert []byte to string 29 | user: "{{ .user | toString }}" # <-- convert []byte to string 30 | 31 | data: 32 | - secretKey: user 33 | remoteRef: 34 | key: /grafana/user 35 | - secretKey: password 36 | remoteRef: 37 | key: /grafana/password 38 | {% endraw %} 39 | -------------------------------------------------------------------------------- /docs/snippets/template-v2-from-secret.yaml: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | # define your template in a config map 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: grafana-config-tpl 7 | data: 8 | config.yaml: | 9 | datasources: 10 | - name: Graphite 11 | type: graphite 12 | access: proxy 13 | url: http://localhost:8080 14 | password: "{{ .password }}" 15 | user: "{{ .user }}" 16 | --- 17 | apiVersion: external-secrets.io/v1alpha1 18 | kind: ExternalSecret 19 | metadata: 20 | name: my-template-example 21 | spec: 22 | # ... 23 | target: 24 | name: secret-to-be-created 25 | template: 26 | engineVersion: v2 27 | templateFrom: 28 | - configMap: 29 | # name of the configmap to pull in 30 | name: grafana-config-tpl 31 | # here you define the keys that should be used as template 32 | items: 33 | - key: config.yaml 34 | data: 35 | - secretKey: user 36 | remoteRef: 37 | key: /grafana/user 38 | - secretKey: password 39 | remoteRef: 40 | key: /grafana/password 41 | {% endraw %} 42 | -------------------------------------------------------------------------------- /e2e/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG GO_VERSION=1.17 2 | FROM golang:$GO_VERSION-buster as builder 3 | 4 | ENV KUBECTL_VERSION="v1.21.2" 5 | ENV HELM_VERSION="v3.7.1" 6 | 7 | RUN go get -u github.com/onsi/ginkgo/v2/ginkgo 8 | RUN wget -q https://storage.googleapis.com/kubernetes-release/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl -O /usr/local/bin/kubectl && \ 9 | chmod +x /usr/local/bin/kubectl && \ 10 | wget -q https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz -O - | tar -xzO linux-amd64/helm > /usr/local/bin/helm && \ 11 | chmod +x /usr/local/bin/helm 12 | 13 | FROM alpine:3.15.0 14 | RUN apk add -U --no-cache \ 15 | ca-certificates \ 16 | bash \ 17 | curl \ 18 | tzdata \ 19 | libc6-compat \ 20 | openssl 21 | 22 | COPY --from=builder /go/bin/ginkgo /usr/local/bin/ 23 | COPY --from=builder /usr/local/bin/kubectl /usr/local/bin/ 24 | COPY --from=builder /usr/local/bin/helm /usr/local/bin/ 25 | 26 | COPY entrypoint.sh /entrypoint.sh 27 | COPY e2e.test /e2e.test 28 | COPY k8s /k8s 29 | 30 | CMD [ "/entrypoint.sh" ] 31 | -------------------------------------------------------------------------------- /docs/guides-controller-class.md: -------------------------------------------------------------------------------- 1 | # Controller Classes 2 | 3 | > NOTE: this feature is experimental and not highly tested 4 | 5 | Controller classes are a proprierty set during the deployment that allows multiple controllers to work in a group of workload. It works by separating which secretStores are going to be attributed to which controller. For the behavior of a single controller, no extra configuration is needed. 6 | 7 | ## Setting up Controller Class 8 | 9 | In order to deploy the controller with a specific class, install the helm charts specifying the controller class, and create a `SecretStore` with the appropriate `spec.controller` values: 10 | ``` 11 | helm install custom-external-secrets external-secrets/external-secrets --set controllerClass=custom 12 | ``` 13 | ``` yaml 14 | {% include 'controller-class-store.yaml' %} 15 | ``` 16 | 17 | Now, any `ExternalSecret` bound to this secret store will be evaluated by the operator with the controllerClass custom. 18 | 19 | > Note: Any SecretStore without `spec.controller` set will be considered as valid by any operator, regardless of their respective controllerClasses. 20 | -------------------------------------------------------------------------------- /e2e/suite/import.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package suite 15 | 16 | import ( 17 | 18 | // import different e2e test suites. 19 | _ "github.com/external-secrets/external-secrets/e2e/suite/aws/parameterstore" 20 | _ "github.com/external-secrets/external-secrets/e2e/suite/aws/secretsmanager" 21 | _ "github.com/external-secrets/external-secrets/e2e/suite/azure" 22 | _ "github.com/external-secrets/external-secrets/e2e/suite/gcp" 23 | _ "github.com/external-secrets/external-secrets/e2e/suite/template" 24 | _ "github.com/external-secrets/external-secrets/e2e/suite/vault" 25 | ) 26 | -------------------------------------------------------------------------------- /terraform/gcp/eso_gcp_modules/gke/variable.tf: -------------------------------------------------------------------------------- 1 | variable "project_id" { 2 | default = "my-project-1475718618821" 3 | } 4 | variable "env" { 5 | default = "dev" 6 | } 7 | variable "region" { 8 | default = "europe-west1" 9 | } 10 | variable "zone" { 11 | default = "europe-west1-b" 12 | } 13 | variable "zones" { 14 | default = ["europe-west1-a", "europe-west1-b", "europe-west1-c"] 15 | } 16 | variable "network" { 17 | default = "dev-vpc" 18 | } 19 | variable "subnetwork" { 20 | default = "dev-subnetwork" 21 | } 22 | variable "ip_pod_range" { 23 | default = "dev-pod-ip-range" 24 | } 25 | variable "ip_service_range" { 26 | default = "dev-service-ip-range" 27 | } 28 | variable "horizontal_pod_autoscaling" { 29 | default = false 30 | } 31 | variable "node_count" { 32 | default = 2 33 | } 34 | variable "node_min_count" { 35 | default = 2 36 | } 37 | variable "node_max_count" { 38 | default = 2 39 | } 40 | variable "initial_node_count" { 41 | default = 2 42 | } 43 | variable "preemptible" { 44 | default = true 45 | } 46 | 47 | variable "GCP_GSA_NAME" {type = string} 48 | variable "GCP_KSA_NAME" {type = string} 49 | -------------------------------------------------------------------------------- /docs/snippets/vault-kubernetes-store.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1alpha1 2 | kind: SecretStore 3 | metadata: 4 | name: vault-backend 5 | namespace: example 6 | spec: 7 | provider: 8 | vault: 9 | server: "https://vault.acme.org" 10 | path: "secret" 11 | version: "v2" 12 | auth: 13 | # Authenticate against Vault using a Kubernetes ServiceAccount 14 | # token stored in a Secret. 15 | # https://www.vaultproject.io/docs/auth/kubernetes 16 | kubernetes: 17 | # Path where the Kubernetes authentication backend is mounted in Vault 18 | mountPath: "kubernetes" 19 | # A required field containing the Vault Role to assume. 20 | role: "demo" 21 | # Optional service account field containing the name 22 | # of a kubernetes ServiceAccount 23 | serviceAccountRef: 24 | name: "my-sa" 25 | # Optional secret field containing a Kubernetes ServiceAccount JWT 26 | # used for authenticating with Vault 27 | secretRef: 28 | name: "my-secret" 29 | key: "vault" 30 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1beta1/secretstore_webhook.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1beta1 16 | 17 | import ( 18 | ctrl "sigs.k8s.io/controller-runtime" 19 | ) 20 | 21 | func (c *SecretStore) SetupWebhookWithManager(mgr ctrl.Manager) error { 22 | return ctrl.NewWebhookManagedBy(mgr). 23 | For(c). 24 | WithValidator(&GenericStoreValidator{}). 25 | Complete() 26 | } 27 | 28 | func (c *ClusterSecretStore) SetupWebhookWithManager(mgr ctrl.Manager) error { 29 | return ctrl.NewWebhookManagedBy(mgr). 30 | For(c). 31 | WithValidator(&GenericStoreValidator{}). 32 | Complete() 33 | } 34 | -------------------------------------------------------------------------------- /pkg/template/v2/_testdata/intermediate-chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBJzCB2qADAgECAhEArvunrLoYXTmwMROkmbAlBTAFBgMrZXAwEjEQMA4GA1UE 3 | AxMHcm9vdC1jYTAeFw0yMjAyMDkxMDI1MzBaFw0zMjAyMDcxMDI1MzBaMBIxEDAO 4 | BgNVBAMTB3Jvb3QtY2EwKjAFBgMrZXADIQDSw5uQ1io+jcKevCH0sl+tGTB6/BQs 5 | Bu84ibw13QoP36NFMEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8C 6 | AQEwHQYDVR0OBBYEFGtn1GnNjmd6cxOhMnVau1L8IkGtMAUGAytlcANBAOHSAS4z 7 | /6ctcvRwlGr9Hyt7vVLROImD2t3rFdDDHLLL1znikK3JZvVbETyMFOMbOMQS33C/ 8 | 4FtLGenZFXySjQw= 9 | -----END CERTIFICATE----- 10 | -----BEGIN CERTIFICATE----- 11 | MIIBgDCCATKgAwIBAgIRAOzjpCdp42oW5MoccLpRXpAwBQYDK2VwMBIxEDAOBgNV 12 | BAMTB3Jvb3QtY2EwHhcNMjIwMjA5MTAyNTMxWhcNMzIwMjA3MTAyNTMxWjAaMRgw 13 | FgYDVQQDEw9pbnRlcm1lZGlhdGUtY2EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC 14 | AATekdyX6cZe0Ajmme363TQoWnrQwXnARzeWEf4FRQE8BGWgf8z7wljjpb4M4S4f 15 | +CJAYYY/6x38UnlsxXEeBTofo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/ 16 | BAgwBgEB/wIBADAdBgNVHQ4EFgQUIuDzQn9tkFs535jz5X3iXnEzbMQwHwYDVR0j 17 | BBgwFoAUa2fUac2OZ3pzE6EydVq7UvwiQa0wBQYDK2VwA0EA4gntaGs/3ME6q1y9 18 | gO4ntri2qwoC25l3q7q9BiFBmeBmvS6I1w9HCZHtB3JnVC/IYDTCYDNTbpGWEOjl 19 | aCKLCA== 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /docs/snippets/template-v1-from-secret.yaml: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | # define your template in a config map 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: grafana-config-tpl 7 | data: 8 | config.yaml: | 9 | datasources: 10 | - name: Graphite 11 | type: graphite 12 | access: proxy 13 | url: http://localhost:8080 14 | password: "{{ .password | toString }}" # <-- convert []byte to string 15 | user: "{{ .user | toString }}" # <-- convert []byte to string 16 | --- 17 | apiVersion: external-secrets.io/v1alpha1 18 | kind: ExternalSecret 19 | metadata: 20 | name: my-template-example 21 | spec: 22 | # ... 23 | target: 24 | name: secret-to-be-created 25 | template: 26 | templateFrom: 27 | - configMap: 28 | # name of the configmap to pull in 29 | name: grafana-config-tpl 30 | # here you define the keys that should be used as template 31 | items: 32 | - key: config.yaml 33 | data: 34 | - secretKey: user 35 | remoteRef: 36 | key: /grafana/user 37 | - secretKey: password 38 | remoteRef: 39 | key: /grafana/password 40 | {% endraw %} 41 | -------------------------------------------------------------------------------- /hack/api-docs/pkg.tpl: -------------------------------------------------------------------------------- 1 | {{ define "packages" }} 2 | 3 | {{ with .packages}} 4 |

Packages:

5 | 12 | {{ end}} 13 | 14 | {{ range .packages }} 15 |

16 | {{- packageDisplayName . -}} 17 |

18 | 19 | {{ with (index .GoPackages 0 )}} 20 | {{ with .DocComments }} 21 |

22 | {{ safe (renderComments .) }} 23 |

24 | {{ end }} 25 | {{ end }} 26 | 27 | Resource Types: 28 | 37 | 38 | {{ range (visibleTypes (sortedTypes .Types))}} 39 | {{ template "type" . }} 40 | {{ end }} 41 |
42 | {{ end }} 43 | 44 |

45 | Generated with gen-crd-api-reference-docs. 46 |

47 | 48 | {{ end }} 49 | -------------------------------------------------------------------------------- /pkg/template/engine.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | limitations under the License. 12 | */ 13 | package template 14 | 15 | import ( 16 | corev1 "k8s.io/api/core/v1" 17 | 18 | esapi "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" 19 | v1 "github.com/external-secrets/external-secrets/pkg/template/v1" 20 | v2 "github.com/external-secrets/external-secrets/pkg/template/v2" 21 | ) 22 | 23 | type ExecFunc func(tpl, data map[string][]byte, secret *corev1.Secret) error 24 | 25 | func EngineForVersion(version esapi.TemplateEngineVersion) (ExecFunc, error) { 26 | switch version { 27 | case esapi.TemplateEngineV1: 28 | return v1.Execute, nil 29 | case esapi.TemplateEngineV2: 30 | return v2.Execute, nil 31 | } 32 | 33 | // in case we run with a old v1alpha1 CRD 34 | // we must return v1 as default 35 | return v1.Execute, nil 36 | } 37 | -------------------------------------------------------------------------------- /hack/api-docs/members.tpl: -------------------------------------------------------------------------------- 1 | {{ define "members" }} 2 | 3 | {{ range .Members }} 4 | {{ if not (hiddenMember .)}} 5 | 6 | 7 | {{ fieldName . }}
8 | 9 | {{ if linkForType .Type }} 10 | 11 | {{ typeDisplayName .Type }} 12 | 13 | {{ else }} 14 | {{ typeDisplayName .Type }} 15 | {{ end }} 16 | 17 | 18 | 19 | {{ if fieldEmbedded . }} 20 |

21 | (Members of {{ fieldName . }} are embedded into this type.) 22 |

23 | {{ end}} 24 | 25 | {{ if isOptionalMember .}} 26 | (Optional) 27 | {{ end }} 28 | 29 | {{ safe (renderComments .CommentLines) }} 30 | 31 | {{ if and (eq (.Type.Name.Name) "ObjectMeta") }} 32 | Refer to the Kubernetes API documentation for the fields of the 33 | metadata field. 34 | {{ end }} 35 | 36 | {{ if or (eq (fieldName .) "spec") }} 37 |
38 |
39 | 40 | {{ template "members" .Type }} 41 |
42 | {{ end }} 43 | 44 | 45 | {{ end }} 46 | {{ end }} 47 | 48 | {{ end }} 49 | -------------------------------------------------------------------------------- /docs/guides-all-keys-one-secret.md: -------------------------------------------------------------------------------- 1 | # All Keys, One Secret 2 | 3 | To get multiple key-values from an external secret, not having to worry about how many, or what these keys are, we have to use the dataFrom field of the ExternalSecret resource, instead of the data field. We will give an example here with the gcp provider (should work with other providers in the same way). 4 | 5 | Please follow the authentication and SecretStore steps of the [Google Cloud Secrets Manager guide](provider-google-secrets-manager.md) to setup access to your google cloud account first. 6 | 7 | Then create a secret in Google Cloud Secret Manager that contains a JSON string with multiple key values like this: 8 | 9 | ![secret-value](./pictures/screenshot_json_string_gcp_secret_value.png) 10 | 11 | Let's call this secret all-keys-example-secret on Google Cloud. 12 | 13 | 14 | ### Creating dataFrom external secret 15 | 16 | Now, when creating our ExternalSecret resource, instead of using the data field, we use the dataFrom field: 17 | 18 | ```yaml 19 | {% include 'gcpsm-data-from-external-secret.yaml' %} 20 | ``` 21 | 22 | To check both values we can run: 23 | 24 | ``` 25 | kubectl get secret secret-to-be-created -n -o jsonpath='{.data.username}' | base64 -d 26 | kubectl get secret secret-to-be-created -n -o jsonpath='{.data.surname}' | base64 -d 27 | ``` 28 | -------------------------------------------------------------------------------- /.github/workflows/ok-to-test.yml: -------------------------------------------------------------------------------- 1 | # If someone with write access comments "/ok-to-test" on a pull request, emit a repository_dispatch event 2 | name: Ok To Test 3 | 4 | on: 5 | issue_comment: 6 | types: [created] 7 | 8 | jobs: 9 | ok-to-test: 10 | runs-on: ubuntu-latest 11 | # Only run for PRs, not issue comments 12 | if: ${{ github.event.issue.pull_request }} 13 | steps: 14 | # Generate a GitHub App installation access token from an App ID and private key 15 | # To create a new GitHub App: 16 | # https://developer.github.com/apps/building-github-apps/creating-a-github-app/ 17 | # See app.yml for an example app manifest 18 | - name: Generate token 19 | id: generate_token 20 | uses: tibdex/github-app-token@v1 21 | with: 22 | app_id: ${{ secrets.APP_ID }} 23 | private_key: ${{ secrets.PRIVATE_KEY }} 24 | 25 | - name: Slash Command Dispatch 26 | uses: peter-evans/slash-command-dispatch@v2.3.0 27 | env: 28 | TOKEN: ${{ steps.generate_token.outputs.token }} 29 | with: 30 | token: ${{ env.TOKEN }} # GitHub App installation access token 31 | # token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} # PAT or OAuth token will also work 32 | reaction-token: ${{ secrets.GITHUB_TOKEN }} 33 | issue-type: pull-request 34 | commands: ok-to-test 35 | permission: maintain 36 | -------------------------------------------------------------------------------- /pkg/provider/aws/parameterstore/fake/fake.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package fake 15 | 16 | import ( 17 | "fmt" 18 | 19 | "github.com/aws/aws-sdk-go/service/ssm" 20 | "github.com/google/go-cmp/cmp" 21 | ) 22 | 23 | // Client implements the aws parameterstore interface. 24 | type Client struct { 25 | valFn func(*ssm.GetParameterInput) (*ssm.GetParameterOutput, error) 26 | } 27 | 28 | func (sm *Client) GetParameter(in *ssm.GetParameterInput) (*ssm.GetParameterOutput, error) { 29 | return sm.valFn(in) 30 | } 31 | 32 | func (sm *Client) WithValue(in *ssm.GetParameterInput, val *ssm.GetParameterOutput, err error) { 33 | sm.valFn = func(paramIn *ssm.GetParameterInput) (*ssm.GetParameterOutput, error) { 34 | if !cmp.Equal(paramIn, in) { 35 | return nil, fmt.Errorf("unexpected test argument") 36 | } 37 | return val, err 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /pkg/provider/alibaba/fake/fake.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package fake 16 | 17 | import ( 18 | kmssdk "github.com/aliyun/alibaba-cloud-sdk-go/services/kms" 19 | ) 20 | 21 | type AlibabaMockClient struct { 22 | getSecretValue func(request *kmssdk.GetSecretValueRequest) (response *kmssdk.GetSecretValueResponse, err error) 23 | } 24 | 25 | func (mc *AlibabaMockClient) GetSecretValue(*kmssdk.GetSecretValueRequest) (result *kmssdk.GetSecretValueResponse, err error) { 26 | return mc.getSecretValue(&kmssdk.GetSecretValueRequest{}) 27 | } 28 | 29 | func (mc *AlibabaMockClient) WithValue(in *kmssdk.GetSecretValueRequest, val *kmssdk.GetSecretValueResponse, err error) { 30 | if mc != nil { 31 | mc.getSecretValue = func(paramIn *kmssdk.GetSecretValueRequest) (*kmssdk.GetSecretValueResponse, error) { 32 | return val, err 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /.github/workflows/ok-to-test-managed.yml: -------------------------------------------------------------------------------- 1 | # If someone with write access comments "/ok-to-test-managed" on a pull request, emit a repository_dispatch event 2 | name: Ok To Test 3 | 4 | on: 5 | issue_comment: 6 | types: [created] 7 | 8 | jobs: 9 | ok-to-test-managed: 10 | runs-on: ubuntu-latest 11 | # Only run for PRs, not issue comments 12 | if: ${{ github.event.issue.pull_request }} 13 | steps: 14 | # Generate a GitHub App installation access token from an App ID and private key 15 | # To create a new GitHub App: 16 | # https://developer.github.com/apps/building-github-apps/creating-a-github-app/ 17 | # See app.yml for an example app manifest 18 | - name: Generate token 19 | id: generate_token 20 | uses: tibdex/github-app-token@v1 21 | with: 22 | app_id: ${{ secrets.APP_ID }} 23 | private_key: ${{ secrets.PRIVATE_KEY }} 24 | 25 | - name: Slash Command Dispatch 26 | uses: peter-evans/slash-command-dispatch@v2.3.0 27 | env: 28 | TOKEN: ${{ steps.generate_token.outputs.token }} 29 | with: 30 | token: ${{ env.TOKEN }} # GitHub App installation access token 31 | # token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} # PAT or OAuth token will also work 32 | reaction-token: ${{ secrets.GITHUB_TOKEN }} 33 | issue-type: pull-request 34 | commands: ok-to-test-managed 35 | permission: maintain 36 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1alpha1/secretstore_ibm_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1alpha1 16 | 17 | import ( 18 | esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" 19 | ) 20 | 21 | // Configures an store to sync secrets using a IBM Cloud Secrets Manager 22 | // backend. 23 | type IBMProvider struct { 24 | // Auth configures how secret-manager authenticates with the IBM secrets manager. 25 | Auth IBMAuth `json:"auth"` 26 | 27 | // ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance 28 | ServiceURL *string `json:"serviceUrl,omitempty"` 29 | } 30 | 31 | type IBMAuth struct { 32 | SecretRef IBMAuthSecretRef `json:"secretRef"` 33 | } 34 | 35 | type IBMAuthSecretRef struct { 36 | // The SecretAccessKey is used for authentication 37 | // +optional 38 | SecretAPIKey esmeta.SecretKeySelector `json:"secretApiKeySecretRef,omitempty"` 39 | } 40 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1beta1/secretstore_ibm_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1beta1 16 | 17 | import ( 18 | esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" 19 | ) 20 | 21 | // Configures an store to sync secrets using a IBM Cloud Secrets Manager 22 | // backend. 23 | type IBMProvider struct { 24 | // Auth configures how secret-manager authenticates with the IBM secrets manager. 25 | Auth IBMAuth `json:"auth"` 26 | 27 | // ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance 28 | ServiceURL *string `json:"serviceUrl,omitempty"` 29 | } 30 | 31 | type IBMAuth struct { 32 | SecretRef IBMAuthSecretRef `json:"secretRef"` 33 | } 34 | 35 | type IBMAuthSecretRef struct { 36 | // The SecretAccessKey is used for authentication 37 | // +optional 38 | SecretAPIKey esmeta.SecretKeySelector `json:"secretApiKeySecretRef,omitempty"` 39 | } 40 | -------------------------------------------------------------------------------- /deploy/charts/external-secrets/README.md.gotmpl: -------------------------------------------------------------------------------- 1 | {{- $valuesYAML := "https://github.com/external-secrets/external-secrets/blob/master/deploy/charts/external-secrets/values.yaml" -}} 2 | {{- $chartRepo := "https://charts.external-secrets.io" -}} 3 | {{- $org := "external-secrets" -}} 4 | # External Secrets 5 | 6 |

7 | 8 | [//]: # (README.md generated by gotmpl. DO NOT EDIT.) 9 | 10 | {{ template "chart.typeBadge" . }}{{ template "chart.versionBadge" . }} 11 | 12 | {{ template "chart.description" . }} 13 | 14 | ## TL;DR 15 | ```bash 16 | helm repo add {{ $org }} {{ $chartRepo }} 17 | helm install {{ $org }}/{{ template "chart.name" . }} 18 | ``` 19 | 20 | ## Installing the Chart 21 | To install the chart with the release name `{{ template "chart.name" . }}`: 22 | ```bash 23 | helm install {{ template "chart.name" . }} {{ $org }}/{{ template "chart.name" . }} 24 | ``` 25 | 26 | ### Custom Resources 27 | By default, the chart will install external-secrets CRDs, this can be controlled with `installCRDs` value. 28 | 29 | ## Uninstalling the Chart 30 | To uninstall the `{{ template "chart.name" . }}` deployment: 31 | ```bash 32 | helm uninstall {{ template "chart.name" . }} 33 | ``` 34 | The command removes all the Kubernetes components associated with the chart and deletes the release. 35 | 36 | {{ template "chart.valuesSection" . }} 37 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1beta1/secretstore_gitlab_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1beta1 16 | 17 | import ( 18 | esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" 19 | ) 20 | 21 | // Configures a store to sync secrets with a GitLab instance. 22 | type GitlabProvider struct { 23 | // URL configures the GitLab instance URL. Defaults to https://gitlab.com/. 24 | URL string `json:"url,omitempty"` 25 | 26 | // Auth configures how secret-manager authenticates with a GitLab instance. 27 | Auth GitlabAuth `json:"auth"` 28 | 29 | // ProjectID specifies a project where secrets are located. 30 | ProjectID string `json:"projectID,omitempty"` 31 | } 32 | 33 | type GitlabAuth struct { 34 | SecretRef GitlabSecretRef `json:"SecretRef"` 35 | } 36 | 37 | type GitlabSecretRef struct { 38 | // AccessToken is used for authentication. 39 | AccessToken esmeta.SecretKeySelector `json:"accessToken,omitempty"` 40 | } 41 | -------------------------------------------------------------------------------- /pkg/provider/yandex/lockbox/client/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package client 15 | 16 | import ( 17 | "context" 18 | "time" 19 | 20 | "github.com/yandex-cloud/go-genproto/yandex/cloud/lockbox/v1" 21 | "github.com/yandex-cloud/go-sdk/iamkey" 22 | ) 23 | 24 | // Creates Lockbox clients and Yandex.Cloud IAM tokens. 25 | type YandexCloudCreator interface { 26 | CreateLockboxClient(ctx context.Context, apiEndpoint string, authorizedKey *iamkey.Key, caCertificate []byte) (LockboxClient, error) 27 | CreateIamToken(ctx context.Context, apiEndpoint string, authorizedKey *iamkey.Key) (*IamToken, error) 28 | Now() time.Time 29 | } 30 | 31 | type IamToken struct { 32 | Token string 33 | ExpiresAt time.Time 34 | } 35 | 36 | // Responsible for accessing Lockbox secrets. 37 | type LockboxClient interface { 38 | GetPayloadEntries(ctx context.Context, iamToken, secretID, versionID string) ([]*lockbox.Payload_Entry, error) 39 | } 40 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1alpha1/secretstore_gitlab_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1alpha1 16 | 17 | import ( 18 | esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" 19 | ) 20 | 21 | // Configures a store to sync secrets with a GitLab instance. 22 | type GitlabProvider struct { 23 | // URL configures the GitLab instance URL. Defaults to https://gitlab.com/. 24 | URL string `json:"url,omitempty"` 25 | 26 | // Auth configures how secret-manager authenticates with a GitLab instance. 27 | Auth GitlabAuth `json:"auth"` 28 | 29 | // ProjectID specifies a project where secrets are located. 30 | ProjectID string `json:"projectID,omitempty"` 31 | } 32 | 33 | type GitlabAuth struct { 34 | SecretRef GitlabSecretRef `json:"SecretRef"` 35 | } 36 | 37 | type GitlabSecretRef struct { 38 | // AccessToken is used for authentication. 39 | AccessToken esmeta.SecretKeySelector `json:"accessToken,omitempty"` 40 | } 41 | -------------------------------------------------------------------------------- /docs/api-externalsecret.md: -------------------------------------------------------------------------------- 1 | The `ExternalSecret` describes what data should be fetched, how the data should 2 | be transformed and saved as a `Kind=Secret`: 3 | 4 | * tells the operator what secrets should be synced by using `spec.data` to 5 | explicitly sync individual keys or use `spec.dataFrom` to get **all values** 6 | from the external API. 7 | * you can specify how the secret should look like by specifying a 8 | `spec.target.template` 9 | 10 | ## Template 11 | 12 | When the controller reconciles the `ExternalSecret` it will use the `spec.template` as a blueprint to construct a new `Kind=Secret`. You can use golang templates to define the blueprint and use template functions to transform secret values. You can also pull in `ConfigMaps` that contain golang-template data using `templateFrom`. See [advanced templating](guides-templating.md) for details. 13 | 14 | ## Update Behavior 15 | 16 | The `Kind=Secret` is updated when: 17 | 18 | * the `spec.refreshInterval` has passed and is not `0` 19 | * the `ExternalSecret`'s `labels` or `annotations` are changed 20 | * the `ExternalSecret`'s `spec` has been changed 21 | 22 | You can trigger a secret refresh by using kubectl or any other kubernetes api client: 23 | 24 | ``` 25 | kubectl annotate es my-es force-sync=$(date +%s) --overwrite 26 | ``` 27 | 28 | ## Example 29 | 30 | Take a look at an annotated example to understand the design behind the 31 | `ExternalSecret`. 32 | 33 | ``` yaml 34 | {% include 'full-external-secret.yaml' %} 35 | ``` 36 | -------------------------------------------------------------------------------- /pkg/provider/oracle/fake/fake.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package fake 15 | 16 | import ( 17 | "context" 18 | 19 | secrets "github.com/oracle/oci-go-sdk/v56/secrets" 20 | ) 21 | 22 | type OracleMockClient struct { 23 | getSecret func(ctx context.Context, request secrets.GetSecretBundleByNameRequest) (response secrets.GetSecretBundleByNameResponse, err error) 24 | } 25 | 26 | func (mc *OracleMockClient) GetSecretBundleByName(ctx context.Context, request secrets.GetSecretBundleByNameRequest) (response secrets.GetSecretBundleByNameResponse, err error) { 27 | return mc.getSecret(ctx, request) 28 | } 29 | 30 | func (mc *OracleMockClient) WithValue(input secrets.GetSecretBundleByNameRequest, output secrets.GetSecretBundleByNameResponse, err error) { 31 | if mc != nil { 32 | mc.getSecret = func(ctx context.Context, paramReq secrets.GetSecretBundleByNameRequest) (secrets.GetSecretBundleByNameResponse, error) { 33 | return output, err 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /pkg/provider/akeyless/fake/fake.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package fake 15 | 16 | import ( 17 | "context" 18 | ) 19 | 20 | type AkeylessMockClient struct { 21 | getSecret func(secretName, token string, version int32) (string, error) 22 | } 23 | 24 | func (mc *AkeylessMockClient) TokenFromSecretRef(ctx context.Context) (string, error) { 25 | return "newToken", nil 26 | } 27 | 28 | func (mc *AkeylessMockClient) GetSecretByType(secretName, token string, version int32) (string, error) { 29 | return mc.getSecret(secretName, token, version) 30 | } 31 | 32 | func (mc *AkeylessMockClient) WithValue(in *Input, out *Output) { 33 | if mc != nil { 34 | mc.getSecret = func(secretName, token string, version int32) (string, error) { 35 | return out.Value, out.Err 36 | } 37 | } 38 | } 39 | 40 | type Input struct { 41 | SecretName string 42 | Token string 43 | Version int32 44 | } 45 | 46 | type Output struct { 47 | Value string 48 | Err error 49 | } 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /webhook/bin 3 | /webhook/certcontroller/bin 4 | /bin 5 | /vendor 6 | cover.out 7 | 8 | # ignore vim swp 9 | *.swp 10 | 11 | # ignore ide files (debug config etc...) 12 | /.vscode 13 | /.idea 14 | 15 | # helm chart dependencies 16 | **/charts/*.tgz 17 | **/charts/**/requirements.lock 18 | .tagmanifest 19 | deploy/charts/external-secrets/templates/crds/*.yaml 20 | 21 | site/ 22 | e2e/k8s/deploy 23 | e2e/e2e.test 24 | 25 | # tf ignores 26 | # Local .terraform directories 27 | **/.terraform/* 28 | 29 | # .tfstate files 30 | *.tfstate 31 | *.tfstate.* 32 | 33 | # Crash log files 34 | crash.log 35 | crash.*.log 36 | 37 | # Exclude all .tfvars files, which are likely to contain sentitive data, such as 38 | # password, private keys, and other secrets. These should not be part of version 39 | # control as they are data points which are potentially sensitive and subject 40 | # to change depending on the environment. 41 | # 42 | *.tfvars 43 | 44 | # Ignore override files as they are usually used to override resources locally and so 45 | # are not checked in 46 | override.tf 47 | override.tf.json 48 | *_override.tf 49 | *_override.tf.json 50 | 51 | # Include override files you do wish to add to version control using negated pattern 52 | # 53 | # !example_override.tf 54 | 55 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 56 | # example: *tfplan* 57 | 58 | # Ignore CLI configuration files 59 | .terraformrc 60 | terraform.rc 61 | **/secrets/** 62 | .terraform.lock.hcl 63 | -------------------------------------------------------------------------------- /e2e/suite/oracle/oracle.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | limitations under the License. 12 | */ 13 | package oracle 14 | 15 | import ( 16 | 17 | // nolint 18 | . "github.com/onsi/ginkgo/v2" 19 | // nolint 20 | . "github.com/onsi/ginkgo/v2/extensions/table" 21 | 22 | "github.com/external-secrets/external-secrets/e2e/framework" 23 | "github.com/external-secrets/external-secrets/e2e/suite/common" 24 | ) 25 | 26 | var _ = Describe("[oracle]", Label("oracle"), func() { 27 | f := framework.New("eso-oracle") 28 | prov := newFromEnv(f) 29 | 30 | DescribeTable("sync secrets", framework.TableFunc(f, prov), 31 | Entry(common.SimpleDataSync(f)), 32 | Entry(common.NestedJSONWithGJSON(f)), 33 | Entry(common.JSONDataFromSync(f)), 34 | Entry(common.JSONDataWithProperty(f)), 35 | Entry(common.JSONDataWithTemplate(f)), 36 | Entry(common.DockerJSONConfig(f)), 37 | Entry(common.DataPropertyDockerconfigJSON(f)), 38 | Entry(common.SSHKeySync(f)), 39 | Entry(common.SSHKeySyncDataProperty(f)), 40 | Entry(common.SyncWithoutTargetName(f)), 41 | Entry(common.JSONDataWithoutTargetName(f)), 42 | ) 43 | }) 44 | -------------------------------------------------------------------------------- /pkg/provider/aws/auth/resolver_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package auth 15 | 16 | import ( 17 | "os" 18 | "testing" 19 | 20 | "github.com/stretchr/testify/assert" 21 | ) 22 | 23 | func TestResolver(t *testing.T) { 24 | tbl := []struct { 25 | env string 26 | service string 27 | url string 28 | }{ 29 | { 30 | env: SecretsManagerEndpointEnv, 31 | service: "secretsmanager", 32 | url: "http://sm.foo", 33 | }, 34 | { 35 | env: SSMEndpointEnv, 36 | service: "ssm", 37 | url: "http://ssm.foo", 38 | }, 39 | { 40 | env: STSEndpointEnv, 41 | service: "sts", 42 | url: "http://sts.foo", 43 | }, 44 | } 45 | 46 | for _, item := range tbl { 47 | os.Setenv(item.env, item.url) 48 | defer os.Unsetenv(item.env) 49 | } 50 | 51 | f := ResolveEndpoint() 52 | 53 | for _, item := range tbl { 54 | ep, err := f.EndpointFor(item.service, "") 55 | assert.Nil(t, err) 56 | assert.Equal(t, item.url, ep.URL) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /pkg/template/v2/jwk.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package template 15 | 16 | import ( 17 | "crypto/x509" 18 | 19 | "github.com/lestrrat-go/jwx/jwk" 20 | ) 21 | 22 | func jwkPublicKeyPem(jwkjson string) (string, error) { 23 | k, err := jwk.ParseKey([]byte(jwkjson)) 24 | if err != nil { 25 | return "", err 26 | } 27 | var rawkey interface{} 28 | err = k.Raw(&rawkey) 29 | if err != nil { 30 | return "", err 31 | } 32 | mpk, err := x509.MarshalPKIXPublicKey(rawkey) 33 | if err != nil { 34 | return "", err 35 | } 36 | return pemEncode(string(mpk), "PUBLIC KEY") 37 | } 38 | 39 | func jwkPrivateKeyPem(jwkjson string) (string, error) { 40 | k, err := jwk.ParseKey([]byte(jwkjson)) 41 | if err != nil { 42 | return "", err 43 | } 44 | var mpk []byte 45 | var pk interface{} 46 | err = k.Raw(&pk) 47 | if err != nil { 48 | return "", err 49 | } 50 | mpk, err = x509.MarshalPKCS8PrivateKey(pk) 51 | if err != nil { 52 | return "", err 53 | } 54 | return pemEncode(string(mpk), "PRIVATE KEY") 55 | } 56 | -------------------------------------------------------------------------------- /e2e/suite/azure/azure_secret.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | limitations under the License. 12 | */ 13 | package azure 14 | 15 | import ( 16 | 17 | // nolint 18 | . "github.com/onsi/ginkgo/v2" 19 | 20 | "github.com/external-secrets/external-secrets/e2e/framework" 21 | "github.com/external-secrets/external-secrets/e2e/suite/common" 22 | ) 23 | 24 | // keyvault type=secret should behave just like any other secret store. 25 | var _ = Describe("[azure]", Label("azure", "keyvault", "secret"), func() { 26 | f := framework.New("eso-azure") 27 | prov := newFromEnv(f) 28 | 29 | DescribeTable("sync secrets", framework.TableFunc(f, prov), 30 | Entry(common.SimpleDataSync(f)), 31 | Entry(common.NestedJSONWithGJSON(f)), 32 | Entry(common.JSONDataFromSync(f)), 33 | Entry(common.JSONDataWithProperty(f)), 34 | Entry(common.JSONDataWithTemplate(f)), 35 | Entry(common.DockerJSONConfig(f)), 36 | Entry(common.DataPropertyDockerconfigJSON(f)), 37 | Entry(common.SSHKeySync(f)), 38 | Entry(common.SSHKeySyncDataProperty(f)), 39 | Entry(common.SyncWithoutTargetName(f)), 40 | Entry(common.JSONDataWithoutTargetName(f)), 41 | ) 42 | }) 43 | -------------------------------------------------------------------------------- /pkg/provider/aws/util/errors_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package util 15 | 16 | import ( 17 | "errors" 18 | "testing" 19 | 20 | "github.com/stretchr/testify/assert" 21 | ) 22 | 23 | func TestSanitize(t *testing.T) { 24 | tbl := []struct { 25 | err error 26 | expected string 27 | }{ 28 | { 29 | err: errors.New("some AccessDeniedException: User: arn:aws:sts::123123123123:assumed-role/foobar is not authorized to perform: secretsmanager:GetSecretValue on resource: example\n\tstatus code: 400, request id: df34-75f-0c5f-4b4c-a71a-f93d581d177c"), 30 | expected: "some AccessDeniedException: User: arn:aws:sts::123123123123:assumed-role/foobar is not authorized to perform: secretsmanager:GetSecretValue on resource: example\n\tstatus code: 400, ", 31 | }, 32 | { 33 | err: errors.New("some generic error"), 34 | expected: "some generic error", 35 | }, 36 | } 37 | 38 | for _, c := range tbl { 39 | out := SanitizeErr(c.err) 40 | assert.Equal(t, c.expected, out.Error()) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /deploy/charts/external-secrets/templates/validatingwebhook.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: admissionregistration.k8s.io/v1 2 | kind: ValidatingWebhookConfiguration 3 | metadata: 4 | name: secretstore-validate 5 | labels: 6 | external-secrets.io/component: webhook 7 | webhooks: 8 | - name: "validate.secretstore.external-secrets.io" 9 | rules: 10 | - apiGroups: ["external-secrets.io"] 11 | apiVersions: ["v1beta1"] 12 | operations: ["CREATE", "UPDATE", "DELETE"] 13 | resources: ["secretstores"] 14 | scope: "Namespaced" 15 | clientConfig: 16 | service: 17 | namespace: {{ .Release.Namespace | quote }} 18 | name: {{ include "external-secrets.fullname" . }}-webhook 19 | path: /validate-external-secrets-io-v1beta1-secretstore 20 | # will be set by controller 21 | caBundle: Cg== 22 | admissionReviewVersions: ["v1", "v1beta1"] 23 | sideEffects: None 24 | timeoutSeconds: 5 25 | 26 | - name: "validate.clustersecretstore.external-secrets.io" 27 | rules: 28 | - apiGroups: ["external-secrets.io"] 29 | apiVersions: ["v1beta1"] 30 | operations: ["CREATE", "UPDATE", "DELETE"] 31 | resources: ["clustersecretstores"] 32 | scope: "Cluster" 33 | clientConfig: 34 | service: 35 | namespace: {{ .Release.Namespace | quote }} 36 | name: {{ include "external-secrets.fullname" . }}-webhook 37 | path: /validate-external-secrets-io-v1beta1-clustersecretstore 38 | caBundle: Cg== # will be set by controller 39 | admissionReviewVersions: ["v1", "v1beta1"] 40 | sideEffects: None 41 | timeoutSeconds: 5 42 | -------------------------------------------------------------------------------- /e2e/suite/aws/parameterstore/parameterstore.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package aws 16 | 17 | import ( 18 | 19 | // nolint 20 | . "github.com/onsi/ginkgo/v2" 21 | 22 | "github.com/external-secrets/external-secrets/e2e/framework" 23 | "github.com/external-secrets/external-secrets/e2e/suite/common" 24 | ) 25 | 26 | var _ = Describe("[aws] ", Label("aws", "parameterstore"), func() { 27 | f := framework.New("eso-aws-ps") 28 | prov := NewFromEnv(f) 29 | 30 | DescribeTable("sync secrets", 31 | framework.TableFunc(f, 32 | prov), 33 | Entry(common.SimpleDataSync(f)), 34 | Entry(common.NestedJSONWithGJSON(f)), 35 | Entry(common.JSONDataFromSync(f)), 36 | Entry(common.JSONDataWithProperty(f)), 37 | Entry(common.JSONDataWithTemplate(f)), 38 | Entry(common.DockerJSONConfig(f)), 39 | Entry(common.DataPropertyDockerconfigJSON(f)), 40 | Entry(common.SSHKeySync(f)), 41 | Entry(common.SSHKeySyncDataProperty(f)), 42 | Entry(common.SyncWithoutTargetName(f)), 43 | Entry(common.JSONDataWithoutTargetName(f)), 44 | ) 45 | }) 46 | -------------------------------------------------------------------------------- /e2e/suite/aws/secretsmanager/secretsmanager.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package aws 16 | 17 | import ( 18 | 19 | // nolint 20 | . "github.com/onsi/ginkgo/v2" 21 | 22 | "github.com/external-secrets/external-secrets/e2e/framework" 23 | "github.com/external-secrets/external-secrets/e2e/suite/common" 24 | ) 25 | 26 | var _ = Describe("[aws] ", Label("aws", "secretsmanager"), func() { 27 | f := framework.New("eso-aws-sm") 28 | prov := NewFromEnv(f) 29 | 30 | DescribeTable("sync secrets", 31 | framework.TableFunc(f, 32 | prov), 33 | Entry(common.SimpleDataSync(f)), 34 | Entry(common.NestedJSONWithGJSON(f)), 35 | Entry(common.JSONDataFromSync(f)), 36 | Entry(common.JSONDataWithProperty(f)), 37 | Entry(common.JSONDataWithTemplate(f)), 38 | Entry(common.DockerJSONConfig(f)), 39 | Entry(common.DataPropertyDockerconfigJSON(f)), 40 | Entry(common.SSHKeySync(f)), 41 | Entry(common.SSHKeySyncDataProperty(f)), 42 | Entry(common.SyncWithoutTargetName(f)), 43 | Entry(common.JSONDataWithoutTargetName(f)), 44 | ) 45 | }) 46 | -------------------------------------------------------------------------------- /e2e/e2e_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package e2e 15 | 16 | import ( 17 | "testing" 18 | 19 | // nolint 20 | . "github.com/onsi/ginkgo/v2" 21 | // nolint 22 | . "github.com/onsi/gomega" 23 | 24 | "github.com/external-secrets/external-secrets/e2e/framework/addon" 25 | "github.com/external-secrets/external-secrets/e2e/framework/util" 26 | _ "github.com/external-secrets/external-secrets/e2e/suite" 27 | ) 28 | 29 | var _ = SynchronizedBeforeSuite(func() []byte { 30 | cfg := &addon.Config{} 31 | cfg.KubeConfig, cfg.KubeClientSet, cfg.CRClient = util.NewConfig() 32 | 33 | By("installing eso") 34 | addon.InstallGlobalAddon(addon.NewESO(), cfg) 35 | 36 | return nil 37 | }, func([]byte) {}) 38 | 39 | var _ = SynchronizedAfterSuite(func() {}, func() { 40 | By("Cleaning up global addons") 41 | addon.UninstallGlobalAddons() 42 | if CurrentSpecReport().Failed() { 43 | addon.PrintLogs() 44 | } 45 | }) 46 | 47 | func TestE2E(t *testing.T) { 48 | NewWithT(t) 49 | RegisterFailHandler(Fail) 50 | RunSpecs(t, "external-secrets e2e suite", Label("e2e")) 51 | } 52 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1alpha1/secretstore_alibaba_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1alpha1 16 | 17 | import ( 18 | esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" 19 | ) 20 | 21 | // AlibabaAuth contains a secretRef for credentials. 22 | type AlibabaAuth struct { 23 | SecretRef AlibabaAuthSecretRef `json:"secretRef"` 24 | } 25 | 26 | // AlibabaAuthSecretRef holds secret references for Alibaba credentials. 27 | type AlibabaAuthSecretRef struct { 28 | // The AccessKeyID is used for authentication 29 | AccessKeyID esmeta.SecretKeySelector `json:"accessKeyIDSecretRef"` 30 | // The AccessKeySecret is used for authentication 31 | AccessKeySecret esmeta.SecretKeySelector `json:"accessKeySecretSecretRef"` 32 | } 33 | 34 | // AlibabaProvider configures a store to sync secrets using the Alibaba Secret Manager provider. 35 | type AlibabaProvider struct { 36 | Auth *AlibabaAuth `json:"auth"` 37 | // +optional 38 | Endpoint string `json:"endpoint"` 39 | // Alibaba Region to be used for the provider 40 | RegionID string `json:"regionID"` 41 | } 42 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1beta1/secretstore_alibaba_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1beta1 16 | 17 | import ( 18 | esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" 19 | ) 20 | 21 | // AlibabaAuth contains a secretRef for credentials. 22 | type AlibabaAuth struct { 23 | SecretRef AlibabaAuthSecretRef `json:"secretRef"` 24 | } 25 | 26 | // AlibabaAuthSecretRef holds secret references for Alibaba credentials. 27 | type AlibabaAuthSecretRef struct { 28 | // The AccessKeyID is used for authentication 29 | AccessKeyID esmeta.SecretKeySelector `json:"accessKeyIDSecretRef"` 30 | // The AccessKeySecret is used for authentication 31 | AccessKeySecret esmeta.SecretKeySelector `json:"accessKeySecretSecretRef"` 32 | } 33 | 34 | // AlibabaProvider configures a store to sync secrets using the Alibaba Secret Manager provider. 35 | type AlibabaProvider struct { 36 | Auth *AlibabaAuth `json:"auth"` 37 | // +optional 38 | Endpoint string `json:"endpoint"` 39 | // Alibaba Region to be used for the provider 40 | RegionID string `json:"regionID"` 41 | } 42 | -------------------------------------------------------------------------------- /e2e/suite/alibaba/alibaba.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package alibaba 16 | 17 | import ( 18 | 19 | // nolint 20 | . "github.com/onsi/ginkgo/v2" 21 | // nolint 22 | . "github.com/onsi/ginkgo/v2/extensions/table" 23 | 24 | "github.com/external-secrets/external-secrets/e2e/framework" 25 | "github.com/external-secrets/external-secrets/e2e/suite/common" 26 | ) 27 | 28 | var _ = Describe("[alibaba]", Label("alibaba"), func() { 29 | f := framework.New("eso-alibaba") 30 | prov := newFromEnv(f) 31 | 32 | DescribeTable("sync secrets", framework.TableFunc(f, prov), 33 | Entry(common.SimpleDataSync(f)), 34 | Entry(common.NestedJSONWithGJSON(f)), 35 | Entry(common.JSONDataFromSync(f)), 36 | Entry(common.JSONDataWithProperty(f)), 37 | Entry(common.JSONDataWithTemplate(f)), 38 | Entry(common.DockerJSONConfig(f)), 39 | Entry(common.DataPropertyDockerconfigJSON(f)), 40 | Entry(common.SSHKeySync(f)), 41 | Entry(common.SSHKeySyncDataProperty(f)), 42 | Entry(common.SyncWithoutTargetName(f)), 43 | Entry(common.JSONDataWithoutTargetName(f)), 44 | ) 45 | }) 46 | -------------------------------------------------------------------------------- /e2e/suite/akeyless/akeyless.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package akeyless 16 | 17 | import ( 18 | 19 | // nolint 20 | . "github.com/onsi/ginkgo/v2" 21 | // nolint 22 | . "github.com/onsi/ginkgo/v2/extensions/table" 23 | 24 | "github.com/external-secrets/external-secrets/e2e/framework" 25 | "github.com/external-secrets/external-secrets/e2e/suite/common" 26 | ) 27 | 28 | var _ = Describe("[akeyless]", Label("akeyless"), func() { 29 | f := framework.New("eso-akeyless") 30 | prov := newFromEnv(f) 31 | 32 | DescribeTable("sync secrets", framework.TableFunc(f, prov), 33 | Entry(common.SimpleDataSync(f)), 34 | Entry(common.NestedJSONWithGJSON(f)), 35 | Entry(common.JSONDataFromSync(f)), 36 | Entry(common.JSONDataWithProperty(f)), 37 | Entry(common.JSONDataWithTemplate(f)), 38 | Entry(common.DockerJSONConfig(f)), 39 | Entry(common.DataPropertyDockerconfigJSON(f)), 40 | Entry(common.SSHKeySync(f)), 41 | Entry(common.SSHKeySyncDataProperty(f)), 42 | Entry(common.SyncWithoutTargetName(f)), 43 | Entry(common.JSONDataWithoutTargetName(f)), 44 | ) 45 | }) 46 | -------------------------------------------------------------------------------- /pkg/provider/aws/util/provider.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package util 15 | 16 | import ( 17 | "fmt" 18 | 19 | esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" 20 | ) 21 | 22 | const ( 23 | errNilStore = "found nil store" 24 | errMissingStoreSpec = "store is missing spec" 25 | errMissingProvider = "storeSpec is missing provider" 26 | errInvalidProvider = "invalid provider spec. Missing AWS field in store %s" 27 | ) 28 | 29 | // GetAWSProvider does the necessary nil checks on the generic store 30 | // it returns the aws provider or an error. 31 | func GetAWSProvider(store esv1beta1.GenericStore) (*esv1beta1.AWSProvider, error) { 32 | if store == nil { 33 | return nil, fmt.Errorf(errNilStore) 34 | } 35 | spc := store.GetSpec() 36 | if spc == nil { 37 | return nil, fmt.Errorf(errMissingStoreSpec) 38 | } 39 | if spc.Provider == nil { 40 | return nil, fmt.Errorf(errMissingProvider) 41 | } 42 | prov := spc.Provider.AWS 43 | if prov == nil { 44 | return nil, fmt.Errorf(errInvalidProvider, store.GetObjectMeta().String()) 45 | } 46 | return prov, nil 47 | } 48 | -------------------------------------------------------------------------------- /pkg/template/v2/pem.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package template 15 | 16 | import ( 17 | "bytes" 18 | "encoding/pem" 19 | "errors" 20 | "strings" 21 | ) 22 | 23 | const ( 24 | errJunk = "error filtering pem: found junk" 25 | ) 26 | 27 | func filterPEM(pemType, input string) (string, error) { 28 | data := []byte(input) 29 | var blocks []byte 30 | var block *pem.Block 31 | var rest []byte 32 | for { 33 | block, rest = pem.Decode(data) 34 | data = rest 35 | 36 | if block == nil { 37 | break 38 | } 39 | if !strings.EqualFold(block.Type, pemType) { 40 | continue 41 | } 42 | 43 | var buf bytes.Buffer 44 | err := pem.Encode(&buf, block) 45 | if err != nil { 46 | return "", err 47 | } 48 | blocks = append(blocks, buf.Bytes()...) 49 | } 50 | 51 | if len(blocks) == 0 && len(rest) != 0 { 52 | return "", errors.New(errJunk) 53 | } 54 | 55 | return string(blocks), nil 56 | } 57 | 58 | func pemEncode(thing, kind string) (string, error) { 59 | buf := bytes.NewBuffer(nil) 60 | err := pem.Encode(buf, &pem.Block{Type: kind, Bytes: []byte(thing)}) 61 | return buf.String(), err 62 | } 63 | -------------------------------------------------------------------------------- /pkg/template/v2/_testdata/disjunct-chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBJzCB2qADAgECAhEArvunrLoYXTmwMROkmbAlBTAFBgMrZXAwEjEQMA4GA1UE 3 | AxMHcm9vdC1jYTAeFw0yMjAyMDkxMDI1MzBaFw0zMjAyMDcxMDI1MzBaMBIxEDAO 4 | BgNVBAMTB3Jvb3QtY2EwKjAFBgMrZXADIQDSw5uQ1io+jcKevCH0sl+tGTB6/BQs 5 | Bu84ibw13QoP36NFMEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8C 6 | AQEwHQYDVR0OBBYEFGtn1GnNjmd6cxOhMnVau1L8IkGtMAUGAytlcANBAOHSAS4z 7 | /6ctcvRwlGr9Hyt7vVLROImD2t3rFdDDHLLL1znikK3JZvVbETyMFOMbOMQS33C/ 8 | 4FtLGenZFXySjQw= 9 | -----END CERTIFICATE----- 10 | -----BEGIN CERTIFICATE----- 11 | MIIBgDCCATKgAwIBAgIRAOzjpCdp42oW5MoccLpRXpAwBQYDK2VwMBIxEDAOBgNV 12 | BAMTB3Jvb3QtY2EwHhcNMjIwMjA5MTAyNTMxWhcNMzIwMjA3MTAyNTMxWjAaMRgw 13 | FgYDVQQDEw9pbnRlcm1lZGlhdGUtY2EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC 14 | AATekdyX6cZe0Ajmme363TQoWnrQwXnARzeWEf4FRQE8BGWgf8z7wljjpb4M4S4f 15 | +CJAYYY/6x38UnlsxXEeBTofo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/ 16 | BAgwBgEB/wIBADAdBgNVHQ4EFgQUIuDzQn9tkFs535jz5X3iXnEzbMQwHwYDVR0j 17 | BBgwFoAUa2fUac2OZ3pzE6EydVq7UvwiQa0wBQYDK2VwA0EA4gntaGs/3ME6q1y9 18 | gO4ntri2qwoC25l3q7q9BiFBmeBmvS6I1w9HCZHtB3JnVC/IYDTCYDNTbpGWEOjl 19 | aCKLCA== 20 | -----END CERTIFICATE----- 21 | -----BEGIN CERTIFICATE----- 22 | MIIBOTCB7KADAgECAhEA0cArEY0s5JoP8JfqIDv2BTAFBgMrZXAwGzEZMBcGA1UE 23 | AxMQZGlzanVuY3Qtcm9vdC1jYTAeFw0yMjAyMDkxMDI1MzBaFw0zMjAyMDcxMDI1 24 | MzBaMBsxGTAXBgNVBAMTEGRpc2p1bmN0LXJvb3QtY2EwKjAFBgMrZXADIQAJER3w 25 | QFZH1DBmxZm9IkaZ5noangcg/CYNP+GtcyQPL6NFMEMwDgYDVR0PAQH/BAQDAgEG 26 | MBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFMddJG4lWXTN/x9InsiJUTxu 27 | d4+HMAUGAytlcANBABcyLV4om9LPV0TGDf0jiM+JxH1R+ATvAE8FHDtd8L66BrzA 28 | Id656nPz3fz9ZMB9VZr7iGcghXYlTHxu6NkQEgA= 29 | -----END CERTIFICATE----- 30 | -------------------------------------------------------------------------------- /e2e/suite/gitlab/gitlab.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | limitations under the License. 12 | */ 13 | package gitlab 14 | 15 | // TODO - Gitlab only accepts variable names with alphanumeric and '_' 16 | // whereas ESO only accepts names with alphanumeric and '-'. 17 | // Current workaround is to remove all hyphens and underscores set in e2e/framework/util/util.go 18 | // and in e2e/suite/common/common.go, but this breaks Azure provider. 19 | 20 | import ( 21 | 22 | // nolint 23 | . "github.com/onsi/ginkgo/v2" 24 | // nolint 25 | . "github.com/onsi/ginkgo/v2/extensions/table" 26 | 27 | "github.com/external-secrets/external-secrets/e2e/framework" 28 | "github.com/external-secrets/external-secrets/e2e/suite/common" 29 | ) 30 | 31 | var _ = Describe("[gitlab]", Label("gitlab"), func() { 32 | f := framework.New("eso-gitlab") 33 | prov := newFromEnv(f) 34 | 35 | DescribeTable("sync secrets", framework.TableFunc(f, prov), 36 | Entry(common.SimpleDataSync(f)), 37 | Entry(common.JSONDataWithProperty(f)), 38 | Entry(common.JSONDataFromSync(f)), 39 | Entry(common.NestedJSONWithGJSON(f)), 40 | Entry(common.JSONDataWithTemplate(f)), 41 | Entry(common.SyncWithoutTargetName(f)), 42 | Entry(common.JSONDataWithoutTargetName(f)), 43 | ) 44 | }) 45 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1beta1/secretstore_akeyless_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1beta1 16 | 17 | import ( 18 | esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" 19 | ) 20 | 21 | // AkeylessProvider Configures an store to sync secrets using Akeyless KV. 22 | type AkeylessProvider struct { 23 | 24 | // Akeyless GW API Url from which the secrets to be fetched from. 25 | AkeylessGWApiURL *string `json:"akeylessGWApiURL"` 26 | 27 | // Auth configures how the operator authenticates with Akeyless. 28 | Auth *AkeylessAuth `json:"authSecretRef"` 29 | } 30 | 31 | type AkeylessAuth struct { 32 | SecretRef AkeylessAuthSecretRef `json:"secretRef"` 33 | } 34 | 35 | // AkeylessAuthSecretRef 36 | //AKEYLESS_ACCESS_TYPE_PARAM: AZURE_OBJ_ID OR GCP_AUDIENCE OR ACCESS_KEY OR KUB_CONFIG_NAME. 37 | type AkeylessAuthSecretRef struct { 38 | // The SecretAccessID is used for authentication 39 | AccessID esmeta.SecretKeySelector `json:"accessID,omitempty"` 40 | AccessType esmeta.SecretKeySelector `json:"accessType,omitempty"` 41 | AccessTypeParam esmeta.SecretKeySelector `json:"accessTypeParam,omitempty"` 42 | } 43 | -------------------------------------------------------------------------------- /hack/api-docs/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2020 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | GOPATH=${GOPATH:-$(go env GOPATH)} 22 | 23 | # "go env" doesn't print anything if GOBIN is the default, so we 24 | # have to manually default it. 25 | GOBIN=${GOBIN:-$(go env GOBIN)} 26 | GOBIN=${GOBIN:-${GOPATH}/bin} 27 | 28 | readonly HERE=$(cd $(dirname $0) && pwd) 29 | readonly REPO=$(cd ${HERE}/../.. && pwd) 30 | 31 | gendoc::build() { 32 | go install github.com/ahmetb/gen-crd-api-reference-docs 33 | } 34 | 35 | # Exec the doc generator. 36 | gendoc::exec() { 37 | local readonly confdir="${REPO}/hack/api-docs" 38 | 39 | ${GOBIN}/gen-crd-api-reference-docs \ 40 | -template-dir ${confdir} \ 41 | -config ${confdir}/config.json \ 42 | "$@" 43 | } 44 | 45 | if [ "$#" != "1" ]; then 46 | echo "usage: generate.sh OUTFILE" 47 | exit 2 48 | fi 49 | 50 | gendoc::build 51 | gendoc::exec \ 52 | -api-dir github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1 \ 53 | -out-file "$1" 54 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1alpha1/secretstore_akeyless_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1alpha1 16 | 17 | import ( 18 | esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" 19 | ) 20 | 21 | // AkeylessProvider Configures an store to sync secrets using Akeyless KV. 22 | type AkeylessProvider struct { 23 | 24 | // Akeyless GW API Url from which the secrets to be fetched from. 25 | AkeylessGWApiURL *string `json:"akeylessGWApiURL"` 26 | 27 | // Auth configures how the operator authenticates with Akeyless. 28 | Auth *AkeylessAuth `json:"authSecretRef"` 29 | } 30 | 31 | type AkeylessAuth struct { 32 | SecretRef AkeylessAuthSecretRef `json:"secretRef"` 33 | } 34 | 35 | // AkeylessAuthSecretRef 36 | //AKEYLESS_ACCESS_TYPE_PARAM: AZURE_OBJ_ID OR GCP_AUDIENCE OR ACCESS_KEY OR KUB_CONFIG_NAME. 37 | type AkeylessAuthSecretRef struct { 38 | // The SecretAccessID is used for authentication 39 | AccessID esmeta.SecretKeySelector `json:"accessID,omitempty"` 40 | AccessType esmeta.SecretKeySelector `json:"accessType,omitempty"` 41 | AccessTypeParam esmeta.SecretKeySelector `json:"accessTypeParam,omitempty"` 42 | } 43 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1alpha1/secretstore_yandexlockbox_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1alpha1 16 | 17 | import ( 18 | esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" 19 | ) 20 | 21 | type YandexLockboxAuth struct { 22 | // The authorized key used for authentication 23 | // +optional 24 | AuthorizedKey esmeta.SecretKeySelector `json:"authorizedKeySecretRef,omitempty"` 25 | } 26 | 27 | type YandexLockboxCAProvider struct { 28 | Certificate esmeta.SecretKeySelector `json:"certSecretRef,omitempty"` 29 | } 30 | 31 | // YandexLockboxProvider Configures a store to sync secrets using the Yandex Lockbox provider. 32 | type YandexLockboxProvider struct { 33 | // Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') 34 | // +optional 35 | APIEndpoint string `json:"apiEndpoint,omitempty"` 36 | 37 | // Auth defines the information necessary to authenticate against Yandex Lockbox 38 | Auth YandexLockboxAuth `json:"auth"` 39 | 40 | // The provider for the CA bundle to use to validate Yandex.Cloud server certificate. 41 | // +optional 42 | CAProvider *YandexLockboxCAProvider `json:"caProvider,omitempty"` 43 | } 44 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1beta1/secretstore_yandexlockbox_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1beta1 16 | 17 | import ( 18 | esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" 19 | ) 20 | 21 | type YandexLockboxAuth struct { 22 | // The authorized key used for authentication 23 | // +optional 24 | AuthorizedKey esmeta.SecretKeySelector `json:"authorizedKeySecretRef,omitempty"` 25 | } 26 | 27 | type YandexLockboxCAProvider struct { 28 | Certificate esmeta.SecretKeySelector `json:"certSecretRef,omitempty"` 29 | } 30 | 31 | // YandexLockboxProvider Configures a store to sync secrets using the Yandex Lockbox provider. 32 | type YandexLockboxProvider struct { 33 | // Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') 34 | // +optional 35 | APIEndpoint string `json:"apiEndpoint,omitempty"` 36 | 37 | // Auth defines the information necessary to authenticate against Yandex Lockbox 38 | Auth YandexLockboxAuth `json:"auth"` 39 | 40 | // The provider for the CA bundle to use to validate Yandex.Cloud server certificate. 41 | // +optional 42 | CAProvider *YandexLockboxCAProvider `json:"caProvider,omitempty"` 43 | } 44 | -------------------------------------------------------------------------------- /pkg/provider/aws/auth/fake/assumeroler.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package fake 15 | 16 | import ( 17 | "github.com/aws/aws-sdk-go/aws" 18 | "github.com/aws/aws-sdk-go/aws/credentials" 19 | "github.com/aws/aws-sdk-go/aws/request" 20 | "github.com/aws/aws-sdk-go/service/sts" 21 | "github.com/aws/aws-sdk-go/service/sts/stsiface" 22 | ) 23 | 24 | type AssumeRoler struct { 25 | stsiface.STSAPI 26 | AssumeRoleFunc func(*sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) 27 | } 28 | 29 | func (f *AssumeRoler) AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) { 30 | return f.AssumeRoleFunc(input) 31 | } 32 | 33 | func (f *AssumeRoler) AssumeRoleWithContext(ctx aws.Context, input *sts.AssumeRoleInput, opts ...request.Option) (*sts.AssumeRoleOutput, error) { 34 | return f.AssumeRoleFunc(input) 35 | } 36 | 37 | type CredentialsProvider struct { 38 | RetrieveFunc func() (credentials.Value, error) 39 | IsExpiredFunc func() bool 40 | } 41 | 42 | func (t CredentialsProvider) Retrieve() (credentials.Value, error) { 43 | return t.RetrieveFunc() 44 | } 45 | 46 | func (t CredentialsProvider) IsExpired() bool { 47 | return t.IsExpiredFunc() 48 | } 49 | -------------------------------------------------------------------------------- /pkg/provider/register/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package register 16 | 17 | // packages imported here are registered to the controller schema. 18 | // nolint:revive 19 | import ( 20 | _ "github.com/external-secrets/external-secrets/pkg/provider/akeyless" 21 | _ "github.com/external-secrets/external-secrets/pkg/provider/alibaba" 22 | _ "github.com/external-secrets/external-secrets/pkg/provider/aws" 23 | _ "github.com/external-secrets/external-secrets/pkg/provider/azure/keyvault" 24 | _ "github.com/external-secrets/external-secrets/pkg/provider/fake" 25 | _ "github.com/external-secrets/external-secrets/pkg/provider/gcp/secretmanager" 26 | _ "github.com/external-secrets/external-secrets/pkg/provider/gitlab" 27 | _ "github.com/external-secrets/external-secrets/pkg/provider/ibm" 28 | _ "github.com/external-secrets/external-secrets/pkg/provider/kubernetes" 29 | _ "github.com/external-secrets/external-secrets/pkg/provider/oracle" 30 | _ "github.com/external-secrets/external-secrets/pkg/provider/vault" 31 | _ "github.com/external-secrets/external-secrets/pkg/provider/webhook" 32 | _ "github.com/external-secrets/external-secrets/pkg/provider/yandex/lockbox" 33 | ) 34 | -------------------------------------------------------------------------------- /docs/snippets/vault-anchore-engine-access-credentials-external-secret.yaml: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | apiVersion: external-secrets.io/v1alpha1 3 | kind: ExternalSecret 4 | metadata: 5 | name: anchore-access-credentials 6 | namespace: security 7 | spec: 8 | refreshInterval: 1m 9 | secretStoreRef: 10 | name: vault-backend 11 | kind: ClusterSecretStore 12 | target: 13 | name: anchore-access-credentials 14 | template: 15 | 16 | data: 17 | ANCHORE_ADMIN_USERNAME: >- 18 | {{ printf "{{ .username | toString }}" }} 19 | ANCHORE_ADMIN_PASSWORD: >- 20 | {{ printf "{{ .password | toString }}" }} 21 | ANCHORE_DB_PASSWORD: >- 22 | {{ printf "{{ .dbPassword | toString }}" }} 23 | db-url: >- 24 | {{ printf "{{ .dbUrl | toString }}" }} 25 | db-user: >- 26 | {{ printf "{{ .dbUser | toString }}" }} 27 | postgres-password: >- 28 | {{ printf "{{ .postgresPassword | toString }}" }} 29 | 30 | data: 31 | - secretKey: password 32 | remoteRef: 33 | key: anchore-engine 34 | property: ANCHORE_ADMIN_PASSWORD 35 | - secretKey: username 36 | remoteRef: 37 | key: anchore-engine 38 | property: ANCHORE_ADMIN_USERNAME 39 | - secretKey: dbPassword 40 | remoteRef: 41 | key: anchore-engine 42 | property: ANCHORE_DB_PASSWORD 43 | - secretKey: dbUrl 44 | remoteRef: 45 | key: anchore-engine 46 | property: db-url 47 | - secretKey: dbUser 48 | remoteRef: 49 | key: anchore-engine 50 | property: db-user 51 | - secretKey: postgresPassword 52 | remoteRef: 53 | key: anchore-engine 54 | property: postgres-password 55 | {% endraw %} -------------------------------------------------------------------------------- /e2e/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2019 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -euo pipefail 18 | 19 | NC='\e[0m' 20 | BGREEN='\e[32m' 21 | 22 | E2E_NODES=${E2E_NODES:-5} 23 | 24 | if [ ! -f "${HOME}/.kube/config" ]; then 25 | kubectl config set-cluster dev --certificate-authority=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt --embed-certs=true --server="https://kubernetes.default/" 26 | kubectl config set-credentials user --token="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" 27 | kubectl config set-context default --cluster=dev --user=user 28 | kubectl config use-context default 29 | fi 30 | 31 | ginkgo_args=( 32 | "--randomize-suites" 33 | "--randomize-all" 34 | "--flake-attempts=2" 35 | "-p" 36 | "-progress" 37 | "-trace" 38 | "--slow-spec-threshold=5m" 39 | "-r" 40 | "-v" 41 | "-timeout=45m" 42 | ) 43 | 44 | kubectl apply -f /k8s/deploy/crds 45 | 46 | echo -e "${BGREEN}Running e2e test suite (LABELS=${GINKGO_LABELS})...${NC}" 47 | ACK_GINKGO_RC=true ginkgo "${ginkgo_args[@]}" \ 48 | -label-filter="${GINKGO_LABELS}" \ 49 | -nodes="${E2E_NODES}" \ 50 | /e2e.test 51 | -------------------------------------------------------------------------------- /apis/meta/v1/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1 16 | 17 | // A reference to a specific 'key' within a Secret resource, 18 | // In some instances, `key` is a required field. 19 | type SecretKeySelector struct { 20 | // The name of the Secret resource being referred to. 21 | Name string `json:"name,omitempty"` 22 | // Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults 23 | // to the namespace of the referent. 24 | // +optional 25 | Namespace *string `json:"namespace,omitempty"` 26 | // The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be 27 | // defaulted, in others it may be required. 28 | // +optional 29 | Key string `json:"key,omitempty"` 30 | } 31 | 32 | // A reference to a ServiceAccount resource. 33 | type ServiceAccountSelector struct { 34 | // The name of the ServiceAccount resource being referred to. 35 | Name string `json:"name"` 36 | // Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults 37 | // to the namespace of the referent. 38 | // +optional 39 | Namespace *string `json:"namespace,omitempty"` 40 | } 41 | -------------------------------------------------------------------------------- /pkg/provider/gitlab/fake/fake.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package fake 15 | 16 | import ( 17 | gitlab "github.com/xanzy/go-gitlab" 18 | ) 19 | 20 | type GitlabMockClient struct { 21 | getVariable func(pid interface{}, key string, options ...gitlab.RequestOptionFunc) (*gitlab.ProjectVariable, *gitlab.Response, error) 22 | } 23 | 24 | func (mc *GitlabMockClient) GetVariable(pid interface{}, key string, options ...gitlab.RequestOptionFunc) (*gitlab.ProjectVariable, *gitlab.Response, error) { 25 | return mc.getVariable(pid, key, nil) 26 | } 27 | 28 | func (mc *GitlabMockClient) WithValue(projectIDinput, keyInput string, output *gitlab.ProjectVariable, err error) { 29 | if mc != nil { 30 | mc.getVariable = func(pid interface{}, key string, options ...gitlab.RequestOptionFunc) (*gitlab.ProjectVariable, *gitlab.Response, error) { 31 | // type secretmanagerpb.AccessSecretVersionRequest contains unexported fields 32 | // use cmpopts.IgnoreUnexported to ignore all the unexported fields in the cmp. 33 | // if !cmp.Equal(paramReq, input, cmpopts.IgnoreUnexported(gitlab.ProjectVariable{})) { 34 | // return nil, nil, fmt.Errorf("unexpected test argument") 35 | // } 36 | return output, nil, err 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /terraform/aws/modules/cluster/auth.tf: -------------------------------------------------------------------------------- 1 | 2 | data "aws_eks_cluster_auth" "this" { 3 | name = module.eks.cluster_id 4 | } 5 | 6 | data "aws_caller_identity" "current" {} 7 | 8 | locals { 9 | kubeconfig = yamlencode({ 10 | apiVersion = "v1" 11 | kind = "Config" 12 | current-context = "terraform" 13 | clusters = [{ 14 | name = module.eks.cluster_id 15 | cluster = { 16 | certificate-authority-data = module.eks.cluster_certificate_authority_data 17 | server = module.eks.cluster_endpoint 18 | } 19 | }] 20 | contexts = [{ 21 | name = "terraform" 22 | context = { 23 | cluster = module.eks.cluster_id 24 | user = "terraform" 25 | } 26 | }] 27 | users = [{ 28 | name = "terraform" 29 | user = { 30 | token = data.aws_eks_cluster_auth.this.token 31 | } 32 | }] 33 | }) 34 | 35 | # we have to allow the root account to access the api 36 | aws_auth_configmap_yaml = <<-EOT 37 | ${chomp(module.eks.aws_auth_configmap_yaml)} 38 | - rolearn: arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/admin 39 | username: system:aws:root 40 | groups: 41 | - system:masters 42 | EOT 43 | } 44 | 45 | resource "null_resource" "patch_cm" { 46 | triggers = { 47 | kubeconfig = base64encode(local.kubeconfig) 48 | cmd_patch = <<-EOT 49 | kubectl patch configmap/aws-auth --patch "${local.aws_auth_configmap_yaml}" -n kube-system --kubeconfig <(echo $KUBECONFIG | base64 --decode) 50 | EOT 51 | } 52 | 53 | provisioner "local-exec" { 54 | interpreter = ["/bin/bash", "-c"] 55 | environment = { 56 | KUBECONFIG = self.triggers.kubeconfig 57 | } 58 | command = self.triggers.cmd_patch 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /pkg/template/v2/_testdata/chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBqjCCAU+gAwIBAgIRAPnGGsBUMbZhmh5QdnYdBmUwCgYIKoZIzj0EAwIwGjEY 3 | MBYGA1UEAxMPaW50ZXJtZWRpYXRlLWNhMB4XDTIyMDIwOTEwMjUzMVoXDTIyMDIx 4 | MDEwMjUzMVowDjEMMAoGA1UEAxMDZm9vMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD 5 | QgAEqnxdeInykx8JZsLi13rZLekoG2cosQ3F+2InVNy7hCQ7soMqdaJsGQ6LFtov 6 | ogUFtOOTRWrunblqNWGZsowHbKOBgTB/MA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUE 7 | FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFLtundVbuKd73OWzo6SY 8 | by0Ajeb2MB8GA1UdIwQYMBaAFCLg80J/bZBbOd+Y8+V94l5xM2zEMA4GA1UdEQQH 9 | MAWCA2ZvbzAKBggqhkjOPQQDAgNJADBGAiEA4K4SbVNqrEtl7RfwBfJFMnWI+X8D 10 | zMPMc4Xqzp2qTxcCIQDsySgtiakypZfWakpB49zJph0kLwGK8xhWvGMUw1N1/w== 11 | -----END CERTIFICATE----- 12 | -----BEGIN CERTIFICATE----- 13 | MIIBJzCB2qADAgECAhEArvunrLoYXTmwMROkmbAlBTAFBgMrZXAwEjEQMA4GA1UE 14 | AxMHcm9vdC1jYTAeFw0yMjAyMDkxMDI1MzBaFw0zMjAyMDcxMDI1MzBaMBIxEDAO 15 | BgNVBAMTB3Jvb3QtY2EwKjAFBgMrZXADIQDSw5uQ1io+jcKevCH0sl+tGTB6/BQs 16 | Bu84ibw13QoP36NFMEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8C 17 | AQEwHQYDVR0OBBYEFGtn1GnNjmd6cxOhMnVau1L8IkGtMAUGAytlcANBAOHSAS4z 18 | /6ctcvRwlGr9Hyt7vVLROImD2t3rFdDDHLLL1znikK3JZvVbETyMFOMbOMQS33C/ 19 | 4FtLGenZFXySjQw= 20 | -----END CERTIFICATE----- 21 | -----BEGIN CERTIFICATE----- 22 | MIIBgDCCATKgAwIBAgIRAOzjpCdp42oW5MoccLpRXpAwBQYDK2VwMBIxEDAOBgNV 23 | BAMTB3Jvb3QtY2EwHhcNMjIwMjA5MTAyNTMxWhcNMzIwMjA3MTAyNTMxWjAaMRgw 24 | FgYDVQQDEw9pbnRlcm1lZGlhdGUtY2EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC 25 | AATekdyX6cZe0Ajmme363TQoWnrQwXnARzeWEf4FRQE8BGWgf8z7wljjpb4M4S4f 26 | +CJAYYY/6x38UnlsxXEeBTofo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/ 27 | BAgwBgEB/wIBADAdBgNVHQ4EFgQUIuDzQn9tkFs535jz5X3iXnEzbMQwHwYDVR0j 28 | BBgwFoAUa2fUac2OZ3pzE6EydVq7UvwiQa0wBQYDK2VwA0EA4gntaGs/3ME6q1y9 29 | gO4ntri2qwoC25l3q7q9BiFBmeBmvS6I1w9HCZHtB3JnVC/IYDTCYDNTbpGWEOjl 30 | aCKLCA== 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /pkg/provider/ibm/fake/fake.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package fake 15 | 16 | import ( 17 | "fmt" 18 | 19 | "github.com/IBM/go-sdk-core/v5/core" 20 | sm "github.com/IBM/secrets-manager-go-sdk/secretsmanagerv1" 21 | "github.com/google/go-cmp/cmp" 22 | "github.com/google/go-cmp/cmp/cmpopts" 23 | ) 24 | 25 | type IBMMockClient struct { 26 | getSecret func(getSecretOptions *sm.GetSecretOptions) (result *sm.GetSecret, response *core.DetailedResponse, err error) 27 | } 28 | 29 | func (mc *IBMMockClient) GetSecret(getSecretOptions *sm.GetSecretOptions) (result *sm.GetSecret, response *core.DetailedResponse, err error) { 30 | return mc.getSecret(getSecretOptions) 31 | } 32 | 33 | func (mc *IBMMockClient) WithValue(input *sm.GetSecretOptions, output *sm.GetSecret, err error) { 34 | if mc != nil { 35 | mc.getSecret = func(paramReq *sm.GetSecretOptions) (*sm.GetSecret, *core.DetailedResponse, error) { 36 | // type secretmanagerpb.AccessSecretVersionRequest contains unexported fields 37 | // use cmpopts.IgnoreUnexported to ignore all the unexported fields in the cmp. 38 | if !cmp.Equal(paramReq, input, cmpopts.IgnoreUnexported(sm.GetSecret{})) { 39 | return nil, nil, fmt.Errorf("unexpected test argument") 40 | } 41 | return output, nil, err 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1beta1/secretstore_gcpsm_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1beta1 16 | 17 | import ( 18 | esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" 19 | ) 20 | 21 | type GCPSMAuth struct { 22 | // +optional 23 | SecretRef *GCPSMAuthSecretRef `json:"secretRef,omitempty"` 24 | // +optional 25 | WorkloadIdentity *GCPWorkloadIdentity `json:"workloadIdentity,omitempty"` 26 | } 27 | 28 | type GCPSMAuthSecretRef struct { 29 | // The SecretAccessKey is used for authentication 30 | // +optional 31 | SecretAccessKey esmeta.SecretKeySelector `json:"secretAccessKeySecretRef,omitempty"` 32 | } 33 | 34 | type GCPWorkloadIdentity struct { 35 | ServiceAccountRef esmeta.ServiceAccountSelector `json:"serviceAccountRef"` 36 | ClusterLocation string `json:"clusterLocation"` 37 | ClusterName string `json:"clusterName"` 38 | } 39 | 40 | // GCPSMProvider Configures a store to sync secrets using the GCP Secret Manager provider. 41 | type GCPSMProvider struct { 42 | // Auth defines the information necessary to authenticate against GCP 43 | // +optional 44 | Auth GCPSMAuth `json:"auth,omitempty"` 45 | 46 | // ProjectID project where secret is located 47 | ProjectID string `json:"projectID,omitempty"` 48 | } 49 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1alpha1/secretstore_gcpsm_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package v1alpha1 16 | 17 | import ( 18 | esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" 19 | ) 20 | 21 | type GCPSMAuth struct { 22 | // +optional 23 | SecretRef *GCPSMAuthSecretRef `json:"secretRef,omitempty"` 24 | // +optional 25 | WorkloadIdentity *GCPWorkloadIdentity `json:"workloadIdentity,omitempty"` 26 | } 27 | 28 | type GCPSMAuthSecretRef struct { 29 | // The SecretAccessKey is used for authentication 30 | // +optional 31 | SecretAccessKey esmeta.SecretKeySelector `json:"secretAccessKeySecretRef,omitempty"` 32 | } 33 | 34 | type GCPWorkloadIdentity struct { 35 | ServiceAccountRef esmeta.ServiceAccountSelector `json:"serviceAccountRef"` 36 | ClusterLocation string `json:"clusterLocation"` 37 | ClusterName string `json:"clusterName"` 38 | } 39 | 40 | // GCPSMProvider Configures a store to sync secrets using the GCP Secret Manager provider. 41 | type GCPSMProvider struct { 42 | // Auth defines the information necessary to authenticate against GCP 43 | // +optional 44 | Auth GCPSMAuth `json:"auth,omitempty"` 45 | 46 | // ProjectID project where secret is located 47 | ProjectID string `json:"projectID,omitempty"` 48 | } 49 | -------------------------------------------------------------------------------- /deploy/charts/external-secrets/templates/cert-controller-rbac.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.certController.rbac.create -}} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: {{ include "external-secrets.fullname" . }}-cert-controller 6 | labels: 7 | {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} 8 | rules: 9 | - apiGroups: 10 | - "apiextensions.k8s.io" 11 | resources: 12 | - "customresourcedefinitions" 13 | verbs: 14 | - "get" 15 | - "list" 16 | - "watch" 17 | - "update" 18 | - "patch" 19 | - apiGroups: 20 | - "admissionregistration.k8s.io" 21 | resources: 22 | - "validatingwebhookconfigurations" 23 | verbs: 24 | - "get" 25 | - "list" 26 | - "watch" 27 | - "update" 28 | - "patch" 29 | - apiGroups: 30 | - "" 31 | resources: 32 | - "endpoints" 33 | verbs: 34 | - "list" 35 | - "get" 36 | - "watch" 37 | - apiGroups: 38 | - "" 39 | resources: 40 | - "events" 41 | verbs: 42 | - "create" 43 | - "patch" 44 | - apiGroups: 45 | - "" 46 | resources: 47 | - "secrets" 48 | verbs: 49 | - "get" 50 | - "list" 51 | - "watch" 52 | - "update" 53 | - "patch" 54 | --- 55 | apiVersion: rbac.authorization.k8s.io/v1 56 | kind: ClusterRoleBinding 57 | metadata: 58 | name: {{ include "external-secrets.fullname" . }}-cert-controller 59 | labels: 60 | {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} 61 | roleRef: 62 | apiGroup: rbac.authorization.k8s.io 63 | kind: ClusterRole 64 | name: {{ include "external-secrets.fullname" . }}-cert-controller 65 | subjects: 66 | - name: {{ include "external-secrets-cert-controller.serviceAccountName" . }} 67 | namespace: {{ .Release.Namespace | quote }} 68 | kind: ServiceAccount 69 | {{- end }} 70 | -------------------------------------------------------------------------------- /pkg/provider/aws/auth/token_fetcher.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package auth 15 | 16 | import ( 17 | "fmt" 18 | 19 | "github.com/aws/aws-sdk-go/aws/credentials" 20 | authv1 "k8s.io/api/authentication/v1" 21 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | corev1 "k8s.io/client-go/kubernetes/typed/core/v1" 23 | ) 24 | 25 | // mostly taken from: 26 | // https://github.com/aws/secrets-store-csi-driver-provider-aws/blob/main/auth/auth.go#L140-L145 27 | const ( 28 | tokenAudience = "sts.amazonaws.com" 29 | ) 30 | 31 | type authTokenFetcher struct { 32 | Namespace string 33 | ServiceAccount string 34 | k8sClient corev1.CoreV1Interface 35 | } 36 | 37 | // FetchToken satisfies the stscreds.TokenFetcher interface 38 | // it is used to generate service account tokens which are consumed by the aws sdk. 39 | func (p authTokenFetcher) FetchToken(ctx credentials.Context) ([]byte, error) { 40 | log.V(1).Info("fetching token", "ns", p.Namespace, "sa", p.ServiceAccount) 41 | tokRsp, err := p.k8sClient.ServiceAccounts(p.Namespace).CreateToken(ctx, p.ServiceAccount, &authv1.TokenRequest{ 42 | Spec: authv1.TokenRequestSpec{ 43 | Audiences: []string{tokenAudience}, 44 | }, 45 | }, metav1.CreateOptions{}) 46 | if err != nil { 47 | return nil, fmt.Errorf("error creating service account token: %w", err) 48 | } 49 | return []byte(tokRsp.Status.Token), nil 50 | } 51 | -------------------------------------------------------------------------------- /pkg/provider/aws/auth/resolver.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package auth 15 | 16 | import ( 17 | "os" 18 | 19 | "github.com/aws/aws-sdk-go/aws/endpoints" 20 | ) 21 | 22 | const ( 23 | SecretsManagerEndpointEnv = "AWS_SECRETSMANAGER_ENDPOINT" 24 | STSEndpointEnv = "AWS_STS_ENDPOINT" 25 | SSMEndpointEnv = "AWS_SSM_ENDPOINT" 26 | ) 27 | 28 | // ResolveEndpoint returns a ResolverFunc with 29 | // customizable endpoints. 30 | func ResolveEndpoint() endpoints.ResolverFunc { 31 | customEndpoints := make(map[string]string) 32 | if v := os.Getenv(SecretsManagerEndpointEnv); v != "" { 33 | customEndpoints["secretsmanager"] = v 34 | } 35 | if v := os.Getenv(SSMEndpointEnv); v != "" { 36 | customEndpoints["ssm"] = v 37 | } 38 | if v := os.Getenv(STSEndpointEnv); v != "" { 39 | customEndpoints["sts"] = v 40 | } 41 | return ResolveEndpointWithServiceMap(customEndpoints) 42 | } 43 | 44 | func ResolveEndpointWithServiceMap(customEndpoints map[string]string) endpoints.ResolverFunc { 45 | defaultResolver := endpoints.DefaultResolver() 46 | return func(service, region string, opts ...func(*endpoints.Options)) (endpoints.ResolvedEndpoint, error) { 47 | if ep, ok := customEndpoints[service]; ok { 48 | return endpoints.ResolvedEndpoint{ 49 | URL: ep, 50 | }, nil 51 | } 52 | return defaultResolver.EndpointFor(service, region, opts...) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /design/000-template.md: -------------------------------------------------------------------------------- 1 | ```yaml 2 | --- 3 | title: My Shiny New Feature 4 | version: v1alpha1 5 | authors: you, me 6 | creation-date: 2020-09-01 7 | status: draft 8 | --- 9 | ``` 10 | 11 | # My Shiny New Feature 12 | 13 | ## Table of Contents 14 | 15 | 16 | // autogen please 17 | 18 | 19 | 20 | ## Summary 21 | Please provide a summary of this proposal. 22 | 23 | ## Motivation 24 | What is the motivation of this proposal? Why is it useful and relevant? 25 | 26 | ### Goals 27 | What are the goals of this proposal, what's the problem we want to solve? 28 | 29 | ### Non-Goals 30 | What are explicit non-goals of this proposal? 31 | 32 | ## Proposal 33 | How does the proposal look like? 34 | 35 | ### User Stories 36 | How would users use this feature, what are their needs? 37 | 38 | ### API 39 | Please describe the API (CRD or other) and show some examples. 40 | 41 | ### Behavior 42 | How should the new CRD or feature behave? Are there edge cases? 43 | 44 | ### Drawbacks 45 | If we implement this feature, what are drawbacks and disadvantages of this approach? 46 | 47 | ### Acceptance Criteria 48 | What does it take to make this feature producation ready? Please take the time to think about: 49 | * how would you rollout this feature and rollback if it causes harm? 50 | * Test Roadmap: what kinds of tests do we want to ensure a good user experience? 51 | * observability: Do users need to get insights into the inner workings of that feature? 52 | * monitoring: How can users tell whether the feature is working as expected or not? 53 | can we provide dashboards, metrics, reasonable SLIs/SLOs 54 | or example alerts for this feature? 55 | * troubleshooting: How would users want to troubleshoot this particular feature? 56 | Think about different failure modes of this feature. 57 | 58 | ## Alternatives 59 | What alternatives do we have and what are their pros and cons? 60 | 61 | 62 | -------------------------------------------------------------------------------- /pkg/provider/aws/auth/token_fetcher_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package auth 15 | 16 | import ( 17 | "context" 18 | "testing" 19 | 20 | "github.com/stretchr/testify/assert" 21 | authv1 "k8s.io/api/authentication/v1" 22 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 | k8sv1 "k8s.io/client-go/kubernetes/typed/core/v1" 24 | ) 25 | 26 | func TestTokenFetcher(t *testing.T) { 27 | tf := &authTokenFetcher{ 28 | ServiceAccount: "foobar", 29 | Namespace: "example", 30 | k8sClient: &mockK8sV1{}, 31 | } 32 | token, err := tf.FetchToken(context.Background()) 33 | assert.Nil(t, err) 34 | assert.Equal(t, []byte("FAKETOKEN"), token) 35 | } 36 | 37 | // Mock K8s client for creating tokens. 38 | type mockK8sV1 struct { 39 | k8sv1.CoreV1Interface 40 | } 41 | 42 | func (m *mockK8sV1) ServiceAccounts(namespace string) k8sv1.ServiceAccountInterface { 43 | return &mockK8sV1SA{v1mock: m} 44 | } 45 | 46 | // Mock the K8s service account client. 47 | type mockK8sV1SA struct { 48 | k8sv1.ServiceAccountInterface 49 | v1mock *mockK8sV1 50 | } 51 | 52 | func (ma *mockK8sV1SA) CreateToken( 53 | ctx context.Context, 54 | serviceAccountName string, 55 | tokenRequest *authv1.TokenRequest, 56 | opts metav1.CreateOptions, 57 | ) (*authv1.TokenRequest, error) { 58 | return &authv1.TokenRequest{ 59 | Status: authv1.TokenRequestStatus{ 60 | Token: "FAKETOKEN", 61 | }, 62 | }, nil 63 | } 64 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1beta1/secretstore_oracle_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | http://www.apache.org/licenses/LICENSE-2.0 6 | Unless required by applicable law or agreed to in writing, software 7 | distributed under the License is distributed on an "AS IS" BASIS, 8 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9 | See the License for the specific language governing permissions and 10 | limitations under the License. 11 | */ 12 | 13 | package v1beta1 14 | 15 | import ( 16 | esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" 17 | ) 18 | 19 | // Configures an store to sync secrets using a Oracle Vault 20 | // backend. 21 | type OracleProvider struct { 22 | // Region is the region where vault is located. 23 | Region string `json:"region"` 24 | 25 | // Vault is the vault's OCID of the specific vault where secret is located. 26 | Vault string `json:"vault"` 27 | 28 | // Auth configures how secret-manager authenticates with the Oracle Vault. 29 | // If empty, use the instance principal, otherwise the user credentials specified in Auth. 30 | // +optional 31 | Auth *OracleAuth `json:"auth,omitempty"` 32 | } 33 | 34 | type OracleAuth struct { 35 | // Tenancy is the tenancy OCID where user is located. 36 | Tenancy string `json:"tenancy"` 37 | 38 | // User is an access OCID specific to the account. 39 | User string `json:"user"` 40 | 41 | // SecretRef to pass through sensitive information. 42 | SecretRef OracleSecretRef `json:"secretRef"` 43 | } 44 | 45 | type OracleSecretRef struct { 46 | // PrivateKey is the user's API Signing Key in PEM format, used for authentication. 47 | PrivateKey esmeta.SecretKeySelector `json:"privatekey"` 48 | 49 | // Fingerprint is the fingerprint of the API private key. 50 | Fingerprint esmeta.SecretKeySelector `json:"fingerprint"` 51 | } 52 | -------------------------------------------------------------------------------- /apis/externalsecrets/v1alpha1/secretstore_oracle_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | http://www.apache.org/licenses/LICENSE-2.0 6 | Unless required by applicable law or agreed to in writing, software 7 | distributed under the License is distributed on an "AS IS" BASIS, 8 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9 | See the License for the specific language governing permissions and 10 | limitations under the License. 11 | */ 12 | 13 | package v1alpha1 14 | 15 | import ( 16 | esmeta "github.com/external-secrets/external-secrets/apis/meta/v1" 17 | ) 18 | 19 | // Configures an store to sync secrets using a Oracle Vault 20 | // backend. 21 | type OracleProvider struct { 22 | // Region is the region where vault is located. 23 | Region string `json:"region"` 24 | 25 | // Vault is the vault's OCID of the specific vault where secret is located. 26 | Vault string `json:"vault"` 27 | 28 | // Auth configures how secret-manager authenticates with the Oracle Vault. 29 | // If empty, use the instance principal, otherwise the user credentials specified in Auth. 30 | // +optional 31 | Auth *OracleAuth `json:"auth,omitempty"` 32 | } 33 | 34 | type OracleAuth struct { 35 | // Tenancy is the tenancy OCID where user is located. 36 | Tenancy string `json:"tenancy"` 37 | 38 | // User is an access OCID specific to the account. 39 | User string `json:"user"` 40 | 41 | // SecretRef to pass through sensitive information. 42 | SecretRef OracleSecretRef `json:"secretRef"` 43 | } 44 | 45 | type OracleSecretRef struct { 46 | // PrivateKey is the user's API Signing Key in PEM format, used for authentication. 47 | PrivateKey esmeta.SecretKeySelector `json:"privatekey"` 48 | 49 | // Fingerprint is the fingerprint of the API private key. 50 | Fingerprint esmeta.SecretKeySelector `json:"fingerprint"` 51 | } 52 | -------------------------------------------------------------------------------- /e2e/suite/azure/azure_cert.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | limitations under the License. 12 | */ 13 | package azure 14 | 15 | import ( 16 | "fmt" 17 | 18 | // nolint 19 | . "github.com/onsi/ginkgo/v2" 20 | v1 "k8s.io/api/core/v1" 21 | 22 | // nolint 23 | esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1" 24 | "github.com/external-secrets/external-secrets/e2e/framework" 25 | ) 26 | 27 | // azure keyvault type=cert should get a certificate from the api. 28 | var _ = Describe("[azure]", Label("azure", "keyvault", "cert"), func() { 29 | f := framework.New("eso-azure-certtype") 30 | prov := newFromEnv(f) 31 | var certBytes []byte 32 | var certName string 33 | 34 | BeforeEach(func() { 35 | certName = fmt.Sprintf("%s-%s", f.Namespace.Name, "certtest") 36 | prov.CreateCertificate(certName) 37 | certBytes = prov.GetCertificate(certName) 38 | }) 39 | 40 | AfterEach(func() { 41 | prov.DeleteCertificate(certName) 42 | }) 43 | 44 | ff := framework.TableFunc(f, prov) 45 | It("should sync keyvault objects with type=cert", func() { 46 | ff(func(tc *framework.TestCase) { 47 | secretKey := "azkv-cert" 48 | 49 | tc.ExpectedSecret = &v1.Secret{ 50 | Type: v1.SecretTypeOpaque, 51 | Data: map[string][]byte{ 52 | secretKey: certBytes, 53 | }, 54 | } 55 | tc.ExternalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{ 56 | { 57 | SecretKey: secretKey, 58 | RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{ 59 | Key: "cert/" + certName, 60 | }, 61 | }, 62 | } 63 | }) 64 | }) 65 | 66 | }) 67 | -------------------------------------------------------------------------------- /e2e/Makefile: -------------------------------------------------------------------------------- 1 | MAKEFLAGS += --warn-undefined-variables 2 | SHELL := /bin/bash 3 | .SHELLFLAGS := -euo pipefail -c 4 | 5 | KIND_IMG = "kindest/node:v1.23.3@sha256:0df8215895129c0d3221cda19847d1296c4f29ec93487339149333bd9d899e5a" 6 | BUILD_ARGS ?= 7 | 8 | export E2E_IMAGE_REGISTRY ?= ghcr.io/external-secrets/external-secrets-e2e 9 | export GINKGO_LABELS ?= !managed 10 | 11 | start-kind: ## Start kind cluster 12 | kind create cluster \ 13 | --name external-secrets \ 14 | --config kind.yaml \ 15 | --retain \ 16 | --image "$(KIND_IMG)" 17 | 18 | test: e2e-image ## Run e2e tests against current kube context 19 | $(MAKE) -C ../ docker.build \ 20 | IMAGE_REGISTRY=$(IMAGE_REGISTRY) \ 21 | VERSION=$(VERSION) \ 22 | ARCH=amd64 \ 23 | BUILD_ARGS="${BUILD_ARGS} --build-arg TARGETARCH=amd64 --build-arg TARGETOS=linux" 24 | kind load docker-image --name="external-secrets" $(IMAGE_REGISTRY):$(VERSION) 25 | kind load docker-image --name="external-secrets" $(E2E_IMAGE_REGISTRY):$(VERSION) 26 | ./run.sh 27 | 28 | test.managed: e2e-image ## Run e2e tests against current kube context 29 | $(MAKE) -C ../ docker.build \ 30 | VERSION=$(VERSION) \ 31 | ARCH=amd64 \ 32 | BUILD_ARGS="${BUILD_ARGS} --build-arg TARGETARCH=amd64 --build-arg TARGETOS=linux" 33 | $(MAKE) -C ../ docker.push \ 34 | VERSION=$(VERSION) 35 | $(MAKE) -C ../ docker.push \ 36 | IMAGE_REGISTRY=$(E2E_IMAGE_REGISTRY) \ 37 | VERSION=$(VERSION) 38 | ./run.sh 39 | 40 | e2e-bin: 41 | CGO_ENABLED=0 go run github.com/onsi/ginkgo/v2/ginkgo build . 42 | 43 | e2e-image: e2e-bin 44 | -rm -rf ./k8s/deploy 45 | mkdir -p k8s 46 | $(MAKE) -C ../ helm.generate 47 | cp -r ../deploy ./k8s 48 | docker build $(BUILD_ARGS) -t $(E2E_IMAGE_REGISTRY):$(VERSION) . 49 | 50 | stop-kind: ## Stop kind cluster 51 | kind delete cluster \ 52 | --name external-secrets \ 53 | 54 | help: ## displays this help message 55 | @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_\/-]+:.*?## / {printf "\033[34m%-18s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | \ 56 | sort | \ 57 | grep -v '#' 58 | --------------------------------------------------------------------------------