search_index.json 635 KB

1
  1. {"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Sponsored by","text":""},{"location":"#introduction","title":"Introduction","text":"<p>External Secrets Operator is a Kubernetes operator that integrates external secret management systems like AWS Secrets Manager, HashiCorp Vault, Google Secrets Manager, Azure Key Vault, IBM Cloud Secrets Manager, CyberArk Conjur and many more. The operator reads information from external APIs and automatically injects the values into a Kubernetes Secret.</p>"},{"location":"#what-is-the-goal-of-external-secrets-operator","title":"What is the goal of External Secrets Operator?","text":"<p>The goal of External Secrets Operator is to synchronize secrets from external APIs into Kubernetes. ESO is a collection of custom API resources - <code>ExternalSecret</code>, <code>SecretStore</code> and <code>ClusterSecretStore</code> that provide a user-friendly abstraction for the external API that stores and manages the lifecycle of the secrets for you.</p>"},{"location":"#where-to-get-started","title":"Where to get started","text":"<p>To get started, please read through API overview this should give you a high-level overview to understand the API and use-cases. After that please follow one of our guides to get a jump start using the operator. See our getting started guide for installation instructions.</p> <p>For a complete reference of the API types please refer to our API Reference.</p>"},{"location":"#how-to-get-involved","title":"How to get involved","text":"<p>This project is driven by its users and contributors, and we welcome everybody to get involved. Join our meetings, open issues or ask questions in Slack. The success of this project depends on your input: No contribution is too small - even opinions matter!</p> <p>How to get involved:</p> <ul> <li>Bi-weekly Development Meeting every odd week at 8:00 PM Berlin Time on Wednesday (agenda, jitsi call)</li> <li>Kubernetes Slack #external-secrets</li> <li>Contributing Process</li> <li>Twitter</li> </ul>"},{"location":"#kicked-off-by","title":"Kicked off by","text":""},{"location":"eso-blogs/","title":"ESO Blogs","text":"<p>A list of blogs written by people all over the community. Feel free to let us know if you are writing about ESO at some place! We would be happy to mention you here!</p>"},{"location":"eso-blogs/#pulumi-esc-and-external-secrets-operator-the-perfect-solution-for-todays-cloud-native-secret-management","title":"Pulumi ESC and External Secrets Operator: The Perfect Solution for Today's Cloud-Native Secret Management","text":"<p>@Engin Diri walks through the integration of ESO with Pulumi ESC, offering a practical guide for enhancing security from cloud-native application development to infrastructure provisioning. This blog provides a hands-on guide to setting up ESO and Pulumi ESC, and demonstrates how to use them together to manage secrets in a Kubernetes cluster.</p>"},{"location":"eso-blogs/#from-vulnerable-to-unhackable-secrets-management-in-cloud-native-environments","title":"From vulnerable to unhackable: secrets management in cloud-native environments","text":"<p>@Saliha Mallem writes about integrating ESO with IBM Cloud Secrets Manager. In her blog, she outlines the steps to deploy ESO and demonstrates how to use both the Secrets Manager API and the Vault API for seamless integration. The blog is user-friendly and easy to follow.</p>"},{"location":"eso-blogs/#enhancing-kubernetes-security-and-flexibility-with-the-cyberark-conjur-and-eso-integration","title":"Enhancing Kubernetes Security and Flexibility with the CyberArk Conjur and ESO Integration","text":"<p>@szh Writes about using ESO with CyberArk Conjur. He includes detailed steps on how to set up a local environment with Docker Desktop and how to deploy ESO and Conjur OSS on it.</p>"},{"location":"eso-blogs/#comparing-external-secrets-operator-with-secret-storage-csi-as-kubernetes-external-secrets-is-deprecated","title":"Comparing External Secrets Operator with Secret Storage CSI as Kubernetes External Secrets is Deprecated","text":"<p>@riddle writes about choosing ESO when comparing with Secret Store CSI Driver in their specific use case. They show us the relevant differences between the projects when looking at their scenario and requirements while integrating with ArgoCD. Comparing External Secrets Operator with Secret Storage CSI as Kubernetes External Secrets is Deprecated</p>"},{"location":"eso-blogs/#tutorial-getting-started-with-external-secrets-operator-on-kubernetes-using-aws-secrets-manager","title":"Tutorial: Getting Started with External Secrets Operator on Kubernetes using AWS Secrets Manager","text":"<p>Puru writes about getting started using ESO with AWS Secrets Manager. He uses illustrations to explain ESO to new users and get's you to quickly start using ESO, as article is easy to follow along. Getting Started with External Secrets Operator on Kubernetes using AWS Secrets Manager</p>"},{"location":"eso-blogs/#tutorial-how-to-set-external-secrets-with-azure-keyvault","title":"Tutorial: How to Set External-Secrets with Azure KeyVault","text":"<p>Gustavo writes about how to setup ESO with Azure Key Vault and adds an guide on how to make it a bit more secure with OPA (Open Policy Agent). How to Set External-Secrets with Azure KeyVault</p>"},{"location":"eso-blogs/#tutorial-how-to-set-external-secrets-with-gcp-secret-manager","title":"Tutorial: How to Set External-Secrets with GCP Secret Manager","text":"<p>Gustavo writes about how to setup ESO with GCP Secret Manager. He also shows you how to make a simple multi tenant setup with a ClusterSecretStore. How to Set External-Secrets with GCP Secret Manager</p>"},{"location":"eso-blogs/#tutorial-how-to-set-external-secrets-with-hashicorp-vault","title":"Tutorial: How to Set External-Secrets with Hashicorp Vault","text":"<p>Gustavo writes about how to setup ESO with Hashicorp Vault. He also shows you how to make this scale with multiple replicas of the operator and leader election enabled to lead balance handling synchronization work. How to Set External-Secrets with Hashicorp Vault</p>"},{"location":"eso-blogs/#tutorial-how-to-set-external-secrets-with-aws","title":"Tutorial: How to Set External-Secrets with AWS","text":"<p>Gustavo writes about how to setup ESO with AWS Secrets Manager. He also shows you how to limit access and give granular permissions with better policies and roles for your service accounts to use. How to Set External-Secrets with AWS</p>"},{"location":"eso-blogs/#tutorial-how-to-set-external-secrets-with-ibm-secrets-manager","title":"Tutorial: How to Set External-Secrets with IBM Secrets Manager","text":"<p>In this multi-articles series, Xavier writes about how to setup ESO with IBM Secrets Manager using the web user-interface. Xavier also shares how it is integrated into his pipeline scripts. How to Set External-Secrets with IBM Secrets Manager</p>"},{"location":"eso-blogs/#kubernetes-hardening-tutorial-part-2-network","title":"Kubernetes Hardening Tutorial Part 2: Network","text":"<p>Tiexin Guo Writes about Kubernetes hardening in this series of blogs. He mentions ESO as one of the convenient options when dealing with secrets in Kubernetes, and how to use it with AWS Secret Manager using AWS credentials. Kubernetes Hardening Tutorial Part 2: Network</p>"},{"location":"eso-blogs/#tutorial-how-to-manage-secrets-in-openshift-using-vault-and-external-secrets-operator","title":"Tutorial: How to manage secrets in OpenShift using Vault and External Secrets Operator","text":"<p>Balkrishna Pandey published a video tutorial and a blog post on integrating HashiCorp Vault and External Secret Operator (ESO) to manage application secrets on OpenShift Cluster. In this blog, he demonstrates the strength of the <code>ClusterSecretStore</code> functionality, a cluster scoped SecretStore and is global to the Cluster that all <code>ExternalSecrets</code> can reference from all namespaces.</p>"},{"location":"eso-blogs/#tutorial-leverage-aws-secrets-stores-from-eks-fargate-with-external-secrets-operator","title":"Tutorial: Leverage AWS secrets stores from EKS Fargate with External Secrets Operator","text":"<p>In this AWS Containers blog post, Ryan writes about how to leverage External Secret Operator with an EKS Fargate cluster using IAM Roles for Service Accounts (IRSA). This setup supports the requirements of Fargate based workloads. Leverage AWS secrets stores from EKS Fargate with External Secrets Operator</p>"},{"location":"eso-blogs/#cloud-native-secret-management-with-external-secrets-operator","title":"Cloud Native Secret Management with External Secrets Operator","text":"<p>Emin writes about what problems ESO can solve and how to setup ESO on an Amazon EKS Cluster with integrations for AWS Secrets Manager using IAM Roles for Service Accounts (IRSA). In this blog post, there is also a GitHub repository with example codes for everyone to follow this demonstration.</p>"},{"location":"eso-blogs/#external-secrets-operator-integration-with-hashicorp-vault","title":"External Secrets Operator Integration with HashiCorp Vault","text":"<p>Emin writes about integration between External Secrets Operator and HashiCorp Vault with a demonstration on installing ESO and Vault on a Kubernetes Cluster and configuration of the permissions and other integration parts.</p>"},{"location":"eso-blogs/#reversing-the-workflow-with-external-secrets-operators-push-secret-feature","title":"Reversing the Workflow with External Secrets Operator\u2019s Push Secret Feature","text":"<p>Emin writes about the Push Secret feature of ESO and how this new feature reverse the workflow of ESO by pushing Kubernetes secrets to external secret management providers.</p>"},{"location":"eso-blogs/#gcp-secret-manager-with-self-hosted-kubernetes","title":"GCP Secret Manager with self-hosted Kubernetes","text":"<p>Jacek writes about bringing GCP secrets to on-premises cluster through External Secrets Operator intergration with workload identity.</p>"},{"location":"eso-blogs/#injecting-aws-secrets-in-a-kubernetes-cluster-with-external-secrets-operator","title":"Injecting AWS Secrets in a Kubernetes Cluster with External Secrets Operator","text":"<p>Ali writes about integrating AWS Secrets Manager and Parameter Store secrets within an EKS Cluster using ESO. He shows a quick setup of the operator, and how to fetch secrets in a repeatable fashion. The guide is bundled with cool illustrations and code snippets that describe the ESO architecture and injection process</p>"},{"location":"eso-blogs/#encoding-decoding-kubernetes-secrets-eso-advanced-templating","title":"Encoding &amp; Decoding Kubernetes Secrets \u2014 ESO Advanced Templating","text":"<p>Here, Ali briefly introduces templates within ESO and describes some use cases where templating can be crucial. Code snippets are included where needed too.</p>"},{"location":"eso-demos/","title":"ESO Demos","text":"<p>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!</p>"},{"location":"eso-demos/#manage-kubernetes-secrets-with-external-secrets-operator-on-devops-toolkit","title":"Manage Kubernetes Secrets With External Secrets Operator on DevOps Toolkit","text":"<p>Viktor Farvik shows us how to use ESO with GCP provider and explores a simple workflow with the project.</p> <p></p>"},{"location":"eso-demos/#managing-kubernetes-secrets-comparing-external-secrets-operator-and-secrets-store-csi-driver","title":"Managing Kubernetes Secrets: Comparing External Secrets Operator and Secrets Store CSI Driver","text":"<p>Kim Schlesinger and Daniel Hix show us how to install and use both projects, comparing their features and limitations in different situations.</p> <p></p>"},{"location":"eso-demos/#gcp-sm-aws-sm-azure-key-vault-demo","title":"GCP SM + AWS SM + Azure Key Vault Demo","text":"<p>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.</p> <p></p>"},{"location":"eso-demos/#how-to-manage-secrets-in-openshift-using-vault-and-external-secrets-operator","title":"How to manage secrets in OpenShift using Vault and External Secrets Operator","text":"<p>Balkrishna Pandey shows us here how to use ClusterSecretStore and how to integrate ESO with Hashicorp Vault on Openshift.</p> <p></p>"},{"location":"eso-demos/#managing-sensitive-data-in-kubernetes-with-sealed-secrets-and-external-secrets-operator-eso","title":"Managing Sensitive Data in Kubernetes with Sealed Secrets and External Secrets Operator (ESO)","text":"<p>Lukonde Mwila demonstrates how ESO works and how to fetch secrets from AWS Secrets Manager into your Kubernetes cluster.</p> <p></p>"},{"location":"eso-demos/#external-secrets-operator-a-cloud-native-way-to-manage-your-secrets","title":"External Secrets Operator: A Cloud Native way to manage your secrets","text":"<p>Charl Klein gives an overview of the external secrets project, and a walkthrough of getting ESO up and running with Azure Key Vault </p> <p></p>"},{"location":"eso-talks/","title":"ESO Talks","text":"<p>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!</p>"},{"location":"eso-talks/#kubernetes-community-days-uk","title":"Kubernetes Community Days UK","text":""},{"location":"eso-talks/#cncf-community-groups-canada","title":"CNCF Community Groups Canada","text":""},{"location":"eso-talks/#container-days-hamburg","title":"Container Days Hamburg","text":""},{"location":"eso-talks/#kubernetes-community-days-uk-2022","title":"Kubernetes Community Days UK - 2022","text":""},{"location":"eso-talks/#aws-containers-from-the-couch","title":"AWS Containers from the Couch","text":""},{"location":"eso-talks/#fosdem-23-containers-devroom","title":"FOSDEM '23 (Containers devroom)","text":"<p>FOSDEM '23 (Containers devroom)</p>"},{"location":"eso-talks/#form3-tech-podcast-building-and-maintaining-external-secrets-operator","title":"Form3 .tech Podcast - Building and maintaining External Secrets Operator","text":"<p>Podcast and Blog</p>"},{"location":"eso-talks/#enlightning-exploring-external-secrets-operator","title":"\u26a1\ufe0f Enlightning - Exploring External Secrets Operator","text":""},{"location":"eso-talks/#kubecon-eu-23-protecting-your-crown-jewels-with-external-secrets-operator","title":"KubeCon EU '23 - Protecting Your Crown Jewels with External Secrets Operator","text":""},{"location":"eso-tools/","title":"ESO Tools","text":"<p>This page lists tools that are useful for working with External Secrets Operator. help you work with External Secrets Operator better.</p>"},{"location":"eso-tools/#secret2es","title":"secret2es","text":"<p>This tool allows administrators to migrate secrets originally created by argocd-vault-plugin to external-secrets ES object.</p>"},{"location":"provider-passworddepot/","title":"Password Depot","text":"<p>External Secrets Operator integrates with Password Depot API to sync Password Depot to secrets held on the Kubernetes cluster.</p>"},{"location":"provider-passworddepot/#authentication","title":"Authentication","text":"<p>The API requires a username and password. </p> <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: password-depot-secret\n labels: \n type: password-depot\ntype: Opaque \nstringData:\n username: the-username-for-password-depot\n password: the secret password\n</code></pre>"},{"location":"provider-passworddepot/#update-secret-store","title":"Update secret store","text":"<p>Be sure the <code>passworddepot</code> provider is listed in the <code>Kind=SecretStore</code> and host and database are set.</p> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: ClusterSecretStore\nmetadata:\n name: external-secrets-store\nspec:\n\n # provider field contains the configuration to access the provider\n # which contains the secret exactly one provider must be configured.\n provider:\n\n passworddepot:\n host: host-of-password-depot # port is 8714 by default\n database: \"password depot database name\"\n auth:\n SecretRef:\n credentials:\n name: password-depot-secret\n namespace: external-secrets\n</code></pre>"},{"location":"provider-passworddepot/#creating-external-secret","title":"Creating external secret","text":"<p>To sync a Password Depot variable to a secret on the Kubernetes cluster, a <code>Kind=ExternalSecret</code> is needed.</p> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: ExternalSecret\nmetadata:\n name: passworddepot-external-secret-example\nspec:\n refreshInterval: 1h\n\n secretStoreRef:\n kind: SecretStore\n name: passworddepot-secret-store # Must match SecretStore on the cluster\n\n target:\n name: passworddepot-secret-to-create # Name for the secret to be created on the cluster\n creationPolicy: Owner\n\n data:\n - secretKey: username # Key given to the secret to be created on the cluster\n remoteRef: \n key: Production.mySecret\n property: login # field named in passworddepot\n</code></pre>"},{"location":"provider-passworddepot/#using-datafrom","title":"Using DataFrom","text":"<p>DataFrom can be used to get a variable as a JSON string and attempt to parse it.</p> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: ExternalSecret\nmetadata:\n name: passworddepot-external-secret-example\nspec:\n refreshInterval: 1h\n\n secretStoreRef:\n kind: SecretStore\n name: passworddepot-secret-store # Must match SecretStore on the cluster\n\n target:\n name: passworddepot-secret-to-create # Name for the secret to be created on the cluster\n creationPolicy: Owner\n\n # each property in the secret will be used as the secret key in the SECRET k8s target object\n dataFrom:\n - key: \"Production.mySecret\" # Key of the secret\n</code></pre>"},{"location":"provider-passworddepot/#getting-the-kubernetes-secret","title":"Getting the Kubernetes secret","text":"<p>The operator will fetch the project variable and inject it as a <code>Kind=Secret</code>. <pre><code>kubectl get secret passworddepot-secret-to-create -o jsonpath='{.data.secretKey}' | base64 -d\n</code></pre></p>"},{"location":"api/clusterexternalsecret/","title":"ClusterExternalSecret","text":"<p>The <code>ClusterExternalSecret</code> is a cluster scoped resource that can be used to manage <code>ExternalSecret</code> resources in specific namespaces.</p> <p>With <code>namespaceSelectors</code> you can select namespaces in which the ExternalSecret should be created. If there is a conflict with an existing resource the controller will error out.</p>"},{"location":"api/clusterexternalsecret/#example","title":"Example","text":"<p>Below is an example of the <code>ClusterExternalSecret</code> in use.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ClusterExternalSecret\nmetadata:\n name: \"hello-world\"\nspec:\n # The name to be used on the ExternalSecrets\n externalSecretName: \"hello-world-es\"\n\n # This is a basic label selector to select the namespaces to deploy ExternalSecrets to.\n # you can read more about them here https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#resources-that-support-set-based-requirements\n # Deprecated: Use namespaceSelectors instead.\n # namespaceSelector:\n # matchLabels:\n # cool: label\n\n # This is a list of basic label selector to select the namespaces to deploy ExternalSecrets to.\n # you can read more about them here https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#resources-that-support-set-based-requirements\n # The list is OR'd together, so if any of the namespaceSelectors match the namespace,\n # the ExternalSecret will be deployed to that namespace.\n namespaceSelectors:\n - matchLabels:\n cool: label\n\n # How often the ClusterExternalSecret should reconcile itself\n # This will decide how often to check and make sure that the ExternalSecrets exist in the matching namespaces\n refreshTime: \"1m\"\n\n # This is the spec of the ExternalSecrets to be created\n # The content of this was taken from our ExternalSecret example\n externalSecretSpec:\n secretStoreRef:\n name: secret-store-name\n kind: SecretStore\n\n refreshInterval: \"1h\"\n target:\n name: my-secret\n creationPolicy: 'Merge'\n template:\n type: kubernetes.io/dockerconfigjson\n\n metadata:\n annotations: {}\n labels: {}\n data:\n config.yml: |\n endpoints:\n - https://{{ .data.user }}:{{ .data.password }}@api.exmaple.com\n templateFrom:\n - configMap:\n name: alertmanager\n items:\n - key: alertmanager.yaml\n data:\n - secretKey: secret-key-to-be-managed\n remoteRef:\n key: provider-key\n version: provider-key-version\n property: provider-key-property\n dataFrom:\n - key: provider-key\n version: provider-key-version\n property: provider-key-property\n\nstatus:\n # This will list any namespaces where the creation of the ExternalSecret failed\n # This will not list any issues with the ExternalSecrets, you will have to check the\n # ExternalSecrets to see any issues with them.\n failedNamespaces:\n - namespace: \"matching-ns-1\"\n # This is one of the possible messages, and likely the most common\n reason: \"external secret already exists in namespace\"\n\n # You can find all matching and successfully deployed namespaces here\n provisionedNamespaces:\n - \"matching-ns-3\"\n - \"matching-ns-2\"\n\n # The condition can be Ready, PartiallyReady, or NotReady \n # PartiallyReady would indicate an error in 1 or more namespaces\n # NotReady would indicate errors in all namespaces meaning all ExternalSecrets resulted in errors\n conditions:\n - type: PartiallyReady\n status: \"True\"\n lastTransitionTime: \"2022-01-12T12:33:02Z\"\n</code></pre>"},{"location":"api/clusterexternalsecret/#deprecations","title":"Deprecations","text":""},{"location":"api/clusterexternalsecret/#namespaceselector","title":"namespaceSelector","text":"<p>The field <code>namespaceSelector</code> has been deprecated in favor of <code>namespaceSelectors</code> and will be removed in a future version.</p>"},{"location":"api/clustersecretstore/","title":"ClusterSecretStore","text":"<p>The <code>ClusterSecretStore</code> is a cluster scoped SecretStore that can be referenced by all <code>ExternalSecrets</code> from all namespaces. Use it to offer a central gateway to your secret backend.</p>"},{"location":"api/clustersecretstore/#example","title":"Example","text":"<p>For a full list of supported fields see spec or dig into our guides.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ClusterSecretStore\nmetadata:\n name: example\nspec:\n # Used to select the correct ESO controller (think: ingress.ingressClassName)\n # The ESO controller is instantiated with a specific controller name\n # and filters ES based on this property\n # Optional\n controller: dev\n\n # provider field contains the configuration to access the provider\n # which contains the secret exactly one provider must be configured.\n provider:\n # (1): AWS Secrets Manager\n # aws configures this store to sync secrets using AWS Secret Manager provider\n aws:\n service: SecretsManager\n # Role is a Role ARN which the SecretManager provider will assume\n role: iam-role\n # AWS Region to be used for the provider\n region: eu-central-1\n # Auth defines the information necessary to authenticate against AWS\n auth:\n # Getting the accessKeyID and secretAccessKey from an already created Kubernetes Secret\n secretRef:\n accessKeyIDSecretRef:\n name: awssm-secret\n key: access-key\n secretAccessKeySecretRef:\n name: awssm-secret\n key: secret-access-key\n # IAM roles for service accounts\n # https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html\n jwt:\n serviceAccountRef:\n name: my-serviceaccount\n namespace: sa-namespace\n\n vault:\n server: \"https://vault.acme.org\"\n # Path is the mount path of the Vault KV backend endpoint\n # Used as a path prefix for the external secret key\n path: \"secret\"\n # Version is the Vault KV secret engine version.\n # This can be either \"v1\" or \"v2\", defaults to \"v2\"\n version: \"v2\"\n # vault enterprise namespace: https://www.vaultproject.io/docs/enterprise/namespaces\n namespace: \"a-team\"\n # base64 encoded string of certificate\n caBundle: \"...\"\n # Instead of caBundle you can also specify a caProvider\n # this will retrieve the cert from a Secret or ConfigMap\n caProvider:\n # Can be Secret or ConfigMap\n type: \"Secret\"\n # namespace is mandatory for ClusterSecretStore and not relevant for SecretStore\n namespace: \"my-cert-secret-namespace\"\n name: \"my-cert-secret\"\n key: \"cert-key\"\n auth:\n # static token: https://www.vaultproject.io/docs/auth/token\n tokenSecretRef:\n name: \"my-secret\"\n namespace: \"secret-admin\"\n key: \"vault-token\"\n\n # AppRole auth: https://www.vaultproject.io/docs/auth/approle\n appRole:\n path: \"approle\"\n roleId: \"db02de05-fa39-4855-059b-67221c5c2f63\"\n secretRef:\n name: \"my-secret\"\n namespace: \"secret-admin\"\n key: \"vault-token\"\n\n # Kubernetes auth: https://www.vaultproject.io/docs/auth/kubernetes\n kubernetes:\n mountPath: \"kubernetes\"\n role: \"demo\"\n # Optional service account reference\n serviceAccountRef:\n name: \"my-sa\"\n namespace: \"secret-admin\"\n # Optional secret field containing a Kubernetes ServiceAccount JWT\n # used for authenticating with Vault\n secretRef:\n name: \"my-secret\"\n namespace: \"secret-admin\"\n key: \"vault\"\n\n # (2): GCP Secret Manager\n gcpsm:\n # Auth defines the information necessary to authenticate against GCP by getting\n # the credentials from an already created Kubernetes Secret.\n auth:\n secretRef:\n secretAccessKeySecretRef:\n name: gcpsm-secret\n key: secret-access-credentials\n namespace: example\n projectID: myproject\n\n # (3): Kubernetes provider\n kubernetes:\n server:\n url: \"https://myapiserver.tld\"\n caProvider:\n type: Secret\n name: my-cluster-secrets\n namespace: example\n key: ca.crt\n auth:\n serviceAccount:\n name: \"example-sa\"\n namespace: \"example\"\n\n # (4): Oracle provider\n oracle:\n # The vault OCID\n vault: ocid1.vault.oc1.eu-frankfurt-1.aaa1aaaaaaaaa.aaaaaaaaaaaaaa1aaaaaaa111aaaaaaaaaaaaaaaa\n # The vault region\n region: eu-frankfurt-1\n auth:\n # The user OCID\n user: ocid1.user.oc1..aaa1aaaaaaaaa.aaaaaaaaaaaaaa1aaaaaaa111aaaaaaaaaaaaaaaa\n # The tenancy OCID\n tenancy: ocid1.tenancy.oc1..aaa1aaaaaaaaa.aaaaaaaaaaaaaa1aaaaaaa111aaaaaaaaaaaaaaaa\n secretRef:\n privatekey:\n # The secret that contains your privatekey\n name: oci-secret-name\n key: privateKey\n namespace: example-namespace\n fingerprint:\n # The secret that contains your fingerprint\n name: oci-secret-name\n key: fingerprint\n namespace: example-namespace\n\n # (TODO): add more provider examples here\n\n # Conditions about namespaces in which the ClusterSecretStore is usable for ExternalSecrets\n conditions:\n # Options are namespaceSelector, namespaces or namespacesRegex\n - namespaceSelector:\n matchLabels:\n my.namespace.io/some-label: \"value\" # Only namespaces with that label will work\n\n - namespaces:\n - \"namespace-a\"\n - \"namespace-b\"\n\n # Namespace regexes are useful for policy management or when external tools auto-generate namespaces with prefixes/suffixes\n - namespaceRegexes:\n - \"namespace-a-.*\" # All namespaces prefixed by namespace-a- will work\n - \"namespace-b-.*\" # All namespaces prefixed by namespace-b- will work\n\n # conditions needs only one of the conditions to meet for the CSS to be usable in the namespace.\n\nstatus:\n # Standard condition schema\n conditions:\n # SecretStore ready condition indicates the given store is in ready\n # state and able to referenced by ExternalSecrets\n # If the `status` of this condition is `False`, ExternalSecret controllers\n # should prevent attempts to fetch secrets\n - type: Ready\n status: \"False\"\n reason: \"ConfigError\"\n message: \"SecretStore validation failed\"\n lastTransitionTime: \"2019-08-12T12:33:02Z\"\n</code></pre>"},{"location":"api/components/","title":"Components","text":""},{"location":"api/components/#overview","title":"Overview","text":"<p>Exernal Secrets comes with three components: <code>Core Controller</code>, <code>Webhook</code> and <code>Cert Controller</code>.</p> <p>This is due to the need to implement conversion webhooks in order to convert custom resources between api versions and to provide a ValidatingWebhook for the <code>ExternalSecret</code> and <code>SecretStore</code> resources.</p> <p>These features are optional but highly recommended. You can disable them with helm chart values <code>certController.create=false</code> and <code>webhook.create=false</code>.</p> <p> </p>"},{"location":"api/components/#tls-bootstrap","title":"TLS Bootstrap","text":"<p>Cert-controller is responsible for (1) generating TLS credentials which will be used by the webhook component and (2) injecting the certificate as <code>caBundle</code> into <code>Kind=CustomResourceDefinition</code> for conversion webhooks and <code>Kind=ValidatingWebhookConfiguration</code> for validating admission webhook. The TLS credentials are stored in a <code>Kind=Secret</code> which is consumed by the webhook.</p> <p></p>"},{"location":"api/controller-options/","title":"Controller Options","text":"<p>The external-secrets binary includes three components: <code>core controller</code>, <code>certcontroller</code> and <code>webook</code>.</p>"},{"location":"api/controller-options/#core-controller-flags","title":"Core Controller Flags","text":"<p>The core controller is invoked without a subcommand and can be configured with the following flags:</p> Name Type Default Description <code>--client-burst</code> int uses rest client default (10) Maximum Burst allowed to be passed to rest.Client <code>--client-qps</code> float32 uses rest client default (5) QPS configuration to be passed to rest.Client <code>--concurrent</code> int 1 The number of concurrent reconciles. <code>--controller-class</code> string default The controller is instantiated with a specific controller name and filters ES based on this property <code>--enable-cluster-external-secret-reconciler</code> boolean true Enables the cluster external secret reconciler. <code>--enable-cluster-store-reconciler</code> boolean true Enables the cluster store reconciler. <code>--enable-push-secret-reconciler</code> boolean true Enables the push secret reconciler. <code>--enable-secrets-caching</code> boolean false Enables the secrets caching for external-secrets pod. <code>--enable-configmaps-caching</code> boolean false Enables the ConfigMap caching for external-secrets pod. <code>--enable-flood-gate</code> boolean true Enable flood gate. External secret will be reconciled only if the ClusterStore or Store have an healthy or unknown state. <code>--enable-extended-metric-labels</code> boolean true Enable recommended kubernetes annotations as labels in metrics. <code>--enable-leader-election</code> boolean false Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager. <code>--experimental-enable-aws-session-cache</code> boolean false Enable experimental AWS session cache. External secret will reuse the AWS session without creating a new one on each request. <code>--help</code> help for external-secrets <code>--loglevel</code> string info loglevel to use, one of: debug, info, warn, error, dpanic, panic, fatal <code>--zap-time-encoding</code> string epoch loglevel to use, one of: epoch, millis, nano, iso8601, rfc3339, rfc3339nano <code>--metrics-addr</code> string :8080 The address the metric endpoint binds to. <code>--namespace</code> string - watch external secrets scoped in the provided namespace only. ClusterSecretStore can be used but only work if it doesn't reference resources from other namespaces <code>--store-requeue-interval</code> duration 5m0s Default Time duration between reconciling (Cluster)SecretStores"},{"location":"api/controller-options/#cert-controller-flags","title":"Cert Controller Flags","text":"Name Type Default Descripton <code>--crd-requeue-interval</code> duration 5m0s Time duration between reconciling CRDs for new certs <code>--enable-leader-election</code> boolean false Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager. <code>--healthz-addr</code> string :8081 The address the health endpoint binds to. <code>--help</code> help for certcontroller <code>--loglevel</code> string info loglevel to use, one of: debug, info, warn, error, dpanic, panic, fatal <code>--zap-time-encoding</code> string epoch time encoding to use, one of: epoch, millis, nano, iso8601, rfc3339, rfc3339nano <code>--metrics-addr</code> string :8080 The address the metric endpoint binds to. <code>--secret-name</code> string external-secrets-webhook Secret to store certs for webhook <code>--secret-namespace</code> string default namespace of the secret to store certs <code>--service-name</code> string external-secrets-webhook Webhook service name <code>--service-namespace</code> string default Webhook service namespace"},{"location":"api/controller-options/#webhook-flags","title":"Webhook Flags","text":"Name Type Default Description <code>--cert-dir</code> string /tmp/k8s-webhook-server/serving-certs path to check for certs <code>--check-interval</code> duration 5m0s certificate check interval <code>--dns-name</code> string localhost DNS name to validate certificates with <code>--healthz-addr</code> string :8081 The address the health endpoint binds to. <code>--help</code> help for webhook <code>--loglevel</code> string info loglevel to use, one of: debug, info, warn, error, dpanic, panic, fatal <code>--zap-time-encoding</code> string epoch time encoding to use, one of: epoch, millis, nano, iso8601, rfc3339, rfc3339nano <code>--lookahead-interval</code> duration 2160h0m0s (90d) certificate check interval <code>--metrics-addr</code> string :8080 The address the metric endpoint binds to. <code>--port</code> number 10250 Port number that the webhook server will serve. <code>--tls-ciphers</code> string comma separated list of tls ciphers allowed. This does not apply to TLS 1.3 as the ciphers are selected automatically. The order of this list does not give preference to the ciphers, the ordering is done automatically. Full lists of available ciphers can be found at https://pkg.go.dev/crypto/tls#pkg-constants. E.g. 'TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256' <code>--tls-min-version</code> string 1.2 minimum version of TLS supported."},{"location":"api/externalsecret/","title":"ExternalSecret","text":"<p>The <code>ExternalSecret</code> describes what data should be fetched, how the data should be transformed and saved as a <code>Kind=Secret</code>:</p> <ul> <li>tells the operator what secrets should be synced by using <code>spec.data</code> to explicitly sync individual keys or use <code>spec.dataFrom</code> to get all values from the external API.</li> <li>you can specify how the secret should look like by specifying a <code>spec.target.template</code></li> </ul>"},{"location":"api/externalsecret/#template","title":"Template","text":"<p>When the controller reconciles the <code>ExternalSecret</code> it will use the <code>spec.template</code> as a blueprint to construct a new <code>Kind=Secret</code>. You can use golang templates to define the blueprint and use template functions to transform secret values. You can also pull in <code>ConfigMaps</code> that contain golang-template data using <code>templateFrom</code>. See advanced templating for details.</p>"},{"location":"api/externalsecret/#update-behavior","title":"Update Behavior","text":"<p>The <code>Kind=Secret</code> is updated when:</p> <ul> <li>the <code>spec.refreshInterval</code> has passed and is not <code>0</code></li> <li>the <code>ExternalSecret</code>'s <code>labels</code> or <code>annotations</code> are changed</li> <li>the <code>ExternalSecret</code>'s <code>spec</code> has been changed</li> </ul> <p>You can trigger a secret refresh by using kubectl or any other kubernetes api client:</p> <pre><code>kubectl annotate es my-es force-sync=$(date +%s) --overwrite\n</code></pre>"},{"location":"api/externalsecret/#features","title":"Features","text":"<p>Individual features are described in the Guides section:</p> <ul> <li>Find many secrets / Extract from structured data</li> <li>Templating</li> <li>Using Generators</li> <li>Secret Ownership and Deletion</li> <li>Key Rewriting</li> <li>Decoding Strategy</li> </ul>"},{"location":"api/externalsecret/#example","title":"Example","text":"<p>Take a look at an annotated example to understand the design behind the <code>ExternalSecret</code>.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: \"hello-world\"\n\n # labels and annotations are copied over to the\n # secret that will be created\n labels:\n acme.org/owned-by: \"q-team\"\n annotations:\n acme.org/sha: 1234\n\nspec:\n\n # Optional, SecretStoreRef defines the default SecretStore to use when fetching the secret data.\n secretStoreRef:\n name: aws-store\n kind: SecretStore # or ClusterSecretStore\n\n # RefreshInterval is the amount of time before the values reading again from the SecretStore provider\n # Valid time units are \"ns\", \"us\" (or \"\u00b5s\"), \"ms\", \"s\", \"m\", \"h\" (from time.ParseDuration)\n # May be set to zero to fetch and create it once\n refreshInterval: \"1h\"\n\n # the target describes the secret that shall be created\n # there can only be one target per ExternalSecret\n target:\n\n # The secret name of the resource\n # Defaults to .metadata.name of the ExternalSecret\n # It is immutable\n name: application-config\n\n # Specifies the ExternalSecret ownership details in the created Secret. Options:\n # - Owner: (default) Creates the Secret and sets .metadata.ownerReferences. If the ExternalSecret is deleted, the Secret will also be deleted.\n # - Merge: Does not create the Secret but merges data fields into the existing Secret (expects the Secret to already exist).\n # - Orphan: Creates the Secret but does not set .metadata.ownerReferences. If the Secret already exists, it will be updated.\n # - None: Does not create or update the Secret (reserved for future use with injector).\n creationPolicy: Merge\n\n # Specifies what happens to the Secret when data fields are deleted from the provider (e.g., Vault, AWS Parameter Store). Options:\n # - Retain: (default) Retains the Secret if all Secret data fields have been deleted from the provider.\n # - Delete: Removes the Secret if all Secret data fields from the provider are deleted.\n # - Merge: Removes keys from the Secret but not the Secret itself.\n deletionPolicy: Retain\n\n # Specify a blueprint for the resulting Kind=Secret\n template:\n type: kubernetes.io/dockerconfigjson # or TLS...\n\n metadata:\n annotations: {}\n labels: {}\n\n # Use inline templates to construct your desired config file that contains your secret\n data:\n config.yml: |\n database:\n connection: postgres://{{ .username }}:{{ .password }}@{{ .database_host }}:5432/payments\n\n # Uses an existing template from configmap\n # Secret is fetched, merged and templated within the referenced configMap data\n # It does not update the configmap, it creates a secret with: data[\"alertmanager.yml\"] = ...result...\n templateFrom:\n - configMap:\n name: application-config-tmpl\n items:\n - key: config.yml\n\n # Data defines the connection between the Kubernetes Secret keys and the Provider data\n data:\n - secretKey: username\n remoteRef:\n key: database-credentials\n version: v1\n property: username\n decodingStrategy: None # can be None, Base64, Base64URL or Auto\n\n # define the source of the secret. Can be a SecretStore or a Generator kind\n sourceRef:\n # point to a SecretStore that should be used to fetch a secret.\n # must be defined if no spec.secretStoreRef is defined.\n storeRef:\n name: aws-secretstore\n kind: ClusterSecretStore\n\n # Used to fetch all properties from the Provider key\n # If multiple dataFrom are specified, secrets are merged in the specified order\n # Can be defined using sourceRef.generatorRef or extract / find\n # Both use cases are exemplified below\n dataFrom:\n - sourceRef:\n generatorRef:\n apiVersion: generators.external-secrets.io/v1alpha1\n kind: ECRAuthorizationToken\n name: \"my-ecr\"\n #Or\n dataFrom:\n - extract:\n key: database-credentials\n version: v1\n property: data\n conversionStrategy: Default\n decodingStrategy: Auto\n rewrite:\n - regexp:\n source: \"exp-(.*?)-ression\"\n target: \"rewriting-${1}-with-groups\"\n - find:\n path: path-to-filter\n name:\n regexp: \".*foobar.*\"\n tags:\n foo: bar\n conversionStrategy: Unicode\n decodingStrategy: Base64\n rewrite:\n - regexp:\n source: \"foo\"\n target: \"bar\"\n\nstatus:\n # refreshTime is the time and date the external secret was fetched and\n # the target secret updated\n refreshTime: \"2019-08-12T12:33:02Z\"\n # Standard condition schema\n conditions:\n # ExternalSecret ready condition indicates the secret is ready for use.\n # This is defined as:\n # - The target secret exists\n # - The target secret has been refreshed within the last refreshInterval\n # - The target secret content is up-to-date based on any target templates\n - type: Ready\n status: \"True\" # False if last refresh was not successful\n reason: \"SecretSynced\"\n message: \"Secret was synced\"\n lastTransitionTime: \"2019-08-12T12:33:02Z\"\n</code></pre>"},{"location":"api/metrics/","title":"Metrics","text":"<p>The External Secrets Operator exposes its Prometheus metrics in the <code>/metrics</code> path. To enable it, set the <code>serviceMonitor.enabled</code> Helm flag to <code>true</code>.</p> <p>If you are using a different monitoring tool that also needs a <code>/metrics</code> endpoint, you can set the <code>metrics.service.enabled</code> Helm flag to <code>true</code>. In addition you can also set <code>webhook.metrics.service.enabled</code> and <code>certController.metrics.service.enabled</code> to scrape the other components.</p> <p>The Operator has the controller-runtime metrics inherited from kubebuilder plus some custom metrics with a resource name prefix, such as <code>externalsecret_</code>.</p>"},{"location":"api/metrics/#cluster-external-secret-metrics","title":"Cluster External Secret Metrics","text":"Name Type Description <code>clusterexternalsecret_status_condition</code> Gauge The status condition of a specific Cluster External Secret <code>clusterexternalsecret_reconcile_duration</code> Gauge The duration time to reconcile the Cluster External Secret"},{"location":"api/metrics/#external-secret-metrics","title":"External Secret Metrics","text":"Name Type Description <code>externalsecret_provider_api_calls_count</code> Counter Number of API calls made to an upstream secret provider API. The metric provides a <code>provider</code>, <code>call</code> and <code>status</code> labels. <code>externalsecret_sync_calls_total</code> Counter Total number of the External Secret sync calls <code>externalsecret_sync_calls_error</code> Counter Total number of the External Secret sync errors <code>externalsecret_status_condition</code> Gauge The status condition of a specific External Secret <code>externalsecret_reconcile_duration</code> Gauge The duration time to reconcile the External Secret"},{"location":"api/metrics/#cluster-secret-store-metrics","title":"Cluster Secret Store Metrics","text":"Name Type Description <code>clustersecretstore_status_condition</code> Gauge The status condition of a specific Cluster Secret Store <code>clustersecretstore_reconcile_duration</code> Gauge The duration time to reconcile the Cluster Secret Store"},{"location":"api/metrics/#secret-store-metrics","title":"Secret Store Metrics","text":"Name Type Description <code>secretstore_status_condition</code> Gauge The status condition of a specific Secret Store <code>secretstore_reconcile_duration</code> Gauge The duration time to reconcile the Secret Store"},{"location":"api/metrics/#controller-runtime-metrics","title":"Controller Runtime Metrics","text":"<p>See the kubebuilder documentation on the default exported metrics by controller-runtime.</p>"},{"location":"api/metrics/#dashboard","title":"Dashboard","text":"<p>We provide a Grafana Dashboard that gives you an overview of External Secrets Operator:</p> <p> </p>"},{"location":"api/metrics/#service-level-indicators-and-alerts","title":"Service Level Indicators and Alerts","text":"<p>We find the following Service Level Indicators (SLIs) useful when operating ESO. They should give you a good starting point and hints to develop your own Service Level Objectives (SLOs).</p>"},{"location":"api/metrics/#webhook-http-status-codes","title":"Webhook HTTP Status Codes","text":"<p>The webhook HTTP status code indicates that a HTTP Request was answered successfully or not. If the Webhook pod is not able to serve the requests properly then that failure may cascade down to the controller or any other user of <code>kube-apiserver</code>.</p> <p>SLI Example: request error percentage. <pre><code>sum(increase(controller_runtime_webhook_requests_total{service=~\"external-secrets.*\",code=\"500\"}[1m]))\n/\nsum(increase(controller_runtime_webhook_requests_total{service=~\"external-secrets.*\"}[1m]))\n</code></pre></p>"},{"location":"api/metrics/#webhook-http-request-latency","title":"Webhook HTTP Request Latency","text":"<p>If the webhook server is not able to respond in time then that may cause a timeout at the client. This failure may cascade down to the controller or any other user of <code>kube-apiserver</code>.</p> <p>SLI Example: p99 across all webhook requests. <pre><code>histogram_quantile(0.99,\n sum(rate(controller_runtime_webhook_latency_seconds_bucket{service=~\"external-secrets.*\"}[5m])) by (le)\n)\n</code></pre></p>"},{"location":"api/metrics/#controller-workqueue-depth","title":"Controller Workqueue Depth","text":"<p>If the workqueue depth is &gt; 0 for a longer period of time then this is an indicator for the controller not being able to reconcile resources in time. I.e. delivery of secret updates is delayed.</p> <p>Note: when a controller is restarted, then <code>queue length = total number of resources</code>. Make sure to measure the time it takes for the controller to fully reconcile all secrets after a restart. In large clusters this may take a while, make sure to define an acceptable timeframe to fully reconcile all resources.</p> <pre><code>sum(\n workqueue_depth{service=~\"external-secrets.*\"}\n) by (name)\n</code></pre>"},{"location":"api/metrics/#controller-reconcile-latency","title":"Controller Reconcile Latency","text":"<p>The controller should be able to reconcile resources within a reasonable timeframe. When latency is high secret delivery may impacted.</p> <p>SLI Example: p99 across all controllers. <pre><code>histogram_quantile(0.99,\n sum(rate(controller_runtime_reconcile_time_seconds_bucket{service=~\"external-secrets.*\"}[5m])) by (le)\n)\n</code></pre></p>"},{"location":"api/metrics/#controller-reconcile-error","title":"Controller Reconcile Error","text":"<p>The controller should be able to reconcile resources without errors. When errors occurr secret delivery may be impacted which could cascade down to the secret consuming applications.</p> <pre><code>sum(increase(\n controller_runtime_reconcile_total{service=~\"external-secrets.*\",controller=~\"$controller\",result=\"error\"}[1m])\n) by (result)\n</code></pre>"},{"location":"api/pushsecret/","title":"PushSecret","text":"<p>The <code>PushSecret</code> is namespaced and it describes what data should be pushed to the secret provider.</p> <ul> <li>tells the operator what secrets should be pushed by using <code>spec.selector</code>.</li> <li>you can specify what secret keys should be pushed by using <code>spec.data</code>.</li> <li>you can also template the resulting property values using templating.</li> </ul> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: pushsecret-example # Customisable\n namespace: default # Same of the SecretStores\nspec:\n updatePolicy: Replace # Policy to overwrite existing secrets in the provider on sync\n deletionPolicy: Delete # the provider' secret will be deleted if the PushSecret is deleted\n refreshInterval: 10s # Refresh interval for which push secret will reconcile\n secretStoreRefs: # A list of secret stores to push secrets to\n - name: aws-parameterstore\n kind: SecretStore\n selector:\n secret:\n name: pokedex-credentials # Source Kubernetes secret to be pushed\n # Alternatively, you can point to a generator that produces values to be pushed\n generatorRef:\n apiVersion: external-secrets.io/v1alpha1\n kind: ECRAuthorizationToken\n name: prod-registry-credentials\n template:\n metadata:\n annotations: { }\n labels: { }\n data:\n best-pokemon: \"{{ .best-pokemon | toString | upper }} is the really best!\"\n # Uses an existing template from configmap\n # Secret is fetched, merged and templated within the referenced configMap data\n # It does not update the configmap, it creates a secret with: data[\"alertmanager.yml\"] = ...result...\n templateFrom:\n - configMap:\n name: application-config-tmpl\n items:\n - key: config.yml\n data:\n - conversionStrategy: None # Also supports the ReverseUnicode strategy\n match:\n secretKey: best-pokemon # Source Kubernetes secret key to be pushed\n remoteRef:\n remoteKey: my-first-parameter # Remote reference (where the secret is going to be pushed)\n</code></pre>"},{"location":"api/pushsecret/#templating","title":"Templating","text":"<p>When the controller reconciles the <code>PushSecret</code> it will use the <code>spec.template</code> as a blueprint to construct a new property. You can use golang templates to define the blueprint and use template functions to transform the defined properties. You can also pull in <code>ConfigMaps</code> that contain golang-template data using <code>templateFrom</code>. See advanced templating for details.</p>"},{"location":"api/secretstore/","title":"SecretStore","text":"<p>The <code>SecretStore</code> is namespaced and specifies how to access the external API. The SecretStore maps to exactly one instance of an external API.</p> <p>By design, SecretStores are bound to a namespace and can not reference resources across namespaces. If you want to design cross-namespace SecretStores you must use ClusterSecretStores which do not have this limitation.</p>"},{"location":"api/secretstore/#example","title":"Example","text":"<p>For a full list of supported fields see spec or dig into our guides.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: example\n namespace: example-ns\nspec:\n\n # Used to select the correct ESO controller (think: ingress.ingressClassName)\n # The ESO controller is instantiated with a specific controller name\n # and filters ES based on this property\n # Optional\n controller: dev\n\n # You can specify retry settings for the http connection\n # these fields allow you to set a maxRetries before failure, and\n # an interval between the retries.\n # Current supported providers: AWS, Hashicorp Vault, IBM\n retrySettings:\n maxRetries: 5\n retryInterval: \"10s\"\n\n # provider field contains the configuration to access the provider\n # which contains the secret exactly one provider must be configured.\n provider:\n\n # (1): AWS Secrets Manager\n # aws configures this store to sync secrets using AWS Secret Manager provider\n aws:\n service: SecretsManager\n # Role is a Role ARN which the SecretManager provider will assume\n role: iam-role\n # AWS Region to be used for the provider\n region: eu-central-1\n # Auth defines the information necessary to authenticate against AWS by\n # getting the accessKeyID and secretAccessKey from an already created Kubernetes Secret\n auth:\n secretRef:\n accessKeyIDSecretRef:\n name: awssm-secret\n key: access-key\n secretAccessKeySecretRef:\n name: awssm-secret\n key: secret-access-key\n\n # (2) Hashicorp Vault\n vault:\n server: \"https://vault.acme.org\"\n # Path is the mount path of the Vault KV backend endpoint\n # Used as a path prefix for the external secret key\n path: \"secret\"\n # Version is the Vault KV secret engine version.\n # This can be either \"v1\" or \"v2\", defaults to \"v2\"\n version: \"v2\"\n # vault enterprise namespace: https://www.vaultproject.io/docs/enterprise/namespaces\n namespace: \"a-team\"\n # base64 encoded string of certificate\n caBundle: \"...\"\n # Instead of caBundle you can also specify a caProvider\n # this will retrieve the cert from a Secret or ConfigMap\n caProvider:\n # Can be Secret or ConfigMap\n type: \"Secret\"\n name: \"my-cert-secret\"\n key: \"cert-key\"\n # client side related TLS communication, when the Vault server requires mutual authentication\n tls:\n clientCert:\n namespace: ...\n name: \"my-cert-secret\"\n key: \"tls.crt\"\n secretRef:\n namespace: ...\n name: \"my-cert-secret\"\n key: \"tls.key\"\n\n auth:\n # static token: https://www.vaultproject.io/docs/auth/token\n tokenSecretRef:\n name: \"my-secret\"\n key: \"vault-token\"\n\n # AppRole auth: https://www.vaultproject.io/docs/auth/approle\n appRole:\n path: \"approle\"\n roleId: \"db02de05-fa39-4855-059b-67221c5c2f63\"\n secretRef:\n name: \"my-secret\"\n key: \"vault-token\"\n\n # Kubernetes auth: https://www.vaultproject.io/docs/auth/kubernetes\n kubernetes:\n mountPath: \"kubernetes\"\n role: \"demo\"\n # Optional service account reference\n serviceAccountRef:\n name: \"my-sa\"\n # Optional secret field containing a Kubernetes ServiceAccount JWT\n # used for authenticating with Vault\n secretRef:\n name: \"my-secret\"\n key: \"vault\"\n\n # TLS certificates auth method: https://developer.hashicorp.com/vault/docs/auth/cert\n cert:\n clientCert:\n namespace: ...\n name: \"my-cert-secret\"\n key: \"tls.crt\"\n secretRef:\n namespace: ...\n name: \"my-cert-secret\"\n key: \"tls.key\"\n\n # (3): GCP Secret Manager\n gcpsm:\n # Auth defines the information necessary to authenticate against GCP by getting\n # the credentials from an already created Kubernetes Secret.\n auth:\n secretRef:\n secretAccessKeySecretRef:\n name: gcpsm-secret\n key: secret-access-credentials\n projectID: myproject\n # (TODO): add more provider examples here\n\nstatus:\n # Standard condition schema\n conditions:\n # SecretStore ready condition indicates the given store is in ready\n # state and able to referenced by ExternalSecrets\n # If the `status` of this condition is `False`, ExternalSecret controllers\n # should prevent attempts to fetch secrets\n - type: Ready\n status: \"False\"\n reason: \"ConfigError\"\n message: \"SecretStore validation failed\"\n lastTransitionTime: \"2019-08-12T12:33:02Z\"\n</code></pre>"},{"location":"api/spec/","title":"API specification","text":"<p>Packages:</p> <ul> <li> external-secrets.io/v1beta1 </li> </ul>"},{"location":"api/spec/#external-secrets.io/v1beta1","title":"external-secrets.io/v1beta1","text":"<p> <p>Package v1beta1 contains resources for external-secrets</p> </p> <p>Resource Types:</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.AWSAuth","title":"AWSAuth","text":"<p> (Appears on: AWSProvider) </p> <p> <p>AWSAuth tells the controller how to do authentication with aws. Only one of secretRef or jwt can be specified. if none is specified the controller will load credentials using the aws sdk defaults.</p> </p> Field Description <code>secretRef</code> AWSAuthSecretRef (Optional) <code>jwt</code> AWSJWTAuth (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.AWSAuthSecretRef","title":"AWSAuthSecretRef","text":"<p> (Appears on: AWSAuth) </p> <p> <p>AWSAuthSecretRef holds secret references for AWS credentials both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate.</p> </p> Field Description <code>accessKeyIDSecretRef</code> External Secrets meta/v1.SecretKeySelector <p>The AccessKeyID is used for authentication</p> <code>secretAccessKeySecretRef</code> External Secrets meta/v1.SecretKeySelector <p>The SecretAccessKey is used for authentication</p> <code>sessionTokenSecretRef</code> External Secrets meta/v1.SecretKeySelector <p>The SessionToken used for authentication This must be defined if AccessKeyID and SecretAccessKey are temporary credentials see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.AWSJWTAuth","title":"AWSJWTAuth","text":"<p> (Appears on: AWSAuth) </p> <p> <p>Authenticate against AWS using service account tokens.</p> </p> Field Description <code>serviceAccountRef</code> External Secrets meta/v1.ServiceAccountSelector"},{"location":"api/spec/#external-secrets.io/v1beta1.AWSProvider","title":"AWSProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>AWSProvider configures a store to sync secrets with AWS.</p> </p> Field Description <code>service</code> AWSServiceType <p>Service defines which service should be used to fetch the secrets</p> <code>auth</code> AWSAuth (Optional) <p>Auth defines the information necessary to authenticate against AWS if not set aws sdk will infer credentials from your environment see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials</p> <code>role</code> string (Optional) <p>Role is a Role ARN which the provider will assume</p> <code>region</code> string <p>AWS Region to be used for the provider</p> <code>additionalRoles</code> []string (Optional) <p>AdditionalRoles is a chained list of Role ARNs which the provider will sequentially assume before assuming the Role</p> <code>externalID</code> string <p>AWS External ID set on assumed IAM roles</p> <code>sessionTags</code> []*github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1.Tag (Optional) <p>AWS STS assume role session tags</p> <code>secretsManager</code> SecretsManager (Optional) <p>SecretsManager defines how the provider behaves when interacting with AWS SecretsManager</p> <code>transitiveTagKeys</code> []*string (Optional) <p>AWS STS assume role transitive session tags. Required when multiple rules are used with the provider</p> <code>prefix</code> string (Optional) <p>Prefix adds a prefix to all retrieved values.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.AWSServiceType","title":"AWSServiceType (<code>string</code> alias)","text":"<p> (Appears on: AWSProvider) </p> <p> <p>AWSServiceType is a enum that defines the service/API that is used to fetch the secrets.</p> </p> Value Description <p>\"ParameterStore\"</p> <p>AWSServiceParameterStore is the AWS SystemsManager ParameterStore service. see: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html</p> <p>\"SecretsManager\"</p> <p>AWSServiceSecretsManager is the AWS SecretsManager service. see: https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.AkeylessAuth","title":"AkeylessAuth","text":"<p> (Appears on: AkeylessProvider) </p> <p> </p> Field Description <code>secretRef</code> AkeylessAuthSecretRef (Optional) <p>Reference to a Secret that contains the details to authenticate with Akeyless.</p> <code>kubernetesAuth</code> AkeylessKubernetesAuth (Optional) <p>Kubernetes authenticates with Akeyless by passing the ServiceAccount token stored in the named Secret resource.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.AkeylessAuthSecretRef","title":"AkeylessAuthSecretRef","text":"<p> (Appears on: AkeylessAuth) </p> <p> <p>AkeylessAuthSecretRef AKEYLESS_ACCESS_TYPE_PARAM: AZURE_OBJ_ID OR GCP_AUDIENCE OR ACCESS_KEY OR KUB_CONFIG_NAME.</p> </p> Field Description <code>accessID</code> External Secrets meta/v1.SecretKeySelector <p>The SecretAccessID is used for authentication</p> <code>accessType</code> External Secrets meta/v1.SecretKeySelector <code>accessTypeParam</code> External Secrets meta/v1.SecretKeySelector"},{"location":"api/spec/#external-secrets.io/v1beta1.AkeylessKubernetesAuth","title":"AkeylessKubernetesAuth","text":"<p> (Appears on: AkeylessAuth) </p> <p> <p>Authenticate with Kubernetes ServiceAccount token stored.</p> </p> Field Description <code>accessID</code> string <p>the Akeyless Kubernetes auth-method access-id</p> <code>k8sConfName</code> string <p>Kubernetes-auth configuration name in Akeyless-Gateway</p> <code>serviceAccountRef</code> External Secrets meta/v1.ServiceAccountSelector (Optional) <p>Optional service account field containing the name of a kubernetes ServiceAccount. If the service account is specified, the service account secret token JWT will be used for authenticating with Akeyless. If the service account selector is not supplied, the secretRef will be used instead.</p> <code>secretRef</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>Optional secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Akeyless. If a name is specified without a key, <code>token</code> is the default. If one is not specified, the one bound to the controller will be used.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.AkeylessProvider","title":"AkeylessProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>AkeylessProvider Configures an store to sync secrets using Akeyless KV.</p> </p> Field Description <code>akeylessGWApiURL</code> string <p>Akeyless GW API Url from which the secrets to be fetched from.</p> <code>authSecretRef</code> AkeylessAuth <p>Auth configures how the operator authenticates with Akeyless.</p> <code>caBundle</code> []byte (Optional) <p>PEM/base64 encoded CA bundle used to validate Akeyless Gateway certificate. Only used if the AkeylessGWApiURL URL is using HTTPS protocol. If not set the system root certificates are used to validate the TLS connection.</p> <code>caProvider</code> CAProvider (Optional) <p>The provider for the CA bundle to use to validate Akeyless Gateway certificate.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.AlibabaAuth","title":"AlibabaAuth","text":"<p> (Appears on: AlibabaProvider) </p> <p> <p>AlibabaAuth contains a secretRef for credentials.</p> </p> Field Description <code>secretRef</code> AlibabaAuthSecretRef (Optional) <code>rrsa</code> AlibabaRRSAAuth (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.AlibabaAuthSecretRef","title":"AlibabaAuthSecretRef","text":"<p> (Appears on: AlibabaAuth) </p> <p> <p>AlibabaAuthSecretRef holds secret references for Alibaba credentials.</p> </p> Field Description <code>accessKeyIDSecretRef</code> External Secrets meta/v1.SecretKeySelector <p>The AccessKeyID is used for authentication</p> <code>accessKeySecretSecretRef</code> External Secrets meta/v1.SecretKeySelector <p>The AccessKeySecret is used for authentication</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.AlibabaProvider","title":"AlibabaProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>AlibabaProvider configures a store to sync secrets using the Alibaba Secret Manager provider.</p> </p> Field Description <code>auth</code> AlibabaAuth <code>regionID</code> string <p>Alibaba Region to be used for the provider</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.AlibabaRRSAAuth","title":"AlibabaRRSAAuth","text":"<p> (Appears on: AlibabaAuth) </p> <p> <p>Authenticate against Alibaba using RRSA.</p> </p> Field Description <code>oidcProviderArn</code> string <code>oidcTokenFilePath</code> string <code>roleArn</code> string <code>sessionName</code> string"},{"location":"api/spec/#external-secrets.io/v1beta1.AzureAuthType","title":"AzureAuthType (<code>string</code> alias)","text":"<p> (Appears on: AzureKVProvider) </p> <p> <p>AuthType describes how to authenticate to the Azure Keyvault Only one of the following auth types may be specified. If none of the following auth type is specified, the default one is ServicePrincipal.</p> </p> Value Description <p>\"ManagedIdentity\"</p> <p>Using Managed Identity to authenticate. Used with aad-pod-identity installed in the cluster.</p> <p>\"ServicePrincipal\"</p> <p>Using service principal to authenticate, which needs a tenantId, a clientId and a clientSecret.</p> <p>\"WorkloadIdentity\"</p> <p>Using Workload Identity service accounts to authenticate.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.AzureEnvironmentType","title":"AzureEnvironmentType (<code>string</code> alias)","text":"<p> (Appears on: AzureKVProvider) </p> <p> <p>AzureEnvironmentType specifies the Azure cloud environment endpoints to use for connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud</p> </p> Value Description <p>\"ChinaCloud\"</p> <p>\"GermanCloud\"</p> <p>\"PublicCloud\"</p> <p>\"USGovernmentCloud\"</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.AzureKVAuth","title":"AzureKVAuth","text":"<p> (Appears on: AzureKVProvider) </p> <p> <p>Configuration used to authenticate with Azure.</p> </p> Field Description <code>clientId</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>The Azure clientId of the service principle or managed identity used for authentication.</p> <code>tenantId</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>The Azure tenantId of the managed identity used for authentication.</p> <code>clientSecret</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>The Azure ClientSecret of the service principle used for authentication.</p> <code>clientCertificate</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>The Azure ClientCertificate of the service principle used for authentication.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.AzureKVProvider","title":"AzureKVProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>Configures an store to sync secrets using Azure KV.</p> </p> Field Description <code>authType</code> AzureAuthType (Optional) <p>Auth type defines how to authenticate to the keyvault service. Valid values are: - \u201cServicePrincipal\u201d (default): Using a service principal (tenantId, clientId, clientSecret) - \u201cManagedIdentity\u201d: Using Managed Identity assigned to the pod (see aad-pod-identity)</p> <code>vaultUrl</code> string <p>Vault Url from which the secrets to be fetched from.</p> <code>tenantId</code> string (Optional) <p>TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. Optional for WorkloadIdentity.</p> <code>environmentType</code> AzureEnvironmentType <p>EnvironmentType specifies the Azure cloud environment endpoints to use for connecting and authenticating with Azure. By default it points to the public cloud AAD endpoint. The following endpoints are available, also see here: https://github.com/Azure/go-autorest/blob/main/autorest/azure/environments.go#L152 PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud</p> <code>authSecretRef</code> AzureKVAuth (Optional) <p>Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity.</p> <code>serviceAccountRef</code> External Secrets meta/v1.ServiceAccountSelector (Optional) <p>ServiceAccountRef specified the service account that should be used when authenticating with WorkloadIdentity.</p> <code>identityId</code> string (Optional) <p>If multiple Managed Identity is assigned to the pod, you can select the one to be used</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.BeyondTrustProviderSecretRef","title":"BeyondTrustProviderSecretRef","text":"<p> (Appears on: BeyondtrustAuth) </p> <p> </p> Field Description <code>value</code> string (Optional) <p>Value can be specified directly to set a value without using a secret.</p> <code>secretRef</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>SecretRef references a key in a secret that will be used as value.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.BeyondtrustAuth","title":"BeyondtrustAuth","text":"<p> (Appears on: BeyondtrustProvider) </p> <p> <p>Configures a store to sync secrets using BeyondTrust Password Safe.</p> </p> Field Description <code>clientId</code> BeyondTrustProviderSecretRef <code>clientSecret</code> BeyondTrustProviderSecretRef <code>certificate</code> BeyondTrustProviderSecretRef <p>Content of the certificate (cert.pem) for use when authenticating with an OAuth client Id using a Client Certificate.</p> <code>certificateKey</code> BeyondTrustProviderSecretRef <p>Certificate private key (key.pem). For use when authenticating with an OAuth client Id</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.BeyondtrustProvider","title":"BeyondtrustProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> </p> Field Description <code>auth</code> BeyondtrustAuth <p>Auth configures how the operator authenticates with Beyondtrust.</p> <code>server</code> BeyondtrustServer <p>Auth configures how API server works.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.BeyondtrustServer","title":"BeyondtrustServer","text":"<p> (Appears on: BeyondtrustProvider) </p> <p> <p>Configures a store to sync secrets using BeyondTrust Password Safe.</p> </p> Field Description <code>apiUrl</code> string <code>retrievalType</code> string <p>The secret retrieval type. SECRET = Secrets Safe (credential, text, file). MANAGED_ACCOUNT = Password Safe account associated with a system.</p> <code>separator</code> string <p>A character that separates the folder names.</p> <code>verifyCA</code> bool <code>clientTimeOutSeconds</code> int <p>Timeout specifies a time limit for requests made by this Client. The timeout includes connection time, any redirects, and reading the response body. Defaults to 45 seconds.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.BitwardenSecretsManagerAuth","title":"BitwardenSecretsManagerAuth","text":"<p> (Appears on: BitwardenSecretsManagerProvider) </p> <p> <p>BitwardenSecretsManagerAuth contains the ref to the secret that contains the machine account token.</p> </p> Field Description <code>secretRef</code> BitwardenSecretsManagerSecretRef"},{"location":"api/spec/#external-secrets.io/v1beta1.BitwardenSecretsManagerProvider","title":"BitwardenSecretsManagerProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>BitwardenSecretsManagerProvider configures a store to sync secrets with a Bitwarden Secrets Manager instance.</p> </p> Field Description <code>apiURL</code> string <code>identityURL</code> string <code>bitwardenServerSDKURL</code> string <code>caBundle</code> string (Optional) <p>Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack can be performed.</p> <code>caProvider</code> CAProvider (Optional) <p>see: https://external-secrets.io/latest/spec/#external-secrets.io/v1alpha1.CAProvider</p> <code>organizationID</code> string <p>OrganizationID determines which organization this secret store manages.</p> <code>projectID</code> string <p>ProjectID determines which project this secret store manages.</p> <code>auth</code> BitwardenSecretsManagerAuth <p>Auth configures how secret-manager authenticates with a bitwarden machine account instance. Make sure that the token being used has permissions on the given secret.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.BitwardenSecretsManagerSecretRef","title":"BitwardenSecretsManagerSecretRef","text":"<p> (Appears on: BitwardenSecretsManagerAuth) </p> <p> <p>BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance.</p> </p> Field Description <code>credentials</code> External Secrets meta/v1.SecretKeySelector <p>AccessToken used for the bitwarden instance.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.CAProvider","title":"CAProvider","text":"<p> (Appears on: AkeylessProvider, BitwardenSecretsManagerProvider, ConjurProvider, KubernetesServer, VaultProvider) </p> <p> <p>Used to provide custom certificate authority (CA) certificates for a secret store. The CAProvider points to a Secret or ConfigMap resource that contains a PEM-encoded certificate.</p> </p> Field Description <code>type</code> CAProviderType <p>The type of provider to use such as \u201cSecret\u201d, or \u201cConfigMap\u201d.</p> <code>name</code> string <p>The name of the object located at the provider type.</p> <code>key</code> string <p>The key where the CA certificate can be found in the Secret or ConfigMap.</p> <code>namespace</code> string (Optional) <p>The namespace the Provider type is in. Can only be defined when used in a ClusterSecretStore.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.CAProviderType","title":"CAProviderType (<code>string</code> alias)","text":"<p> (Appears on: CAProvider) </p> <p> </p> Value Description <p>\"ConfigMap\"</p> <p>\"Secret\"</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.CertAuth","title":"CertAuth","text":"<p> (Appears on: KubernetesAuth) </p> <p> </p> Field Description <code>clientCert</code> External Secrets meta/v1.SecretKeySelector <code>clientKey</code> External Secrets meta/v1.SecretKeySelector"},{"location":"api/spec/#external-secrets.io/v1beta1.ChefAuth","title":"ChefAuth","text":"<p> (Appears on: ChefProvider) </p> <p> <p>ChefAuth contains a secretRef for credentials.</p> </p> Field Description <code>secretRef</code> ChefAuthSecretRef"},{"location":"api/spec/#external-secrets.io/v1beta1.ChefAuthSecretRef","title":"ChefAuthSecretRef","text":"<p> (Appears on: ChefAuth) </p> <p> <p>ChefAuthSecretRef holds secret references for chef server login credentials.</p> </p> Field Description <code>privateKeySecretRef</code> External Secrets meta/v1.SecretKeySelector <p>SecretKey is the Signing Key in PEM format, used for authentication.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ChefProvider","title":"ChefProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>ChefProvider configures a store to sync secrets using basic chef server connection credentials.</p> </p> Field Description <code>auth</code> ChefAuth <p>Auth defines the information necessary to authenticate against chef Server</p> <code>username</code> string <p>UserName should be the user ID on the chef server</p> <code>serverUrl</code> string <p>ServerURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a \u201c/\u201d</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ClusterExternalSecret","title":"ClusterExternalSecret","text":"<p> <p>ClusterExternalSecret is the Schema for the clusterexternalsecrets API.</p> </p> Field Description <code>metadata</code> Kubernetes meta/v1.ObjectMeta Refer to the Kubernetes API documentation for the fields of the <code>metadata</code> field. <code>spec</code> ClusterExternalSecretSpec <code>externalSecretSpec</code> ExternalSecretSpec <p>The spec for the ExternalSecrets to be created</p> <code>externalSecretName</code> string (Optional) <p>The name of the external secrets to be created defaults to the name of the ClusterExternalSecret</p> <code>externalSecretMetadata</code> ExternalSecretMetadata (Optional) <p>The metadata of the external secrets to be created</p> <code>namespaceSelector</code> Kubernetes meta/v1.LabelSelector (Optional) <p>The labels to select by to find the Namespaces to create the ExternalSecrets in. Deprecated: Use NamespaceSelectors instead.</p> <code>namespaceSelectors</code> []*k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector (Optional) <p>A list of labels to select by to find the Namespaces to create the ExternalSecrets in. The selectors are ORed.</p> <code>namespaces</code> []string (Optional) <p>Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing.</p> <code>refreshTime</code> Kubernetes meta/v1.Duration <p>The time in which the controller should reconcile its objects and recheck namespaces for labels.</p> <code>status</code> ClusterExternalSecretStatus"},{"location":"api/spec/#external-secrets.io/v1beta1.ClusterExternalSecretConditionType","title":"ClusterExternalSecretConditionType (<code>string</code> alias)","text":"<p> (Appears on: ClusterExternalSecretStatusCondition) </p> <p> </p> Value Description <p>\"Ready\"</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ClusterExternalSecretNamespaceFailure","title":"ClusterExternalSecretNamespaceFailure","text":"<p> (Appears on: ClusterExternalSecretStatus) </p> <p> <p>ClusterExternalSecretNamespaceFailure represents a failed namespace deployment and it\u2019s reason.</p> </p> Field Description <code>namespace</code> string <p>Namespace is the namespace that failed when trying to apply an ExternalSecret</p> <code>reason</code> string (Optional) <p>Reason is why the ExternalSecret failed to apply to the namespace</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ClusterExternalSecretSpec","title":"ClusterExternalSecretSpec","text":"<p> (Appears on: ClusterExternalSecret) </p> <p> <p>ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret.</p> </p> Field Description <code>externalSecretSpec</code> ExternalSecretSpec <p>The spec for the ExternalSecrets to be created</p> <code>externalSecretName</code> string (Optional) <p>The name of the external secrets to be created defaults to the name of the ClusterExternalSecret</p> <code>externalSecretMetadata</code> ExternalSecretMetadata (Optional) <p>The metadata of the external secrets to be created</p> <code>namespaceSelector</code> Kubernetes meta/v1.LabelSelector (Optional) <p>The labels to select by to find the Namespaces to create the ExternalSecrets in. Deprecated: Use NamespaceSelectors instead.</p> <code>namespaceSelectors</code> []*k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector (Optional) <p>A list of labels to select by to find the Namespaces to create the ExternalSecrets in. The selectors are ORed.</p> <code>namespaces</code> []string (Optional) <p>Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing.</p> <code>refreshTime</code> Kubernetes meta/v1.Duration <p>The time in which the controller should reconcile its objects and recheck namespaces for labels.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ClusterExternalSecretStatus","title":"ClusterExternalSecretStatus","text":"<p> (Appears on: ClusterExternalSecret) </p> <p> <p>ClusterExternalSecretStatus defines the observed state of ClusterExternalSecret.</p> </p> Field Description <code>externalSecretName</code> string <p>ExternalSecretName is the name of the ExternalSecrets created by the ClusterExternalSecret</p> <code>failedNamespaces</code> []ClusterExternalSecretNamespaceFailure (Optional) <p>Failed namespaces are the namespaces that failed to apply an ExternalSecret</p> <code>provisionedNamespaces</code> []string (Optional) <p>ProvisionedNamespaces are the namespaces where the ClusterExternalSecret has secrets</p> <code>conditions</code> []ClusterExternalSecretStatusCondition (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.ClusterExternalSecretStatusCondition","title":"ClusterExternalSecretStatusCondition","text":"<p> (Appears on: ClusterExternalSecretStatus) </p> <p> </p> Field Description <code>type</code> ClusterExternalSecretConditionType <code>status</code> Kubernetes core/v1.ConditionStatus <code>message</code> string (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.ClusterSecretStore","title":"ClusterSecretStore","text":"<p> <p>ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of <code>storeRef</code> fields.</p> </p> Field Description <code>metadata</code> Kubernetes meta/v1.ObjectMeta Refer to the Kubernetes API documentation for the fields of the <code>metadata</code> field. <code>spec</code> SecretStoreSpec <code>controller</code> string (Optional) <p>Used to select the correct ESO controller (think: ingress.ingressClassName) The ESO controller is instantiated with a specific controller name and filters ES based on this property</p> <code>provider</code> SecretStoreProvider <p>Used to configure the provider. Only one provider may be set</p> <code>retrySettings</code> SecretStoreRetrySettings (Optional) <p>Used to configure http retries if failed</p> <code>refreshInterval</code> int (Optional) <p>Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config.</p> <code>conditions</code> []ClusterSecretStoreCondition (Optional) <p>Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore</p> <code>status</code> SecretStoreStatus"},{"location":"api/spec/#external-secrets.io/v1beta1.ClusterSecretStoreCondition","title":"ClusterSecretStoreCondition","text":"<p> (Appears on: SecretStoreSpec) </p> <p> <p>ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in for a ClusterSecretStore instance.</p> </p> Field Description <code>namespaceSelector</code> Kubernetes meta/v1.LabelSelector (Optional) <p>Choose namespace using a labelSelector</p> <code>namespaces</code> []string (Optional) <p>Choose namespaces by name</p> <code>namespaceRegexes</code> []string (Optional) <p>Choose namespaces by using regex matching</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ConjurAPIKey","title":"ConjurAPIKey","text":"<p> (Appears on: ConjurAuth) </p> <p> </p> Field Description <code>account</code> string <code>userRef</code> External Secrets meta/v1.SecretKeySelector <code>apiKeyRef</code> External Secrets meta/v1.SecretKeySelector"},{"location":"api/spec/#external-secrets.io/v1beta1.ConjurAuth","title":"ConjurAuth","text":"<p> (Appears on: ConjurProvider) </p> <p> </p> Field Description <code>apikey</code> ConjurAPIKey (Optional) <code>jwt</code> ConjurJWT (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.ConjurJWT","title":"ConjurJWT","text":"<p> (Appears on: ConjurAuth) </p> <p> </p> Field Description <code>account</code> string <code>serviceID</code> string <p>The conjur authn jwt webservice id</p> <code>hostId</code> string (Optional) <p>Optional HostID for JWT authentication. This may be used depending on how the Conjur JWT authenticator policy is configured.</p> <code>secretRef</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>Optional SecretRef that refers to a key in a Secret resource containing JWT token to authenticate with Conjur using the JWT authentication method.</p> <code>serviceAccountRef</code> External Secrets meta/v1.ServiceAccountSelector (Optional) <p>Optional ServiceAccountRef specifies the Kubernetes service account for which to request a token for with the <code>TokenRequest</code> API.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ConjurProvider","title":"ConjurProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> </p> Field Description <code>url</code> string <code>caBundle</code> string (Optional) <code>caProvider</code> CAProvider (Optional) <code>auth</code> ConjurAuth"},{"location":"api/spec/#external-secrets.io/v1beta1.DelineaProvider","title":"DelineaProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>See https://github.com/DelineaXPM/dsv-sdk-go/blob/main/vault/vault.go.</p> </p> Field Description <code>clientId</code> DelineaProviderSecretRef <p>ClientID is the non-secret part of the credential.</p> <code>clientSecret</code> DelineaProviderSecretRef <p>ClientSecret is the secret part of the credential.</p> <code>tenant</code> string <p>Tenant is the chosen hostname / site name.</p> <code>urlTemplate</code> string (Optional) <p>URLTemplate If unset, defaults to \u201chttps://%s.secretsvaultcloud.%s/v1/%s%s\u201d.</p> <code>tld</code> string (Optional) <p>TLD is based on the server location that was chosen during provisioning. If unset, defaults to \u201ccom\u201d.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.DelineaProviderSecretRef","title":"DelineaProviderSecretRef","text":"<p> (Appears on: DelineaProvider) </p> <p> </p> Field Description <code>value</code> string (Optional) <p>Value can be specified directly to set a value without using a secret.</p> <code>secretRef</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>SecretRef references a key in a secret that will be used as value.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.Device42Auth","title":"Device42Auth","text":"<p> (Appears on: Device42Provider) </p> <p> </p> Field Description <code>secretRef</code> Device42SecretRef"},{"location":"api/spec/#external-secrets.io/v1beta1.Device42Provider","title":"Device42Provider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>Device42Provider configures a store to sync secrets with a Device42 instance.</p> </p> Field Description <code>host</code> string <p>URL configures the Device42 instance URL.</p> <code>auth</code> Device42Auth <p>Auth configures how secret-manager authenticates with a Device42 instance.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.Device42SecretRef","title":"Device42SecretRef","text":"<p> (Appears on: Device42Auth) </p> <p> </p> Field Description <code>credentials</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>Username / Password is used for authentication.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.DopplerAuth","title":"DopplerAuth","text":"<p> (Appears on: DopplerProvider) </p> <p> </p> Field Description <code>secretRef</code> DopplerAuthSecretRef"},{"location":"api/spec/#external-secrets.io/v1beta1.DopplerAuthSecretRef","title":"DopplerAuthSecretRef","text":"<p> (Appears on: DopplerAuth) </p> <p> </p> Field Description <code>dopplerToken</code> External Secrets meta/v1.SecretKeySelector <p>The DopplerToken is used for authentication. See https://docs.doppler.com/reference/api#authentication for auth token types. The Key attribute defaults to dopplerToken if not specified.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.DopplerProvider","title":"DopplerProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>DopplerProvider configures a store to sync secrets using the Doppler provider. Project and Config are required if not using a Service Token.</p> </p> Field Description <code>auth</code> DopplerAuth <p>Auth configures how the Operator authenticates with the Doppler API</p> <code>project</code> string (Optional) <p>Doppler project (required if not using a Service Token)</p> <code>config</code> string (Optional) <p>Doppler config (required if not using a Service Token)</p> <code>nameTransformer</code> string (Optional) <p>Environment variable compatible name transforms that change secret names to a different format</p> <code>format</code> string (Optional) <p>Format enables the downloading of secrets as a file (string)</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecret","title":"ExternalSecret","text":"<p> <p>ExternalSecret is the Schema for the external-secrets API.</p> </p> Field Description <code>metadata</code> Kubernetes meta/v1.ObjectMeta Refer to the Kubernetes API documentation for the fields of the <code>metadata</code> field. <code>spec</code> ExternalSecretSpec <code>secretStoreRef</code> SecretStoreRef (Optional) <code>target</code> ExternalSecretTarget (Optional) <code>refreshInterval</code> Kubernetes meta/v1.Duration <p>RefreshInterval is the amount of time before the values are read again from the SecretStore provider Valid time units are \u201cns\u201d, \u201cus\u201d (or \u201c\u00b5s\u201d), \u201cms\u201d, \u201cs\u201d, \u201cm\u201d, \u201ch\u201d May be set to zero to fetch and create it once. Defaults to 1h.</p> <code>data</code> []ExternalSecretData (Optional) <p>Data defines the connection between the Kubernetes Secret keys and the Provider data</p> <code>dataFrom</code> []ExternalSecretDataFromRemoteRef (Optional) <p>DataFrom is used to fetch all properties from a specific Provider data If multiple entries are specified, the Secret keys are merged in the specified order</p> <code>status</code> ExternalSecretStatus"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretConditionType","title":"ExternalSecretConditionType (<code>string</code> alias)","text":"<p> (Appears on: ExternalSecretStatusCondition) </p> <p> </p> Value Description <p>\"Deleted\"</p> <p>\"Ready\"</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretConversionStrategy","title":"ExternalSecretConversionStrategy (<code>string</code> alias)","text":"<p> (Appears on: ExternalSecretDataRemoteRef, ExternalSecretFind) </p> <p> </p> Value Description <p>\"Default\"</p> <p>\"Unicode\"</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretCreationPolicy","title":"ExternalSecretCreationPolicy (<code>string</code> alias)","text":"<p> (Appears on: ExternalSecretTarget) </p> <p> <p>ExternalSecretCreationPolicy defines rules on how to create the resulting Secret.</p> </p> Value Description <p>\"Merge\"</p> <p>Merge does not create the Secret, but merges the data fields to the Secret.</p> <p>\"None\"</p> <p>None does not create a Secret (future use with injector).</p> <p>\"Orphan\"</p> <p>Orphan creates the Secret and does not set the ownerReference. I.e. it will be orphaned after the deletion of the ExternalSecret.</p> <p>\"Owner\"</p> <p>Owner creates the Secret and sets .metadata.ownerReferences to the ExternalSecret resource.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretData","title":"ExternalSecretData","text":"<p> (Appears on: ExternalSecretSpec) </p> <p> <p>ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. Field Description <code>secretKey</code> string <p>SecretKey defines the key in which the controller stores the value. This is the key in the Kind=Secret</p> <code>remoteRef</code> ExternalSecretDataRemoteRef <p>RemoteRef points to the remote secret and defines which secret (version/property/..) to fetch.</p> <code>sourceRef</code> StoreSourceRef <p>SourceRef allows you to override the source from which the value will pulled from.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretDataFromRemoteRef","title":"ExternalSecretDataFromRemoteRef","text":"<p> (Appears on: ExternalSecretSpec) </p> <p> </p> Field Description <code>extract</code> ExternalSecretDataRemoteRef (Optional) <p>Used to extract multiple key/value pairs from one secret Note: Extract does not support sourceRef.Generator or sourceRef.GeneratorRef.</p> <code>find</code> ExternalSecretFind (Optional) <p>Used to find secrets based on tags or regular expressions Note: Find does not support sourceRef.Generator or sourceRef.GeneratorRef.</p> <code>rewrite</code> []ExternalSecretRewrite (Optional) <p>Used to rewrite secret Keys after getting them from the secret Provider Multiple Rewrite operations can be provided. They are applied in a layered order (first to last)</p> <code>sourceRef</code> StoreGeneratorSourceRef <p>SourceRef points to a store or generator which contains secret values ready to use. Use this in combination with Extract or Find pull values out of a specific SecretStore. When sourceRef points to a generator Extract or Find is not supported. The generator returns a static map of values</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretDataRemoteRef","title":"ExternalSecretDataRemoteRef","text":"<p> (Appears on: ExternalSecretData, ExternalSecretDataFromRemoteRef) </p> <p> <p>ExternalSecretDataRemoteRef defines Provider data location.</p> </p> Field Description <code>key</code> string <p>Key is the key used in the Provider, mandatory</p> <code>metadataPolicy</code> ExternalSecretMetadataPolicy (Optional) <p>Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None</p> <code>property</code> string (Optional) <p>Used to select a specific property of the Provider value (if a map), if supported</p> <code>version</code> string (Optional) <p>Used to select a specific version of the Provider value, if supported</p> <code>conversionStrategy</code> ExternalSecretConversionStrategy (Optional) <p>Used to define a conversion Strategy</p> <code>decodingStrategy</code> ExternalSecretDecodingStrategy (Optional) <p>Used to define a decoding Strategy</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretDecodingStrategy","title":"ExternalSecretDecodingStrategy (<code>string</code> alias)","text":"<p> (Appears on: ExternalSecretDataRemoteRef, ExternalSecretFind) </p> <p> </p> Value Description <p>\"Auto\"</p> <p>\"Base64\"</p> <p>\"Base64URL\"</p> <p>\"None\"</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretDeletionPolicy","title":"ExternalSecretDeletionPolicy (<code>string</code> alias)","text":"<p> (Appears on: ExternalSecretTarget) </p> <p> <p>ExternalSecretDeletionPolicy defines rules on how to delete the resulting Secret.</p> </p> Value Description <p>\"Delete\"</p> <p>Delete deletes the secret if all provider secrets are deleted. If a secret gets deleted on the provider side and is not accessible anymore this is not considered an error and the ExternalSecret does not go into SecretSyncedError status.</p> <p>\"Merge\"</p> <p>Merge removes keys in the secret, but not the secret itself. If a secret gets deleted on the provider side and is not accessible anymore this is not considered an error and the ExternalSecret does not go into SecretSyncedError status.</p> <p>\"Retain\"</p> <p>Retain will retain the secret if all provider secrets have been deleted. If a provider secret does not exist the ExternalSecret gets into the SecretSyncedError status.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretFind","title":"ExternalSecretFind","text":"<p> (Appears on: ExternalSecretDataFromRemoteRef) </p> <p> </p> Field Description <code>path</code> string (Optional) <p>A root path to start the find operations.</p> <code>name</code> FindName (Optional) <p>Finds secrets based on the name.</p> <code>tags</code> map[string]string (Optional) <p>Find secrets based on tags.</p> <code>conversionStrategy</code> ExternalSecretConversionStrategy (Optional) <p>Used to define a conversion Strategy</p> <code>decodingStrategy</code> ExternalSecretDecodingStrategy (Optional) <p>Used to define a decoding Strategy</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretMetadata","title":"ExternalSecretMetadata","text":"<p> (Appears on: ClusterExternalSecretSpec) </p> <p> <p>ExternalSecretMetadata defines metadata fields for the ExternalSecret generated by the ClusterExternalSecret.</p> </p> Field Description <code>annotations</code> map[string]string (Optional) <code>labels</code> map[string]string (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretMetadataPolicy","title":"ExternalSecretMetadataPolicy (<code>string</code> alias)","text":"<p> (Appears on: ExternalSecretDataRemoteRef) </p> <p> </p> Value Description <p>\"Fetch\"</p> <p>\"None\"</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretRewrite","title":"ExternalSecretRewrite","text":"<p> (Appears on: ExternalSecretDataFromRemoteRef) </p> <p> </p> Field Description <code>regexp</code> ExternalSecretRewriteRegexp (Optional) <p>Used to rewrite with regular expressions. The resulting key will be the output of a regexp.ReplaceAll operation.</p> <code>transform</code> ExternalSecretRewriteTransform (Optional) <p>Used to apply string transformation on the secrets. The resulting key will be the output of the template applied by the operation.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretRewriteRegexp","title":"ExternalSecretRewriteRegexp","text":"<p> (Appears on: ExternalSecretRewrite) </p> <p> </p> Field Description <code>source</code> string <p>Used to define the regular expression of a re.Compiler.</p> <code>target</code> string <p>Used to define the target pattern of a ReplaceAll operation.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretRewriteTransform","title":"ExternalSecretRewriteTransform","text":"<p> (Appears on: ExternalSecretRewrite) </p> <p> </p> Field Description <code>template</code> string <p>Used to define the template to apply on the secret name. <code>.value</code> will specify the secret name in the template.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretSpec","title":"ExternalSecretSpec","text":"<p> (Appears on: ClusterExternalSecretSpec, ExternalSecret) </p> <p> <p>ExternalSecretSpec defines the desired state of ExternalSecret.</p> </p> Field Description <code>secretStoreRef</code> SecretStoreRef (Optional) <code>target</code> ExternalSecretTarget (Optional) <code>refreshInterval</code> Kubernetes meta/v1.Duration <p>RefreshInterval is the amount of time before the values are read again from the SecretStore provider Valid time units are \u201cns\u201d, \u201cus\u201d (or \u201c\u00b5s\u201d), \u201cms\u201d, \u201cs\u201d, \u201cm\u201d, \u201ch\u201d May be set to zero to fetch and create it once. Defaults to 1h.</p> <code>data</code> []ExternalSecretData (Optional) <p>Data defines the connection between the Kubernetes Secret keys and the Provider data</p> <code>dataFrom</code> []ExternalSecretDataFromRemoteRef (Optional) <p>DataFrom is used to fetch all properties from a specific Provider data If multiple entries are specified, the Secret keys are merged in the specified order</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretStatus","title":"ExternalSecretStatus","text":"<p> (Appears on: ExternalSecret) </p> <p> </p> Field Description <code>refreshTime</code> Kubernetes meta/v1.Time <p>refreshTime is the time and date the external secret was fetched and the target secret updated</p> <code>syncedResourceVersion</code> string <p>SyncedResourceVersion keeps track of the last synced version</p> <code>conditions</code> []ExternalSecretStatusCondition (Optional) <code>binding</code> Kubernetes core/v1.LocalObjectReference <p>Binding represents a servicebinding.io Provisioned Service reference to the secret</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretStatusCondition","title":"ExternalSecretStatusCondition","text":"<p> (Appears on: ExternalSecretStatus) </p> <p> </p> Field Description <code>type</code> ExternalSecretConditionType <code>status</code> Kubernetes core/v1.ConditionStatus <code>reason</code> string (Optional) <code>message</code> string (Optional) <code>lastTransitionTime</code> Kubernetes meta/v1.Time (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretTarget","title":"ExternalSecretTarget","text":"<p> (Appears on: ExternalSecretSpec) </p> <p> <p>ExternalSecretTarget defines the Kubernetes Secret to be created There can be only one target per ExternalSecret.</p> </p> Field Description <code>name</code> string (Optional) <p>Name defines the name of the Secret resource to be managed This field is immutable Defaults to the .metadata.name of the ExternalSecret resource</p> <code>creationPolicy</code> ExternalSecretCreationPolicy (Optional) <p>CreationPolicy defines rules on how to create the resulting Secret Defaults to \u2018Owner\u2019</p> <code>deletionPolicy</code> ExternalSecretDeletionPolicy (Optional) <p>DeletionPolicy defines rules on how to delete the resulting Secret Defaults to \u2018Retain\u2019</p> <code>template</code> ExternalSecretTemplate (Optional) <p>Template defines a blueprint for the created Secret resource.</p> <code>immutable</code> bool (Optional) <p>Immutable defines if the final secret will be immutable</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretTemplate","title":"ExternalSecretTemplate","text":"<p> (Appears on: ExternalSecretTarget) </p> <p> <p>ExternalSecretTemplate defines a blueprint for the created Secret resource. we can not use native corev1.Secret, it will have empty ObjectMeta values: https://github.com/kubernetes-sigs/controller-tools/issues/448</p> </p> Field Description <code>type</code> Kubernetes core/v1.SecretType (Optional) <code>engineVersion</code> TemplateEngineVersion <p>EngineVersion specifies the template engine version that should be used to compile/execute the template specified in .data and .templateFrom[].</p> <code>metadata</code> ExternalSecretTemplateMetadata (Optional) <code>mergePolicy</code> TemplateMergePolicy <code>data</code> map[string]string (Optional) <code>templateFrom</code> []TemplateFrom (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretTemplateMetadata","title":"ExternalSecretTemplateMetadata","text":"<p> (Appears on: ExternalSecretTemplate) </p> <p> <p>ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint.</p> </p> Field Description <code>annotations</code> map[string]string (Optional) <code>labels</code> map[string]string (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.ExternalSecretValidator","title":"ExternalSecretValidator","text":""},{"location":"api/spec/#external-secrets.io/v1beta1.FakeProvider","title":"FakeProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>FakeProvider configures a fake provider that returns static values.</p> </p> Field Description <code>data</code> []FakeProviderData"},{"location":"api/spec/#external-secrets.io/v1beta1.FakeProviderData","title":"FakeProviderData","text":"<p> (Appears on: FakeProvider) </p> <p> </p> Field Description <code>key</code> string <code>value</code> string <code>valueMap</code> map[string]string <p>Deprecated: ValueMap is deprecated and is intended to be removed in the future, use the <code>value</code> field instead.</p> <code>version</code> string"},{"location":"api/spec/#external-secrets.io/v1beta1.FindName","title":"FindName","text":"<p> (Appears on: ExternalSecretFind) </p> <p> </p> Field Description <code>regexp</code> string (Optional) <p>Finds secrets base</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.FortanixProvider","title":"FortanixProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> </p> Field Description <code>apiUrl</code> string <p>APIURL is the URL of SDKMS API. Defaults to <code>sdkms.fortanix.com</code>.</p> <code>apiKey</code> FortanixProviderSecretRef <p>APIKey is the API token to access SDKMS Applications.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.FortanixProviderSecretRef","title":"FortanixProviderSecretRef","text":"<p> (Appears on: FortanixProvider) </p> <p> </p> Field Description <code>secretRef</code> External Secrets meta/v1.SecretKeySelector <p>SecretRef is a reference to a secret containing the SDKMS API Key.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.GCPSMAuth","title":"GCPSMAuth","text":"<p> (Appears on: GCPSMProvider) </p> <p> </p> Field Description <code>secretRef</code> GCPSMAuthSecretRef (Optional) <code>workloadIdentity</code> GCPWorkloadIdentity (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.GCPSMAuthSecretRef","title":"GCPSMAuthSecretRef","text":"<p> (Appears on: GCPSMAuth) </p> <p> </p> Field Description <code>secretAccessKeySecretRef</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>The SecretAccessKey is used for authentication</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.GCPSMProvider","title":"GCPSMProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>GCPSMProvider Configures a store to sync secrets using the GCP Secret Manager provider.</p> </p> Field Description <code>auth</code> GCPSMAuth (Optional) <p>Auth defines the information necessary to authenticate against GCP</p> <code>projectID</code> string <p>ProjectID project where secret is located</p> <code>location</code> string <p>Location optionally defines a location for a secret</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.GCPWorkloadIdentity","title":"GCPWorkloadIdentity","text":"<p> (Appears on: GCPSMAuth) </p> <p> </p> Field Description <code>serviceAccountRef</code> External Secrets meta/v1.ServiceAccountSelector <code>clusterLocation</code> string <code>clusterName</code> string <code>clusterProjectID</code> string"},{"location":"api/spec/#external-secrets.io/v1beta1.GeneratorRef","title":"GeneratorRef","text":"<p> (Appears on: StoreGeneratorSourceRef, StoreSourceRef) </p> <p> <p>GeneratorRef points to a generator custom resource.</p> </p> Field Description <code>apiVersion</code> string <p>Specify the apiVersion of the generator resource</p> <code>kind</code> string <p>Specify the Kind of the resource, e.g. Password, ACRAccessToken etc.</p> <code>name</code> string <p>Specify the name of the generator resource</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.GenericStore","title":"GenericStore","text":"<p> <p>GenericStore is a common interface for interacting with ClusterSecretStore or a namespaced SecretStore.</p> </p>"},{"location":"api/spec/#external-secrets.io/v1beta1.GenericStoreValidator","title":"GenericStoreValidator","text":""},{"location":"api/spec/#external-secrets.io/v1beta1.GitlabAuth","title":"GitlabAuth","text":"<p> (Appears on: GitlabProvider) </p> <p> </p> Field Description <code>SecretRef</code> GitlabSecretRef"},{"location":"api/spec/#external-secrets.io/v1beta1.GitlabProvider","title":"GitlabProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>Configures a store to sync secrets with a GitLab instance.</p> </p> Field Description <code>url</code> string <p>URL configures the GitLab instance URL. Defaults to https://gitlab.com/.</p> <code>auth</code> GitlabAuth <p>Auth configures how secret-manager authenticates with a GitLab instance.</p> <code>projectID</code> string <p>ProjectID specifies a project where secrets are located.</p> <code>inheritFromGroups</code> bool <p>InheritFromGroups specifies whether parent groups should be discovered and checked for secrets.</p> <code>groupIDs</code> []string <p>GroupIDs specify, which gitlab groups to pull secrets from. Group secrets are read from left to right followed by the project variables.</p> <code>environment</code> string <p>Environment environment_scope of gitlab CI/CD variables (Please see https://docs.gitlab.com/ee/ci/environments/#create-a-static-environment on how to create environments)</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.GitlabSecretRef","title":"GitlabSecretRef","text":"<p> (Appears on: GitlabAuth) </p> <p> </p> Field Description <code>accessToken</code> External Secrets meta/v1.SecretKeySelector <p>AccessToken is used for authentication.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.IBMAuth","title":"IBMAuth","text":"<p> (Appears on: IBMProvider) </p> <p> </p> Field Description <code>secretRef</code> IBMAuthSecretRef <code>containerAuth</code> IBMAuthContainerAuth"},{"location":"api/spec/#external-secrets.io/v1beta1.IBMAuthContainerAuth","title":"IBMAuthContainerAuth","text":"<p> (Appears on: IBMAuth) </p> <p> <p>IBM Container-based auth with IAM Trusted Profile.</p> </p> Field Description <code>profile</code> string <p>the IBM Trusted Profile</p> <code>tokenLocation</code> string <p>Location the token is mounted on the pod</p> <code>iamEndpoint</code> string"},{"location":"api/spec/#external-secrets.io/v1beta1.IBMAuthSecretRef","title":"IBMAuthSecretRef","text":"<p> (Appears on: IBMAuth) </p> <p> </p> Field Description <code>secretApiKeySecretRef</code> External Secrets meta/v1.SecretKeySelector <p>The SecretAccessKey is used for authentication</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.IBMProvider","title":"IBMProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>Configures an store to sync secrets using a IBM Cloud Secrets Manager backend.</p> </p> Field Description <code>auth</code> IBMAuth <p>Auth configures how secret-manager authenticates with the IBM secrets manager.</p> <code>serviceUrl</code> string <p>ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.InfisicalAuth","title":"InfisicalAuth","text":"<p> (Appears on: InfisicalProvider) </p> <p> </p> Field Description <code>universalAuthCredentials</code> UniversalAuthCredentials (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.InfisicalProvider","title":"InfisicalProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>InfisicalProvider configures a store to sync secrets using the Infisical provider.</p> </p> Field Description <code>auth</code> InfisicalAuth <p>Auth configures how the Operator authenticates with the Infisical API</p> <code>secretsScope</code> MachineIdentityScopeInWorkspace <code>hostAPI</code> string (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.KeeperSecurityProvider","title":"KeeperSecurityProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>KeeperSecurityProvider Configures a store to sync secrets using Keeper Security.</p> </p> Field Description <code>authRef</code> External Secrets meta/v1.SecretKeySelector <code>folderID</code> string"},{"location":"api/spec/#external-secrets.io/v1beta1.KubernetesAuth","title":"KubernetesAuth","text":"<p> (Appears on: KubernetesProvider) </p> <p> </p> Field Description <code>cert</code> CertAuth (Optional) <p>has both clientCert and clientKey as secretKeySelector</p> <code>token</code> TokenAuth (Optional) <p>use static token to authenticate with</p> <code>serviceAccount</code> External Secrets meta/v1.ServiceAccountSelector (Optional) <p>points to a service account that should be used for authentication</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.KubernetesProvider","title":"KubernetesProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>Configures a store to sync secrets with a Kubernetes instance.</p> </p> Field Description <code>server</code> KubernetesServer (Optional) <p>configures the Kubernetes server Address.</p> <code>auth</code> KubernetesAuth (Optional) <p>Auth configures how secret-manager authenticates with a Kubernetes instance.</p> <code>authRef</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>A reference to a secret that contains the auth information.</p> <code>remoteNamespace</code> string (Optional) <p>Remote namespace to fetch the secrets from</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.KubernetesServer","title":"KubernetesServer","text":"<p> (Appears on: KubernetesProvider) </p> <p> </p> Field Description <code>url</code> string (Optional) <p>configures the Kubernetes server Address.</p> <code>caBundle</code> []byte (Optional) <p>CABundle is a base64-encoded CA certificate</p> <code>caProvider</code> CAProvider (Optional) <p>see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.MachineIdentityScopeInWorkspace","title":"MachineIdentityScopeInWorkspace","text":"<p> (Appears on: InfisicalProvider) </p> <p> </p> Field Description <code>secretsPath</code> string (Optional) <code>recursive</code> bool (Optional) <code>environmentSlug</code> string <code>projectSlug</code> string"},{"location":"api/spec/#external-secrets.io/v1beta1.NoSecretError","title":"NoSecretError","text":"<p> <p>NoSecretError shall be returned when a GetSecret can not find the desired secret. This is used for deletionPolicy.</p> </p>"},{"location":"api/spec/#external-secrets.io/v1beta1.NotModifiedError","title":"NotModifiedError","text":"<p> <p>NotModifiedError to signal that the webhook received no changes, and it should just return without doing anything.</p> </p>"},{"location":"api/spec/#external-secrets.io/v1beta1.OnboardbaseAuthSecretRef","title":"OnboardbaseAuthSecretRef","text":"<p> (Appears on: OnboardbaseProvider) </p> <p> <p>OnboardbaseAuthSecretRef holds secret references for onboardbase API Key credentials.</p> </p> Field Description <code>apiKeyRef</code> External Secrets meta/v1.SecretKeySelector <p>OnboardbaseAPIKey is the APIKey generated by an admin account. It is used to recognize and authorize access to a project and environment within onboardbase</p> <code>passcodeRef</code> External Secrets meta/v1.SecretKeySelector <p>OnboardbasePasscode is the passcode attached to the API Key</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.OnboardbaseProvider","title":"OnboardbaseProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>OnboardbaseProvider configures a store to sync secrets using the Onboardbase provider. Project and Config are required if not using a Service Token.</p> </p> Field Description <code>auth</code> OnboardbaseAuthSecretRef <p>Auth configures how the Operator authenticates with the Onboardbase API</p> <code>apiHost</code> string <p>APIHost use this to configure the host url for the API for selfhosted installation, default is https://public.onboardbase.com/api/v1/</p> <code>project</code> string <p>Project is an onboardbase project that the secrets should be pulled from</p> <code>environment</code> string <p>Environment is the name of an environmnent within a project to pull the secrets from</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.OnePasswordAuth","title":"OnePasswordAuth","text":"<p> (Appears on: OnePasswordProvider) </p> <p> <p>OnePasswordAuth contains a secretRef for credentials.</p> </p> Field Description <code>secretRef</code> OnePasswordAuthSecretRef"},{"location":"api/spec/#external-secrets.io/v1beta1.OnePasswordAuthSecretRef","title":"OnePasswordAuthSecretRef","text":"<p> (Appears on: OnePasswordAuth) </p> <p> <p>OnePasswordAuthSecretRef holds secret references for 1Password credentials.</p> </p> Field Description <code>connectTokenSecretRef</code> External Secrets meta/v1.SecretKeySelector <p>The ConnectToken is used for authentication to a 1Password Connect Server.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.OnePasswordProvider","title":"OnePasswordProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>OnePasswordProvider configures a store to sync secrets using the 1Password Secret Manager provider.</p> </p> Field Description <code>auth</code> OnePasswordAuth <p>Auth defines the information necessary to authenticate against OnePassword Connect Server</p> <code>connectHost</code> string <p>ConnectHost defines the OnePassword Connect Server to connect to</p> <code>vaults</code> map[string]int <p>Vaults defines which OnePassword vaults to search in which order</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.OracleAuth","title":"OracleAuth","text":"<p> (Appears on: OracleProvider) </p> <p> </p> Field Description <code>tenancy</code> string <p>Tenancy is the tenancy OCID where user is located.</p> <code>user</code> string <p>User is an access OCID specific to the account.</p> <code>secretRef</code> OracleSecretRef <p>SecretRef to pass through sensitive information.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.OraclePrincipalType","title":"OraclePrincipalType (<code>string</code> alias)","text":"<p> (Appears on: OracleProvider) </p> <p> </p> Value Description <p>\"InstancePrincipal\"</p> <p>InstancePrincipal represents a instance principal.</p> <p>\"UserPrincipal\"</p> <p>UserPrincipal represents a user principal.</p> <p>\"Workload\"</p> <p>WorkloadPrincipal represents a workload principal.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.OracleProvider","title":"OracleProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>Configures an store to sync secrets using a Oracle Vault backend.</p> </p> Field Description <code>region</code> string <p>Region is the region where vault is located.</p> <code>vault</code> string <p>Vault is the vault\u2019s OCID of the specific vault where secret is located.</p> <code>compartment</code> string (Optional) <p>Compartment is the vault compartment OCID. Required for PushSecret</p> <code>encryptionKey</code> string (Optional) <p>EncryptionKey is the OCID of the encryption key within the vault. Required for PushSecret</p> <code>principalType</code> OraclePrincipalType (Optional) <p>The type of principal to use for authentication. If left blank, the Auth struct will determine the principal type. This optional field must be specified if using workload identity.</p> <code>auth</code> OracleAuth (Optional) <p>Auth configures how secret-manager authenticates with the Oracle Vault. If empty, use the instance principal, otherwise the user credentials specified in Auth.</p> <code>serviceAccountRef</code> External Secrets meta/v1.ServiceAccountSelector (Optional) <p>ServiceAccountRef specified the service account that should be used when authenticating with WorkloadIdentity.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.OracleSecretRef","title":"OracleSecretRef","text":"<p> (Appears on: OracleAuth) </p> <p> </p> Field Description <code>privatekey</code> External Secrets meta/v1.SecretKeySelector <p>PrivateKey is the user\u2019s API Signing Key in PEM format, used for authentication.</p> <code>fingerprint</code> External Secrets meta/v1.SecretKeySelector <p>Fingerprint is the fingerprint of the API private key.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.PassboltAuth","title":"PassboltAuth","text":"<p> (Appears on: PassboltProvider) </p> <p> <p>Passbolt contains a secretRef for the passbolt credentials.</p> </p> Field Description <code>passwordSecretRef</code> External Secrets meta/v1.SecretKeySelector <code>privateKeySecretRef</code> External Secrets meta/v1.SecretKeySelector"},{"location":"api/spec/#external-secrets.io/v1beta1.PassboltProvider","title":"PassboltProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> </p> Field Description <code>auth</code> PassboltAuth <p>Auth defines the information necessary to authenticate against Passbolt Server</p> <code>host</code> string <p>Host defines the Passbolt Server to connect to</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.PasswordDepotAuth","title":"PasswordDepotAuth","text":"<p> (Appears on: PasswordDepotProvider) </p> <p> </p> Field Description <code>secretRef</code> PasswordDepotSecretRef"},{"location":"api/spec/#external-secrets.io/v1beta1.PasswordDepotProvider","title":"PasswordDepotProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>Configures a store to sync secrets with a Password Depot instance.</p> </p> Field Description <code>host</code> string <p>URL configures the Password Depot instance URL.</p> <code>database</code> string <p>Database to use as source</p> <code>auth</code> PasswordDepotAuth <p>Auth configures how secret-manager authenticates with a Password Depot instance.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.PasswordDepotSecretRef","title":"PasswordDepotSecretRef","text":"<p> (Appears on: PasswordDepotAuth) </p> <p> </p> Field Description <code>credentials</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>Username / Password is used for authentication.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.PreviderAuth","title":"PreviderAuth","text":"<p> (Appears on: PreviderProvider) </p> <p> <p>PreviderAuth contains a secretRef for credentials.</p> </p> Field Description <code>secretRef</code> PreviderAuthSecretRef (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.PreviderAuthSecretRef","title":"PreviderAuthSecretRef","text":"<p> (Appears on: PreviderAuth) </p> <p> <p>PreviderAuthSecretRef holds secret references for Previder Vault credentials.</p> </p> Field Description <code>accessToken</code> External Secrets meta/v1.SecretKeySelector <p>The AccessToken is used for authentication</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.PreviderProvider","title":"PreviderProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>PreviderProvider configures a store to sync secrets using the Previder Secret Manager provider.</p> </p> Field Description <code>auth</code> PreviderAuth <code>baseUri</code> string (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.Provider","title":"Provider","text":"<p> <p>Provider is a common interface for interacting with secret backends.</p> </p>"},{"location":"api/spec/#external-secrets.io/v1beta1.PulumiProvider","title":"PulumiProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> </p> Field Description <code>apiUrl</code> string <p>APIURL is the URL of the Pulumi API.</p> <code>accessToken</code> PulumiProviderSecretRef <p>AccessToken is the access tokens to sign in to the Pulumi Cloud Console.</p> <code>organization</code> string <p>Organization are a space to collaborate on shared projects and stacks. To create a new organization, visit https://app.pulumi.com/ and click \u201cNew Organization\u201d.</p> <code>project</code> string <p>Project is the name of the Pulumi ESC project the environment belongs to.</p> <code>environment</code> string <p>Environment are YAML documents composed of static key-value pairs, programmatic expressions, dynamically retrieved values from supported providers including all major clouds, and other Pulumi ESC environments. To create a new environment, visit https://www.pulumi.com/docs/esc/environments/ for more information.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.PulumiProviderSecretRef","title":"PulumiProviderSecretRef","text":"<p> (Appears on: PulumiProvider) </p> <p> </p> Field Description <code>secretRef</code> External Secrets meta/v1.SecretKeySelector <p>SecretRef is a reference to a secret containing the Pulumi API token.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.PushSecretData","title":"PushSecretData","text":"<p> <p>PushSecretData is an interface to allow using v1alpha1.PushSecretData content in Provider registered in v1beta1.</p> </p>"},{"location":"api/spec/#external-secrets.io/v1beta1.PushSecretRemoteRef","title":"PushSecretRemoteRef","text":"<p> <p>PushSecretRemoteRef is an interface to allow using v1alpha1.PushSecretRemoteRef in Provider registered in v1beta1.</p> </p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ScalewayProvider","title":"ScalewayProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> </p> Field Description <code>apiUrl</code> string (Optional) <p>APIURL is the url of the api to use. Defaults to https://api.scaleway.com</p> <code>region</code> string <p>Region where your secrets are located: https://developers.scaleway.com/en/quickstart/#region-and-zone</p> <code>projectId</code> string <p>ProjectID is the id of your project, which you can find in the console: https://console.scaleway.com/project/settings</p> <code>accessKey</code> ScalewayProviderSecretRef <p>AccessKey is the non-secret part of the api key.</p> <code>secretKey</code> ScalewayProviderSecretRef <p>SecretKey is the non-secret part of the api key.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.ScalewayProviderSecretRef","title":"ScalewayProviderSecretRef","text":"<p> (Appears on: ScalewayProvider) </p> <p> </p> Field Description <code>value</code> string (Optional) <p>Value can be specified directly to set a value without using a secret.</p> <code>secretRef</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>SecretRef references a key in a secret that will be used as value.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.SecretServerProvider","title":"SecretServerProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>See https://github.com/DelineaXPM/tss-sdk-go/blob/main/server/server.go.</p> </p> Field Description <code>username</code> SecretServerProviderRef <p>Username is the secret server account username.</p> <code>password</code> SecretServerProviderRef <p>Password is the secret server account password.</p> <code>serverURL</code> string <p>ServerURL URL to your secret server installation</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.SecretServerProviderRef","title":"SecretServerProviderRef","text":"<p> (Appears on: SecretServerProvider) </p> <p> </p> Field Description <code>value</code> string (Optional) <p>Value can be specified directly to set a value without using a secret.</p> <code>secretRef</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>SecretRef references a key in a secret that will be used as value.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.SecretStore","title":"SecretStore","text":"<p> <p>SecretStore represents a secure external location for storing secrets, which can be referenced as part of <code>storeRef</code> fields.</p> </p> Field Description <code>metadata</code> Kubernetes meta/v1.ObjectMeta Refer to the Kubernetes API documentation for the fields of the <code>metadata</code> field. <code>spec</code> SecretStoreSpec <code>controller</code> string (Optional) <p>Used to select the correct ESO controller (think: ingress.ingressClassName) The ESO controller is instantiated with a specific controller name and filters ES based on this property</p> <code>provider</code> SecretStoreProvider <p>Used to configure the provider. Only one provider may be set</p> <code>retrySettings</code> SecretStoreRetrySettings (Optional) <p>Used to configure http retries if failed</p> <code>refreshInterval</code> int (Optional) <p>Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config.</p> <code>conditions</code> []ClusterSecretStoreCondition (Optional) <p>Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore</p> <code>status</code> SecretStoreStatus"},{"location":"api/spec/#external-secrets.io/v1beta1.SecretStoreCapabilities","title":"SecretStoreCapabilities (<code>string</code> alias)","text":"<p> (Appears on: SecretStoreStatus) </p> <p> <p>SecretStoreCapabilities defines the possible operations a SecretStore can do.</p> </p> Value Description <p>\"ReadOnly\"</p> <p>\"ReadWrite\"</p> <p>\"WriteOnly\"</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.SecretStoreConditionType","title":"SecretStoreConditionType (<code>string</code> alias)","text":"<p> (Appears on: SecretStoreStatusCondition) </p> <p> </p> Value Description <p>\"Ready\"</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.SecretStoreProvider","title":"SecretStoreProvider","text":"<p> (Appears on: SecretStoreSpec) </p> <p> <p>SecretStoreProvider contains the provider-specific configuration.</p> </p> Field Description <code>aws</code> AWSProvider (Optional) <p>AWS configures this store to sync secrets using AWS Secret Manager provider</p> <code>azurekv</code> AzureKVProvider (Optional) <p>AzureKV configures this store to sync secrets using Azure Key Vault provider</p> <code>akeyless</code> AkeylessProvider (Optional) <p>Akeyless configures this store to sync secrets using Akeyless Vault provider</p> <code>bitwardensecretsmanager</code> BitwardenSecretsManagerProvider (Optional) <p>BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider</p> <code>vault</code> VaultProvider (Optional) <p>Vault configures this store to sync secrets using Hashi provider</p> <code>gcpsm</code> GCPSMProvider (Optional) <p>GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider</p> <code>oracle</code> OracleProvider (Optional) <p>Oracle configures this store to sync secrets using Oracle Vault provider</p> <code>ibm</code> IBMProvider (Optional) <p>IBM configures this store to sync secrets using IBM Cloud provider</p> <code>yandexcertificatemanager</code> YandexCertificateManagerProvider (Optional) <p>YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider</p> <code>yandexlockbox</code> YandexLockboxProvider (Optional) <p>YandexLockbox configures this store to sync secrets using Yandex Lockbox provider</p> <code>gitlab</code> GitlabProvider (Optional) <p>GitLab configures this store to sync secrets using GitLab Variables provider</p> <code>alibaba</code> AlibabaProvider (Optional) <p>Alibaba configures this store to sync secrets using Alibaba Cloud provider</p> <code>onepassword</code> OnePasswordProvider (Optional) <p>OnePassword configures this store to sync secrets using the 1Password Cloud provider</p> <code>webhook</code> WebhookProvider (Optional) <p>Webhook configures this store to sync secrets using a generic templated webhook</p> <code>kubernetes</code> KubernetesProvider (Optional) <p>Kubernetes configures this store to sync secrets using a Kubernetes cluster provider</p> <code>fake</code> FakeProvider (Optional) <p>Fake configures a store with static key/value pairs</p> <code>senhasegura</code> SenhaseguraProvider (Optional) <p>Senhasegura configures this store to sync secrets using senhasegura provider</p> <code>scaleway</code> ScalewayProvider (Optional) <p>Scaleway</p> <code>doppler</code> DopplerProvider (Optional) <p>Doppler configures this store to sync secrets using the Doppler provider</p> <code>previder</code> PreviderProvider (Optional) <p>Previder configures this store to sync secrets using the Previder provider</p> <code>onboardbase</code> OnboardbaseProvider (Optional) <p>Onboardbase configures this store to sync secrets using the Onboardbase provider</p> <code>keepersecurity</code> KeeperSecurityProvider (Optional) <p>KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider</p> <code>conjur</code> ConjurProvider (Optional) <p>Conjur configures this store to sync secrets using conjur provider</p> <code>delinea</code> DelineaProvider (Optional) <p>Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current</p> <code>secretserver</code> SecretServerProvider (Optional) <p>SecretServer configures this store to sync secrets using SecretServer provider https://docs.delinea.com/online-help/secret-server/start.htm</p> <code>chef</code> ChefProvider (Optional) <p>Chef configures this store to sync secrets with chef server</p> <code>pulumi</code> PulumiProvider (Optional) <p>Pulumi configures this store to sync secrets using the Pulumi provider</p> <code>fortanix</code> FortanixProvider (Optional) <p>Fortanix configures this store to sync secrets using the Fortanix provider</p> <code>passworddepot</code> PasswordDepotProvider (Optional) <code>passbolt</code> PassboltProvider (Optional) <code>device42</code> Device42Provider (Optional) <p>Device42 configures this store to sync secrets using the Device42 provider</p> <code>infisical</code> InfisicalProvider (Optional) <p>Infisical configures this store to sync secrets using the Infisical provider</p> <code>beyondtrust</code> BeyondtrustProvider (Optional) <p>Beyondtrust configures this store to sync secrets using Password Safe provider.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.SecretStoreRef","title":"SecretStoreRef","text":"<p> (Appears on: ExternalSecretSpec, StoreGeneratorSourceRef, StoreSourceRef) </p> <p> <p>SecretStoreRef defines which SecretStore to fetch the ExternalSecret data.</p> </p> Field Description <code>name</code> string <p>Name of the SecretStore resource</p> <code>kind</code> string (Optional) <p>Kind of the SecretStore resource (SecretStore or ClusterSecretStore) Defaults to <code>SecretStore</code></p>"},{"location":"api/spec/#external-secrets.io/v1beta1.SecretStoreRetrySettings","title":"SecretStoreRetrySettings","text":"<p> (Appears on: SecretStoreSpec) </p> <p> </p> Field Description <code>maxRetries</code> int32 <code>retryInterval</code> string"},{"location":"api/spec/#external-secrets.io/v1beta1.SecretStoreSpec","title":"SecretStoreSpec","text":"<p> (Appears on: ClusterSecretStore, SecretStore) </p> <p> <p>SecretStoreSpec defines the desired state of SecretStore.</p> </p> Field Description <code>controller</code> string (Optional) <p>Used to select the correct ESO controller (think: ingress.ingressClassName) The ESO controller is instantiated with a specific controller name and filters ES based on this property</p> <code>provider</code> SecretStoreProvider <p>Used to configure the provider. Only one provider may be set</p> <code>retrySettings</code> SecretStoreRetrySettings (Optional) <p>Used to configure http retries if failed</p> <code>refreshInterval</code> int (Optional) <p>Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config.</p> <code>conditions</code> []ClusterSecretStoreCondition (Optional) <p>Used to constraint a ClusterSecretStore to specific namespaces. Relevant only to ClusterSecretStore</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.SecretStoreStatus","title":"SecretStoreStatus","text":"<p> (Appears on: ClusterSecretStore, SecretStore) </p> <p> <p>SecretStoreStatus defines the observed state of the SecretStore.</p> </p> Field Description <code>conditions</code> []SecretStoreStatusCondition (Optional) <code>capabilities</code> SecretStoreCapabilities (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.SecretStoreStatusCondition","title":"SecretStoreStatusCondition","text":"<p> (Appears on: SecretStoreStatus) </p> <p> </p> Field Description <code>type</code> SecretStoreConditionType <code>status</code> Kubernetes core/v1.ConditionStatus <code>reason</code> string (Optional) <code>message</code> string (Optional) <code>lastTransitionTime</code> Kubernetes meta/v1.Time (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.SecretsClient","title":"SecretsClient","text":"<p> <p>SecretsClient provides access to secrets.</p> </p>"},{"location":"api/spec/#external-secrets.io/v1beta1.SecretsManager","title":"SecretsManager","text":"<p> (Appears on: AWSProvider) </p> <p> <p>SecretsManager defines how the provider behaves when interacting with AWS SecretsManager. Some of these settings are only applicable to controlling how secrets are deleted, and hence only apply to PushSecret (and only when deletionPolicy is set to Delete).</p> </p> Field Description <code>forceDeleteWithoutRecovery</code> bool (Optional) <p>Specifies whether to delete the secret without any recovery window. You can\u2019t use both this parameter and RecoveryWindowInDays in the same call. If you don\u2019t use either, then by default Secrets Manager uses a 30 day recovery window. see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-ForceDeleteWithoutRecovery</p> <code>recoveryWindowInDays</code> int64 (Optional) <p>The number of days from 7 to 30 that Secrets Manager waits before permanently deleting the secret. You can\u2019t use both this parameter and ForceDeleteWithoutRecovery in the same call. If you don\u2019t use either, then by default Secrets Manager uses a 30 day recovery window. see: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#SecretsManager-DeleteSecret-request-RecoveryWindowInDays</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.SenhaseguraAuth","title":"SenhaseguraAuth","text":"<p> (Appears on: SenhaseguraProvider) </p> <p> <p>SenhaseguraAuth tells the controller how to do auth in senhasegura.</p> </p> Field Description <code>clientId</code> string <code>clientSecretSecretRef</code> External Secrets meta/v1.SecretKeySelector"},{"location":"api/spec/#external-secrets.io/v1beta1.SenhaseguraModuleType","title":"SenhaseguraModuleType (<code>string</code> alias)","text":"<p> (Appears on: SenhaseguraProvider) </p> <p> <p>SenhaseguraModuleType enum defines senhasegura target module to fetch secrets</p> </p> Value Description <p>\"DSM\"</p> <pre><code> SenhaseguraModuleDSM is the senhasegura DevOps Secrets Management module\nsee: https://senhasegura.com/devops\n</code></pre>"},{"location":"api/spec/#external-secrets.io/v1beta1.SenhaseguraProvider","title":"SenhaseguraProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>SenhaseguraProvider setup a store to sync secrets with senhasegura.</p> </p> Field Description <code>url</code> string <p>URL of senhasegura</p> <code>module</code> SenhaseguraModuleType <p>Module defines which senhasegura module should be used to get secrets</p> <code>auth</code> SenhaseguraAuth <p>Auth defines parameters to authenticate in senhasegura</p> <code>ignoreSslCertificate</code> bool <p>IgnoreSslCertificate defines if SSL certificate must be ignored</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.StoreGeneratorSourceRef","title":"StoreGeneratorSourceRef","text":"<p> (Appears on: ExternalSecretDataFromRemoteRef) </p> <p> <p>StoreGeneratorSourceRef allows you to override the source from which the secret will be pulled from. You can define at maximum one property.</p> </p> Field Description <code>storeRef</code> SecretStoreRef (Optional) <code>generatorRef</code> GeneratorRef (Optional) <p>GeneratorRef points to a generator custom resource.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.StoreSourceRef","title":"StoreSourceRef","text":"<p> (Appears on: ExternalSecretData) </p> <p> <p>StoreSourceRef allows you to override the SecretStore source from which the secret will be pulled from. You can define at maximum one property.</p> </p> Field Description <code>storeRef</code> SecretStoreRef (Optional) <code>generatorRef</code> GeneratorRef <p>GeneratorRef points to a generator custom resource.</p> <p>Deprecated: The generatorRef is not implemented in .data[]. this will be removed with v1.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.Tag","title":"Tag","text":"Field Description <code>key</code> string <code>value</code> string"},{"location":"api/spec/#external-secrets.io/v1beta1.TemplateEngineVersion","title":"TemplateEngineVersion (<code>string</code> alias)","text":"<p> (Appears on: ExternalSecretTemplate) </p> <p> </p> Value Description <p>\"v1\"</p> <p>\"v2\"</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.TemplateFrom","title":"TemplateFrom","text":"<p> (Appears on: ExternalSecretTemplate) </p> <p> </p> Field Description <code>configMap</code> TemplateRef <code>secret</code> TemplateRef <code>target</code> TemplateTarget (Optional) <code>literal</code> string (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.TemplateMergePolicy","title":"TemplateMergePolicy (<code>string</code> alias)","text":"<p> (Appears on: ExternalSecretTemplate) </p> <p> </p> Value Description <p>\"Merge\"</p> <p>\"Replace\"</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.TemplateRef","title":"TemplateRef","text":"<p> (Appears on: TemplateFrom) </p> <p> </p> Field Description <code>name</code> string <code>items</code> []TemplateRefItem"},{"location":"api/spec/#external-secrets.io/v1beta1.TemplateRefItem","title":"TemplateRefItem","text":"<p> (Appears on: TemplateRef) </p> <p> </p> Field Description <code>key</code> string <code>templateAs</code> TemplateScope"},{"location":"api/spec/#external-secrets.io/v1beta1.TemplateScope","title":"TemplateScope (<code>string</code> alias)","text":"<p> (Appears on: TemplateRefItem) </p> <p> </p> Value Description <p>\"KeysAndValues\"</p> <p>\"Values\"</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.TemplateTarget","title":"TemplateTarget (<code>string</code> alias)","text":"<p> (Appears on: TemplateFrom) </p> <p> </p> Value Description <p>\"Annotations\"</p> <p>\"Data\"</p> <p>\"Labels\"</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.TokenAuth","title":"TokenAuth","text":"<p> (Appears on: KubernetesAuth) </p> <p> </p> Field Description <code>bearerToken</code> External Secrets meta/v1.SecretKeySelector"},{"location":"api/spec/#external-secrets.io/v1beta1.UniversalAuthCredentials","title":"UniversalAuthCredentials","text":"<p> (Appears on: InfisicalAuth) </p> <p> </p> Field Description <code>clientId</code> External Secrets meta/v1.SecretKeySelector <code>clientSecret</code> External Secrets meta/v1.SecretKeySelector"},{"location":"api/spec/#external-secrets.io/v1beta1.ValidationResult","title":"ValidationResult (<code>byte</code> alias)","text":"Value Description <p>2</p> <p>Error indicates that there is a misconfiguration.</p> <p>0</p> <p>Ready indicates that the client is configured correctly and can be used.</p> <p>1</p> <p>Unknown indicates that the client can be used but information is missing and it can not be validated.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.VaultAppRole","title":"VaultAppRole","text":"<p> (Appears on: VaultAuth) </p> <p> <p>VaultAppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource.</p> </p> Field Description <code>path</code> string <p>Path where the App Role authentication backend is mounted in Vault, e.g: \u201capprole\u201d</p> <code>roleId</code> string (Optional) <p>RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault.</p> <code>roleRef</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>Reference to a key in a Secret that contains the App Role ID used to authenticate with Vault. The <code>key</code> field must be specified and denotes which entry within the Secret resource is used as the app role id.</p> <code>secretRef</code> External Secrets meta/v1.SecretKeySelector <p>Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The <code>key</code> field must be specified and denotes which entry within the Secret resource is used as the app role secret.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.VaultAuth","title":"VaultAuth","text":"<p> (Appears on: VaultProvider) </p> <p> <p>VaultAuth is the configuration used to authenticate with a Vault server. Only one of <code>tokenSecretRef</code>, <code>appRole</code>, <code>kubernetes</code>, <code>ldap</code>, <code>userPass</code>, <code>jwt</code> or <code>cert</code> can be specified. A namespace to authenticate against can optionally be specified.</p> </p> Field Description <code>namespace</code> string (Optional) <p>Name of the vault namespace to authenticate to. This can be different than the namespace your secret is in. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: \u201cns1\u201d. More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces This will default to Vault.Namespace field if set, or empty otherwise</p> <code>tokenSecretRef</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>TokenSecretRef authenticates with Vault by presenting a token.</p> <code>appRole</code> VaultAppRole (Optional) <p>AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource.</p> <code>kubernetes</code> VaultKubernetesAuth (Optional) <p>Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server.</p> <code>ldap</code> VaultLdapAuth (Optional) <p>Ldap authenticates with Vault by passing username/password pair using the LDAP authentication method</p> <code>jwt</code> VaultJwtAuth (Optional) <p>Jwt authenticates with Vault by passing role and JWT token using the JWT/OIDC authentication method</p> <code>cert</code> VaultCertAuth (Optional) <p>Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate Cert authentication method</p> <code>iam</code> VaultIamAuth (Optional) <p>Iam authenticates with vault by passing a special AWS request signed with AWS IAM credentials AWS IAM authentication method</p> <code>userPass</code> VaultUserPassAuth (Optional) <p>UserPass authenticates with Vault by passing username/password pair</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.VaultAwsAuth","title":"VaultAwsAuth","text":"<p> <p>VaultAwsAuth tells the controller how to do authentication with aws. Only one of secretRef or jwt can be specified. if none is specified the controller will try to load credentials from its own service account assuming it is IRSA enabled.</p> </p> Field Description <code>secretRef</code> VaultAwsAuthSecretRef (Optional) <code>jwt</code> VaultAwsJWTAuth (Optional)"},{"location":"api/spec/#external-secrets.io/v1beta1.VaultAwsAuthSecretRef","title":"VaultAwsAuthSecretRef","text":"<p> (Appears on: VaultAwsAuth, VaultIamAuth) </p> <p> <p>VaultAWSAuthSecretRef holds secret references for AWS credentials both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate.</p> </p> Field Description <code>accessKeyIDSecretRef</code> External Secrets meta/v1.SecretKeySelector <p>The AccessKeyID is used for authentication</p> <code>secretAccessKeySecretRef</code> External Secrets meta/v1.SecretKeySelector <p>The SecretAccessKey is used for authentication</p> <code>sessionTokenSecretRef</code> External Secrets meta/v1.SecretKeySelector <p>The SessionToken used for authentication This must be defined if AccessKeyID and SecretAccessKey are temporary credentials see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.VaultAwsJWTAuth","title":"VaultAwsJWTAuth","text":"<p> (Appears on: VaultAwsAuth, VaultIamAuth) </p> <p> <p>Authenticate against AWS using service account tokens.</p> </p> Field Description <code>serviceAccountRef</code> External Secrets meta/v1.ServiceAccountSelector"},{"location":"api/spec/#external-secrets.io/v1beta1.VaultCertAuth","title":"VaultCertAuth","text":"<p> (Appears on: VaultAuth) </p> <p> <p>VaultJwtAuth authenticates with Vault using the JWT/OIDC authentication method, with the role name and token stored in a Kubernetes Secret resource.</p> </p> Field Description <code>clientCert</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>ClientCert is a certificate to authenticate using the Cert Vault authentication method</p> <code>secretRef</code> External Secrets meta/v1.SecretKeySelector <p>SecretRef to a key in a Secret resource containing client private key to authenticate with Vault using the Cert authentication method</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.VaultClientTLS","title":"VaultClientTLS","text":"<p> (Appears on: VaultProvider) </p> <p> <p>VaultClientTLS is the configuration used for client side related TLS communication, when the Vault server requires mutual authentication.</p> </p> Field Description <code>certSecretRef</code> External Secrets meta/v1.SecretKeySelector <p>CertSecretRef is a certificate added to the transport layer when communicating with the Vault server. If no key for the Secret is specified, external-secret will default to \u2018tls.crt\u2019.</p> <code>keySecretRef</code> External Secrets meta/v1.SecretKeySelector <p>KeySecretRef to a key in a Secret resource containing client private key added to the transport layer when communicating with the Vault server. If no key for the Secret is specified, external-secret will default to \u2018tls.key\u2019.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.VaultIamAuth","title":"VaultIamAuth","text":"<p> (Appears on: VaultAuth) </p> <p> <p>VaultIamAuth authenticates with Vault using the Vault\u2019s AWS IAM authentication method. Refer: https://developer.hashicorp.com/vault/docs/auth/aws</p> </p> Field Description <code>path</code> string <p>Path where the AWS auth method is enabled in Vault, e.g: \u201caws\u201d</p> <code>region</code> string <p>AWS region</p> <code>role</code> string <p>This is the AWS role to be assumed before talking to vault</p> <code>vaultRole</code> string <p>Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine</p> <code>externalID</code> string <p>AWS External ID set on assumed IAM roles</p> <code>vaultAwsIamServerID</code> string <p>X-Vault-AWS-IAM-Server-ID is an additional header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws</p> <code>secretRef</code> VaultAwsAuthSecretRef (Optional) <p>Specify credentials in a Secret object</p> <code>jwt</code> VaultAwsJWTAuth (Optional) <p>Specify a service account with IRSA enabled</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.VaultJwtAuth","title":"VaultJwtAuth","text":"<p> (Appears on: VaultAuth) </p> <p> <p>VaultJwtAuth authenticates with Vault using the JWT/OIDC authentication method, with the role name and a token stored in a Kubernetes Secret resource or a Kubernetes service account token retrieved via <code>TokenRequest</code>.</p> </p> Field Description <code>path</code> string <p>Path where the JWT authentication backend is mounted in Vault, e.g: \u201cjwt\u201d</p> <code>role</code> string (Optional) <p>Role is a JWT role to authenticate using the JWT/OIDC Vault authentication method</p> <code>secretRef</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>Optional SecretRef that refers to a key in a Secret resource containing JWT token to authenticate with Vault using the JWT/OIDC authentication method.</p> <code>kubernetesServiceAccountToken</code> VaultKubernetesServiceAccountTokenAuth (Optional) <p>Optional ServiceAccountToken specifies the Kubernetes service account for which to request a token for with the <code>TokenRequest</code> API.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.VaultKVStoreVersion","title":"VaultKVStoreVersion (<code>string</code> alias)","text":"<p> (Appears on: VaultProvider) </p> <p> </p> Value Description <p>\"v1\"</p> <p>\"v2\"</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.VaultKubernetesAuth","title":"VaultKubernetesAuth","text":"<p> (Appears on: VaultAuth) </p> <p> <p>Authenticate against Vault using a Kubernetes ServiceAccount token stored in a Secret.</p> </p> Field Description <code>mountPath</code> string <p>Path where the Kubernetes authentication backend is mounted in Vault, e.g: \u201ckubernetes\u201d</p> <code>serviceAccountRef</code> External Secrets meta/v1.ServiceAccountSelector (Optional) <p>Optional service account field containing the name of a kubernetes ServiceAccount. If the service account is specified, the service account secret token JWT will be used for authenticating with Vault. If the service account selector is not supplied, the secretRef will be used instead.</p> <code>secretRef</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>Optional secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. If a name is specified without a key, <code>token</code> is the default. If one is not specified, the one bound to the controller will be used.</p> <code>role</code> string <p>A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.VaultKubernetesServiceAccountTokenAuth","title":"VaultKubernetesServiceAccountTokenAuth","text":"<p> (Appears on: VaultJwtAuth) </p> <p> <p>VaultKubernetesServiceAccountTokenAuth authenticates with Vault using a temporary Kubernetes service account token retrieved by the <code>TokenRequest</code> API.</p> </p> Field Description <code>serviceAccountRef</code> External Secrets meta/v1.ServiceAccountSelector <p>Service account field containing the name of a kubernetes ServiceAccount.</p> <code>audiences</code> []string (Optional) <p>Optional audiences field that will be used to request a temporary Kubernetes service account token for the service account referenced by <code>serviceAccountRef</code>. Defaults to a single audience <code>vault</code> it not specified. Deprecated: use serviceAccountRef.Audiences instead</p> <code>expirationSeconds</code> int64 (Optional) <p>Optional expiration time in seconds that will be used to request a temporary Kubernetes service account token for the service account referenced by <code>serviceAccountRef</code>. Deprecated: this will be removed in the future. Defaults to 10 minutes.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.VaultLdapAuth","title":"VaultLdapAuth","text":"<p> (Appears on: VaultAuth) </p> <p> <p>VaultLdapAuth authenticates with Vault using the LDAP authentication method, with the username and password stored in a Kubernetes Secret resource.</p> </p> Field Description <code>path</code> string <p>Path where the LDAP authentication backend is mounted in Vault, e.g: \u201cldap\u201d</p> <code>username</code> string <p>Username is a LDAP user name used to authenticate using the LDAP Vault authentication method</p> <code>secretRef</code> External Secrets meta/v1.SecretKeySelector <p>SecretRef to a key in a Secret resource containing password for the LDAP user used to authenticate with Vault using the LDAP authentication method</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.VaultProvider","title":"VaultProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>Configures an store to sync secrets using a HashiCorp Vault KV backend.</p> </p> Field Description <code>auth</code> VaultAuth <p>Auth configures how secret-manager authenticates with the Vault server.</p> <code>server</code> string <p>Server is the connection address for the Vault server, e.g: \u201chttps://vault.example.com:8200\u201d.</p> <code>path</code> string (Optional) <p>Path is the mount path of the Vault KV backend endpoint, e.g: \u201csecret\u201d. The v2 KV secret engine version specific \u201c/data\u201d path suffix for fetching secrets from Vault is optional and will be appended if not present in specified path.</p> <code>version</code> VaultKVStoreVersion <p>Version is the Vault KV secret engine version. This can be either \u201cv1\u201d or \u201cv2\u201d. Version defaults to \u201cv2\u201d.</p> <code>namespace</code> string (Optional) <p>Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: \u201cns1\u201d. More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces</p> <code>caBundle</code> []byte (Optional) <p>PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection.</p> <code>tls</code> VaultClientTLS (Optional) <p>The configuration used for client side related TLS communication, when the Vault server requires mutual authentication. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. It\u2019s worth noting this configuration is different from the \u201cTLS certificates auth method\u201d, which is available under the <code>auth.cert</code> section.</p> <code>caProvider</code> CAProvider (Optional) <p>The provider for the CA bundle to use to validate Vault server certificate.</p> <code>readYourWrites</code> bool (Optional) <p>ReadYourWrites ensures isolated read-after-write semantics by providing discovered cluster replication states in each request. More information about eventual consistency in Vault can be found here https://www.vaultproject.io/docs/enterprise/consistency</p> <code>forwardInconsistent</code> bool (Optional) <p>ForwardInconsistent tells Vault to forward read-after-write requests to the Vault leader instead of simply retrying within a loop. This can increase performance if the option is enabled serverside. https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header</p> <code>headers</code> map[string]string (Optional) <p>Headers to be added in Vault request</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.VaultUserPassAuth","title":"VaultUserPassAuth","text":"<p> (Appears on: VaultAuth) </p> <p> <p>VaultUserPassAuth authenticates with Vault using UserPass authentication method, with the username and password stored in a Kubernetes Secret resource.</p> </p> Field Description <code>path</code> string <p>Path where the UserPassword authentication backend is mounted in Vault, e.g: \u201cuser\u201d</p> <code>username</code> string <p>Username is a user name used to authenticate using the UserPass Vault authentication method</p> <code>secretRef</code> External Secrets meta/v1.SecretKeySelector <p>SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.WebhookCAProvider","title":"WebhookCAProvider","text":"<p> (Appears on: WebhookProvider) </p> <p> <p>Defines a location to fetch the cert for the webhook provider from.</p> </p> Field Description <code>type</code> WebhookCAProviderType <p>The type of provider to use such as \u201cSecret\u201d, or \u201cConfigMap\u201d.</p> <code>name</code> string <p>The name of the object located at the provider type.</p> <code>key</code> string <p>The key the value inside of the provider type to use, only used with \u201cSecret\u201d type</p> <code>namespace</code> string (Optional) <p>The namespace the Provider type is in.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.WebhookCAProviderType","title":"WebhookCAProviderType (<code>string</code> alias)","text":"<p> (Appears on: WebhookCAProvider) </p> <p> </p> Value Description <p>\"ConfigMap\"</p> <p>\"Secret\"</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.WebhookProvider","title":"WebhookProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>AkeylessProvider Configures an store to sync secrets using Akeyless KV.</p> </p> Field Description <code>method</code> string <p>Webhook Method</p> <code>url</code> string <p>Webhook url to call</p> <code>headers</code> map[string]string (Optional) <p>Headers</p> <code>body</code> string (Optional) <p>Body</p> <code>timeout</code> Kubernetes meta/v1.Duration (Optional) <p>Timeout</p> <code>result</code> WebhookResult <p>Result formatting</p> <code>secrets</code> []WebhookSecret (Optional) <p>Secrets to fill in templates These secrets will be passed to the templating function as key value pairs under the given name</p> <code>caBundle</code> []byte (Optional) <p>PEM encoded CA bundle used to validate webhook server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection.</p> <code>caProvider</code> WebhookCAProvider (Optional) <p>The provider for the CA bundle to use to validate webhook server certificate.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.WebhookResult","title":"WebhookResult","text":"<p> (Appears on: WebhookProvider) </p> <p> </p> Field Description <code>jsonPath</code> string (Optional) <p>Json path of return value</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.WebhookSecret","title":"WebhookSecret","text":"<p> (Appears on: WebhookProvider) </p> <p> </p> Field Description <code>name</code> string <p>Name of this secret in templates</p> <code>secretRef</code> External Secrets meta/v1.SecretKeySelector <p>Secret ref to fill in credentials</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.YandexCertificateManagerAuth","title":"YandexCertificateManagerAuth","text":"<p> (Appears on: YandexCertificateManagerProvider) </p> <p> </p> Field Description <code>authorizedKeySecretRef</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>The authorized key used for authentication</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.YandexCertificateManagerCAProvider","title":"YandexCertificateManagerCAProvider","text":"<p> (Appears on: YandexCertificateManagerProvider) </p> <p> </p> Field Description <code>certSecretRef</code> External Secrets meta/v1.SecretKeySelector"},{"location":"api/spec/#external-secrets.io/v1beta1.YandexCertificateManagerProvider","title":"YandexCertificateManagerProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>YandexCertificateManagerProvider Configures a store to sync secrets using the Yandex Certificate Manager provider.</p> </p> Field Description <code>apiEndpoint</code> string (Optional) <p>Yandex.Cloud API endpoint (e.g. \u2018api.cloud.yandex.net:443\u2019)</p> <code>auth</code> YandexCertificateManagerAuth <p>Auth defines the information necessary to authenticate against Yandex Certificate Manager</p> <code>caProvider</code> YandexCertificateManagerCAProvider (Optional) <p>The provider for the CA bundle to use to validate Yandex.Cloud server certificate.</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.YandexLockboxAuth","title":"YandexLockboxAuth","text":"<p> (Appears on: YandexLockboxProvider) </p> <p> </p> Field Description <code>authorizedKeySecretRef</code> External Secrets meta/v1.SecretKeySelector (Optional) <p>The authorized key used for authentication</p>"},{"location":"api/spec/#external-secrets.io/v1beta1.YandexLockboxCAProvider","title":"YandexLockboxCAProvider","text":"<p> (Appears on: YandexLockboxProvider) </p> <p> </p> Field Description <code>certSecretRef</code> External Secrets meta/v1.SecretKeySelector"},{"location":"api/spec/#external-secrets.io/v1beta1.YandexLockboxProvider","title":"YandexLockboxProvider","text":"<p> (Appears on: SecretStoreProvider) </p> <p> <p>YandexLockboxProvider Configures a store to sync secrets using the Yandex Lockbox provider.</p> </p> Field Description <code>apiEndpoint</code> string (Optional) <p>Yandex.Cloud API endpoint (e.g. \u2018api.cloud.yandex.net:443\u2019)</p> <code>auth</code> YandexLockboxAuth <p>Auth defines the information necessary to authenticate against Yandex Lockbox</p> <code>caProvider</code> YandexLockboxCAProvider (Optional) <p>The provider for the CA bundle to use to validate Yandex.Cloud server certificate.</p> <p> Generated with <code>gen-crd-api-reference-docs</code>. </p>"},{"location":"api/generator/","title":"Index","text":"<p>Generators allow you to generate values. See Generators Guide</p>"},{"location":"api/generator/acr/","title":"Azure Container Registry","text":"<p>The Azure Container Registry (ACR) generator creates a short-lived refresh or access token for accessing ACR. The token is generated for a particular ACR registry defined in <code>spec.registry</code>.</p>"},{"location":"api/generator/acr/#output-keys-and-values","title":"Output Keys and Values","text":"Key Description username username for the <code>docker login</code> command password password for the <code>docker login</code> command"},{"location":"api/generator/acr/#authentication","title":"Authentication","text":"<p>You must choose one out of three authentication mechanisms:</p> <ul> <li>service principal</li> <li>managed identity</li> <li>workload identity</li> </ul> <p>The generated token will inherit the permissions from the assigned policy. I.e. when you assign a read-only policy all generated tokens will be read-only. You must assign a Azure RBAC role, such as <code>AcrPush</code> or <code>AcrPull</code> to the service principal or managed identity in order to be able to authenticate with the Azure container registry API.</p> <p>You can scope tokens to a particular repository using <code>spec.scope</code>.</p>"},{"location":"api/generator/acr/#scope","title":"Scope","text":"<p>First, an Azure Active Directory access token is obtained with the desired authentication method. This AAD access token will be used to authenticate against ACR to issue a refresh token or access token. If <code>spec.scope</code> if it is defined it obtains an ACR access token. If <code>spec.scope</code> is missing it obtains an ACR refresh token:</p> <ul> <li>access tokens are scoped to a specific repository or action (pull,push)</li> <li>refresh tokens can are scoped to whatever policy is attached to the identity that creates the acr refresh token</li> </ul> <p>The Scope grammar is defined in the Docker Registry spec. Note: You can not use wildcards in the scope parameter -- you can match exactly one repository and can define multiple actions like <code>pull</code> or <code>push</code>.</p> <p>Example scopes:</p> <pre><code>repository:my-repository:pull,push\nrepository:my-repository:pull\n</code></pre>"},{"location":"api/generator/acr/#example-manifest","title":"Example Manifest","text":"<pre><code>apiVersion: generators.external-secrets.io/v1alpha1\nkind: ACRAccessToken\nmetadata:\n name: my-azurecr\nspec:\n tenantId: 11111111-2222-3333-4444-111111111111\n registry: example.azurecr.io\n\n # optional; scope token down to a single repository/action\n # if set, it will generate an access token instead of an refresh token.\n scope: \"repository:foo:pull,push\"\n\n # Specify Azure cloud type, defaults to PublicCloud.\n # This is used for authenticating with Azure Active Directory.\n # available options: PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud\n environmentType: \"PublicCloud\"\n\n # choose one authentication method\n auth:\n\n # option 1: point to a secret that contains a client-id and client-secret\n servicePrincipal:\n secretRef:\n clientSecret:\n name: az-secret\n key: clientsecret\n clientId:\n name: az-secret\n key: clientid\n\n # option 2:\n managedIdentity:\n identityId: \"xxxxx\"\n\n # option 3:\n workloadIdentity:\n # note: you can reference service accounts across namespaces.\n serviceAccountRef:\n name: \"my-service-account\"\n audiences: []\n</code></pre> <p>Example <code>ExternalSecret</code> that references the ACR generator: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: azurecr-credentials\nspec:\n dataFrom:\n - sourceRef:\n generatorRef:\n apiVersion: generators.external-secrets.io/v1alpha1\n kind: ACRAccessToken\n name: my-azurecr\n refreshInterval: 12h\n target:\n name: azurecr-credentials\n template:\n type: kubernetes.io/dockerconfigjson\n data:\n .dockerconfigjson: |\n {\n \"auths\": {\n \"myregistry.azurecr.io\": {\n \"username\": \"{{ .username }}\",\n \"password\": \"{{ .password }}\"\n }\n }\n }\n</code></pre></p>"},{"location":"api/generator/ecr/","title":"AWS Elastic Container Registry","text":"<p>ECRAuthorizationTokenSpec uses the GetAuthorizationToken API to retrieve an authorization token. The authorization token is valid for 12 hours. For more information, see registry authentication in the Amazon Elastic Container Registry User Guide.</p>"},{"location":"api/generator/ecr/#output-keys-and-values","title":"Output Keys and Values","text":"Key Description username username for the <code>docker login</code> command. password password for the <code>docker login</code> command. proxy_endpoint The registry URL to use for this authorization token in a <code>docker login</code> command. expires_at time when token expires in UNIX time (seconds since January 1, 1970 UTC)."},{"location":"api/generator/ecr/#authentication","title":"Authentication","text":"<p>You can choose from three authentication mechanisms:</p> <ul> <li>static credentials using <code>spec.auth.secretRef</code></li> <li>point to a IRSA Service Account with <code>spec.auth.jwt</code></li> <li>use credentials from the SDK default credentials chain from the controller environment</li> </ul>"},{"location":"api/generator/ecr/#example-manifest","title":"Example Manifest","text":"<pre><code>apiVersion: generators.external-secrets.io/v1alpha1\nkind: ECRAuthorizationToken\nmetadata:\n name: ecr-gen\nspec:\n\n # specify aws region (mandatory)\n region: eu-west-1\n\n # assume role with the given authentication credentials\n role: \"my-role\"\n\n # choose an authentication strategy\n # if no auth strategy is defined it falls back to using\n # credentials from the environment of the controller.\n auth:\n\n # 1: static credentials\n # point to a secret that contains static credentials\n # like AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY\n secretRef:\n accessKeyIDSecretRef:\n name: \"my-aws-creds\"\n key: \"key-id\"\n secretAccessKeySecretRef:\n name: \"my-aws-creds\"\n key: \"access-secret\"\n\n # option 2: IAM Roles for Service Accounts\n # point to a service account that should be used\n # that is configured for IAM Roles for Service Accounts (IRSA)\n jwt:\n serviceAccountRef:\n name: \"oci-token-sync\"\n</code></pre> <p>Example <code>ExternalSecret</code> that references the ECR generator: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: \"ecr-secret\"\nspec:\n refreshInterval: \"1h\"\n target:\n name: ecr-secret\n dataFrom:\n - sourceRef:\n generatorRef:\n apiVersion: generators.external-secrets.io/v1alpha1\n kind: ECRAuthorizationToken\n name: \"ecr-gen\"\n</code></pre></p>"},{"location":"api/generator/fake/","title":"Fake","text":"<p>The Fake generator provides hard-coded key/value pairs. The intended use is just for debugging and testing. The key/value pairs defined in <code>spec.data</code> is returned as-is.</p>"},{"location":"api/generator/fake/#example-manifest","title":"Example Manifest","text":"<pre><code>apiVersion: generators.external-secrets.io/v1alpha1\nkind: Fake\nmetadata:\n name: fake-key\nspec:\n data:\n foo: bar\n baz: bang\n</code></pre> <p>Example <code>ExternalSecret</code> that references the Fake generator: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: \"fake\"\nspec:\n refreshInterval: \"30m\"\n target:\n name: fake\n dataFrom:\n - sourceRef:\n generatorRef:\n apiVersion: generators.external-secrets.io/v1alpha1\n kind: Fake\n name: \"fake-key\"\n</code></pre></p>"},{"location":"api/generator/gcr/","title":"Google Container Registry","text":"<p>GCRAccessToken creates a GCP Access token that can be used to authenticate with GCR in order to pull OCI images. You won't need any extra permissions to request for a token, but the token would only work against a GCR if the token requester (service Account or WI) has the appropriate access</p> <p>You must specify the <code>spec.projectID</code> in which GCR is located.</p>"},{"location":"api/generator/gcr/#output-keys-and-values","title":"Output Keys and Values","text":"Key Description username username for the <code>docker login</code> command. password password for the <code>docker login</code> command. expiry time when token expires in UNIX time (seconds since January 1, 1970 UTC)."},{"location":"api/generator/gcr/#authentication","title":"Authentication","text":""},{"location":"api/generator/gcr/#workload-identity","title":"Workload Identity","text":"<p>Use <code>spec.auth.workloadIdentity</code> to point to a Service Account that has Workload Identity enabled. For details see GCP Secret Manager.</p>"},{"location":"api/generator/gcr/#gcp-service-account","title":"GCP Service Account","text":"<p>Use <code>spec.auth.secretRef</code> to point to a Secret that contains a GCP Service Account. For details see GCP Secret Manager.</p>"},{"location":"api/generator/gcr/#example-manifest","title":"Example Manifest","text":"<pre><code>apiVersion: generators.external-secrets.io/v1alpha1\nkind: GCRAccessToken\nmetadata:\n name: gcr-gen\nspec:\n # project where gcr lives in\n projectID: \"\"\n\n # choose authentication strategy\n auth:\n # option 1: workload identity\n workloadIdentity:\n # point to the workload identity\n # service account\n serviceAccountRef:\n name: \"\"\n audiences: []\n # the cluster can live in a different project or location\n # use the following fields to configure where the cluster lives\n clusterLocation: \"\"\n clusterName: \"\"\n clusterProjectID: \"\"\n\n\n # option 2: GCP service account\n secretRef:\n secretAccessKeySecretRef:\n name: \"\"\n key: \"\"\n</code></pre> <p>Example <code>ExternalSecret</code> that references the GCR generator: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: \"gcr-token\"\nspec:\n refreshInterval: \"30m\"\n target:\n name: gcr-token\n dataFrom:\n - sourceRef:\n generatorRef:\n apiVersion: generators.external-secrets.io/v1alpha1\n kind: GCRAccessToken\n name: \"gcr-gen\"\n</code></pre></p>"},{"location":"api/generator/github/","title":"Github","text":""},{"location":"api/generator/github/#github-app-authentication-documentation","title":"GitHub App Authentication Documentation","text":""},{"location":"api/generator/github/#1-register-a-github-app","title":"1. Register a GitHub App","text":"<p>To create a GitHub app, follow the instructions provided by GitHub:</p> <ul> <li>Visit: Registering a GitHub App</li> <li>Procedure:</li> <li>Fill in the necessary details for your app.</li> <li>Note the <code>App ID</code> provided after registration.</li> <li>At the bottom of the registration page, click on <code>Generate a private key</code>. Download and securely store this key.</li> </ul>"},{"location":"api/generator/github/#2-store-the-private-key","title":"2. Store the Private Key","text":"<p>After generating your private key, you need to store it securely. If you are using Kubernetes, you can store it as a secret:</p> <pre><code>kubectl create secret generic github-app-pem --from-file=key=path/to/your/private-key.pem\n</code></pre>"},{"location":"api/generator/github/#3-set-permissions-for-the-github-app","title":"3. Set Permissions for the GitHub App","text":"<p>Configure the necessary permissions for your GitHub app depending on what actions it needs to perform:</p> <ul> <li>Visit: Choosing Permissions for a GitHub App</li> <li>Example:</li> <li>For managing OCI images, set read and write permissions for packages.</li> </ul>"},{"location":"api/generator/github/#4-install-your-github-app","title":"4. Install Your GitHub App","text":"<p>Install the GitHub app on your repository or organization to start using it:</p> <ul> <li>Visit: Installing Your Own GitHub App</li> </ul>"},{"location":"api/generator/github/#5-obtain-an-installation-id","title":"5. Obtain an Installation ID","text":"<p>After installation, you need to get the installation ID to authenticate API requests:</p> <ul> <li>Visit: Generating an Installation Access Token for a GitHub App</li> <li>Procedure:</li> <li>Find the installation ID from the URL or API response.</li> </ul>"},{"location":"api/generator/github/#example-kubernetes-manifest-for-github-access-token-generator","title":"Example Kubernetes Manifest for GitHub Access Token Generator","text":"<pre><code># 1. Register Github app https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app#registering-a-github-app\n# `App ID: 123456` will be displayed after you create an app. Next on the bottom of the page, you'll find `Generate a private key` button.\n# 2. Get privateKey https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/managing-private-keys-for-github-apps#generating-private-keys put it in e.g `github-app-pem` k8s secret\n# 3. Set permissions for the app, e.g if you want to push OCI images to ghr set RW for packages https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/choosing-permissions-for-a-github-app#choosing-permissions-for-rest-api-access\n# 4. Install your Github app https://docs.github.com/en/apps/using-github-apps/installing-your-own-github-app\n# 5. Get `installID` https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-an-installation-access-token-for-a-github-app#generating-an-installation-access-token (2)\n---\napiVersion: generators.external-secrets.io/v1alpha1\nkind: GithubAccessToken\nmetadata:\n name: github-auth-token\nspec:\n appID: \"0000000\" # (1)\n installID: \"00000000\" # (5)\n url: \"\" # (Default https://api.github.com.)\n auth:\n privateKey:\n secretRef:\n name: github-app-pem # (2)\n key: key\n</code></pre> <pre><code>---\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: github-auth-token\nspec:\n refreshInterval: \"30m\"\n target:\n name: github-auth-token # Name for the secret to be created on the cluster\n dataFrom:\n - sourceRef:\n generatorRef:\n apiVersion: generators.external-secrets.io/v1alpha1\n kind: GithubAccessToken\n name: github-auth-token\n</code></pre> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: github-auth-template\nspec:\n dataFrom:\n - sourceRef:\n generatorRef:\n apiVersion: generators.external-secrets.io/v1alpha1\n kind: GithubAccessToken\n name: github-auth-token\n refreshInterval: \"15m\"\n target:\n template:\n metadata:\n annotations:\n tekton.dev/git-0: \"https://github.com\"\n type: kubernetes.io/basic-auth\n engineVersion: v2\n data:\n username: \"token\"\n password: \"{{ .token }}\"\n name: github-auth-template\n</code></pre>"},{"location":"api/generator/github/#notes","title":"Notes","text":"<ul> <li>Ensure that all sensitive data such as private keys and IDs are securely handled and stored.</li> <li>Adjust the permissions and configurations according to your specific requirements and security policies.</li> </ul>"},{"location":"api/generator/password/","title":"Password","text":"<p>The Password generator provides random passwords that you can feed into your applications. It uses lower and uppercase alphanumeric characters as well as symbols. Please see below for the symbols in use.</p> <p>Passwords are completely randomized</p> <p>It is possible that we may generate passwords that don't match the expected character set from your application.</p>"},{"location":"api/generator/password/#output-keys-and-values","title":"Output Keys and Values","text":"Key Description password the generated password"},{"location":"api/generator/password/#parameters","title":"Parameters","text":"<p>You can influence the behavior of the generator by providing the following args</p> Key Default Description length 24 Length of the password to be generated. digits 25% of the length Specify the number of digits in the generated password. symbols 25% of the length Specify the number of symbol characters in the generated. symbolCharacters ~!@#$%^&amp;*()_+`-={}|[]\\:\"&lt;&gt;?,./ Specify the character set that should be used when generating the password. noUpper false disable uppercase characters. allowRepeat false allow repeating characters."},{"location":"api/generator/password/#example-manifest","title":"Example Manifest","text":"<pre><code>apiVersion: generators.external-secrets.io/v1alpha1\nkind: Password\nmetadata:\n name: my-password\nspec:\n length: 42\n digits: 5\n symbols: 5\n symbolCharacters: \"-_$@\"\n noUpper: false\n allowRepeat: true\n</code></pre> <p>Example <code>ExternalSecret</code> that references the Password generator: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: \"password\"\nspec:\n refreshInterval: \"30m\"\n target:\n name: password-secret\n dataFrom:\n - sourceRef:\n generatorRef:\n apiVersion: generators.external-secrets.io/v1alpha1\n kind: Password\n name: \"my-password\"\n</code></pre></p> <p>Which will generate a <code>Kind=Secret</code> with a key called 'password' that may look like:</p> <pre><code>RMngCHKtZ@@h@3aja$WZDuDVhkCkN48JBa9OF8jH$R\nVB$pX8SSUMIlk9K8g@XxJAhGz$0$ktbJ1ArMukg-bD\nHi$-aK_3Rrrw1Pj9-sIpPZuk5abvEDJlabUYUcS$9L\n</code></pre> <p>With default values you would get something like:</p> <pre><code>2Cp=O*&amp;8x6sdwM!&lt;74G_gUz5\n-MS`e#n24K|h5A&lt;&amp;6q9Yv7Cj\nZRv-k!y6x/V\"29:43aErSf$1\nVk9*mwXE30Q+&gt;H?lY$5I64_q\n</code></pre>"},{"location":"api/generator/uuid/","title":"UUID","text":"<p>The UUID generator provides random UUIDs that you can feed into your applications. A UUID (Universally Unique Identifier) is a 128-bit label used for information in computer systems. Please see below for the format in use.</p>"},{"location":"api/generator/uuid/#output-keys-and-values","title":"Output Keys and Values","text":"Key Description uuid the generated UUID"},{"location":"api/generator/uuid/#parameters","title":"Parameters","text":"<p>The UUID generator does not require any additional parameters.</p>"},{"location":"api/generator/uuid/#example-manifest","title":"Example Manifest","text":"<pre><code>apiVersion: generators.external-secrets.io/v1alpha1\nkind: Uuid\nmetadata:\n name: my-uuid\nspec: {}\n</code></pre> <p>Example <code>ExternalSecret</code> that references the UUID generator:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: \"uuid\"\nspec:\n refreshInterval: \"30m\"\n target:\n name: uuid-secret\n dataFrom:\n - sourceRef:\n generatorRef:\n apiVersion: generators.external-secrets.io/v1alpha1\n kind: Uuid\n name: \"my-uuid\"\n</code></pre> <p>Which will generate a <code>Kind=Secret</code> with a key called 'uuid' that may look like:</p> <pre><code>EA111697-E7D0-452C-A24C-8E396947E865\n</code></pre> <p>With default values you would get something like:</p> <pre><code>4BEE258F-64C9-4755-92DC-AFF76451471B\n</code></pre>"},{"location":"api/generator/vault/","title":"Vault Dynamic Secret","text":"<p>The <code>VaultDynamicSecret</code> Generator provides an interface to HashiCorp Vault's Secrets engines. Specifically, it enables obtaining dynamic secrets not covered by the HashiCorp Vault provider.</p> <p>Any Vault authentication method supported by the provider can be used here (<code>provider</code> block of the spec).</p> <p>All secrets engines should be supported by providing matching <code>path</code>, <code>method</code> and <code>parameters</code> values to the Generator spec (see example below).</p> <p>Exact output keys and values depend on the Vault secret engine used; nested values are stored into the resulting Secret in JSON format.</p>"},{"location":"api/generator/vault/#example-manifest","title":"Example manifest","text":"<pre><code>apiVersion: generators.external-secrets.io/v1alpha1\nkind: VaultDynamicSecret\nmetadata:\n name: \"pki-example\"\nspec:\n path: \"/pki/issue/example-dot-com\"\n method: \"POST\"\n parameters:\n common_name: \"localhost\"\n ip_sans: \"127.0.0.1,127.0.0.11\"\n provider:\n server: \"http://vault.default.svc.cluster.local:8200\"\n auth:\n kubernetes:\n mountPath: \"kubernetes\"\n role: \"external-secrets-operator\"\n serviceAccountRef:\n name: \"default\"\n</code></pre> <p>Example <code>ExternalSecret</code> that references the Vault generator: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: \"pki-example-com\"\nspec:\n refreshInterval: \"768h\"\n target:\n name: pki-example-com\n dataFrom:\n - sourceRef:\n generatorRef:\n apiVersion: generators.external-secrets.io/v1alpha1\n kind: VaultDynamicSecret\n name: \"pki-example\"\n</code></pre></p>"},{"location":"api/generator/webhook/","title":"Webhook","text":"<p>The Webhook generator is very similar to SecretStore generator, and provides a way to use external systems to generate sensitive information.</p>"},{"location":"api/generator/webhook/#output-keys-and-values","title":"Output Keys and Values","text":"<p>Webhook calls are expected to produce valid JSON objects. All keys within that JSON object will be exported as keys to the kubernetes Secret.</p>"},{"location":"api/generator/webhook/#example-manifest","title":"Example Manifest","text":"<pre><code>apiVersion: generators.external-secrets.io/v1alpha1\nkind: Webhook\nmetadata:\n name: webhook\nspec:\n url: \"http://httpbin.org/get?parameter={{ .auth.param }}\"\n result:\n jsonPath: \"$.args\"\n headers:\n Content-Type: application/json\n Authorization: Basic {{ print .auth.username \":\" .auth.password | b64enc }}\n secrets:\n - name: auth\n secretRef:\n name: webhook-credentials\n---\napiVersion: v1\nkind: Secret\nmetadata:\n name: webhook-credentials\n labels:\n external-secrets.io/type: webhook #Needed to allow webhook to use this secret\ndata:\n username: dGVzdA== # \"test\"\n password: dGVzdA== # \"test\"\n param: dGVzdA== # \"test\"\n</code></pre> <p>Example <code>ExternalSecret</code> that references the Webhook generator using an internal <code>Secret</code>: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: \"webhook\"\nspec:\n refreshInterval: \"30m\"\n target:\n name: webhook-secret\n dataFrom:\n - sourceRef:\n generatorRef:\n apiVersion: generators.external-secrets.io/v1alpha1\n kind: Webhook\n name: \"webhook\"\n</code></pre></p> <p>This will generate a kubernetes secret with the following values: <pre><code>parameter: test\n</code></pre></p>"},{"location":"contributing/coc/","title":"Code of Conduct","text":""},{"location":"contributing/coc/#our-pledge","title":"Our Pledge","text":"<p>We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.</p> <p>We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.</p>"},{"location":"contributing/coc/#our-standards","title":"Our Standards","text":"<p>Examples of behavior that contributes to a positive environment for our community include:</p> <ul> <li>Demonstrating empathy and kindness toward other people</li> <li>Being respectful of differing opinions, viewpoints, and experiences</li> <li>Giving and gracefully accepting constructive feedback</li> <li>Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience</li> <li>Focusing on what is best not just for us as individuals, but for the overall community</li> </ul> <p>Examples of unacceptable behavior include:</p> <ul> <li>The use of sexualized language or imagery, and sexual attention or advances of any kind</li> <li>Trolling, insulting or derogatory comments, and personal or political attacks</li> <li>Public or private harassment</li> <li>Publishing others' private information, such as a physical or email address, without their explicit permission</li> <li>Other conduct which could reasonably be considered inappropriate in a professional setting</li> </ul>"},{"location":"contributing/coc/#enforcement-responsibilities","title":"Enforcement Responsibilities","text":"<p>Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.</p> <p>Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.</p>"},{"location":"contributing/coc/#scope","title":"Scope","text":"<p>This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.</p>"},{"location":"contributing/coc/#enforcement","title":"Enforcement","text":"<p>Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at cncf-ExternalSecretsOp-maintainers@lists.cncf.io. All complaints will be reviewed and investigated promptly and fairly.</p> <p>All community leaders are obligated to respect the privacy and security of the reporter of any incident.</p>"},{"location":"contributing/coc/#enforcement-guidelines","title":"Enforcement Guidelines","text":"<p>Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:</p>"},{"location":"contributing/coc/#1-correction","title":"1. Correction","text":"<p>Community Impact: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.</p> <p>Consequence: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.</p>"},{"location":"contributing/coc/#2-warning","title":"2. Warning","text":"<p>Community Impact: A violation through a single incident or series of actions.</p> <p>Consequence: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.</p>"},{"location":"contributing/coc/#3-temporary-ban","title":"3. Temporary Ban","text":"<p>Community Impact: A serious violation of community standards, including sustained inappropriate behavior.</p> <p>Consequence: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.</p>"},{"location":"contributing/coc/#4-permanent-ban","title":"4. Permanent Ban","text":"<p>Community Impact: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.</p> <p>Consequence: A permanent ban from any sort of public interaction within the community.</p>"},{"location":"contributing/coc/#attribution","title":"Attribution","text":"<p>This Code of Conduct is adapted from the Contributor Covenant, version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.</p> <p>Community Impact Guidelines were inspired by Mozilla's code of conduct enforcement ladder.</p> <p>For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.</p>"},{"location":"contributing/devguide/","title":"Developer guide","text":""},{"location":"contributing/devguide/#getting-started","title":"Getting Started","text":"<p>You must have a working Go environment and then clone the repo:</p> <pre><code>git clone https://github.com/external-secrets/external-secrets.git\ncd external-secrets\n</code></pre> <p>Note: many of the <code>make</code> commands use yq, version 4.2X.X or higher.</p> <p>Our helm chart is tested using <code>helm-unittest</code>. You will need it to run tests locally if you modify the helm chart. Install it with the following command:</p> <pre><code>$ helm plugin install https://github.com/helm-unittest/helm-unittest\n</code></pre>"},{"location":"contributing/devguide/#building-testing","title":"Building &amp; Testing","text":"<p>The project uses the <code>make</code> build system. It'll run code generators, tests and static code analysis.</p> <p>Building the operator binary and docker image:</p> <pre><code>make build\nmake docker.build IMAGE_NAME=external-secrets IMAGE_TAG=latest\n</code></pre> <p>Run tests and lint the code: <pre><code>make test\nmake lint # OR\ndocker run --rm -v $(pwd):/app -w /app golangci/golangci-lint:v1.49.0 golangci-lint run\n</code></pre></p> <p>Build the documentation: <pre><code>make docs\n</code></pre></p>"},{"location":"contributing/devguide/#using-tilt","title":"Using Tilt","text":"<p>Tilt can be used to develop external-secrets. Tilt will hot-reload changes to the code and replace the running binary in the container using a process manager of its own.</p> <p>To run tilt, download the utility for your operating system and run <code>make tilt-up</code>. This will do two things: - downloads tilt for the current OS and ARCH under <code>bin/tilt</code> - make manifest files of your current changes and place them under <code>./bin/deploy/manifests/external-secrets.yaml</code> - run tilt with <code>tilt run</code></p> <p>Hit <code>space</code> and you can observe all the pods starting up and track their output in the tilt UI.</p>"},{"location":"contributing/devguide/#installing","title":"Installing","text":"<p>To install the External Secret Operator into a Kubernetes Cluster run:</p> <pre><code>helm repo add external-secrets https://charts.external-secrets.io\nhelm repo update\nhelm install external-secrets external-secrets/external-secrets\n</code></pre> <p>You can alternatively run the controller on your host system for development purposes:</p> <pre><code>make crds.install\nmake run\n</code></pre> <p>To remove the CRDs run:</p> <pre><code>make crds.uninstall\n</code></pre> <p>If you need to test some other k8s integrations and need the operator to be deployed to the actual cluster while developing, you can use the following workflow:</p> <pre><code># Start a local K8S cluster with KinD\nkind create cluster --name external-secrets\n\nexport TAG=$(make docker.tag)\nexport IMAGE=$(make docker.imagename)\n\n# Build docker image\nmake docker.build\n\n# Load docker image into local kind cluster\nkind load docker-image $IMAGE:$TAG --name external-secrets\n\n# (Optional) Pull the image from GitHub Repo to copy into kind\n# docker pull ghcr.io/external-secrets/external-secrets:v0.8.2\n# kind load docker-image ghcr.io/external-secrets/external-secrets:v0.8.2 -n external-secrets\n# export TAG=v0.8.2\n\n# Update helm charts and install to KinD cluster\nmake helm.generate\nhelm upgrade --install external-secrets ./deploy/charts/external-secrets/ \\\n--set image.repository=$IMAGE --set image.tag=$TAG \\\n--set webhook.image.repository=$IMAGE --set webhook.image.tag=$TAG \\\n--set certController.image.repository=$IMAGE --set certController.image.tag=$TAG\n\n\n# Command to delete the cluster when done\n# kind delete cluster -n external-secrets\n</code></pre> <p>Contributing Flow</p> <p>The HOW TO guide for contributing is at the Contributing Process page.</p>"},{"location":"contributing/devguide/#documentation","title":"Documentation","text":"<p>We use mkdocs material and mike to generate this documentation. See <code>/docs</code> for the source code and <code>/hack/api-docs</code> for the build process.</p> <p>When writing documentation it is advised to run the mkdocs server with livereload:</p> <pre><code>make docs.serve\n</code></pre> <p>Run the following command to run a complete build. The rendered assets are available under <code>/site</code>.</p> <pre><code>make docs\nmake docs.serve\n</code></pre> <p>Open <code>http://localhost:8000</code> in your browser.</p> <p>Since mike uses a branch to create/update documentation, any docs operation will create a diff on your local <code>gh-pages</code> branch.</p> <p>When finished writing/reviewing the docs, clean up your local docs branch changes with <code>git branch -D gh-pages</code></p>"},{"location":"contributing/process/","title":"Contributing Process","text":""},{"location":"contributing/process/#project-management","title":"Project Management","text":"<p>The Code, our TODOs and Documentation is maintained on GitHub. All Issues should be opened in that repository. We have a Roadmap to track progress for our road towards GA.</p>"},{"location":"contributing/process/#issues","title":"Issues","text":"<p>Features, bugs and any issues regarding the documentation should be filed as GitHub Issue in our repository. We use labels like <code>kind/feature</code>, <code>kind/bug</code>, <code>area/aws</code> to organize the issues. Issues labeled <code>good first issue</code> and <code>help wanted</code> are especially good for a first contribution. If you want to pick up an issue just leave a comment.</p>"},{"location":"contributing/process/#submitting-a-pull-request","title":"Submitting a Pull Request","text":"<p>This project uses the well-known pull request process from GitHub. To submit a pull request, fork the repository and push any changes to a branch on the copy, from there a pull request can be made in the main repo. Merging a pull request requires the following steps to be completed before the pull request will be merged:</p> <ul> <li>ideally, there is an issue that documents the problem or feature in depth.</li> <li>code must have a reasonable amount of test coverage</li> <li>tests must pass</li> <li>PR needs be reviewed and approved</li> </ul> <p>Once these steps are completed the PR will be merged by a code owner. We're using the pull request <code>assignee</code> feature to track who is responsible for the lifecycle of the PR: review, merging, ping on inactivity, close. We close pull requests or issues if there is no response from the author for a period of time. Feel free to reopen if you want to get back on it.</p>"},{"location":"contributing/process/#triggering-e2e-tests","title":"Triggering e2e tests","text":"<p>We have an extensive set of e2e tests that test the integration with real cloud provider APIs. Maintainers must trigger these kind of tests manually for PRs that come from forked repositories. These tests run inside a <code>kind</code> cluster in the GitHub Actions runner:</p> <p><pre><code>/ok-to-test sha=&lt;full_commit_hash&gt;\n</code></pre> Examples: <pre><code>/ok-to-test sha=b8ca0040200a7a05d57048d86a972fdf833b8c9b\n</code></pre></p>"},{"location":"contributing/process/#executing-e2e-tests-locally","title":"Executing e2e tests locally","text":"<p>You have to prepare your shell environment with the necessary variables so the e2e test runner knows what credentials to use. See <code>e2e/run.sh</code> for the variables that are passed in. If you e.g. want to test AWS integration make sure set all <code>AWS_*</code> variables mentioned in that file.</p> <p>Use ginkgo labels to select the tests you want to execute. You have to specify <code>!managed</code> to ensure that you do not run managed tests.</p> <pre><code>make test.e2e GINKGO_LABELS='gcp&amp;&amp;!managed'\n</code></pre>"},{"location":"contributing/process/#managed-kubernetes-e2e-tests","title":"Managed Kubernetes e2e tests","text":"<p>There's another suite of e2e tests that integrate with managed Kubernetes offerings. They create real infrastructure at a cloud provider and deploy the controller into that environment. This is necessary to test the authentication integration (GCP Workload Identity, EKS IRSA...).</p> <p>These tests are time intensive (~20-45min) and must be triggered manually by a maintainer when a particular provider or authentication mechanism was changed:</p> <pre><code>/ok-to-test-managed sha=xxxxxx provider=aws\n# or\n/ok-to-test-managed sha=xxxxxx provider=gcp\n# or\n/ok-to-test-managed sha=xxxxxx provider=azure\n</code></pre> <p>Both tests can run in parallel. Once started they add a dynamic GitHub check <code>integration-managed-(gcp|aws|azure)</code> to the PR that triggered the test.</p>"},{"location":"contributing/process/#executing-managed-kubernetes-e2e-tests-locally","title":"Executing Managed Kubernetes e2e tests locally","text":"<p>You have to prepare your shell environment with the necessary variables so the e2e test runner knows what credentials to use. See <code>.github/workflows/e2e-managed.yml</code> for the variables that are passed in. If you e.g. want to test AWS integration make sure set all variables containing <code>AWS_*</code> and <code>TF_VAR_AWS_*</code> mentioned in that file.</p> <p>Then execute <code>tf.apply.aws</code> or <code>tf.apply.gcp</code> to create the infrastructure.</p> <pre><code>make tf.apply.aws\n</code></pre> <p>Then run the <code>managed</code> testsuite. You will need push permissions to the external-secrets ghcr repository. You can set <code>IMAGE_NAME</code> to control which image registry is used to store the controller and e2e test images in.</p> <p>You also have to setup a proper Kubeconfig so the e2e test pod gets deployed into the managed cluster.</p> <pre><code>aws eks update-kubeconfig --name ${AWS_CLUSTER_NAME}\nor\ngcloud container clusters get-credentials ${GCP_GKE_CLUSTER} --region europe-west1-b\n</code></pre> <p>Use ginkgo labels to select the tests you want to execute.</p> <pre><code># you may have to set IMAGE_NAME=docker.io/your-user/external-secrets\nmake test.e2e.managed GINKGO_LABELS='gcp'\n</code></pre>"},{"location":"contributing/process/#proposal-process","title":"Proposal Process","text":"<p>Before we introduce significant changes to the project we want to gather feedback from the community to ensure that we progress in the right direction before we develop and release big changes. Significant changes include for example:</p> <ul> <li>creating new custom resources</li> <li>proposing breaking changes</li> <li>changing the behavior of the controller significantly</li> </ul> <p>Please create a document in the <code>design/</code> directory based on the template <code>000-template.md</code> and fill in your proposal. Open a pull request in draft mode and request feedback. Once the proposal is accepted and the pull request is merged we can create work packages and proceed with the implementation.</p>"},{"location":"contributing/process/#release-planning","title":"Release Planning","text":"<p>We have a GitHub Project Board where we organize issues on a high level. We group issues by milestone. Once all issues of a given milestone are closed we should prepare a new feature release. Issues of the next milestone have priority over other issues - but that does not mean that no one is allowed to start working on them.</p> <p>Issues must be manually added to that board (at least for now, see GH Roadmap). Milestones must be assigned manually as well. If no milestone is assigned it is basically a backlog item. It is the responsibility of the maintainers to:</p> <ol> <li>assign new issues to the GH Project</li> <li>add a milestone if needed</li> <li>add appropriate labels</li> </ol> <p>If you would like to raise the priority of an issue for whatever reason feel free to comment on the issue or ping a maintainer.</p>"},{"location":"contributing/process/#support-questions","title":"Support &amp; Questions","text":"<p>Providing support to end users is an important and difficult task. We have three different channels through which support questions arise:</p> <ol> <li>Kubernetes Slack #external-secrets</li> <li>GitHub Discussions</li> <li>GitHub Issues</li> </ol> <p>We use labels to identify GitHub Issues. Specifically for managing support cases we use the following labels to identify the state a support case is in:</p> <ul> <li><code>triage/needs-information</code>: Indicates an issue needs more information in order to work on it.</li> <li><code>triage/not-reproducible</code>: Indicates an issue can not be reproduced as described.</li> <li><code>triage/support</code>: Indicates an issue that is a support question.</li> </ul>"},{"location":"contributing/process/#cutting-releases","title":"Cutting Releases","text":"<p>The external-secrets project is released on a as-needed basis. Feel free to open a issue to request a release. Details on how to cut a release can be found in the release page.</p>"},{"location":"contributing/release/","title":"Release Process","text":"<p>ESO and the ESO Helm Chart have two distinct lifecycles and can be released independently. Helm Chart releases are named <code>external-secrets-x.y.z</code>.</p> <p>The external-secrets project is released on a as-needed basis. Feel free to open a issue to request a release.</p>"},{"location":"contributing/release/#release-eso","title":"Release ESO","text":"<p>When doing a release it's best to start with with the \"Create Release\" issue template, it has a checklist to go over.</p> <p>\u26a0\ufe0f Note: when releasing multiple versions, make sure to first release the \"old\" version, then the newer version. Otherwise the <code>latest</code> documentation will point to the older version. Also avoid to release both versions at the same time to avoid race conditions in the CI pipeline (updating docs, GitHub Release, helm chart release).</p> <ol> <li>Run <code>Create Release</code> Action to create a new release, pass in the desired version number to release.<ol> <li>choose the right <code>branch</code> to execute the action: use <code>main</code> when creating a new release. Use <code>release-x.y</code> when you want to bump a LTS release.</li> <li>\u26a0\ufe0f make sure that CI on the relevant branch has completed the docker build/push jobs. Otherwise an old image will be promoted.</li> </ol> </li> <li>GitHub Release, Changelog will be created by the <code>release.yml</code> workflow which also promotes the container image.</li> <li>update Helm Chart, see below</li> <li>update OLM bundle, see helm-operator docs</li> </ol>"},{"location":"contributing/release/#release-helm-chart","title":"Release Helm Chart","text":"<ol> <li>Update <code>version</code> and/or <code>appVersion</code> in <code>Chart.yaml</code> and run <code>make helm.docs helm.update.appversion helm.test.update helm.test</code></li> <li>push to branch and open pr</li> <li>run <code>/ok-to-test-managed</code> commands for all cloud providers</li> <li>merge PR if everyhing is green</li> <li>CI picks up the new chart version and creates a new GitHub Release for it</li> <li>create/merge into release branch<ol> <li>on a <code>minor</code> release: create a new branch <code>release-x.y</code></li> <li>on a <code>patch</code> release: merge main into <code>release-x.y</code></li> </ol> </li> </ol>"},{"location":"contributing/release/#release-olm-bundle","title":"Release OLM Bundle","text":"<p>In order to make the latest release available to OperatorHub.io we need to create a bundle and open a PR in the community-operators repository.</p> <p>To create a bundle first increment the <code>VERSION</code> in the Makefile as described above. Then run the following commands in the root of the repository:</p> <pre><code># clone repo\ngit clone https://github.com/external-secrets/external-secrets-helm-operator\ncd external-secrets-helm-operator\n\n# bump version\nexport VERSION=x.y.z\nsed -i \"s/^VERSION ?= .*/VERSION ?= ${VERSION}/\" Makefile\n\n# prep release\nmake prepare-stable-release ATTACH_IMAGE_DIGESTS=0\n</code></pre> <p>Check the generated files in the <code>bundle/</code> directory. If they look good add &amp; commit them, open a PR against this repository. You can always use the OperatorHub.io/preview page to preview the generated CSV.</p> <pre><code>git status\ngit add .\ngit commit -s -m \"chore: bump version xyz\"\ngit push\n</code></pre> <p>Once the PR is merged and the image build job on <code>main</code> has completed, we need create a pull request against both community-operators repositories. There's a make target that does the heavy lifting for you: <pre><code>make attach-image-digests\nmake bundle-operatorhub\n</code></pre></p> <p>This command will add/commit/push and open pull requests in the respective repositories.</p>"},{"location":"contributing/roadmap/","title":"The road to external-secrets GA","text":"<p>The following external-secret custom resource APIs are considered stable:</p> <ul> <li><code>ExternalSecret</code></li> <li><code>ClusterExternalSecret</code></li> <li><code>SecretStore</code></li> <li><code>ClusterSecretStore</code></li> </ul> <p>These CRDs are currently at <code>v1beta1</code> and are considered production ready. Going forward, breaking changes to these APIs will be accompanied by a conversion mechanism.</p> <p>We have identified the following areas of work. This is subject to change while we gather feedback. We have a GitHub Project Board where we organize issues and milestones on a high level.</p> <ul> <li>Conformance testing<ul> <li>\u2713 end to end testing with ArgoCD and Flux</li> <li>\u2713 end to end testing for all project maintained providers</li> </ul> </li> <li>API enhancements<ul> <li>consolidate provider fields</li> <li>\u2713 dataFrom key rewrites</li> <li>provider versioning strategy</li> <li>\u2713 pushing secrets to a provider</li> </ul> </li> <li>Documentation Improvements<ul> <li>Troubleshooting Guides</li> <li>\u2713 FAQ</li> <li>\u2713 review multi tenancy docs</li> <li>\u2713 security model for infosec teams</li> <li>\u2713 security best practices guide</li> <li>\u2713 provider specific guides</li> </ul> </li> <li>Observability<ul> <li>\u2713 Provide Grafana Dashboard and Prometheus alerts</li> <li>\u2713 add provider-level metrics</li> </ul> </li> <li>Pentest</li> <li>\u2713 SBOM</li> </ul>"},{"location":"examples/anchore-engine-credentials/","title":"Getting started","text":"<p>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</p>"},{"location":"examples/anchore-engine-credentials/#installing-with-helm","title":"Installing with Helm","text":"<p>There are several parts of the installation that require credentials these being :-</p> <p>ANCHORE_ADMIN_USERNAME ANCHORE_ADMIN_PASSWORD ANCHORE_DB_PASSWORD db-url db-user postgres-password</p> <p>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.</p>"},{"location":"examples/anchore-engine-credentials/#hashicorp-vault","title":"Hashicorp Vault","text":"<pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: anchore-access-credentials\n namespace: security\nspec:\n refreshInterval: 1m\n secretStoreRef:\n name: vault-backend\n kind: ClusterSecretStore\n target:\n name: anchore-access-credentials\n template:\n\n data:\n ANCHORE_ADMIN_USERNAME: &gt;-\n {{ printf \"{{ .username | toString }}\" }}\n ANCHORE_ADMIN_PASSWORD: &gt;-\n {{ printf \"{{ .password | toString }}\" }}\n ANCHORE_DB_PASSWORD: &gt;-\n {{ printf \"{{ .dbPassword | toString }}\" }}\n db-url: &gt;-\n {{ printf \"{{ .dbUrl | toString }}\" }}\n db-user: &gt;-\n {{ printf \"{{ .dbUser | toString }}\" }}\n postgres-password: &gt;-\n {{ printf \"{{ .postgresPassword | toString }}\" }}\n\n data:\n - secretKey: password\n remoteRef:\n key: anchore-engine\n property: ANCHORE_ADMIN_PASSWORD\n - secretKey: username\n remoteRef:\n key: anchore-engine\n property: ANCHORE_ADMIN_USERNAME\n - secretKey: dbPassword\n remoteRef:\n key: anchore-engine\n property: ANCHORE_DB_PASSWORD\n - secretKey: dbUrl\n remoteRef:\n key: anchore-engine\n property: db-url\n - secretKey: dbUser\n remoteRef:\n key: anchore-engine\n property: db-user\n - secretKey: postgresPassword\n remoteRef:\n key: anchore-engine\n property: postgres-password\n</code></pre>"},{"location":"examples/anchore-engine-credentials/#aws-secrets-manager","title":"AWS Secrets Manager","text":"<pre><code>---\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: anchore-access-credentials\n namespace: ci\nspec:\n refreshInterval: 1m\n secretStoreRef:\n name: cluster-secrets-store\n kind: ClusterSecretStore\n target:\n name: anchore-access-credentials\n dataFrom:\n - extract:\n key: service/anchore-engine/engineAccess\n</code></pre>"},{"location":"examples/bitwarden/","title":"Bitwarden support using webhook provider","text":"<p>Bitwarden is an integrated open source password management solution for individuals, teams, and business organizations.</p>"},{"location":"examples/bitwarden/#how-does-it-work","title":"How does it work?","text":"<p>To make external-secrets compatible with Bitwarden, we need:</p> <ul> <li>External Secrets Operator &gt;= 0.8.0</li> <li>Multiple (Cluster)SecretStores using the webhook provider</li> <li>BitWarden CLI image running <code>bw serve</code></li> </ul> <p>When you create a new external-secret object, the External Secrets webhook provider will query the Bitwarden CLI pod that is synced with the Bitwarden server.</p>"},{"location":"examples/bitwarden/#requirements","title":"Requirements","text":"<ul> <li>Bitwarden account (it also works with Vaultwarden!)</li> <li>A Kubernetes secret which contains your Bitwarden credentials</li> <li>A Docker image running the Bitwarden CLI. You could use <code>ghcr.io/charlesthomas/bitwarden-cli:2023.12.1</code> or build your own.</li> </ul> <p>Here is an example of a Dockerfile used to build the image: <pre><code>FROM debian:sid\n\nENV BW_CLI_VERSION=2023.12.1\n\nRUN apt update &amp;&amp; \\\n apt install -y wget unzip &amp;&amp; \\\n wget https://github.com/bitwarden/clients/releases/download/cli-v${BW_CLI_VERSION}/bw-linux-${BW_CLI_VERSION}.zip &amp;&amp; \\\n unzip bw-linux-${BW_CLI_VERSION}.zip &amp;&amp; \\\n chmod +x bw &amp;&amp; \\\n mv bw /usr/local/bin/bw &amp;&amp; \\\n rm -rfv *.zip\n\nCOPY entrypoint.sh /\n\nCMD [\"/entrypoint.sh\"]\n</code></pre></p> <p>And the content of <code>entrypoint.sh</code>: <pre><code>#!/bin/bash\n\nset -e\n\nbw config server ${BW_HOST}\n\nexport BW_SESSION=$(bw login ${BW_USER} --passwordenv BW_PASSWORD --raw)\n\nbw unlock --check\n\necho 'Running `bw server` on port 8087'\nbw serve --hostname 0.0.0.0 #--disable-origin-protection\n</code></pre></p>"},{"location":"examples/bitwarden/#deploy-bitwarden-credentials","title":"Deploy Bitwarden credentials","text":"<pre><code>apiVersion: v1\ndata:\n BW_HOST: ...\n BW_USERNAME: ...\n BW_PASSWORD: ....\nkind: Secret\nmetadata:\n name: bitwarden-cli\n namespace: bitwarden\ntype: Opaque\n</code></pre>"},{"location":"examples/bitwarden/#deploy-bitwarden-cli-container","title":"Deploy Bitwarden CLI container","text":"<pre><code>apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: bitwarden-cli\n namespace: bitwarden\n labels:\n app.kubernetes.io/instance: bitwarden-cli\n app.kubernetes.io/name: bitwarden-cli\nspec:\n replicas: 1\n strategy:\n type: Recreate\n selector:\n matchLabels:\n app.kubernetes.io/name: bitwarden-cli\n app.kubernetes.io/instance: bitwarden-cli\n template:\n metadata:\n labels:\n app.kubernetes.io/name: bitwarden-cli\n app.kubernetes.io/instance: bitwarden-cli\n spec:\n containers:\n - name: bitwarden-cli\n image: YOUR_BITWARDEN_CLI_IMAGE\n imagePullPolicy: IfNotPresent\n env:\n - name: BW_HOST\n valueFrom:\n secretKeyRef:\n name: bitwarden-cli\n key: BW_HOST\n - name: BW_USER\n valueFrom:\n secretKeyRef:\n name: bitwarden-cli\n key: BW_USERNAME\n - name: BW_PASSWORD\n valueFrom:\n secretKeyRef:\n name: bitwarden-cli\n key: BW_PASSWORD\n ports:\n - name: http\n containerPort: 8087\n protocol: TCP\n livenessProbe:\n exec:\n command:\n - wget\n - -q\n - http://127.0.0.1:8087/sync?force=true\n - --post-data=''\n initialDelaySeconds: 20\n failureThreshold: 3\n timeoutSeconds: 10\n periodSeconds: 120\n readinessProbe:\n tcpSocket:\n port: 8087\n initialDelaySeconds: 20\n failureThreshold: 3\n timeoutSeconds: 1\n periodSeconds: 10\n startupProbe:\n tcpSocket:\n port: 8087\n initialDelaySeconds: 10\n failureThreshold: 30\n timeoutSeconds: 1\n periodSeconds: 5\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: bitwarden-cli\n namespace: bitwarden\n labels:\n app.kubernetes.io/instance: bitwarden-cli\n app.kubernetes.io/name: bitwarden-cli\n annotations:\nspec:\n type: ClusterIP\n ports:\n - port: 8087\n targetPort: http\n protocol: TCP\n name: http\n selector:\n app.kubernetes.io/name: bitwarden-cli\n app.kubernetes.io/instance: bitwarden-cli\n---\nkind: NetworkPolicy\napiVersion: networking.k8s.io/v1\nmetadata:\n namespace: bitwarden\n name: external-secret-2-bw-cli\nspec:\n podSelector:\n matchLabels:\n app.kubernetes.io/instance: bitwarden-cli\n app.kubernetes.io/name: bitwarden-cli\n ingress:\n - from:\n - podSelector:\n matchLabels:\n app.kubernetes.io/instance: external-secrets\n app.kubernetes.io/name: external-secrets\n</code></pre> <p>NOTE: Deploying a network policy is recommended since there is no authentication to query the Bitwarden CLI, which means that your secrets are exposed.</p> <p>NOTE: In this example the Liveness probe is querying /sync to ensure that the Bitwarden CLI is able to connect to the server and is also synchronised. (The secret sync is only every 2 minutes in this example)</p>"},{"location":"examples/bitwarden/#deploy-clustersecretstores","title":"Deploy (Cluster)SecretStores","text":"<p>There are four possible (Cluster)SecretStores to deploy, each can access different types of fields from an item in the Bitwarden vault. It is not required to deploy them all.</p> <pre><code>---\napiVersion: external-secrets.io/v1beta1\nkind: ClusterSecretStore\nmetadata:\n name: bitwarden-login\nspec:\n provider:\n webhook:\n url: \"http://bitwarden-cli:8087/object/item/{{ .remoteRef.key }}\"\n headers:\n Content-Type: application/json\n result:\n jsonPath: \"$.data.login.{{ .remoteRef.property }}\"\n---\napiVersion: external-secrets.io/v1beta1\nkind: ClusterSecretStore\nmetadata:\n name: bitwarden-fields\nspec:\n provider:\n webhook:\n url: \"http://bitwarden-cli:8087/object/item/{{ .remoteRef.key }}\"\n result:\n jsonPath: \"$.data.fields[?@.name==\\\"{{ .remoteRef.property }}\\\"].value\"\n---\napiVersion: external-secrets.io/v1beta1\nkind: ClusterSecretStore\nmetadata:\n name: bitwarden-notes\nspec:\n provider:\n webhook:\n url: \"http://bitwarden-cli:8087/object/item/{{ .remoteRef.key }}\"\n result:\n jsonPath: \"$.data.notes\"\n---\napiVersion: external-secrets.io/v1beta1\nkind: ClusterSecretStore\nmetadata:\n name: bitwarden-attachments\nspec:\n provider:\n webhook:\n url: \"http://bitwarden-cli:8087/object/attachment/{{ .remoteRef.property }}?itemid={{ .remoteRef.key }}\"\n result: {}\n</code></pre>"},{"location":"examples/bitwarden/#usage","title":"Usage","text":"<p>(Cluster)SecretStores:</p> <ul> <li><code>bitwarden-login</code>: Use to get the <code>username</code> or <code>password</code> fields</li> <li><code>bitwarden-fields</code>: Use to get custom fields</li> <li><code>bitwarden-notes</code>: Use to get notes</li> <li><code>bitwarden-attachments</code>: Use to get attachments</li> </ul> <p>remoteRef:</p> <ul> <li> <p><code>key</code>: ID of a secret, which can be found in the URL <code>itemId</code> parameter: <code>https://myvault.com/#/vault?type=login&amp;itemId=........-....-....-....-............</code>s</p> </li> <li> <p><code>property</code>: Name of the field to access</p> <ul> <li><code>username</code> for the username of a secret (<code>bitwarden-login</code> SecretStore)</li> <li><code>password</code> for the password of a secret (<code>bitwarden-login</code> SecretStore)</li> <li><code>name_of_the_custom_field</code> for any custom field (<code>bitwarden-fields</code> SecretStore)</li> <li><code>id_or_name_of_the_attachment</code> for any attachment (<code>bitwarden-attachment</code>, SecretStore)</li> </ul> </li> </ul> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: my-secrets\n namespace: default\nspec:\n target:\n name: my-secrets\n deletionPolicy: Delete\n template:\n type: Opaque\n data:\n username: |-\n {{ .username }}\n password: |-\n {{ .password }}\n postgres-password: |-\n {{ .postgres_password }}\n postgres-replication-password: |-\n {{ .postgres_replication_password }}\n db_url: |-\n postgresql://{{ .username }}:{{ .password }}@my-postgresql:5432/mydb\n service_account_key: |-\n {{ .service_account_key }}\n ssh_pub_key: |-\n {{ .ssh_pub_key }}\n data:\n - secretKey: username\n sourceRef:\n storeRef:\n name: bitwarden-login\n kind: ClusterSecretStore # or SecretStore\n remoteRef:\n key: aaaabbbb-cccc-dddd-eeee-000011112222\n property: username\n - secretKey: password\n sourceRef:\n storeRef:\n name: bitwarden-login\n kind: ClusterSecretStore # or SecretStore\n remoteRef:\n key: aaaabbbb-cccc-dddd-eeee-000011112222\n property: password\n - secretKey: postgres_password\n sourceRef:\n storeRef:\n name: bitwarden-fields\n kind: ClusterSecretStore # or SecretStore\n remoteRef:\n key: aaaabbbb-cccc-dddd-eeee-000011112222\n property: admin-password\n - secretKey: postgres_replication_password\n sourceRef:\n storeRef:\n name: bitwarden-fields\n kind: ClusterSecretStore # or SecretStore\n remoteRef:\n key: aaaabbbb-cccc-dddd-eeee-000011112222\n property: postgres-replication-password\n - secretKey: service_account_key\n sourceRef:\n storeRef:\n name: bitwarden-notes\n kind: ClusterSecretStore # or SecretStore\n remoteRef:\n key: service_account_key\n - secretKey: ssh_pub_key\n sourceRef:\n storeRef:\n name: bitwarden-attachments\n kind: ClusterSecretStore # or SecretStore\n remoteRef:\n key: aaaabbbb-cccc-dddd-eeee-000011112222\n property: id_rsa.pub\n</code></pre>"},{"location":"examples/gitops-using-fluxcd/","title":"GitOps using FluxCD (v2)","text":"<p>FluxCD is a GitOps operator for Kubernetes. It synchronizes the status of the cluster from manifests allocated in different repositories (Git or Helm). This approach fits perfectly with External Secrets on clusters which are dynamically created, to get credentials with no manual intervention from the beginning.</p>"},{"location":"examples/gitops-using-fluxcd/#advantages","title":"Advantages","text":"<p>This approach has several advantages as follows:</p> <ul> <li>Homogenize environments allowing developers to use the same toolset in Kind in the same way they do in the cloud provider distributions such as EKS or GKE. This accelerates the development</li> <li>Reduce security risks, because credentials can be easily obtained, so temptation to store them locally is reduced.</li> <li>Application compatibility increase: Applications are deployed in different ways, and sometimes they need to share credentials. This can be done using External Secrets as a wire for them at real time.</li> <li>Automation by default oh, come on!</li> </ul>"},{"location":"examples/gitops-using-fluxcd/#the-approach","title":"The approach","text":"<p>FluxCD is composed by several controllers dedicated to manage different custom resources. The most important ones are Kustomization (to clarify, Flux one, not Kubernetes' one) and HelmRelease to deploy using the approaches of the same names.</p> <p>External Secrets can be deployed using Helm as explained here. The deployment includes the CRDs if enabled on the <code>values.yaml</code>, but after this, you need to deploy some <code>SecretStore</code> to start getting credentials from your secrets manager with External Secrets.</p> <p>The idea of this guide is to deploy the whole stack, using flux, needed by developers not to worry about the credentials, but only about the application and its code.</p>"},{"location":"examples/gitops-using-fluxcd/#the-problem","title":"The problem","text":"<p>This can sound easy, but External Secrets is deployed using Helm, which is managed by the HelmController, and your custom resources, for example a <code>ClusterSecretStore</code> and the related <code>Secret</code>, are often deployed using a <code>kustomization.yaml</code>, which is deployed by the KustomizeController.</p> <p>Both controllers manage the resources independently, at different moments, with no possibility to wait each other. This means that we have a wonderful race condition where sometimes the CRs (<code>SecretStore</code>,<code>ClusterSecretStore</code>...) tries to be deployed before than the CRDs needed to recognize them.</p>"},{"location":"examples/gitops-using-fluxcd/#the-solution","title":"The solution","text":"<p>Let's see the conditions to start working on a solution:</p> <ul> <li>The External Secrets operator is deployed with Helm, and admits disabling the CRDs deployment</li> <li>The race condition only affects the deployment of <code>CustomResourceDefinition</code> and the CRs needed later</li> <li>CRDs can be deployed directly from the Git repository of the project using a Flux <code>Kustomization</code></li> <li>Required CRs can be deployed using a Flux <code>Kustomization</code> too, allowing dependency between CRDs and CRs</li> <li>All previous manifests can be applied with a Kubernetes <code>kustomization</code></li> </ul>"},{"location":"examples/gitops-using-fluxcd/#create-the-main-kustomization","title":"Create the main kustomization","text":"<p>To have a better view of things needed later, the first manifest to be created is the <code>kustomization.yaml</code></p> <pre><code>apiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\n\nresources:\n# Deploy the Vault access secret\n- namespace.yaml\n- secret-token.yaml\n\n# Deploy the repositories\n- repositories.yaml\n\n# Deploy the CRDs\n- deployment-crds.yaml\n\n# Deploy the operator\n- deployment.yaml\n\n# Deploy default Custom Resources from 'crs' directory\n# INFO: This depends on the CRDs deployment. Will happen after it\n- deployment-crs.yaml\n</code></pre>"},{"location":"examples/gitops-using-fluxcd/#create-the-secret","title":"Create the secret","text":"<p>To access your secret manager, External Secrets needs some credentials. They are stored inside a Secret, which is intended to be deployed by automation as a good practise. This time, a placeholder called <code>secret-token.yaml</code> is show as an example:</p> <pre><code># The namespace.yaml first\napiVersion: v1\nkind: Namespace\nmetadata:\n name: external-secrets\n</code></pre> <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: vault-token-global\n namespace: external-secrets\nstringData:\n # This token must be patched by overlays. Not here for security reasons\n token: change-me-placeholder\n</code></pre>"},{"location":"examples/gitops-using-fluxcd/#creating-the-references-to-repositories","title":"Creating the references to repositories","text":"<p>Create a manifest called <code>repositories.yaml</code> to store the references to external repositories for Flux</p> <pre><code># Reference to Helm repository\napiVersion: source.toolkit.fluxcd.io/v1\nkind: HelmRepository\nmetadata:\n name: external-secrets\n namespace: flux-system\nspec:\n interval: 10m\n url: https://charts.external-secrets.io\n---\napiVersion: source.toolkit.fluxcd.io/v1\nkind: GitRepository\nmetadata:\n name: external-secrets\n namespace: flux-system\nspec:\n interval: 10m\n ref:\n tag: v0.10.3\n url: http://github.com/external-secrets/external-secrets\n</code></pre>"},{"location":"examples/gitops-using-fluxcd/#deploy-the-crds","title":"Deploy the CRDs","text":"<p>As mentioned, CRDs can be deployed using the official Helm package, but to solve the race condition, they will be deployed from our git repository using a Kustomization manifest called <code>deployment-crds.yaml</code> as follows:</p> <pre><code>---\napiVersion: kustomize.toolkit.fluxcd.io/v1\nkind: Kustomization\nmetadata:\n name: external-secrets-crds\n namespace: flux-system\nspec:\n interval: 10m\n path: ./deploy/crds\n prune: true\n sourceRef:\n kind: GitRepository\n name: external-secrets\n</code></pre>"},{"location":"examples/gitops-using-fluxcd/#deploy-the-operator","title":"Deploy the operator","text":"<p>The operator is deployed using a HelmRelease manifest to deploy the Helm package, but due to the special race condition, the deployment must be disabled in the <code>values</code> of the manifest called <code>deployment.yaml</code>, as follows:</p> <pre><code># How to manage values files. Ref: https://fluxcd.io/docs/guides/helmreleases/#refer-to-values-inside-the-chart\n# How to inject values: https://fluxcd.io/docs/guides/helmreleases/#cloud-storage\n---\napiVersion: helm.toolkit.fluxcd.io/v2\nkind: HelmRelease\nmetadata:\n name: external-secrets\n namespace: flux-system\nspec:\n # Override Release name to avoid the pattern Namespace-Release\n # Ref: https://fluxcd.io/flux/components/helm/api/v2/#helm.toolkit.fluxcd.io/v2.HelmRelease\n releaseName: external-secrets\n targetNamespace: external-secrets\n interval: 10m\n chart:\n spec:\n chart: external-secrets\n version: 0.10.3\n sourceRef:\n kind: HelmRepository\n name: external-secrets\n namespace: flux-system\n values:\n installCRDs: false\n\n # Ref: https://fluxcd.io/flux/components/helm/api/v2/#helm.toolkit.fluxcd.io/v2.Install\n install:\n createNamespace: true\n</code></pre>"},{"location":"examples/gitops-using-fluxcd/#deploy-the-crs","title":"Deploy the CRs","text":"<p>Now, be ready for the arcane magic. Create a Kustomization manifest called <code>deployment-crs.yaml</code> with the following content:</p> <pre><code>---\napiVersion: kustomize.toolkit.fluxcd.io/v1\nkind: Kustomization\nmetadata:\n name: external-secrets-crs\n namespace: flux-system\nspec:\n dependsOn:\n - name: external-secrets-crds\n interval: 10m\n path: ./infrastructure/external-secrets/crs\n prune: true\n sourceRef:\n kind: GitRepository\n name: flux-system\n</code></pre> <p>There are several interesting details to see here, that finally solves the race condition:</p> <ol> <li>First one is the field <code>dependsOn</code>, which points to a previous Kustomization called <code>external-secrets-crds</code>. This dependency forces this deployment to wait for the other to be ready, before start being deployed.</li> <li>The reference to the place where to find the CRs <pre><code>path: ./infrastructure/external-secrets/crs\nsourceRef:\n kind: GitRepository\n name: flux-system\n</code></pre> Custom Resources will be searched in the relative path <code>./infrastructure/external-secrets/crs</code> of the GitRepository called <code>flux-system</code>, which is a reference to the same repository that FluxCD watches to synchronize the cluster. With fewer words, a reference to itself, but going to another directory called <code>crs</code></li> </ol> <p>Of course, allocate inside the mentioned path <code>./infrastructure/external-secrets/crs</code>, all the desired CRs to be deployed, for example, a manifest <code>clusterSecretStore.yaml</code> to reach your Hashicorp Vault as follows:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ClusterSecretStore\nmetadata:\n name: vault-backend-global\nspec:\n provider:\n vault:\n server: \"https://vault.your-domain.com\"\n path: secret\n version: v2\n auth:\n # points to a secret that contains a vault token\n # https://www.vaultproject.io/docs/auth/token\n tokenSecretRef:\n name: \"vault-token-global\"\n key: \"token\"\n namespace: external-secrets\n</code></pre>"},{"location":"examples/gitops-using-fluxcd/#results","title":"Results","text":"<p>At the end, the required files tree is shown in the following picture:</p> <p></p>"},{"location":"examples/jenkins-kubernetes-credentials/","title":"Getting started","text":"<p>Jenkins is one of the most popular automation servers for continuous integration, automation, scheduling jobs and for generic pipelining. It has an extensive set of plugins that extend or provide additional functionality including the kubernetes credentials plugin. This plugin takes kubernetes secrets and creates Jenkins credentials from them removing the need for manual entry of secrets, local storage and manual secret rotation.</p>"},{"location":"examples/jenkins-kubernetes-credentials/#examples","title":"Examples","text":"<p>The Jenkins credentials plugin uses labels and annotations on a kubernetes secret to create a Jenkins credential.</p> <p>The different types of Jenkins credentials that can be created are SecretText, privateSSHKey, UsernamePassword.</p>"},{"location":"examples/jenkins-kubernetes-credentials/#secrettext","title":"SecretText","text":"<p>Here are some examples of SecretText with the Hashicorp Vault and AWS External Secrets providers:</p>"},{"location":"examples/jenkins-kubernetes-credentials/#hashicorp-vault","title":"Hashicorp Vault","text":"<pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: sonarqube-api-token\n namespace: ci\nspec:\n refreshInterval: 1m\n secretStoreRef:\n name: vault-backend\n kind: ClusterSecretStore\n target:\n name: sonarqube-api-token\n template:\n metadata:\n labels:\n \"jenkins.io/credentials-type\": \"secretText\"\n annotations:\n \"jenkins.io/credentials-description\": \"sonarqube api token\"\n data:\n text: &gt;-\n {{ printf \"{{ .password | toString }}\" }}\n data:\n - secretKey: password\n remoteRef:\n key: jenkins-credentials\n property: sonarqube-api-token\n</code></pre>"},{"location":"examples/jenkins-kubernetes-credentials/#aws-secrets-manager","title":"AWS Secrets Manager","text":"<pre><code>---\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: sonarqube-api-token\n namespace: ci\nspec:\n refreshInterval: 1m\n secretStoreRef:\n name: cluster-secrets-store\n kind: ClusterSecretStore\n target:\n name: sonarqube-api-token\n template:\n metadata:\n labels:\n \"jenkins.io/credentials-type\": \"secretText\"\n annotations:\n \"jenkins.io/credentials-description\": \"Sonar API token\"\n data:\n - secretKey: text\n remoteRef:\n key: service/sonarqube/apiToken\n</code></pre>"},{"location":"examples/jenkins-kubernetes-credentials/#usernamepassword","title":"UsernamePassword","text":"<p>Here are some examples of UsernamePassword credentials with the Hashicorp Vault and AWS External Secrets providers:</p>"},{"location":"examples/jenkins-kubernetes-credentials/#hashicorp-vault_1","title":"Hashicorp Vault","text":"<pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: harbor-chart-robot\n namespace: ci\nspec:\n refreshInterval: 1m\n secretStoreRef:\n name: vault-backend\n kind: ClusterSecretStore\n target:\n name: harbor-chart-robot\n template:\n metadata:\n labels:\n \"jenkins.io/credentials-type\": \"usernamePassword\"\n annotations:\n \"jenkins.io/credentials-description\": \"harbor chart robot\"\n data:\n username: &gt;-\n {{ printf \"{{ .username | toString }}\" }}\n password: &gt;-\n {{ printf \"{{ .password | toString }}\" }}\n data:\n - secretKey: username\n remoteRef:\n key: my-kv\n property: harbor-chart-robot-username\n - secretKey: password\n remoteRef:\n key: my-kv\n property: harbor-chart-robot-token\n</code></pre>"},{"location":"examples/jenkins-kubernetes-credentials/#aws-secrets-manager_1","title":"AWS Secrets Manager","text":"<pre><code>---\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: harbor-chart-robot\n namespace: ci\nspec:\n refreshInterval: 1m\n secretStoreRef:\n name: cluster-secrets-store\n kind: ClusterSecretStore\n target:\n name: harbor-chart-robot\n template:\n metadata:\n labels:\n \"jenkins.io/credentials-type\": \"usernamePassword\"\n annotations:\n \"jenkins.io/credentials-description\": \"harbor chart robot access\"\n data:\n - secretKey: password\n remoteRef:\n key: service/harbor/chartRobot\n property: password\n - secretKey: username\n remoteRef:\n key: service/harbor/chartRobot\n property: username\n</code></pre>"},{"location":"examples/jenkins-kubernetes-credentials/#basicsshuserprivatekey","title":"basicSSHUserPrivateKey","text":"<p>Here are some examples of basicSSHUserPrivateKey credentials with the Hashicorp Vault and AWS External Secrets providers:</p>"},{"location":"examples/jenkins-kubernetes-credentials/#hashicorp-vault_2","title":"Hashicorp Vault","text":"<pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: github-ssh-access\n namespace: ci\nspec:\n refreshInterval: 1m\n secretStoreRef:\n name: vault-backend\n kind: ClusterSecretStore\n target:\n name: github-ssh-access\n template:\n metadata:\n labels:\n \"jenkins.io/credentials-type\": \"basicSSHUserPrivateKey\"\n annotations:\n \"jenkins.io/credentials-description\": \"github-ssh-access key\"\n data:\n username: &gt;-\n {{ printf \"{{ .username | toString }}\" }}\n privateKey: &gt;-\n {{ printf \"{{ .privateKey | toString }}\" }}\n data:\n - secretKey: username\n remoteRef:\n key: my-kv\n property: github-ssh-access-username\n - secretKey: privateKey\n remoteRef:\n key: my-kv\n property: github-ssh-access-private-key\n</code></pre>"},{"location":"examples/jenkins-kubernetes-credentials/#aws-secrets-manager_2","title":"AWS Secrets Manager","text":"<pre><code>---\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: github-ssh-access\n namespace: ci\nspec:\n refreshInterval: 1m\n secretStoreRef:\n name: cluster-parameter-store\n kind: ClusterSecretStore\n target:\n name: github-ssh-access\n template:\n metadata:\n labels:\n \"jenkins.io/credentials-type\": \"basicSSHUserPrivateKey\"\n annotations:\n \"jenkins.io/credentials-description\": \"github-ssh-access key\"\n data:\n - secretKey: username\n remoteRef:\n key: /service/github/sshUserPrivateKeyUserName\n - secretKey: privateKey\n remoteRef:\n key: /service/github/sshUserPrivateKey\n</code></pre>"},{"location":"guides/all-keys-one-secret/","title":"All Keys, One Secret","text":"<p>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).</p> <p>Please follow the authentication and SecretStore steps of the Google Cloud Secrets Manager guide to setup access to your google cloud account first.</p> <p>Then create a secret in Google Cloud Secret Manager that contains a JSON string with multiple key values like this:</p> <p></p> <p>Let's call this secret all-keys-example-secret on Google Cloud.</p>"},{"location":"guides/all-keys-one-secret/#creating-datafrom-external-secret","title":"Creating dataFrom external secret","text":"<p>Now, when creating our ExternalSecret resource, instead of using the data field, we use the dataFrom field:</p> <p><pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example\nspec:\n refreshInterval: 1h # rate SecretManager pulls GCPSM\n secretStoreRef:\n kind: SecretStore\n name: example # name of the SecretStore (or kind specified)\n target:\n name: secret-to-be-created # name of the k8s Secret to be created\n creationPolicy: Owner\n dataFrom:\n - extract:\n key: all-keys-example-secret # name of the GCPSM secret\n</code></pre> Here, \"example\" is the name of the external secret that will be created in our cluster. Whereas, \"secret-to-be-created\" is the name of Kubernetes secrets that will be created. Note: Since these secrets are namespace-based resources, you can also explicitly specify the \"namespace\" under the \"metadata\" block of the above external secret file. when we use, </p> <p><pre><code> dataFrom:\n - extract:\n key: all-keys-example-secret\n</code></pre> We get all the key-value pairs present over the remote secret store (GCP or AWS or Azure) and can pass either all or a few key-values as environment variables. Please note that, \"all-keys-example-secret\" is the name of your secret present on GCP/AWS secrets manager/Azure </p> <p>We can pass a few secrets as env variables as below: <pre><code> env:\n - name: key1\n valueFrom:\n secretKeyRef:\n name: secret-to-be-created\n key: username\n\n - name: key2\n valueFrom:\n secretKeyRef:\n name: secret-to-be-created\n key: surname\n</code></pre></p> <p>Here, \\&lt;key1&gt; and \\ are the names of keys that will be created and passed as env variables. \\&lt;secret-to-be-created&gt;: is the name of your Kubernetes secret created by you. \\&lt;username&gt; and \\: is the particular key in the secrets manager whose value you want to pass. To check both values we can run: <pre><code>kubectl get secret secret-to-be-created -n &lt;namespace&gt; -o jsonpath='{.data.username}' | base64 -d\nkubectl get secret secret-to-be-created -n &lt;namespace&gt; -o jsonpath='{.data.surname}' | base64 -d\n</code></pre> <p>Also, if you have a large number of secrets and you want to pass all of them as enviromnent variables, then either you can replicate the above steps in your deployment file for all the keys or you can use the envFrom block as below: </p> <pre><code> spec:\n containers:\n - command:\n - mkdir abc.sh\n envFrom:\n - secretRef:\n name: secret-to-be-created\n</code></pre>"},{"location":"guides/common-k8s-secret-types/","title":"A few common k8s secret types examples","text":"<p>Here we will give some examples of how to work with a few common k8s secret types. We will give this examples here with the gcp provider (should work with other providers in the same way). Please also check the guides on Advanced Templating to understand the details.</p> <p>Please follow the authentication and SecretStore steps of the Google Cloud Secrets Manager guide to setup access to your google cloud account first.</p>"},{"location":"guides/common-k8s-secret-types/#dockerconfigjson-example","title":"Dockerconfigjson example","text":"<p>First create a secret in Google Cloud Secrets Manager containing your docker config:</p> <p></p> <p>Let's call this secret docker-config-example on Google Cloud.</p> <p>Then create a ExternalSecret resource taking advantage of templating to populate the generated secret:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: dk-cfg-example\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: example\n kind: SecretStore\n target:\n template:\n type: kubernetes.io/dockerconfigjson\n data:\n .dockerconfigjson: \"{{ .mysecret | toString }}\"\n name: secret-to-be-created\n creationPolicy: Owner\n data:\n - secretKey: mysecret\n remoteRef:\n key: docker-config-example\n</code></pre> <p>For Helm users: since Helm interprets the template above, the ExternalSecret resource can be written this way:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: dk-cfg-example\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: example\n kind: SecretStore\n target:\n template:\n type: kubernetes.io/dockerconfigjson\n engineVersion: v2\n data:\n .dockerconfigjson: \"{{ `{{ .mysecret }}` }}\"\n name: secret-to-be-created\n creationPolicy: Owner\n data:\n - secretKey: mysecret\n remoteRef:\n key: docker-config-example\n</code></pre> <p>For more information, please see this issue</p> <p>This will generate a valid dockerconfigjson secret for you to use!</p> <p>You can get the final value with:</p> <pre><code>kubectl get secret secret-to-be-created -n &lt;namespace&gt; -o jsonpath=\"{.data.\\.dockerconfigjson}\" | base64 -d\n</code></pre> <p>Alternately, if you only have the container registry name and password value, you can take advantage of the advanced ExternalSecret templating functions to create the secret:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: dk-cfg-example\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: example\n kind: SecretStore\n target:\n template:\n type: kubernetes.io/dockerconfigjson\n data:\n .dockerconfigjson: '{\"auths\":{\"{{ .registryName | lower }}.{{ .registryHost }}\":{\"username\":\"{{ .registryName }}\",\"password\":\"{{ .password }}\",\"auth\":\"{{ printf \"%s:%s\" .registryName .password | b64enc }}\"}}}'\n data:\n - secretKey: registryName\n remoteRef:\n key: secret/docker-registry-name # \"myRegistry\"\n - secretKey: registryHost\n remoteRef:\n key: secret/docker-registry-host # \"docker.io\"\n - secretKey: password\n remoteRef:\n key: secret/docker-registry-password\n</code></pre>"},{"location":"guides/common-k8s-secret-types/#tls-cert-example","title":"TLS Cert example","text":"<p>We are assuming here that you already have valid certificates, maybe generated with letsencrypt or any other CA. So to simplify you can use openssl to generate a single secret pkcs12 cert based on your cert.pem and privkey.pen files.</p> <pre><code>openssl pkcs12 -export -out certificate.p12 -inkey privkey.pem -in cert.pem\n</code></pre> <p>With a certificate.p12 you can upload it to Google Cloud Secrets Manager:</p> <p></p> <p>And now you can create an ExternalSecret that gets it. You will end up with a k8s secret of type tls with pem values.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: template-tls-example\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: example\n kind: SecretStore\n target:\n name: secret-to-be-created\n # this is how the Kind=Secret will look like\n template:\n type: kubernetes.io/tls\n data:\n tls.crt: \"{{ .mysecret | pkcs12cert }}\"\n tls.key: \"{{ .mysecret | pkcs12key }}\"\n\n data:\n # this is a pkcs12 archive that contains\n # a cert and a private key\n - secretKey: mysecret\n remoteRef:\n key: ssl-certificate-p12-example\n</code></pre> <p>You can get their values with:</p> <pre><code>kubectl get secret secret-to-be-created -n &lt;namespace&gt; -o jsonpath=\"{.data.tls\\.crt}\" | base64 -d\nkubectl get secret secret-to-be-created -n &lt;namespace&gt; -o jsonpath=\"{.data.tls\\.key}\" | base64 -d\n</code></pre>"},{"location":"guides/common-k8s-secret-types/#ssh-auth-example","title":"SSH Auth example","text":"<p>Add the ssh privkey to a new Google Cloud Secrets Manager secret:</p> <p></p> <p>And now you can create an ExternalSecret that gets it. You will end up with a k8s secret of type ssh-auth with the privatekey value.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: ssh-auth-example\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: example\n kind: SecretStore\n target:\n name: secret-to-be-created\n template:\n type: kubernetes.io/ssh-auth\n data:\n ssh-privatekey: \"{{ .mysecret | toString }}\"\n name: secret-to-be-created\n creationPolicy: Owner\n data:\n - secretKey: mysecret\n remoteRef:\n key: ssh-priv-key-example\n</code></pre> <p>You can get the privkey value with:</p> <pre><code>kubectl get secret secret-to-be-created -n &lt;namespace&gt; -o jsonpath=\"{.data.ssh-privatekey}\" | base64 -d\n</code></pre>"},{"location":"guides/common-k8s-secret-types/#more-examples","title":"More examples","text":"<p>We need more examples here</p> <p>Feel free to contribute with our docs and add more examples here!</p>"},{"location":"guides/controller-class/","title":"Controller Classes","text":"<p>NOTE: this feature is experimental and not highly tested</p> <p>Controller classes are a property 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.</p>"},{"location":"guides/controller-class/#setting-up-controller-class","title":"Setting up Controller Class","text":"<p>In order to deploy the controller with a specific class, install the helm charts specifying the controller class, and create a <code>SecretStore</code> with the appropriate <code>spec.controller</code> values: <pre><code>helm install custom-external-secrets external-secrets/external-secrets --set controllerClass=custom\n</code></pre> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: controller-custom-example\nspec:\n #define the controller label to the matching value of the deployment\n controller: custom\n #configure provider the same way\n provider:\n vault:\n server: \"http://vault.default:8200\"\n path: \"secret\"\n version: \"v2\"\n auth:\n kubernetes:\n mountPath: \"kubernetes\"\n role: \"demo-role\"\n</code></pre></p> <p>Now, any <code>ExternalSecret</code> bound to this secret store will be evaluated by the operator with the controllerClass custom.</p> <p>Note: Any SecretStore without <code>spec.controller</code> set will be considered as valid by any operator, regardless of their respective controllerClasses.</p>"},{"location":"guides/datafrom-rewrite/","title":"Rewriting Keys in DataFrom","text":"<p>When calling out an ExternalSecret with <code>dataFrom.extract</code> or <code>dataFrom.find</code>, it is possible that you end up with a kubernetes secret that has conflicts in the key names, or that you simply want to remove a common path from the secret keys.</p> <p>In order to do so, it is possible to define a set of rewrite operations using <code>dataFrom.rewrite</code>. These operations can be stacked, hence allowing complex manipulations of the secret keys.</p> <p>Rewrite operations are all applied before <code>ConversionStrategy</code> is applied.</p>"},{"location":"guides/datafrom-rewrite/#methods","title":"Methods","text":""},{"location":"guides/datafrom-rewrite/#regexp","title":"Regexp","text":"<p>This method implements rewriting through the use of regular expressions. It needs a <code>source</code> and a <code>target</code> field. The source field is where the definition of the matching regular expression goes, where the <code>target</code> field is where the replacing expression goes.</p> <p>Some considerations about the implementation of Regexp Rewrite:</p> <ol> <li>The input of a subsequent rewrite operation are the outputs of the previous rewrite.</li> <li>If a given set of keys do not match any Rewrite operation, there will be no error. Rather, the original keys will be used.</li> <li>If a <code>source</code> is not a compilable <code>regexp</code> expression, an error will be produced and the external secret goes into a error state.</li> </ol>"},{"location":"guides/datafrom-rewrite/#examples","title":"Examples","text":""},{"location":"guides/datafrom-rewrite/#removing-a-common-path-from-find-operations","title":"Removing a common path from find operations","text":"<p>The following ExternalSecret: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: backend\n target:\n name: secret-to-be-created\n dataFrom:\n - find:\n path: path/to/my\n name: \n regexp: secrets\n rewrite:\n - regexp:\n source: \"path/to/my/secrets/(.*)\"\n target: \"$1\"\n</code></pre> Will get all the secrets matching <code>path/to/my/secrets/*</code> and then rewrite them by removing the common path away.</p> <p>In this example, if we had the following secrets available in the provider: <pre><code>path/to/my/secrets/username\npath/to/my/secrets/password\n</code></pre> the output kubernetes secret would be: <pre><code>apiVersion: v1\nkind: Secret\ntype: Opaque\ndata:\n username: ...\n password: ...\n</code></pre></p>"},{"location":"guides/datafrom-rewrite/#avoiding-key-collisions","title":"Avoiding key collisions","text":"<p>The following ExternalSecret: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: backend\n target:\n name: secret-to-be-created\n dataFrom:\n - extract:\n key: my-secrets-dev\n rewrite:\n - regexp:\n source: \"(.*)\"\n target: \"dev-$1\" \n - extract:\n key: my-secrets-prod\n rewrite:\n - regexp:\n source: \"(.*)\"\n target: \"prod-$1\"\n</code></pre> Will allow two secrets with the same JSON keys to be imported into a Kubernetes Secret without any conflict. In this example, if we had the following secrets available in the provider: <pre><code>{\n \"my-secrets-dev\": {\n \"password\": \"bar\",\n },\n \"my-secrets-prod\": {\n \"password\": \"safebar\",\n }\n}\n</code></pre> the output kubernetes secret would be: <pre><code>apiVersion: v1\nkind: Secret\ntype: Opaque\ndata:\n dev_password: YmFy #bar\n prod_password: c2FmZWJhcg== #safebar\n</code></pre></p>"},{"location":"guides/datafrom-rewrite/#remove-invalid-characters","title":"Remove invalid characters","text":"<p>The following ExternalSecret: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: backend\n target:\n name: secret-to-be-created\n dataFrom:\n - extract:\n key: development\n rewrite:\n - regexp:\n source: \"[^a-zA-Z0-9 -]\"\n target: \"_\"\n</code></pre> Will remove invalid characters from the secret key. In this example, if we had the following secrets available in the provider: <pre><code>{\n \"development\": {\n \"foo/bar\": \"1111\",\n \"foo$baz\": \"2222\"\n }\n}\n</code></pre> the output kubernetes secret would be: <pre><code>apiVersion: v1\nkind: Secret\ntype: Opaque\ndata:\n foo_bar: MTExMQ== #1111\n foo_baz: MjIyMg== #2222\n</code></pre></p>"},{"location":"guides/datafrom-rewrite/#limitations","title":"Limitations","text":"<p>Regexp Rewrite is based on golang <code>regexp</code>, which in turns implements <code>RE2</code> regexp language. There a a series of known limitations to this implementation, such as:</p> <ul> <li>Lack of ability to do lookaheads or lookbehinds;</li> <li>Lack of negation expressions;</li> <li>Lack of support for conditional branches;</li> <li>Lack of support for possessive repetitions.</li> </ul> <p>A list of compatibility and known limitations considering other commonly used regexp frameworks (such as PCRE and PERL) are listed here.</p>"},{"location":"guides/decoding-strategy/","title":"Decoding Strategies","text":"<p>The External Secrets Operator has the feature to allow multiple decoding strategies during an object generation.</p> <p>The <code>decodingStrategy</code> field allows the user to set the following Decoding Strategies based on their needs. <code>decodingStrategy</code> can be placed under <code>spec.data.remoteRef</code>, <code>spec.dataFrom.extract</code> or <code>spec.dataFrom.find</code>. It will configure the decoding strategy for that specific operation, leaving others with the default behavior if not set.</p>"},{"location":"guides/decoding-strategy/#none-default","title":"None (default)","text":"<p>ESO will not try to decode the secret value.</p>"},{"location":"guides/decoding-strategy/#base64","title":"Base64","text":"<p>ESO will try to decode the secret value using base64 method. If the decoding fails, an error is produced.</p>"},{"location":"guides/decoding-strategy/#base64url","title":"Base64URL","text":"<p>ESO will try to decode the secret value using base64url method. If the decoding fails, an error is produced.</p>"},{"location":"guides/decoding-strategy/#auto","title":"Auto","text":"<p>ESO will try to decode using Base64/Base64URL strategies. If the decoding fails, ESO will apply decoding strategy None. No error is produced to the user.</p>"},{"location":"guides/decoding-strategy/#examples","title":"Examples","text":""},{"location":"guides/decoding-strategy/#setting-decoding-strategy-auto-in-a-datafromextract","title":"Setting Decoding strategy Auto in a DataFrom.Extract","text":"<p>Given that we have the given secret information: <pre><code>{\n \"name\": \"Gustavo\",\n \"surname\": \"Fring\",\n \"address\":\"aGFwcHkgc3RyZWV0\",\n}\n</code></pre> if we apply the following dataFrom: <pre><code>spec:\n dataFrom:\n - extract:\n key: my-secret\n decodingStrategy: Auto\n</code></pre> It will render the following Kubernetes Secret: <pre><code>data:\n name: R3VzdGF2bw== #Gustavo\n surname: RnJpbmc= #Fring\n address: aGFwcHkgc3RyZWV0 #happy street\n</code></pre></p>"},{"location":"guides/decoding-strategy/#limitations","title":"Limitations","text":"<p>At this time, decoding Strategy Auto is only trying to check if the original input is valid to perform Base64 operations. This means that some non-encoded secret values might end up being decoded, producing gibberish. This is the case for numbered values like <code>123456</code> or some specially crafted string values such as <code>happy/street</code>. </p> <p>Note</p> <p>If you are using <code>decodeStrategy: Auto</code> and start to see ESO pulling completely wrong secret values into your kubernetes secret, consider changing it to <code>None</code> to investigate it.</p>"},{"location":"guides/disable-cluster-features/","title":"Deploying without ClusterSecretStore and ClusterExternalSecret","text":"<p>When deploying External Secrets Operator via Helm chart, the default configuration will install <code>ClusterSecretStore</code> and <code>ClusterExternalSecret</code> CRDs and these objects will be processed by the operator.</p> <p>In order to disable both or one of these features, it is necessary to configure the <code>crds.*</code> Helm value, as well as the <code>process*</code> Helm value, as these 2 values are connected.</p> <p>If you would like to install the operator without <code>ClusterSecretStore</code> and <code>ClusterExternalSecret</code> management, you will have to :</p> <ul> <li>set <code>crds.createClusterExternalSecret</code> to false</li> <li>set <code>crds.createClusterSecretStore</code> to false</li> <li>set <code>processClusterExternalSecret</code> to false</li> <li>set <code>processClusterStore</code> to false</li> </ul> <p>Example:</p> <pre><code>helm install external-secrets external-secrets/external-secrets --set crds.createClusterExternalSecret=false \\\n--set crds.createClusterSecretStore=false \\\n--set processClusterExternalSecret=false \\\n--set processClusterStore=false\n</code></pre>"},{"location":"guides/generator/","title":"Generators","text":"<p>Generators allow you to generate values. They are used through a ExternalSecret <code>spec.DataFrom</code>. They are referenced from a custom resource using <code>sourceRef.generatorRef</code>.</p> <p>If the External Secret should be refreshed via <code>spec.refreshInterval</code> the generator produces a map of values with the <code>generator.spec</code> as input. The generator does not keep track of the produced values. Every invocation produces a new set of values.</p> <p>These values can be used with the other features like <code>rewrite</code> or <code>template</code>. I.e. you can modify, encode, decode, pack the values as needed.</p>"},{"location":"guides/generator/#reference-custom-resource","title":"Reference Custom Resource","text":"<p>Generators can be defined as a custom resource and re-used across different ExternalSecrets. Every invocation creates a new set of values. I.e. you can not share the same value produced by a generator across different <code>ExternalSecrets</code> or <code>spec.dataFrom[]</code> entries.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: \"ecr-token\"\nspec:\n refreshInterval: \"30m\"\n target:\n name: ecr-token\n dataFrom:\n - sourceRef:\n generatorRef:\n apiVersion: generators.external-secrets.io/v1alpha1\n kind: ECRAuthorizationToken\n name: \"my-ecr\"\n</code></pre>"},{"location":"guides/getallsecrets/","title":"Fetching information from multiple secrets","text":"<p>In some use cases, it might be impractical to bundle all sensitive information into a single secret, or even it is not possible to fully know a given secret name. In such cases, it is possible that a user might need to sync multiple secrets from an external provider into a single Kubernetes Secret. This is possible to be done in external-secrets with the <code>dataFrom.find</code> option.</p> <p>Note</p> <p>The secret's contents as defined in the provider are going to be stored in the kubernetes secret as a single key. Currently, it's possible to apply a decoding Strategy during a find operation, but only at the secret level (e.g. if a secret is a JSON with some B64 encoded data within, <code>decodingStrategy: Auto</code> would not decode it)</p>"},{"location":"guides/getallsecrets/#fetching-secrets-matching-a-given-name-pattern","title":"Fetching secrets matching a given name pattern","text":"<p>To fetch multiple secrets matching a name pattern from a common SecretStore you can apply the following manifest: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: find-by-tags\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: secretstore-sample\n kind: SecretStore\n target:\n name: secret-to-be-created\n dataFrom:\n - find:\n name:\n regexp: \"key\"\n</code></pre></p> <p>Suppose we contain secrets <code>/path/key1</code>, <code>key2/path</code>, and <code>path/to/keyring</code> with their respective values. The above YAML will produce the following kubernetes Secret:</p> <pre><code>_path_key1: Cg==\nkey2_path: Cg==\npath_to_keyring: Cg==\n</code></pre>"},{"location":"guides/getallsecrets/#fetching-secrets-matching-a-set-of-metadata-tags","title":"Fetching secrets matching a set of metadata tags","text":"<p>To fetch multiple secrets matching a name pattern from a common SecretStore you can apply the following manifest: <pre><code>apiVersion: external-secrets.io/v1beta1 \nkind: ExternalSecret\nmetadata:\n name: find-by-tags\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: secretstore-sample\n kind: SecretStore\n target:\n name: secret-to-be-created\n dataFrom:\n - find:\n tags:\n environment: \"prod\"\n application: \"app-name\"\n</code></pre> This will match any secrets containing all of the metadata labels in the <code>tags</code> parameter. At least one tag must be provided in order to allow finding secrets by metadata tags.</p>"},{"location":"guides/getallsecrets/#searching-only-in-a-given-path","title":"Searching only in a given path","text":"<p>Some providers support filtering out a find operation only to a given path, instead of the root path. In order to use this feature, you can pass <code>find.path</code> to filter out these secrets into only this path, instead of the root path.</p>"},{"location":"guides/getallsecrets/#avoiding-name-conflicts","title":"Avoiding name conflicts","text":"<p>By default, kubernetes Secrets accepts only a given range of characters. <code>Find</code> operations will automatically replace any not allowed character with a <code>_</code>. So if we have a given secret <code>a_c</code> and <code>a/c</code> would lead to a naming conflict.</p> <p>If you happen to have a case where a conflict is happening, you can use the <code>rewrite</code> block to apply a regexp on one of the find operations (for more information please refer to Rewriting Keys from DataFrom).</p> <p>You can also set <code>dataFrom.find.conversionStrategy: Unicode</code> to reduce the collistion probability. When using <code>Unicode</code>, any invalid character will be replaced by its unicode, in the form of <code>_UXXXX_</code>. In this case, the available kubernetes keys would be <code>a_c</code> and <code>a_U2215_c</code>, hence avoiding most of possible conflicts.</p> <p>PRs welcome</p> <p>Some providers might not have the implementation needed for fetching multiple secrets. If that's your case, please feel free to contribute!</p>"},{"location":"guides/introduction/","title":"Guides","text":"<p>The following guides demonstrate use-cases and provide examples of how to use the API. Please pick one of the following guides:</p> <ul> <li>Multi-Tenancy Design Considerations</li> <li>Find multiple secrets &amp; Extract Secret values</li> <li>Advanced Templating</li> <li>Generating Passwords using generators</li> <li>Ownership and Deletion Policy</li> <li>Key Rewriting</li> <li>Controller Class</li> <li>Decoding Strategy</li> <li>v1beta1 Migration</li> <li>Deploying image from main</li> <li>Deploying without cluster features</li> </ul>"},{"location":"guides/multi-tenancy/","title":"Multi Tenancy","text":"<p>External Secrets Operator provides different modes of operation to fulfill organizational needs. This guide outlines the flexibility of ESO and should give you a first impression of how you can employ this operator in your organization.</p> <p>For a multi-tenant deployment you should first examine your organizational structure:</p> <ol> <li>what roles (i.e. Application Developers, Cluster Admins, ...) do you have in your organization,</li> <li>what responsibilities do they have and</li> <li>how does that map to Kubernetes RBAC roles.</li> </ol> <p>Further, you should examine how your external API provider manages access control for your secrets. Can you limit access by secret names (e.g. <code>db/dev/*</code>)? Or only on a bucket level? Please keep in mind that not all external APIs provide fine-grained access management for secrets.</p> <p>Note: The following examples should not be considered as best practice but rather as a example to show how to combine different mechanics and techniques for tenant isolation.</p>"},{"location":"guides/multi-tenancy/#shared-clustersecretstore","title":"Shared ClusterSecretStore","text":"<p>A Cluster Administrator deploys a <code>ClusterSecretStore</code> (CSS) and manages access to the external API. The CSS is shared by all tenants within the cluster. Application Developers do reference it in a <code>ExternalSecret</code> but can not create a ClusterSecretStores or SecretStores on their own. Now all application developers have access to all the secrets. You probably want to limit access to certain keys or prefixes that should be used. ESO does not provide a mechanic to limit access to certain keys per namespace. More advanced validation should be done with an Admission Webhook, e.g. with Kyverno or Open Policy Agent).</p> <p>This setup suites well if you have one central bucket that contains all of your secrets and your Cluster Administrators should manage access to it. This setup is very simple but does not scale very well.</p>"},{"location":"guides/multi-tenancy/#managed-secretstore-per-namespace","title":"Managed SecretStore per Namespace","text":"<p>Cluster Administrators manage one or multiple <code>SecretStores</code> per Namespace. Each SecretStore uses it's own role that limits access to a small set of keys. The peculiarity of this is approach is, that access is actually managed by the external API which provides the roles. The Cluster Administrator does just the wiring. This approach may be desirable if you have an external entity - let's call it Secret Administrator - that manages access and lifecycle of the secrets.</p>"},{"location":"guides/multi-tenancy/#eso-as-a-service","title":"ESO as a Service","text":"<p>Every namespace is self-contained. Application developers manage <code>SecretStore</code>, <code>ExternalSecret</code> and secret infrastructure on their own. Cluster Administrators just provide the External Secrets Operator as a service.</p> <p>This makes sense if application developers should be completely autonomous while a central team provides common services.</p>"},{"location":"guides/ownership-deletion-policy/","title":"Lifecycle","text":"<p>The External Secrets Operator manages the lifecycle of secrets in Kubernetes. With <code>creationPolicy</code> and <code>deletionPolicy</code> you get fine-grained control of its lifecycle.</p> <p>Creation/Deletion Policy Combinations</p> <p>Some combinations of creationPolicy/deletionPolicy are not allowed as they would delete existing secrets: - <code>deletionPolicy=Delete</code> &amp; <code>creationPolicy=Merge</code> - <code>deletionPolicy=Delete</code> &amp; <code>creationPolicy=None</code> - <code>deletionPolicy=Merge</code> &amp; <code>creationPolicy=None</code></p>"},{"location":"guides/ownership-deletion-policy/#creation-policy","title":"Creation Policy","text":"<p>The field <code>spec.target.creationPolicy</code> defines how the operator creates the a secret.</p>"},{"location":"guides/ownership-deletion-policy/#owner-default","title":"Owner (default)","text":"<p>The External Secret Operator creates secret and sets the <code>ownerReference</code> field on the Secret. This secret is subject to garbage collection if the initial <code>ExternalSecret</code> is absent. If a secret with the same name already exists that is not owned by the controller it will result in a conflict. The operator will just error out, not claiming the ownership.</p> <p>Secrets with <code>ownerReference</code> field not found</p> <p>If the secret exists and the ownerReference field is not found, the controller treats this secret as orphaned. It will take ownership of this secret by adding an <code>ownerReference</code> field and updating it.</p>"},{"location":"guides/ownership-deletion-policy/#orphan","title":"Orphan","text":"<p>The operator creates the secret but does not set the <code>ownerReference</code> on the Secret. That means the Secret will not be subject to garbage collection. If a secret with the same name already exists it will be updated.</p>"},{"location":"guides/ownership-deletion-policy/#merge","title":"Merge","text":"<p>The operator does not create a secret. Instead, it expects the secret to already exist. Values from the secret provider will be merged into the existing secret. Note: the controller takes ownership of a field even if it is owned by a different entity. Multiple ExternalSecrets can use <code>creationPolicy=Merge</code> with a single secret as long as the fields don't collide - otherwise you end up in an oscillating state.</p>"},{"location":"guides/ownership-deletion-policy/#none","title":"None","text":"<p>The operator does not create or update the secret, this is basically a no-op.</p>"},{"location":"guides/ownership-deletion-policy/#deletion-policy","title":"Deletion Policy","text":"<p>DeletionPolicy defines what should happen if a given secret gets deleted from the provider.</p> <p>DeletionPolicy is only supported on the specific providers, please refer to our stability/support table.</p>"},{"location":"guides/ownership-deletion-policy/#retain-default","title":"Retain (default)","text":"<p>Retain will retain the secret if all provider secrets have been deleted. If a provider secret does not exist the ExternalSecret gets into the SecretSyncedError status.</p>"},{"location":"guides/ownership-deletion-policy/#delete","title":"Delete","text":"<p>Delete deletes the secret if all provider secrets are deleted. If a secret gets deleted on the provider side and is not accessible anymore this is not considered an error and the ExternalSecret does not go into SecretSyncedError status. This is also true for new ExternalSecrets mapping to non-existing secrets in the provider.</p>"},{"location":"guides/ownership-deletion-policy/#merge_1","title":"Merge","text":"<p>Merge removes keys in the secret, but not the secret itself. If a secret gets deleted on the provider side and is not accessible anymore this is not considered an error and the ExternalSecret does not go into SecretSyncedError status.</p>"},{"location":"guides/pushsecrets/","title":"Push Secrets","text":"<p>Contrary to what <code>ExternalSecret</code> does by pulling secrets from secret providers and creating <code>kind=Secret</code> in your cluster, <code>PushSecret</code> reads a local <code>kind=Secret</code> and pushes its content to a secret provider.</p> <p>The update behavior of <code>PushSecret</code> is controlled by <code>spec.updatePolicy</code>. The default policy is <code>Replace</code>, such that secrets are overwritten in the provider, regardless of whether there already is a secret present in the provider at the given location. If you do not want <code>PushSecret</code> to overwrite existing secrets in the provider, you can set <code>spec.UpdatePolicy</code> to <code>IfNotExists</code>. With this policy, the provider becomes the source of truth. Please note that with using <code>spec.updatePolicy=IfNotExists</code> it is possible that the secret value referenced by the <code>PushSecret</code> within the cluster differs from the secret value at the given location in the provider.</p> <p>By default, the secret created in the secret provided will not be deleted even after deleting the <code>PushSecret</code>, unless you set <code>spec.deletionPolicy</code> to <code>Delete</code>.</p> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: pushsecret-example # Customisable\n namespace: default # Same of the SecretStores\nspec:\n updatePolicy: Replace # Policy to overwrite existing secrets in the provider on sync\n deletionPolicy: Delete # the provider' secret will be deleted if the PushSecret is deleted\n refreshInterval: 10s # Refresh interval for which push secret will reconcile\n secretStoreRefs: # A list of secret stores to push secrets to\n - name: aws-parameterstore\n kind: SecretStore\n selector:\n secret:\n name: pokedex-credentials # Source Kubernetes secret to be pushed\n # Alternatively, you can point to a generator that produces values to be pushed\n generatorRef:\n apiVersion: external-secrets.io/v1alpha1\n kind: ECRAuthorizationToken\n name: prod-registry-credentials\n template:\n metadata:\n annotations: { }\n labels: { }\n data:\n best-pokemon: \"{{ .best-pokemon | toString | upper }} is the really best!\"\n # Uses an existing template from configmap\n # Secret is fetched, merged and templated within the referenced configMap data\n # It does not update the configmap, it creates a secret with: data[\"alertmanager.yml\"] = ...result...\n templateFrom:\n - configMap:\n name: application-config-tmpl\n items:\n - key: config.yml\n data:\n - conversionStrategy: None # Also supports the ReverseUnicode strategy\n match:\n secretKey: best-pokemon # Source Kubernetes secret key to be pushed\n remoteRef:\n remoteKey: my-first-parameter # Remote reference (where the secret is going to be pushed)\n</code></pre>"},{"location":"guides/pushsecrets/#backup-use-case","title":"Backup use case","text":"<p>An interesting use case for <code>kind=PushSecret</code> is backing up your current secret from one provider to another one.</p> <p>Imagine you have your secrets in GCP and you want to back them up in Azure Key Vault. You would then create a <code>SecretStore</code> for each provider, and an <code>ExternalSecret</code> to pull the secrets from GCP. This will generate a <code>kind=Secret</code> in your cluster that you can use as the source of a <code>PushSecret</code> configured with the Azure <code>SecretStore</code>.</p> <p></p>"},{"location":"guides/pushsecrets/#pushing-the-whole-secret","title":"Pushing the whole secret","text":"<p>There are two ways to push an entire secret without defining all keys individually.</p> <p>By leaving off the secret key and remote property options.</p> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: pushsecret-example # Customisable\n namespace: default # Same of the SecretStores\nspec:\n deletionPolicy: Delete # the provider' secret will be deleted if the PushSecret is deleted\n refreshInterval: 10s # Refresh interval for which push secret will reconcile\n secretStoreRefs: # A list of secret stores to push secrets to\n - name: aws-parameterstore\n kind: SecretStore\n selector:\n secret:\n name: pokedex-credentials # Source Kubernetes secret to be pushed\n data:\n - match:\n remoteRef:\n remoteKey: my-first-parameter # Remote reference (where the secret is going to be pushed)\n</code></pre> <p>This will result in all keys being pushed as they are into the remote location.</p> <p>By leaving off the secret key but setting the remote property option.</p> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: pushsecret-example # Customisable\n namespace: default # Same of the SecretStores\nspec:\n deletionPolicy: Delete # the provider' secret will be deleted if the PushSecret is deleted\n refreshInterval: 10s # Refresh interval for which push secret will reconcile\n secretStoreRefs: # A list of secret stores to push secrets to\n - name: aws-parameterstore\n kind: SecretStore\n selector:\n secret:\n name: pokedex-credentials # Source Kubernetes secret to be pushed\n data:\n - match:\n secretKey: best-pokemon # Source Kubernetes secret key to be pushed\n remoteRef:\n remoteKey: my-first-parameter # Remote reference (where the secret is going to be pushed)\n property: single-value-secret # the property to use to push into\n</code></pre> <p>This will marshal the entire secret data and push it into this single property as a JSON object.</p> <p>Warning</p> <p>This should ONLY be done if the secret data is marshal-able. Values like, binary data cannot be marshaled and will result in error or invalid secret data.</p>"},{"location":"guides/pushsecrets/#key-conversion-strategy","title":"Key conversion strategy","text":"<p>You can also set <code>data[*].conversionStrategy: ReverseUnicode</code> to reverse the invalid character replaced by the <code>conversionStrategy: Unicode</code> configuration in the <code>ExternalSecret</code> object as documented here.</p>"},{"location":"guides/pushsecrets/#rotate-secrets","title":"Rotate Secrets","text":"<p>You can use ESO to rotate secrets by using the PushSecret and Generator resources. ESO will consult the <code>Kind=Generator</code> to generate a new secret and then ESO will store it. Every <code>spec.refreshInterval</code> the secret will be rotated and the value will be replaced in the store unless <code>spec.updatePolicy=IfNotExist</code> is set. Then ESO will generate the secret once and won't rotate it.</p> <pre><code>apiVersion: generators.external-secrets.io/v1alpha1\nkind: Password\nmetadata:\n name: strong-password\nspec:\n length: 128\n digits: 5\n symbols: 5\n symbolCharacters: \"-_$@\"\n noUpper: false\n allowRepeat: true\n---\napiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: pushsecret-example\nspec:\n refreshInterval: 6h\n secretStoreRefs:\n - name: aws-parameter-store\n kind: SecretStore\n selector:\n generatorRef:\n apiVersion: generators.external-secrets.io/v1alpha1\n kind: Password\n name: strong-password\n data:\n - match:\n secretKey: password # property in the generator output\n remoteRef:\n remoteKey: prod/myql/password\n</code></pre>"},{"location":"guides/security-best-practices/","title":"Security Best Practices","text":"<p>The purpose of this document is to outline a set of best practices for securing the External Secrets Operator (ESO). These practices aim to mitigate the risk of successful attacks against ESO and the Kubernetes cluster it integrates with.</p>"},{"location":"guides/security-best-practices/#security-functions-and-features","title":"Security Functions and Features","text":""},{"location":"guides/security-best-practices/#1-namespace-isolation","title":"1. Namespace Isolation","text":"<p>To maintain security boundaries, ESO ensures that namespaced resources like <code>SecretStore</code> and <code>ExternalSecret</code> are limited to their respective namespaces. The following rules apply:</p> <ol> <li><code>ExternalSecret</code> resources must not have cross-namespace references of <code>Kind=SecretStore</code> or <code>Kind=Secret</code> resources</li> <li><code>SecretStore</code> resources must not have cross-namespace references of <code>Kind=Secret</code> or others</li> </ol> <p>For cluster-wide resources like <code>ClusterSecretStore</code> and <code>ClusterExternalSecret</code>, exercise caution since they have access to Secret resources across all namespaces. Minimize RBAC permissions for administrators and developers to the necessary minimum. If cluster-wide resources are not required, it is recommended to disable them.</p>"},{"location":"guides/security-best-practices/#2-configure-clustersecretstore-match-conditions","title":"2. Configure ClusterSecretStore match conditions","text":"<p>Utilize the ClusterSecretStore resource to define specific match conditions using <code>namespaceSelector</code> or an explicit namespaces list. This restricts the usage of the <code>ClusterSecretStore</code> to a predetermined list of namespaces or a namespace that matches a predefined label. Here's an example:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ClusterSecretStore\nmetadata:\n name: fake\nspec:\n conditions:\n - namespaceSelector:\n matchLabels:\n app: frontend\n</code></pre>"},{"location":"guides/security-best-practices/#3-selectively-disable-reconciliation-of-cluster-wide-resources","title":"3. Selectively Disable Reconciliation of Cluster-Wide Resources","text":"<p>ESO allows you to selectively disable the reconciliation of cluster-wide resources such as <code>ClusterSecretStore</code>, <code>ClusterExternalSecret</code>, and <code>PushSecret</code>. You can disable the installation of CRDs in the Helm chart or disable reconciliation in the core-controller using the following options:</p> <p>To disable CRD installation:</p> <pre><code># disable cluster-wide resources &amp; push secret\ncrds:\n createClusterExternalSecret: false\n createClusterSecretStore: false\n createPushSecret: false\n</code></pre> <p>To disable reconciliation in the core-controller:</p> <pre><code>--enable-cluster-external-secret-reconciler\n--enable-cluster-store-reconciler\n</code></pre>"},{"location":"guides/security-best-practices/#4-implement-namespace-scoped-installation","title":"4. Implement Namespace-Scoped Installation","text":"<p>To further enhance security, consider installing ESO into a specific namespace with restricted access to only that namespace's resources. This prevents access to cluster-wide secrets. Use the following Helm values to scope the controller to a specific namespace:</p> <pre><code># If set to true, create scoped RBAC roles under the scoped namespace\n# and implicitly disable cluster stores and cluster external secrets\nscopedRBAC: true\n\n# Specify the namespace where external secrets should be reconciled\nscopedNamespace: my-namespace\n</code></pre>"},{"location":"guides/security-best-practices/#5-restrict-webhook-tls-ciphers","title":"5. Restrict Webhook TLS Ciphers","text":"<p>Consider installing ESO restricting webhook ciphers. Use the following Helm values to scope webhook for specific TLS ciphers: <pre><code>webhook:\n extraArgs:\n tls-ciphers: \"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\"\n</code></pre></p>"},{"location":"guides/security-best-practices/#pod-security","title":"Pod Security","text":"<p>The Pods of the External Secrets Operator have been configured to meet the Pod Security Standards, specifically the restricted profile. This configuration ensures a strong security posture by implementing recommended best practices for hardening Pods, including those outlined in the NSA Kubernetes Hardening Guide.</p> <p>By adhering to these standards, the External Secrets Operator benefits from a secure and resilient operating environment. The restricted profile has been set as the default configuration since version <code>v0.8.2</code>, and it is recommended to maintain this setting to align with the principle of least privilege.</p>"},{"location":"guides/security-best-practices/#role-based-access-control-rbac","title":"Role-Based Access Control (RBAC)","text":"<p>The External Secrets Operator operates with elevated privileges within your Kubernetes cluster, allowing it to read and write to all secrets across all namespaces. It is crucial to properly restrict access to ESO resources such as <code>ExternalSecret</code> and <code>SecretStore</code> where necessary. This is particularly important for cluster-scoped resources like <code>ClusterExternalSecret</code> and <code>ClusterSecretStore</code>. Unauthorized tampering with these resources by an attacker could lead to unauthorized access to secrets or potential data exfiltration from your system.</p> <p>In most scenarios, the External Secrets Operator is deployed cluster-wide. However, if you prefer to run it on a per-namespace basis, you can scope it to a specific namespace using the <code>scopedRBAC</code> and <code>scopedNamespace</code> options in the helm chart.</p> <p>To ensure a secure RBAC configuration, consider the following checklist:</p> <ul> <li>Restrict access to execute shell commands (pods/exec) within the External Secrets Operator Pod.</li> <li>Restrict access to (Cluster)ExternalSecret and (Cluster)SecretStore resources.</li> <li>Limit access to aggregated ClusterRoles (view/edit/admin) as needed.</li> <li>If necessary, deploy ESO with scoped RBAC or within a specific namespace.</li> </ul> <p>By carefully managing RBAC permissions and scoping the External Secrets Operator appropriately, you can enhance the security of your Kubernetes cluster.</p>"},{"location":"guides/security-best-practices/#network-traffic-and-security","title":"Network Traffic and Security","text":"<p>To ensure a secure network environment, it is recommended to restrict network traffic to and from the External Secrets Operator using <code>NetworkPolicies</code> or similar mechanisms. By default, the External Secrets Operator does not include pre-defined Network Policies.</p> <p>To implement network restrictions effectively, consider the following steps:</p> <ul> <li>Define and apply appropriate NetworkPolicies to limit inbound and outbound traffic for the External Secrets Operator.</li> <li>Specify a \"deny all\" policy by default and selectively permit necessary communication based on your specific requirements.</li> <li>Restrict access to only the required endpoints and protocols for the External Secrets Operator, such as communication with the Kubernetes API server or external secret providers.</li> <li>Regularly review and update the Network Policies to align with changes in your network infrastructure and security requirements.</li> </ul> <p>It is the responsibility of the user to define and configure Network Policies tailored to their specific environment and security needs. By implementing proper network restrictions, you can enhance the overall security posture of the External Secrets Operator within your Kubernetes cluster.</p> <p>Data Exfiltration Risk</p> <p>If not configured properly ESO may be used to exfiltrate data out of your cluster. It is advised to create tight NetworkPolicies and use a policy engine such as kyverno to prevent data exfiltration.</p>"},{"location":"guides/security-best-practices/#outbound-traffic-restrictions","title":"Outbound Traffic Restrictions","text":""},{"location":"guides/security-best-practices/#core-controller","title":"Core Controller","text":"<p>Restrict outbound traffic from the core controller component to the following destinations:</p> <ul> <li><code>kube-apiserver</code>: The Kubernetes API server.</li> <li>Secret provider (e.g., AWS, GCP): Whenever possible, use private endpoints to establish secure and private communication.</li> </ul>"},{"location":"guides/security-best-practices/#webhook","title":"Webhook","text":"<ul> <li>Restrict outbound traffic from the webhook component to the <code>kube-apiserver</code>.</li> </ul>"},{"location":"guides/security-best-practices/#cert-controller","title":"Cert Controller","text":"<ul> <li>Restrict outbound traffic from the cert controller component to the <code>kube-apiserver</code>.</li> </ul>"},{"location":"guides/security-best-practices/#inbound-traffic-restrictions","title":"Inbound Traffic Restrictions","text":""},{"location":"guides/security-best-practices/#core-controller_1","title":"Core Controller","text":"<ul> <li>Restrict inbound traffic to the core controller component by allowing communication on port <code>8080</code> from your monitoring agent.</li> </ul>"},{"location":"guides/security-best-practices/#cert-controller_1","title":"Cert Controller","text":"<ul> <li>Restrict inbound traffic to the cert controller component by allowing communication on port <code>8080</code> from your monitoring agent.</li> <li>Additionally, permit inbound traffic on port <code>8081</code> from the kubelet for health check endpoints (healthz/readyz).</li> </ul>"},{"location":"guides/security-best-practices/#webhook_1","title":"Webhook","text":"<p>Restrict inbound traffic to the webhook component as follows:</p> <ul> <li>Allow communication on port <code>10250</code> from the kube-apiserver.</li> <li>Allow communication on port <code>8080</code> from your monitoring agent.</li> <li>Permit inbound traffic on port <code>8081</code> from the kubelet for health check endpoints (healthz/readyz).</li> </ul>"},{"location":"guides/security-best-practices/#policy-engine-best-practices","title":"Policy Engine Best Practices","text":"<p>To enhance the security and enforce specific policies for External Secrets Operator (ESO) resources such as SecretStore and ExternalSecret, it is recommended to utilize a policy engine like Kyverno or OPA Gatekeeper. These policy engines provide a way to define and enforce custom policies that restrict changes made to ESO resources.</p> <p>Data Exfiltration Risk</p> <p>ESO could be used to exfiltrate data out of your cluster. You should disable all providers you don't need. Further, you should implement <code>NetworkPolicies</code> to restrict network access to known entities (see above), to prevent data exfiltration.</p> <p>Here are some recommendations to consider when configuring your policies:</p> <ol> <li>Explicitly Deny Unused Providers: Create policies that explicitly deny the usage of secret providers that are not required in your environment. This prevents unauthorized access to unnecessary providers and reduces the attack surface.</li> <li>Restrict Access to Secrets: Implement policies that restrict access to secrets based on specific conditions. For example, you can define policies to allow access to secrets only if they have a particular prefix in the <code>.spec.data[].remoteRef.key</code> field. This helps ensure that only authorized entities can access sensitive information.</li> <li>Restrict <code>ClusterSecretStore</code> References: Define policies to restrict the usage of ClusterSecretStore references within ExternalSecret resources. This ensures that the resources are properly scoped and prevent potential unauthorized access to secrets across namespaces.</li> </ol> <p>By leveraging a policy engine, you can implement these recommendations and enforce custom policies that align with your organization's security requirements. Please refer to the documentation of the chosen policy engine (e.g., Kyverno or OPA Gatekeeper) for detailed instructions on how to define and enforce policies for ESO resources.</p> <p>Provider Validation Example Policy</p> <p>The following policy validates the usage of the <code>provider</code> field in the SecretStore manifest.</p> <pre><code>apiVersion: kyverno.io/v1\nkind: ClusterPolicy\nmetadata:\n name: require-secretstore-aws-provider\nspec:\n validationFailureAction: Enforce\n rules:\n - name: require-secretstore-aws-provider\n match:\n any:\n - resources:\n kinds:\n - SecretStore\n - ClusterSecretStore\n validate:\n message: \"You must only use AWS SecretsManager\"\n pattern:\n spec:\n provider:\n aws:\n service: SecretsManager\n</code></pre>"},{"location":"guides/security-best-practices/#regular-patches","title":"Regular Patches","text":"<p>To maintain a secure environment, it is crucial to regularly patch and update all software components of External Secrets Operator and the underlying cluster. By doing so, known vulnerabilities can be addressed, and the overall system's security can be improved. Here are some recommended practices for ensuring timely updates:</p> <ol> <li>Automated Patching and Updating: Utilize automated patching and updating tools to streamline the process of keeping software components up-to-date</li> <li>Regular Update ESO: Stay informed about the latest updates and releases provided for ESO. The development team regularly releases updates to improve stability, performance, and security. Please refer to the Stability and Support documentation for more information on the available updates</li> <li>Cluster-wide Updates: Apart from ESO, ensure that all other software components within your cluster, such as the operating system, container runtime, and Kubernetes itself, are regularly patched and updated.</li> </ol> <p>By adhering to a regular patching and updating schedule, you can proactively mitigate security risks associated with known vulnerabilities and ensure the overall stability and security of your ESO deployment.</p>"},{"location":"guides/security-best-practices/#verify-artefacts","title":"Verify Artefacts","text":""},{"location":"guides/security-best-practices/#verify-container-images","title":"Verify Container Images","text":"<p>The container images of External Secrets Operator are signed using Cosign and the keyless signing feature. To ensure the authenticity and integrity of the container image, you can follow the steps outlined below:</p> <pre><code># Retrieve Image Signature\n$ crane digest ghcr.io/external-secrets/external-secrets:v0.8.1\nsha256:36e606279dbebac51b4b9300b9fa85e8c08c1c673ba3ecc38af1402a0b035554\n\n# verify signature\n$ COSIGN_EXPERIMENTAL=1 cosign verify ghcr.io/external-secrets/external-secrets@sha256:36e606279dbebac51b4b9300b9fa85e8c08c1c673ba3ecc38af1402a0b035554 | jq\n\n# ...\n[\n {\n \"critical\": {\n \"identity\": {\n \"docker-reference\": \"ghcr.io/external-secrets/external-secrets\"\n },\n \"image\": {\n \"docker-manifest-digest\": \"sha256:36e606279dbebac51b4b9300b9fa85e8c08c1c673ba3ecc38af1402a0b035554\"\n },\n \"type\": \"cosign container image signature\"\n },\n \"optional\": {\n \"1.3.6.1.4.1.57264.1.1\": \"https://token.actions.githubusercontent.com\",\n \"1.3.6.1.4.1.57264.1.2\": \"workflow_dispatch\",\n \"1.3.6.1.4.1.57264.1.3\": \"a0d2aef2e35c259c9ee75d65f7587e6ed71ef2ad\",\n \"1.3.6.1.4.1.57264.1.4\": \"Create Release\",\n \"1.3.6.1.4.1.57264.1.5\": \"external-secrets/external-secrets\",\n \"1.3.6.1.4.1.57264.1.6\": \"refs/heads/main\",\n \"Bundle\": {\n # ...\n },\n \"GITHUB_ACTOR\": \"gusfcarvalho\",\n \"Issuer\": \"https://token.actions.githubusercontent.com\",\n \"Subject\": \"https://github.com/external-secrets/external-secrets/.github/workflows/release.yml@refs/heads/main\",\n \"githubWorkflowName\": \"Create Release\",\n \"githubWorkflowRef\": \"refs/heads/main\",\n \"githubWorkflowRepository\": \"external-secrets/external-secrets\",\n \"githubWorkflowSha\": \"a0d2aef2e35c259c9ee75d65f7587e6ed71ef2ad\",\n \"githubWorkflowTrigger\": \"workflow_dispatch\"\n }\n }\n]\n</code></pre> <p>In the output of the verification process, pay close attention to the <code>optional.Issuer</code> and <code>optional.Subject</code> fields. These fields contain important information about the image's authenticity. Verify that the values of Issuer and Subject match the expected values for the ESO container image. If they do not match, it indicates that the image is not legitimate and should not be used.</p> <p>By following these steps and confirming that the Issuer and Subject fields align with the expected values for the ESO container image, you can ensure that the image has not been tampered with and is safe to use.</p>"},{"location":"guides/security-best-practices/#verifying-provenance","title":"Verifying Provenance","text":"<p>The External Secrets Operator employs the SLSA (Supply Chain Levels for Software Artifacts) standard to create and attest to the provenance of its builds. Provenance verification is essential to ensure the integrity and trustworthiness of the software supply chain. This outlines the process of verifying the attested provenance of External Secrets Operator builds using the cosign tool.</p> <pre><code>$ COSIGN_EXPERIMENTAL=1 cosign verify-attestation --type slsaprovenance ghcr.io/external-secrets/external-secrets:v0.8.1 | jq .payload -r | base64 --decode | jq\n\nVerification for ghcr.io/external-secrets/external-secrets:v0.8.1 --\nThe following checks were performed on each of these signatures:\n - The cosign claims were validated\n - Existence of the claims in the transparency log was verified offline\n - Any certificates were verified against the Fulcio roots.\nCertificate subject: https://github.com/external-secrets/external-secrets/.github/workflows/release.yml@refs/heads/main\nCertificate issuer URL: https://token.actions.githubusercontent.com\nGitHub Workflow Trigger: workflow_dispatch\nGitHub Workflow SHA: a0d2aef2e35c259c9ee75d65f7587e6ed71ef2ad\nGitHub Workflow Name: Create Release\nGitHub Workflow Trigger external-secrets/external-secrets\nGitHub Workflow Ref: refs/heads/main\n{\n \"_type\": \"https://in-toto.io/Statement/v0.1\",\n \"predicateType\": \"https://slsa.dev/provenance/v0.2\",\n \"subject\": [\n {\n \"name\": \"ghcr.io/external-secrets/external-secrets\",\n \"digest\": {\n \"sha256\": \"36e606279dbebac51b4b9300b9fa85e8c08c1c673ba3ecc38af1402a0b035554\"\n }\n }\n ],\n \"predicate\": {\n \"builder\": {\n \"id\": \"https://github.com/external-secrets/external-secrets/Attestations/GitHubHostedActions@v1\"\n },\n \"buildType\": \"https://github.com/Attestations/GitHubActionsWorkflow@v1\",\n \"invocation\": {\n \"configSource\": {\n \"uri\": \"git+https://github.com/external-secrets/external-secrets\",\n \"digest\": {\n \"sha1\": \"a0d2aef2e35c259c9ee75d65f7587e6ed71ef2ad\"\n },\n \"entryPoint\": \"Create Release\"\n },\n \"parameters\": {\n \"version\": \"v0.8.1\"\n }\n },\n [...]\n }\n}\n</code></pre>"},{"location":"guides/security-best-practices/#fetching-sbom","title":"Fetching SBOM","text":"<p>Every External Secrets Operator image is accompanied by an SBOM (Software Bill of Materials) in SPDX JSON format. The SBOM provides detailed information about the software components and dependencies used in the image. This technical documentation explains the process of downloading and verifying the SBOM for a specific version of External Secrets Operator using the Cosign tool.</p> <pre><code>$ crane digest ghcr.io/external-secrets/external-secrets:v0.8.1\nsha256:36e606279dbebac51b4b9300b9fa85e8c08c1c673ba3ecc38af1402a0b035554\n\n$ COSIGN_EXPERIMENTAL=1 cosign verify-attestation --type spdx ghcr.io/external-secrets/external-secrets@sha256:36e606279dbebac51b4b9300b9fa85e8c08c1c673ba3ecc38af1402a0b035554 | jq '.payload |= @base64d | .payload | fromjson' | jq '.predicate.Data | fromjson'\n\n[...]\n{\n \"SPDXID\": \"SPDXRef-DOCUMENT\",\n \"name\": \"ghcr.io/external-secrets/external-secrets@sha256-36e606279dbebac51b4b9300b9fa85e8c08c1c673ba3ecc38af1402a0b035554\",\n \"spdxVersion\": \"SPDX-2.2\",\n \"creationInfo\": {\n \"created\": \"2023-03-17T23:17:01.568002344Z\",\n \"creators\": [\n \"Organization: Anchore, Inc\",\n \"Tool: syft-0.40.1\"\n ],\n \"licenseListVersion\": \"3.16\"\n },\n \"dataLicense\": \"CC0-1.0\",\n \"documentNamespace\": \"https://anchore.com/syft/image/ghcr.io/external-secrets/external-secrets@sha256-36e606279dbebac51b4b9300b9fa85e8c08c1c673ba3ecc38af1402a0b035554-83484ebb-b469-45fa-8fcc-9290c4ea4f6f\",\n \"packages\": [\n [...]\n {\n \"SPDXID\": \"SPDXRef-c809070b0beb099e\",\n \"name\": \"tzdata\",\n \"licenseConcluded\": \"NONE\",\n \"downloadLocation\": \"NOASSERTION\",\n \"externalRefs\": [\n {\n \"referenceCategory\": \"SECURITY\",\n \"referenceLocator\": \"cpe:2.3:a:tzdata:tzdata:2021a-1\\\\+deb11u8:*:*:*:*:*:*:*\",\n \"referenceType\": \"cpe23Type\"\n },\n {\n \"referenceCategory\": \"PACKAGE_MANAGER\",\n \"referenceLocator\": \"pkg:deb/debian/tzdata@2021a-1+deb11u8?arch=all&amp;distro=debian-11\",\n \"referenceType\": \"purl\"\n }\n ],\n \"filesAnalyzed\": false,\n \"licenseDeclared\": \"NONE\",\n \"originator\": \"Person: GNU Libc Maintainers &lt;debian-glibc@lists.debian.org&gt;\",\n \"sourceInfo\": \"acquired package info from DPKG DB: /var/lib/dpkg/status.d/tzdata, /usr/share/doc/tzdata/copyright\",\n \"versionInfo\": \"2021a-1+deb11u8\"\n }\n ]\n}\n</code></pre>"},{"location":"guides/templating-v1/","title":"Advanced Templating v1","text":"<p>Warning</p> <p>Templating Engine v1 is deprecated and will be removed in the future. Please migrate to engine v2 and take a look at our upgrade guide for changes.</p> <p>With External Secrets Operator you can transform the data from the external secret provider before it is stored as <code>Kind=Secret</code>. You can do this with the <code>Spec.Target.Template</code>.</p> <p>Each data value is interpreted as a Go template. Please note that referencing a non-existing key in the template will raise an error, instead of being suppressed.</p>"},{"location":"guides/templating-v1/#examples","title":"Examples","text":"<p>You can use templates to inject your secrets into a configuration file that you mount into your pod: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: template\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: secretstore-sample\n kind: SecretStore\n target:\n name: secret-to-be-created\n\n # v2 is the default engineVersion in external-secrets.io/v1beta1\n # v1 is the default engineVersion in external-secrets.io/v1alpha1 (deprecated)\n engineVersion: v1\n\n # this is how the Kind=Secret will look like\n template:\n type: kubernetes.io/tls\n data:\n # multiline string\n config: |\n datasources:\n - name: Graphite\n type: graphite\n access: proxy\n url: http://localhost:8080\n password: \"{{ .password | toString }}\" # &lt;-- convert []byte to string\n user: \"{{ .user | toString }}\" # &lt;-- convert []byte to string\n\n data:\n - secretKey: user\n remoteRef:\n key: /grafana/user\n - secretKey: password\n remoteRef:\n key: /grafana/password\n</code></pre></p> <p>You can also use pre-defined functions to extract data from your secrets. Here: extract key/cert from a pkcs12 archive and store it as PEM. <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: template\nspec:\n # ...\n target:\n template:\n type: kubernetes.io/tls\n engineVersion: v2\n data:\n tls.crt: \"{{ .mysecret | pkcs12cert }}\"\n tls.key: \"{{ .mysecret | pkcs12key }}\"\n\n # if needed unlock the pkcs12 with the password\n tls.crt: \"{{ .mysecret | pkcs12certPass \"my-password\" }}\"\n</code></pre></p>"},{"location":"guides/templating-v1/#templatefrom","title":"TemplateFrom","text":"<p>You do not have to define your templates inline in an ExternalSecret but you can pull <code>ConfigMaps</code> or other Secrets that contain a template. Consider the following example:</p> <pre><code># define your template in a config map\napiVersion: v1\nkind: ConfigMap\nmetadata:\n name: grafana-config-tpl\ndata:\n config.yaml: |\n datasources:\n - name: Graphite\n type: graphite\n access: proxy\n url: http://localhost:8080\n password: \"{{ .password | toString }}\" # &lt;-- convert []byte to string\n user: \"{{ .user | toString }}\" # &lt;-- convert []byte to string\n---\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: my-template-example\nspec:\n # ...\n target:\n name: secret-to-be-created\n template:\n templateFrom:\n - configMap:\n # name of the configmap to pull in\n name: grafana-config-tpl\n # here you define the keys that should be used as template\n items:\n - key: config.yaml\n data:\n - secretKey: user\n remoteRef:\n key: /grafana/user\n - secretKey: password\n remoteRef:\n key: /grafana/password\n</code></pre>"},{"location":"guides/templating-v1/#helper-functions","title":"Helper functions","text":"<p>We provide a bunch of convenience functions that help you transform your secrets. A secret value is a <code>[]byte</code>.</p> Function Description Input Output pkcs12key extracts the private key from a pkcs12 archive <code>[]byte</code> <code>[]byte</code> pkcs12keyPass extracts the private key from a pkcs12 archive using the provided password password <code>string</code>, data <code>[]byte</code> <code>[]byte</code> pkcs12cert extracts the certificate from a pkcs12 archive <code>[]byte</code> <code>[]byte</code> pkcs12certPass extracts the certificate from a pkcs12 archive using the provided password password <code>string</code>, data <code>[]byte</code> <code>[]byte</code> pemPrivateKey PEM encodes the provided bytes as private key <code>[]byte</code> <code>string</code> pemCertificate PEM encodes the provided bytes as certificate <code>[]byte</code> <code>string</code> jwkPublicKeyPem takes an json-serialized JWK as <code>[]byte</code> and returns an PEM block of type <code>PUBLIC KEY</code> that contains the public key (see here) for details <code>[]byte</code> <code>string</code> jwkPrivateKeyPem takes an json-serialized JWK as <code>[]byte</code> and returns an PEM block of type <code>PRIVATE KEY</code> that contains the private key in PKCS #8 format (see here) for details <code>[]byte</code> <code>string</code> base64decode decodes the provided bytes as base64 <code>[]byte</code> <code>[]byte</code> base64encode encodes the provided bytes as base64 <code>[]byte</code> <code>[]byte</code> fromJSON parses the bytes as JSON so you can access individual properties <code>[]byte</code> <code>any</code> toJSON encodes the provided object as json string <code>any</code> <code>string</code> toString converts bytes to string <code>[]byte</code> <code>string</code> toBytes converts string to bytes <code>string</code> <code>[]byte</code> upper converts all characters to their upper case <code>string</code> <code>string</code> lower converts all character to their lower case <code>string</code> <code>string</code>"},{"location":"guides/templating/","title":"Advanced Templating v2","text":"<p>With External Secrets Operator you can transform the data from the external secret provider before it is stored as <code>Kind=Secret</code>. You can do this with the <code>Spec.Target.Template</code>.</p> <p>Each data value is interpreted as a Go template. Please note that referencing a non-existing key in the template will raise an error, instead of being suppressed.</p> <p>Note</p> <p>Consider using camelcase when defining .'spec.data.secretkey', example: serviceAccountToken</p> <p>If your secret keys contain <code>-</code> (dashes), you will need to reference them using <code>index</code> Example: <code>\\{\\{ index .data \"service-account-token\" \\}\\}</code></p>"},{"location":"guides/templating/#helm","title":"Helm","text":"<p>When installing ExternalSecrets via <code>helm</code>, the template must be escaped so that <code>helm</code> will not try to render it. The most straightforward way to accomplish this would be to use backticks (raw string constants):</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: template\nspec:\n # ...\n target:\n template:\n engineVersion: v2\n data:\n name: admin\n # password: \"{{ .mysecret }}\" # If you are using plain manifests or gitops tools\n password: \"{{ `{{ .mysecret }}` }}\" # If you are using helm\n data:\n - secretKey: mysecret\n remoteRef:\n key: /credentials\n</code></pre>"},{"location":"guides/templating/#examples","title":"Examples","text":"<p>You can use templates to inject your secrets into a configuration file that you mount into your pod:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: template\nspec:\n # ...\n target:\n name: secret-to-be-created\n # this is how the Kind=Secret will look like\n template:\n engineVersion: v2\n data:\n # multiline string\n config: |\n datasources:\n - name: Graphite\n type: graphite\n access: proxy\n url: http://localhost:8080\n password: \"{{ .password }}\"\n user: \"{{ .user }}\"\n # using replace function to rewrite secret\n connection: '{{ .dburl | replace \"postgres://\" \"postgresql://\" }}'\n\n data:\n - secretKey: user\n remoteRef:\n key: /grafana/user\n - secretKey: password\n remoteRef:\n key: /grafana/password\n - secretKey: dburl\n remoteRef:\n key: /database/url\n</code></pre> <p>Another example with two keys in the same secret:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: template\nspec:\n # ...\n target:\n template:\n engineVersion: v2\n data:\n name: admin\n password: \"{{ .mysecret }}\" # If you are using plain manifests or gitops tools\n # password: \"{{ `{{ .mysecret }}` }}\" # If you are using templated tools like helm\n data:\n - secretKey: mysecret\n remoteRef:\n key: /credentials\n</code></pre>"},{"location":"guides/templating/#mergepolicy","title":"MergePolicy","text":"<p>By default, the templating mechanism will not use any information available from the original <code>data</code> and <code>dataFrom</code> queries to the provider, and only keep the templated information. It is possible to change this behavior through the use of the <code>mergePolicy</code> field. <code>mergePolicy</code> currently accepts two values: <code>Replace</code> (the default) and <code>Merge</code>. When using <code>Merge</code>, <code>data</code> and <code>dataFrom</code> keys will also be embedded into the templated secret, having lower priority than the template outcome. See the example for more information:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: template\nspec:\n # ...\n target:\n template:\n mergePolicy: Merge\n engineVersion: v2\n data:\n name: admin\n password: \"{{ .password | b64dec }}\" # Overwrites the password from the data call and use this output\n data:\n - secretKey: password\n remoteRef:\n key: /credentials/password\n - secretKey: username # Preserves the username in the templated Secret\n remoteRef:\n key: /credentials/username\n</code></pre>"},{"location":"guides/templating/#templatefrom","title":"TemplateFrom","text":"<p>You do not have to define your templates inline in an ExternalSecret but you can pull <code>ConfigMaps</code> or other Secrets that contain a template. Consider the following example:</p> <pre><code># define your template in a config map\napiVersion: v1\nkind: ConfigMap\nmetadata:\n name: grafana-config-tpl\ndata:\n config.yaml: |\n datasources:\n - name: Graphite\n type: graphite\n access: proxy\n url: \"{{ .uri }}\"\n password: \"{{ .password }}\"\n user: \"{{ .user }}\"\n templated: |\n # key and value templated\n my-application-{{ .user}}: {{ .password | b64enc }}\n # conditional keys\n {{- if hasPrefix \"oci://\" .uri }}\n enableOCI: true\n {{- else }}\n enableOCI: false\n {{- end }}\n # Fixed values\n application-type: grafana\n annotations: |\n #dynamic timestamp generation\n last-synced-for-user/{{ .user }}: {{ now }}\n---\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: my-template-example\nspec:\n # ...\n target:\n name: secret-to-be-created\n template:\n engineVersion: v2\n templateFrom:\n - target: Data\n configMap:\n # name of the configmap to pull in\n name: grafana-config-tpl\n # here you define the keys that should be used as template\n items:\n - key: config.yaml\n templateAs: Values\n - key: templated\n templateAs: KeysAndValues\n - target: Annotations\n configMap:\n # name of the configmap to pull in\n name: grafana-config-tpl\n # here you define the keys that should be used as template\n items:\n - key: annotations\n templateAs: KeysAndValues\n data:\n - secretKey: user\n remoteRef:\n key: /grafana/user\n - secretKey: password\n remoteRef:\n key: /grafana/password\n - secretKey: uri\n remoteRef:\n key: /grafana/uri\n</code></pre> <p><code>TemplateFrom</code> also gives you the ability to Target your template to the Secret's Annotations, Labels or the Data block. It also allows you to render the templated information as <code>Values</code> or as <code>KeysAndValues</code> through the <code>templateAs</code> configuration:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: my-template-example\nspec:\n # ...\n target:\n name: secret-to-be-created\n template:\n engineVersion: v2\n templateFrom:\n - target: Annotations\n literal: \"last-sync-for-user/{{ .user }}: {{ .now }}\"\n data:\n - secretKey: user\n remoteRef:\n key: /grafana/user\n - secretKey: password\n remoteRef:\n key: /grafana/password\n</code></pre> <p>Lastly, <code>TemplateFrom</code> also supports adding <code>Literal</code> blocks for quick templating. These <code>Literal</code> blocks differ from <code>Template.Data</code> as they are rendered as a a <code>key:value</code> pair (while the <code>Template.Data</code>, you can only template the value).</p> <p>See an example, how to produce a <code>htpasswd</code> file that can be used by an ingress-controller (for example: https://kubernetes.github.io/ingress-nginx/examples/auth/basic/) where the contents of the <code>htpasswd</code> file needs to be presented via the <code>auth</code> key. We use the <code>htpasswd</code> function to create a <code>bcrytped</code> hash of the password.</p> <p>Suppose you have multiple key-value pairs within your provider secret like</p> <pre><code>{\n \"user1\": \"password1\",\n \"user2\": \"password2\",\n ...\n}\n</code></pre> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: my-template-example\nspec:\n # ...\n target:\n name: secret-to-be-created\n template:\n engineVersion: v2\n templateFrom:\n - target: Data\n literal: |-\n {{- $creds := list }}\n {{- range $user, $pw := . }}\n {{- $creds = append $creds (printf \"%s\" (htpasswd $user $pw)) }}\n {{- end }}\n auth: {{ $creds | join \"\\n\" | quote }}\n dataFrom:\n - extract:\n key: /ingress-controller/valid-users\n</code></pre>"},{"location":"guides/templating/#extract-keys-and-certificates-from-pkcs12-archive","title":"Extract Keys and Certificates from PKCS#12 Archive","text":"<p>You can use pre-defined functions to extract data from your secrets. Here: extract keys and certificates from a PKCS#12 archive and store it as PEM.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: template\nspec:\n # ...\n target:\n template:\n type: kubernetes.io/tls\n engineVersion: v2\n data:\n tls.crt: \"{{ .mysecret | pkcs12cert }}\"\n tls.key: \"{{ .mysecret | pkcs12key }}\"\n\n # if needed unlock the pkcs12 with the password\n tls.crt: \"{{ .mysecret | pkcs12certPass \"my-password\" }}\"\n</code></pre>"},{"location":"guides/templating/#extract-from-jwk","title":"Extract from JWK","text":"<p>You can extract the public or private key parts of a JWK and use them as PKCS#8 private key or PEM-encoded PKIX public key.</p> <p>A JWK looks similar to this:</p> <pre><code>{\n \"kty\": \"RSA\",\n \"kid\": \"cc34c0a0-bd5a-4a3c-a50d-a2a7db7643df\",\n \"use\": \"sig\",\n \"n\": \"pjdss...\",\n \"e\": \"AQAB\"\n // ...\n}\n</code></pre> <p>And what you want may be a PEM-encoded public or private key portion of it. Take a look at this example on how to transform it into the desired format:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: template\nspec:\n # ...\n target:\n template:\n engineVersion: v2\n data:\n # .myjwk is a json-encoded JWK string.\n #\n # this template will produce for jwk_pub a PEM encoded public key:\n # -----BEGIN PUBLIC KEY-----\n # MIIBI...\n # ...\n # ...AQAB\n # -----END PUBLIC KEY-----\n jwk_pub: \"{{ .myjwk | jwkPublicKeyPem }}\"\n # private key is a pem-encoded PKCS#8 private key\n jwk_priv: \"{{ .myjwk | jwkPrivateKeyPem }}\"\n</code></pre>"},{"location":"guides/templating/#filter-pem-blocks","title":"Filter PEM blocks","text":"<p>Consider you have a secret that contains both a certificate and a private key encoded in PEM format and it is your goal to use only the certificate from that secret.</p> <pre><code>-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCvxGZOW4IXvGlh\n . . .\nm8JCpbJXDfSSVxKHgK1Siw4K6pnTsIA2e/Z+Ha2fvtocERjq7VQMAJFaIZSTKo9Q\nJwwY+vj0yxWjyzHUzZB33tg=\n-----END PRIVATE KEY-----\n-----BEGIN CERTIFICATE-----\nMIIDMDCCAhigAwIBAgIQabPaXuZCQaCg+eQAVptGGDANBgkqhkiG9w0BAQsFADAV\n . . .\nNtFUGA95RGN9s+pl6XY0YARPHf5O76ErC1OZtDTR5RdyQfcM+94gYZsexsXl0aQO\n9YD3Wg==\n-----END CERTIFICATE-----\n</code></pre> <p>You can achieve that by using the <code>filterPEM</code> function to extract a specific type of PEM block from that secret. If multiple blocks of that type (here: <code>CERTIFICATE</code>) exist, all of them are returned in the order specified. To extract a specific type of PEM block, pass the type as a string argument to the filterPEM function. Take a look at this example of how to transform a secret which contains a private key and a certificate into the desired format:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: template\nspec:\n # ...\n target:\n template:\n type: kubernetes.io/tls\n engineVersion: v2\n data:\n tls.crt: \"{{ .mysecret | filterPEM \"CERTIFICATE\" }}\"\n tls.key: \"{{ .mysecret | filterPEM \"PRIVATE KEY\" }}\"\n</code></pre>"},{"location":"guides/templating/#templating-with-pushsecret","title":"Templating with PushSecret","text":"<p><code>PushSecret</code> templating is much like <code>ExternalSecrets</code> templating. In-fact under the hood, it's using the same data structure. Which means, anything described in the above should be possible with push secret as well resulting in a templated secret created at the provider.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: PushSecret\nmetadata:\n name: template\nspec:\n # ...\n template:\n engineVersion: v2\n data:\n token: \"{{ .token | toString | upper }} was templated\"\n data:\n - match:\n secretKey: token\n remoteRef:\n remoteKey: create-secret-name\n property: token\n</code></pre>"},{"location":"guides/templating/#helper-functions","title":"Helper functions","text":"<p>Info</p> <p>Note: we removed <code>env</code> and <code>expandenv</code> from sprig functions for security reasons.</p> <p>We provide a couple of convenience functions that help you transform your secrets. This is useful when dealing with PKCS#12 archives or JSON Web Keys (JWK).</p> <p>In addition to that you can use over 200+ sprig functions. If you feel a function is missing or might be valuable feel free to open an issue and submit a pull request.</p> <p></p> Function Description pkcs12key Extracts all private keys from a PKCS#12 archive and encodes them in PKCS#8 PEM format. pkcs12keyPass Same as <code>pkcs12key</code>. Uses the provided password to decrypt the PKCS#12 archive. pkcs12cert Extracts all certificates from a PKCS#12 archive and orders them if possible. If disjunct or multiple leaf certs are provided they are returned as-is. Sort order: <code>leaf / intermediate(s) / root</code>. pkcs12certPass Same as <code>pkcs12cert</code>. Uses the provided password to decrypt the PKCS#12 archive. pemToPkcs12 Takes a PEM encoded certificate and key and creates a base64 encoded PKCS#12 archive. pemToPkcs12Pass Same as <code>pemToPkcs12</code>. Uses the provided password to encrypt the PKCS#12 archive. fullPemToPkcs12 Takes a PEM encoded certificates chain and key and creates a base64 encoded PKCS#12 archive. fullPemToPkcs12Pass Same as <code>fullPemToPkcs12</code>. Uses the provided password to encrypt the PKCS#12 archive. filterPEM Filters PEM blocks with a specific type from a list of PEM blocks. jwkPublicKeyPem Takes an json-serialized JWK and returns an PEM block of type <code>PUBLIC KEY</code> that contains the public key. See here for details. jwkPrivateKeyPem Takes an json-serialized JWK as <code>string</code> and returns an PEM block of type <code>PRIVATE KEY</code> that contains the private key in PKCS #8 format. See here for details. toYaml Takes an interface, marshals it to yaml. It returns a string, even on marshal error (empty string). fromYaml Function converts a YAML document into a map[string]any."},{"location":"guides/templating/#migrating-from-v1","title":"Migrating from v1","text":"<p>If you are still using <code>v1alpha1</code>, You have to opt-in to use the new engine version by specifying <code>template.engineVersion=v2</code>:</p> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: ExternalSecret\nmetadata:\n name: secret\nspec:\n # ...\n target:\n template:\n engineVersion: v2\n # ...\n</code></pre> <p>The biggest change was that basically all function parameter types were changed from accepting/returning <code>[]byte</code> to <code>string</code>. This is relevant for you because now you don't need to specify <code>toString</code> all the time at the end of a template pipeline.</p> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: ExternalSecret\n# ...\nspec:\n target:\n template:\n engineVersion: v2\n data:\n # this used to be {{ .foobar | toString }}\n egg: \"new: {{ .foobar }}\"\n</code></pre>"},{"location":"guides/templating/#functions-removedreplaced","title":"Functions removed/replaced","text":"<ul> <li><code>base64encode</code> was renamed to <code>b64enc</code>.</li> <li><code>base64decode</code> was renamed to <code>b64dec</code>. Any errors that occur during decoding are silenced.</li> <li><code>fromJSON</code> was renamed to <code>fromJson</code>. Any errors that occur during unmarshalling are silenced.</li> <li><code>toJSON</code> was renamed to <code>toJson</code>. Any errors that occur during marshalling are silenced.</li> <li><code>pkcs12key</code> and <code>pkcs12keyPass</code> encode the PKCS#8 key directly into PEM format. There is no need to call <code>pemPrivateKey</code> anymore. Also, these functions do extract all private keys from the PKCS#12 archive not just the first one.</li> <li><code>pkcs12cert</code> and <code>pkcs12certPass</code> encode the certs directly into PEM format. There is no need to call <code>pemCertificate</code> anymore. These functions now extract all certificates from the PKCS#12 archive not just the first one.</li> <li><code>toString</code> implementation was replaced by the <code>sprig</code> implementation and should be api-compatible.</li> <li><code>toBytes</code> was removed.</li> <li><code>pemPrivateKey</code> was removed. It's now implemented within the <code>pkcs12*</code> functions.</li> <li><code>pemCertificate</code> was removed. It's now implemented within the <code>pkcs12*</code> functions.</li> </ul>"},{"location":"guides/threat-model/","title":"Threat Model","text":""},{"location":"guides/threat-model/#background","title":"Background","text":"<p>The External Secrets Operator is a Kubernetes Operator that seamlessly incorporates external secret management systems into Kubernetes. This Operator retrieves data from the external API and generates Kubernetes Secret resources using the corresponding secret values. This process occurs continuously in the background through regular polling of the external API. Consequently, whenever a secret undergoes changes in the external API, the corresponding Kubernetes Secret will also be updated accordingly.</p>"},{"location":"guides/threat-model/#summary","title":"Summary","text":"Purpose Description Intended Usage Sync Secrets into Kubernetes Data Classifiation Critical Highest Risk Impact Organisation takeover"},{"location":"guides/threat-model/#components","title":"Components","text":"<p>ESO comprises three main components: <code>webhook</code>, <code>cert controller</code> and a <code>core controller</code>. For more detailed information, please refer to the documentation on components.</p>"},{"location":"guides/threat-model/#overview","title":"Overview","text":"<p>This section provides an overview of the security aspects of the External Secrets Operator (ESO) and includes information on assets, threats, and controls involved in its operation.</p> <p>The following diagram illustrates the security perspective of how ESO functions, highlighting the assets (items to protect), threats (potential risks), and controls (measures to mitigate threats).</p> <p></p>"},{"location":"guides/threat-model/#scope","title":"Scope","text":"<p>For the purpose of this threat model, we assume an ESO installation using helm and default settings on a public cloud provider. It is important to note that the Kubernetes SIG Security team has defined an Admission Control Threat Model, which is recommended reading for a better understanding of the security aspects that partially apply to External Secrets Operator.</p> <p>ESO utilizes the <code>ValidatingWebhookConfiguration</code> mechanism to validate <code>(Cluster)SecretStore</code> and <code>(Cluster)ExternalSecret</code> resources. However, it is essential to understand that this validation process does not serve as a security control mechanism. Instead, ESO performs validation by enforcing additional rules that go beyond the CustomResourceDefinition OpenAPI v3 Validation schema.</p>"},{"location":"guides/threat-model/#assets","title":"Assets","text":""},{"location":"guides/threat-model/#a01-cluster-level-access-to-secrets","title":"A01: Cluster-Level access to secrets","text":"<p>The controller possesses privileged access to the <code>kube-apiserver</code> and is authorized to read and write secret resources across all namespaces within a cluster.</p>"},{"location":"guides/threat-model/#a02-crd-and-webhook-write-access","title":"A02: CRD and Webhook Write access","text":"<p>The cert-controller component has read/write access to <code>ValidatingWebhookConfigurations</code> and <code>CustomResourceDefinitions</code> resources. This access is necessary to inject/modify the caBundle property.</p>"},{"location":"guides/threat-model/#a03-secret-provider-access","title":"A03: secret provider access","text":"<p>The <code>core-controller</code> component accesses a secret provider using user-supplied credentials. These credentials can be derived from environment variables, mounted service account tokens, files within the controller container, or fetched from the Kubernetes API (e.g., <code>Kind=Secret</code>). The scope of these credentials may vary, potentially providing full access to a cloud provider.</p>"},{"location":"guides/threat-model/#a04-capability-to-modify-resources","title":"A04: capability to modify resources","text":"<p>The webhook component validates and converts ExternalSecret and SecretStore resources. The conversion webhook is essential for migrating resources from the old version <code>v1alpha1</code> to the new version <code>v1beta1</code>. The webhook component possesses the ability to modify resources during runtime.</p>"},{"location":"guides/threat-model/#threats","title":"Threats","text":""},{"location":"guides/threat-model/#t01-tampering-with-resources-through-mitm","title":"T01: Tampering with resources through MITM","text":"<p>An adversary could launch a Man-in-the-Middle (MITM) attack to hijack the webhook pod, enabling them to manipulate the data of the conversion webhook. This could involve injecting malicious resources or causing a Denial-of-Service (DoS) attack. To mitigate this threat, a mutual authentication mechanism should be enforced for the connection between the Kubernetes API server and the webhook service to ensure that only authenticated endpoints can communicate.</p>"},{"location":"guides/threat-model/#t02-webhook-dos","title":"T02: Webhook DOS","text":"<p>Currently, ESO generates an X.509 certificate for webhook registration without authenticating the kube-apiserver. Consequently, if an attacker gains network access to the webhook Pod, they can overload the webhook server and initiate a DoS attack. As a result, modifications to ESO resources may fail, and the ESO core controller may be impacted due to the unavailability of the conversion webhook.</p>"},{"location":"guides/threat-model/#t03-unauthorized-access-to-cluster-secrets","title":"T03: Unauthorized access to cluster secrets","text":"<p>An attacker can gain unauthorized access to secrets by utilizing the service account token of the ESO core controller Pod or exploiting software vulnerabilities. This unauthorized access allows the attacker to read secrets within the cluster, potentially leading to a cluster takeover.</p>"},{"location":"guides/threat-model/#t04-unauthorized-access-to-secret-provider-credentials","title":"T04: unauthorized access to secret provider credentials","text":"<p>An attacker can gain unauthorized access to credentials that provide access to external APIs storing secrets. If the credentials have overly broad permissions, this could result in an organization takeover.</p>"},{"location":"guides/threat-model/#t05-data-exfiltration-through-malicious-resources","title":"T05: data exfiltration through malicious resources","text":"<p>An attacker can exfiltrate data from the cluster by utilizing maliciously crafted resources. Multiple attack vectors can be employed, e.g.:</p> <ol> <li>copying data from a namespace to an unauthorized namespace</li> <li>exfiltrating data to an unauthorized secret provider</li> <li>exfiltrating data through an authorized secret provider to a malicious provider account</li> </ol> <p>Successful data exfiltration can lead to intellectual property loss, information misuse, loss of customer trust, and damage to the brand or reputation.</p>"},{"location":"guides/threat-model/#t06-supply-chain-attacks","title":"T06: supply chain attacks","text":"<p>An attack can infiltrate the ESO container through various attack vectors. The following are some potential entry points, although this is not an exhaustive list. For a comprehensive analysis, refer to SLSA Threats and mitigations or GCP software supply chain threats.</p> <ol> <li>Source Threats: Unauthorized changes or inclusion of vulnerable code in ESO through code submissions.</li> <li>Build Threats: Creation and distribution of malicious builds of ESO, such as in container registries, Artifact Hub, or Operator Hub.</li> <li>Dependency Threats: Introduction of vulnerable code into ESO dependencies.</li> <li>Deployment and Runtime Threats: Injection of malicious code through compromised deployment processes.</li> </ol>"},{"location":"guides/threat-model/#t07-malicious-workloads-in-eso-namespace","title":"T07: malicious workloads in eso namespace","text":"<p>An attacker can deploy malicious workloads within the external-secrets namespace, taking advantage of the ESO service account with potentially cluster-wide privileges.</p>"},{"location":"guides/threat-model/#controls","title":"Controls","text":""},{"location":"guides/threat-model/#c01-network-security-policy","title":"C01: Network Security Policy","text":"<p>Implement a NetworkPolicy to restrict traffic in both inbound and outbound directions on all networks. Employ a \"deny all\" / \"permit by exception\" approach for inbound and outbound network traffic. The specific network policies for the core-controller depend on the chosen provider. The webhook and cert-controller have well-defined sets of endpoints they communicate with. Refer to the Security Best Practices documentation for inbound and outbound network requirements.</p> <p>Please note that ESO does not provide pre-packaged network policies, and it is the user's responsibility to implement the necessary security controls.</p>"},{"location":"guides/threat-model/#c02-least-privilege-rbac","title":"C02: Least Privilege RBAC","text":"<p>Adhere to the principle of least privilege by configuring Role-Based Access Control (RBAC) permissions not only for the ESO workload but also for all users interacting with it. Ensure that RBAC permissions on provider side are appropriate according to your setup, by for example limiting which sensitive information a given credential can have access to. Ensure that kubernetes RBAC are set up to grant access to ESO resources only where necessary. For example, allowing write access to <code>ClusterSecretStore</code>/<code>ExternalSecret</code> may be sufficient for a threat to become a reality.</p>"},{"location":"guides/threat-model/#c03-policy-enforcement","title":"C03: Policy Enforcement","text":"<p>Implement a Policy Engine such as Kyverno or OPA to enforce restrictions on changes to ESO resources. The specific policies to be enforced depend on the environment. Here are a few suggestions:</p> <ol> <li>(Cluster)SecretStore: Restrict the allowed secret providers, disallowing unused or undesired providers (e.g. Webhook).</li> <li>(Cluster)SecretStore: Restrict the permitted authentication mechanisms (e.g. prevent usage of <code>secretRef</code>).</li> <li>(Cluster)SecretStore: Enforce limitations on modifications to provider-specific fields relevant for security, such as <code>caBundle</code>, <code>caProvider</code>, <code>region</code>, <code>role</code>, <code>url</code>, <code>environmentType</code>, <code>identityId</code>, and <code>others</code>.</li> <li>ClusterSecretStore: Control the usage of <code>namespaceSelector</code>, such as forbidding or mandating the usage of the <code>kube-system</code> namespace.</li> <li>ClusterExternalSecret: Restrict the usage of <code>namespaceSelector</code>.</li> </ol> <p>Please note that ESO does not provide pre-packaged policies, and it is the user's responsibility to implement the necessary security controls.</p>"},{"location":"guides/threat-model/#c04-provider-access-policy","title":"C04: Provider Access Policy","text":"<p>Configure fine-grained access control on the HTTP endpoint of the secret provider to prevent data exfiltration across accounts or organizations. Consult the documentation of your specific provider (e.g.: AWS Secrets Manager VPC Endpoint Policies, GCP Private Service Connect, or Azure Private Link) for guidance on setting up access policies.</p>"},{"location":"guides/threat-model/#c05-entirely-disable-crds","title":"C05: Entirely disable CRDs","text":"<p>You should disable unused CRDs to narrow down your attack surface. Not all users require the use of <code>PushSecret</code>, <code>ClusterSecretStore</code> or <code>ClusterExternalSecret</code> resources.</p>"},{"location":"guides/using-latest-image/","title":"Using Latest Image","text":"<p>You can test a feature that was not yet released using the following methods, use them at your own discretion:</p>"},{"location":"guides/using-latest-image/#helm","title":"Helm","text":"<ol> <li>Create a <code>values.yaml</code> file with the following content: <pre><code>replicaCount: 1\n\nimage:\n repository: ghcr.io/external-secrets/external-secrets\n pullPolicy: IfNotPresent\n # -- The image tag to use. The default is the chart appVersion.\n tag: \"main\"\n\n# -- If set, install and upgrade CRDs through helm chart.\ninstallCRDs: false\n</code></pre></li> <li>Install the crds <pre><code>make crds.install\n</code></pre></li> <li>Install the external-secrets Helm chart indicating the values file created before: <pre><code>helm install external-secrets external-secrets/external-secrets -f values.yaml\n</code></pre></li> </ol>"},{"location":"guides/using-latest-image/#manual","title":"Manual","text":"<ol> <li>Build the Docker image <pre><code>docker build -f Dockerfile.standalone -t my-org/external-secrets:latest .\n</code></pre></li> <li>Apply the <code>bundle.yaml</code> <pre><code>kubectl apply -f deploy/crds/bundle.yaml\n</code></pre></li> <li>Modify your configs to use the image <pre><code>kind: Deployment\nmetadata:\n name: external-secrets|external-secrets-webhook|external-secrets-cert-controller\n...\n image: my-org/external-secrets:latest\n</code></pre></li> </ol>"},{"location":"guides/v1beta1/","title":"Upgrading CRD versions","text":"<p>From version v0.5.0, <code>v1alpha1</code> version is deprecated, and <code>v1beta1</code> is in place. This guide will cover the main differences between the two versions, and a procedure on how to safely upgrade it.</p>"},{"location":"guides/v1beta1/#differences-between-versions","title":"Differences between versions","text":"<p>Versions v1alpha1 and v1beta1 are fully-compatible for SecretStores and ClusterSecretStores. For ExternalSecrets, there is a difference on the <code>dataFrom</code> method.</p> <p>While in v1alpha1, we could define a <code>dataFrom</code> with the following format:</p> <pre><code>spec:\n dataFrom:\n - key: my-key\n - key: my-other-key\n</code></pre> <p>In v1beta1 is possible to use two methods. One of them is <code>Extract</code> and has the exact same behavior as <code>dataFrom</code> in v1alpha1. The other is <code>Find</code>, which allows finding multiple external secrets and map them into a single Kubernetes secret. Here is an example of <code>Find</code>:</p> <pre><code>spec:\n dataFrom:\n - find:\n name: #matches any secret name ending in foo-bar\n regexp: .*foo-bar$\n - find:\n tags: #matches any secrets with the following metadata.\n env: dev \n app: web\n</code></pre>"},{"location":"guides/v1beta1/#upgrading","title":"Upgrading","text":"<p>If you already have an installation of ESO using <code>v1alpha1</code>, we recommend you to upgrade to <code>v1beta1</code>. If you do not use <code>dataFrom</code> in your ExternalSecrets, or if you deploy the CRDs using the official Helm charts, the upgrade can be done with no risk of losing data. </p> <p>If you are installing CRDs manually, you will need to deploy the bundle CRD file available at <code>deploys/crds/bundle.yaml</code>. This bundle file contains <code>v1beta1</code> definition and a conversion webhook configuration. This configuration will ensure that new requests to handle any CRD object will only be valid after the upgrade is successfully complete - so there are no risks of losing data due to an incomplete upgrade. Once the new CRDs are applied, you can proceed to upgrade the controller version.</p> <p>Once the upgrade is finished, at each reconcile, any <code>ExternalSecret</code>, <code>SecretStore</code>, and <code>ClusterSecretStore</code> stored in <code>v1alpha1</code> will be automatically converted to <code>v1beta1</code>. </p>"},{"location":"introduction/deprecation-policy/","title":"Deprecation Policy","text":"<p>We follow the Kubernetes Deprecation Policy and API Versioning Scheme: alpha, beta, GA.</p> <p>The project is currently in <code>beta</code> state. Please try the <code>beta</code> features and provide feedback. After the features exits beta, it may not be practical to make more changes.</p> <ul> <li> <p>alpha</p> <ul> <li>The support for a feature may be dropped at any time without notice.</li> <li>The API may change in incompatible ways in a later software release without notice.</li> <li>The software is recommended for use only in short-lived testing clusters, due to increased risk of bugs and lack of long-term support.</li> </ul> </li> <li> <p>beta</p> <ul> <li>The software is well tested. Enabling a feature is considered safe. Features are enabled by default.</li> <li>The support for a feature will not be dropped, though the details may change.</li> <li>The schema and/or semantics of objects may change in incompatible ways in a subsequent beta or stable release. When this happens, migration instructions are provided. Schema changes may require deleting, editing, and re-creating API objects. The editing process may not be straightforward. The migration may require downtime for applications that rely on the feature.</li> <li>The software is not recommended for production uses. Subsequent releases may introduce incompatible changes. If you have multiple clusters which can be upgraded independently, you may be able to relax this restriction.</li> </ul> </li> <li>GA<ul> <li>The stable versions of features appear in released software for many subsequent versions.</li> <li>Use it in production ;)</li> </ul> </li> </ul>"},{"location":"introduction/deprecation-policy/#api-surface","title":"API Surface","text":"<p>We define the following scope that is covered by our deprecation policy. We follow the 9 Rules of the Kubernetes Deprecation Policy.</p>"},{"location":"introduction/deprecation-policy/#scope","title":"Scope","text":"<ul> <li>API Objects and fields: <code>.Spec</code>, <code>.Status</code> and <code>.Status.Conditions[]</code></li> <li>Enums and constant values</li> <li>Controller Configuration: CLI flags &amp; environment variables</li> <li>Metrics as defined in the Kubernetes docs</li> <li>a feature or specific behavior:<ul> <li><code>ExternalSecret</code> update mechanics</li> </ul> </li> </ul>"},{"location":"introduction/deprecation-policy/#non-scope","title":"Non-Scope","text":"<p>We do not provide stability guarantee for source code imports. The Interfaces and the behavior will change in a unexpected and backwards-incompatible way. However, The maintained helm chart is not part of this deprecation policy.</p>"},{"location":"introduction/faq/","title":"FAQ","text":""},{"location":"introduction/faq/#can-i-manually-trigger-a-secret-refresh","title":"Can I manually trigger a secret refresh?","text":"<p>You can trigger a secret refresh by using kubectl or any other kubernetes api client. You just need to change an annotation, label or the spec of the resource:</p> <pre><code>kubectl annotate es my-es force-sync=$(date +%s) --overwrite\n</code></pre>"},{"location":"introduction/faq/#how-do-i-know-when-my-secret-was-last-synced","title":"How do I know when my secret was last synced?","text":"<p>The last synchronization timestamp of an ExternalSecret can be retrieved from the field <code>refreshTime</code>. </p> <pre><code>kubectl get es my-external-secret -o yaml | grep refreshTime\n refreshTime: \"2022-05-21T23:02:47Z\"\n</code></pre> <p>The interval can be changed by the <code>spec.refreshInterval</code> in the ExternalSecret.</p>"},{"location":"introduction/faq/#how-do-i-know-when-the-status-of-my-secret-changed-the-last-time","title":"How do I know when the status of my secret changed the last time?","text":"<p>Every ExternalSecret resource contains a status condition that indicates whether a secret was successfully synchronized, along with the timestamp of the last status change of the ExternalSecret (e.g. from SecretSyncedError to SecretSynced). This can be obtained from the field <code>lastTransitionTime</code>:</p> <pre><code>kubectl get es my-external-secret -o yaml | grep condition -A 5\n conditions:\n - lastTransitionTime: \"2022-05-21T21:02:47Z\"\n message: Secret was synced\n reason: SecretSynced\n status: \"True\"\n type: Ready\n</code></pre>"},{"location":"introduction/faq/#differences-to-csi-secret-store","title":"Differences to csi-secret-store","text":"<p>Please take a look at this issue comment here.</p>"},{"location":"introduction/faq/#how-do-i-debug-an-external-secret-that-doesnt-sync","title":"How do I debug an external-secret that doesn't sync?","text":"<p>First, check the status of the ExternalSecret resource using <code>kubectl describe</code>. That displays the status conditions as well as recent events. You should expect a status condition with <code>Type=Ready</code>, <code>Status=True</code>. Further you shouldn't see any events with <code>Type=Warning</code>. Read carefully if they exist.</p> <pre><code>kubectl describe es my-external-secret\n[...]\nStatus:\n Conditions:\n Last Transition Time: 2022-05-21T21:02:47Z\n Message: Secret was synced\n Reason: SecretSynced\n Status: True\n Type: Ready\n Refresh Time: 2022-05-21T21:06:47Z\n Synced Resource Version: 1-5c833527afd7ba3f426cb0082ee7e083\nEvents:\n Type Reason Age From Message\n ---- ------ ---- ---- -------\n Warning UpdateFailed 4m12s external-secrets secrets \"yyyyyyy\" already exists\n Normal Updated 12s (x4 over 3m12s) external-secrets Updated Secret\n</code></pre> <p>If everything looks good you should check the corresponding secret store resource that is referenced from an ExternalSecret. Again, use <code>kubectl describe</code> to show status conditions and events and look for warning signs as described above.</p> <p>In an ideally, the store should be validated and Ready.</p> <pre><code>kubectl describe css kubernetes\n[...]\nStatus:\n Conditions:\n Last Transition Time: 2022-05-21T21:02:47Z\n Message: store validated\n Reason: Valid\n Status: True\n Type: Ready\nEvents:\n Type Reason Age From Message\n ---- ------ ---- ---- -------\n Normal Valid 52s (x4 over 10m) cluster-secret-store store validated\n Normal Valid 52s (x4 over 10m) cluster-secret-store store validated\n</code></pre> <p>If everything looks normal so far, please go ahead and ensure that the created secret has the expected value. Also, take a look at the logs of the controller.</p>"},{"location":"introduction/faq/#upgrading-from-kes-to-eso","title":"Upgrading from KES to ESO","text":"<p>Migrating from KES to ESO is quite tricky! There is a tool we built to help users out available here, and there is a small migration procedure.</p> <p>There are some incompatibilities between KES to ESO, and while the tool tries to cover most of them, some of them will require manual intervention. We recommend to first convert the manifest files, and actually see if the tool provides a warning about any file needed to be changed. Beware that the tool points the SecretStores to use KES Service Account, so you'll also need to tweak that if you plan to uninstall KES after the upgrade.</p>"},{"location":"introduction/getting-started/","title":"Getting started","text":"<p>External-secrets runs within your Kubernetes cluster as a deployment resource. It utilizes CustomResourceDefinitions to configure access to secret providers through SecretStore resources and manages Kubernetes secret resources with ExternalSecret resources.</p> <p>Note: The minimum supported version of Kubernetes is <code>1.16.0</code>. Users still running Kubernetes v1.15 or below should upgrade to a supported version before installing external-secrets.</p>"},{"location":"introduction/getting-started/#installing-with-helm","title":"Installing with Helm","text":"<p>The default install options will automatically install and manage the CRDs as part of your helm release. If you do not want the CRDs to be automatically upgraded and managed, you must set the <code>installCRDs</code> option to <code>false</code>. (e.g. <code>--set installCRDs=false</code>)</p> <p>You can install those CRDs outside of <code>helm</code> using: <pre><code>kubectl apply -k \"https://raw.githubusercontent.com/external-secrets/external-secrets/&lt;replace_with_your_version&gt;/deploy/crds/bundle.yaml\"\n</code></pre></p> <p>Uncomment the relevant line in the next steps to disable the automatic install of CRDs.</p>"},{"location":"introduction/getting-started/#option-1-install-from-chart-repository","title":"Option 1: Install from chart repository","text":"<pre><code>helm repo add external-secrets https://charts.external-secrets.io\n\nhelm install external-secrets \\\n external-secrets/external-secrets \\\n -n external-secrets \\\n --create-namespace \\\n # --set installCRDs=false\n</code></pre>"},{"location":"introduction/getting-started/#option-2-install-chart-from-local-build","title":"Option 2: Install chart from local build","text":"<p>Build and install the Helm chart locally after cloning the repository.</p> <pre><code>make helm.build\n\nhelm install external-secrets \\\n ./bin/chart/external-secrets.tgz \\\n -n external-secrets \\\n --create-namespace \\\n # --set installCRDs=false\n</code></pre>"},{"location":"introduction/getting-started/#create-a-secret-containing-your-aws-credentials","title":"Create a secret containing your AWS credentials","text":"<pre><code>echo -n 'KEYID' &gt; ./access-key\necho -n 'SECRETKEY' &gt; ./secret-access-key\nkubectl create secret generic awssm-secret --from-file=./access-key --from-file=./secret-access-key\n</code></pre>"},{"location":"introduction/getting-started/#create-your-first-secretstore","title":"Create your first SecretStore","text":"<p>Create a file 'basic-secret-store.yaml' with the following content.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: secretstore-sample\nspec:\n provider:\n aws:\n service: SecretsManager\n region: us-east-1\n auth:\n secretRef:\n accessKeyIDSecretRef:\n name: awssm-secret\n key: access-key\n secretAccessKeySecretRef:\n name: awssm-secret\n key: secret-access-key\n</code></pre> <p>Apply it to create a SecretStore resource.</p> <pre><code>kubectl apply -f \"basic-secret-store.yaml\"\n</code></pre>"},{"location":"introduction/getting-started/#create-your-first-externalsecret","title":"Create your first ExternalSecret","text":"<p>Create a file 'basic-external-secret.yaml' with the following content.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: secretstore-sample\n kind: SecretStore\n target:\n name: secret-to-be-created\n creationPolicy: Owner\n data:\n - secretKey: secret-key-to-be-managed\n remoteRef:\n key: provider-key\n version: provider-key-version\n property: provider-key-property\n dataFrom:\n - extract:\n key: remote-key-in-the-provider\n</code></pre> <p>Apply it to create an External Secret resource.</p> <pre><code>kubectl apply -f \"basic-external-secret.yaml\"\n</code></pre> <pre><code>kubectl describe externalsecret example\n# [...]\nName: example\nStatus:\n Binding:\n Name: secret-to-be-created\n Conditions:\n Last Transition Time: 2021-02-24T16:45:23Z\n Message: Secret was synced\n Reason: SecretSynced\n Status: True\n Type: Ready\n Refresh Time: 2021-02-24T16:45:24Z\nEvents: &lt;none&gt;\n</code></pre> <p>For more advanced examples, please read the other guides.</p>"},{"location":"introduction/getting-started/#installing-with-olm","title":"Installing with OLM","text":"<p>External-secrets can be managed by Operator Lifecycle Manager (OLM) via an installer operator. It is made available through OperatorHub.io, this installation method is suited best for OpenShift. See installation instructions on the external-secrets-operator package.</p>"},{"location":"introduction/getting-started/#uninstalling","title":"Uninstalling","text":"<p>Before continuing, ensure that all external-secret resources that have been created by users have been deleted. You can check for any existing resources with the following command:</p> <pre><code>kubectl get SecretStores,ClusterSecretStores,ExternalSecrets --all-namespaces\n</code></pre> <p>Once all these resources have been deleted you are ready to uninstall external-secrets.</p>"},{"location":"introduction/getting-started/#uninstalling-with-helm","title":"Uninstalling with Helm","text":"<p>Uninstall the helm release using the delete command.</p> <pre><code>helm delete external-secrets --namespace external-secrets\n</code></pre>"},{"location":"introduction/overview/","title":"API Overview","text":""},{"location":"introduction/overview/#architecture","title":"Architecture","text":"<p>The External Secrets Operator extends Kubernetes with Custom Resources, which define where secrets live and how to synchronize them. The controller fetches secrets from an external API and creates Kubernetes secrets. If the secret from the external API changes, the controller will reconcile the state in the cluster and update the secrets accordingly.</p>"},{"location":"introduction/overview/#resource-model","title":"Resource model","text":"<p>To understand the mechanics of the operator let's start with the data model. The SecretStore references a bucket of key/value pairs. But because every external API is slightly different this bucket may be e.g. an instance of an Azure KeyVault or a AWS Secrets Manager in a certain AWS Account and region. Please take a look at the provider documentation to see what the Bucket actually maps to.</p> <p></p>"},{"location":"introduction/overview/#secretstore","title":"SecretStore","text":"<p>The idea behind the SecretStore resource is to separate concerns of authentication/access and the actual Secret and configuration needed for workloads. The ExternalSecret specifies what to fetch, the SecretStore specifies how to access. This resource is namespaced.</p> <p><pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: secretstore-sample\nspec:\n provider:\n aws:\n service: SecretsManager\n region: us-east-1\n auth:\n secretRef:\n accessKeyIDSecretRef:\n name: awssm-secret\n key: access-key\n secretAccessKeySecretRef:\n name: awssm-secret\n key: secret-access-key\n</code></pre> The <code>SecretStore</code> contains references to secrets which hold credentials to access the external API.</p>"},{"location":"introduction/overview/#externalsecret","title":"ExternalSecret","text":"<p>An ExternalSecret declares what data to fetch. It has a reference to a <code>SecretStore</code> which knows how to access that data. The controller uses that <code>ExternalSecret</code> as a blueprint to create secrets.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: secretstore-sample\n kind: SecretStore\n target:\n name: secret-to-be-created\n creationPolicy: Owner\n data:\n - secretKey: secret-key-to-be-managed\n remoteRef:\n key: provider-key\n version: provider-key-version\n property: provider-key-property\n dataFrom:\n - extract:\n key: remote-key-in-the-provider\n</code></pre>"},{"location":"introduction/overview/#clustersecretstore","title":"ClusterSecretStore","text":"<p>The ClusterSecretStore is a global, cluster-wide SecretStore that can be referenced from all namespaces. You can use it to provide a central gateway to your secret provider.</p>"},{"location":"introduction/overview/#behavior","title":"Behavior","text":"<p>The External Secret Operator (ESO for brevity) reconciles <code>ExternalSecrets</code> in the following manner:</p> <ol> <li>ESO uses <code>spec.secretStoreRef</code> to find an appropriate <code>SecretStore</code>. If it doesn't exist or the <code>spec.controller</code> field doesn't match it won't further process this ExternalSecret.</li> <li>ESO instanciates an external API client using the specified credentials from the <code>SecretStore</code> spec.</li> <li>ESO fetches the secrets as requested by the <code>ExternalSecret</code>, it will decode the secrets if required</li> <li>ESO creates an <code>Kind=Secret</code> based on the template provided by <code>ExternalSecret.target.template</code>. The <code>Secret.data</code> can be templated using the secret values from the external API.</li> <li>ESO ensures that the secret values stay in sync with the external API</li> </ol>"},{"location":"introduction/overview/#roles-and-responsibilities","title":"Roles and responsibilities","text":"<p>The External Secret Operator is designed to target the following persona:</p> <ul> <li>Cluster Operator: The cluster operator is responsible for setting up the External Secret Operator, managing access policies and creating ClusterSecretStores.</li> <li>Application developer: The Application developer is responsible for defining ExternalSecrets and the application configuration</li> </ul> <p>Each persona will roughly map to a Kubernetes RBAC role. Depending on your environment these roles can map to a single user. Note: There is no Secret Operator that handles the lifecycle of the secret, this is out of the scope of ESO.</p>"},{"location":"introduction/overview/#access-control","title":"Access Control","text":"<p>The External Secrets Operator runs as a deployment in your cluster with elevated privileges. It will create/read/update secrets in all namespaces and has access to secrets stored in some external API. Ensure that the credentials you provide give ESO the least privilege necessary.</p> <p>Design your <code>SecretStore</code>/<code>ClusterSecretStore</code> carefully! Be sure to restrict access of application developers to read only certain keys in a shared environment.</p> <p>You should also consider using Kubernetes' admission control system (e.g. OPA or Kyverno) for fine-grained access control.</p>"},{"location":"introduction/overview/#running-multiple-controller","title":"Running multiple Controller","text":"<p>You can run multiple controllers within the cluster. One controller can be limited to only process <code>SecretStores</code> with a predefined <code>spec.controller</code> field.</p> <p>Testers welcome</p> <p>This is not widely tested. Please help us test the setup and/or document use-cases.</p>"},{"location":"introduction/stability-support/","title":"Stability and Support","text":"<p>This page lists the status, timeline and policy for currently supported ESO releases and its providers. Please also see our deprecation policy that describes API versioning, deprecation and API surface.</p>"},{"location":"introduction/stability-support/#supported-versions","title":"Supported Versions","text":"<p>We want to provide security patches and critical bug fixes in a timely manner to our users. To do so, we offer long-term support for our latest two (N, N-1) software releases. We aim for a 2-3 month minor release cycle, i.e. a given release is supported for about 4-6 months.</p> <p>We want to cover the following cases:</p> <ul> <li>regular image rebuilds to update OS dependencies</li> <li>regular go dependency updates</li> <li>backport bug fixes on demand</li> </ul> ESO Version Kubernetes Version Release Date End of Life 0.10.x 1.19 \u2192 1.31 Aug 3, 2024 Release of 0.12 0.9.x 1.19 \u2192 1.30 Jun 22, 2023 Release of 0.11 0.8.x 1.19 \u2192 1.28 Mar 16, 2023 Aug 3, 2024 0.7.x 1.19 \u2192 1.26 Dec 11, 2022 Jun 22, 2023 0.6.x 1.19 \u2192 1.24 Oct 9, 2022 Mar 16, 2023 0.5.x 1.19 \u2192 1.24 Apr 6, 2022 Dec 11, 2022 0.4.x 1.16 \u2192 1.24 Feb 2, 2022 Oct 9, 2022 0.3.x 1.16 \u2192 1.24 Jul 25, 2021 Apr 6, 2022"},{"location":"introduction/stability-support/#provider-stability-and-support-level","title":"Provider Stability and Support Level","text":"<p>The following table describes the stability level of each provider and who's responsible.</p> Provider Stability Maintainer AWS Secrets Manager stable external-secrets AWS Parameter Store stable external-secrets Hashicorp Vault stable external-secrets GCP Secret Manager stable external-secrets Azure Keyvault stable external-secrets IBM Cloud Secrets Manager stable @knelasevero @sebagomez @ricardoptcosta @IdanAdar Kubernetes beta external-secrets Yandex Lockbox alpha @AndreyZamyslov @knelasevero GitLab Variables alpha @Jabray5 Alibaba Cloud KMS alpha @ElsaChelala Oracle Vault alpha @KianTigger @EladGabay Akeyless alpha @renanaAkeyless 1Password alpha @SimSpaceCorp @snarlysodboxer Generic Webhook alpha @willemm senhasegura DevOps Secrets Management (DSM) alpha @lfraga Doppler SecretOps Platform alpha @ryan-blunden @nmanoogian Keeper Security alpha @ppodevlab Scaleway alpha @azert9 Conjur stable @davidh-cyberark @szh Delinea alpha @michaelsauter Beyondtrust alpha @btfhernandez SecretServer alpha @billhamilton Pulumi ESC alpha @dirien Passbolt alpha Infisical alpha @akhilmhdh Device42 alpha Bitwarden Secrets Manager alpha @skarlso Previder stable @previder"},{"location":"introduction/stability-support/#provider-feature-support","title":"Provider Feature Support","text":"<p>The following table show the support for features across different providers.</p> Provider find by name find by tags metadataPolicy Fetch referent authentication store validation push secret DeletionPolicy Merge/Delete AWS Secrets Manager x x x x x x x AWS Parameter Store x x x x x x x Hashicorp Vault x x x x x x x GCP Secret Manager x x x x x x x Azure Keyvault x x x x x x x Kubernetes x x x x x x x IBM Cloud Secrets Manager x x x Yandex Lockbox x GitLab Variables x x x Alibaba Cloud KMS x Oracle Vault x Akeyless x x x 1Password x x x x Generic Webhook x senhasegura DSM x Doppler x x Keeper Security x x x Scaleway x x x x x Conjur x x x Delinea x x Beyondtrust x x SecretServer x x Pulumi ESC x x Passbolt x x Infisical x x x Device42 x Bitwarden Secrets Manager x x x x Previder x x"},{"location":"introduction/stability-support/#support-policy","title":"Support Policy","text":"<p>We provide technical support and security / bug fixes for the above listed versions.</p>"},{"location":"introduction/stability-support/#technical-support","title":"Technical support","text":"<p>We provide assistance for deploying/upgrading etc. on a best-effort basis. You can request support through the following channels:</p> <ul> <li>Kubernetes Slack #external-secrets</li> <li>GitHub Issues</li> <li>GitHub Discussions</li> </ul> <p>Even though we have active maintainers and people assigned to this project, we kindly ask for patience when asking for support. We will try to get to priority issues as fast as possible, but there may be some delays.</p>"},{"location":"provider/1password-automation/","title":"1Password Secrets Automation","text":""},{"location":"provider/1password-automation/#1password-secrets-automation","title":"1Password Secrets Automation","text":"<p>External Secrets Operator integrates with 1Password Secrets Automation for secret management.</p>"},{"location":"provider/1password-automation/#important-note-about-this-documentation","title":"Important note about this documentation","text":"<p>The 1Password API calls the entries in vaults 'Items'. These docs use the same term.</p>"},{"location":"provider/1password-automation/#behavior","title":"Behavior","text":"<ul> <li>How an Item is equated to an ExternalSecret:<ul> <li><code>remoteRef.key</code> is equated to an Item's Title</li> <li><code>remoteRef.property</code> is equated to:<ul> <li>An Item's field's Label (Password type)</li> <li>An Item's file's Name (Document type)</li> <li>If empty, defaults to the first file name, or the field labeled <code>password</code></li> </ul> </li> <li><code>remoteRef.version</code> is currently not supported.</li> <li>One Item in a vault can equate to one Kubernetes Secret to keep things easy to comprehend.</li> </ul> </li> <li>Support for 1Password secret types of <code>Password</code> and <code>Document</code>.<ul> <li>The <code>Password</code> type can get data from multiple <code>fields</code> in the Item.</li> <li>The <code>Document</code> type can get data from files.</li> <li>See creating 1Password Items compatible with ExternalSecrets.</li> </ul> </li> <li>Ordered vaults<ul> <li>Specify an ordered list of vaults in a SecretStore and the value will be sourced from the first vault with a matching Item.</li> <li>If no matching Item is found, an error is returned.</li> <li>This supports having a default or shared set of values that can also be overriden for specific environments.</li> </ul> </li> <li><code>dataFrom</code>:<ul> <li><code>find.path</code> is equated to Item Title.</li> <li><code>find.name.regexp</code> is equated to field Labels.</li> <li><code>find.tags</code> are not supported at this time.</li> </ul> </li> </ul>"},{"location":"provider/1password-automation/#prerequisites","title":"Prerequisites","text":"<ul> <li>1Password requires running a 1Password Connect Server to which the API requests will be made.<ul> <li>External Secrets does not run this server. See Deploy a Connect Server.</li> <li>One Connect Server is needed per 1Password Automation Environment.</li> <li>Many Vaults can be added to an Automation Environment, and Tokens can be generated in that Environment with access to any set or subset of those Vaults.</li> </ul> </li> <li>1Password Connect Server version 1.5.6 or higher.</li> </ul>"},{"location":"provider/1password-automation/#setup-authentication","title":"Setup Authentication","text":"<p>Authentication requires a <code>1password-credentials.json</code> file provided to the Connect Server, and a related 'Access Token' for the client in this provider to authenticate to that Connect Server. Both of these are generated by 1Password.</p> <ol> <li>Setup an Automation Environment at 1Password.com, or via the op CLI.<ul> <li>Note: don't be confused by the <code>op connect server create</code> syntax. This will create an Automation Environment in 1Password, and corresponding credentials for a Connect Server, nothing more.</li> <li>This will result in a <code>1password-credentials.json</code> file to provide to a Connect Server Deployment, and an Access Token to provide as a Secret referenced by a <code>SecretStore</code> or <code>ClusterSecretStore</code>.</li> </ul> </li> <li>Create a Kubernetes secret with the Access Token <pre><code>---\napiVersion: v1\nkind: Secret\nmetadata:\n name: onepassword-connect-token-staging\ntype: Opaque\nstringData:\n token: my-token\n</code></pre></li> <li>Reference the secret in a SecretStore or ClusterSecretStore <pre><code>---\napiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: staging\nspec:\n provider:\n onepassword:\n connectHost: https://onepassword-connect-staging\n vaults:\n staging: 1 # look in this vault first\n shared: 2 # next look in here. error if not found\n auth:\n secretRef:\n connectTokenSecretRef:\n name: onepassword-connect-token-staging\n key: token\n</code></pre></li> <li>Create a Kubernetes secret with the Connect Server credentials <pre><code>---\napiVersion: v1\nkind: Secret\nmetadata:\n name: connect-server-credentials\ntype: Opaque\nstringData:\n # NOTE: This secret value must be base64 encoded after it becomes the OP_SESSION env var in the Connect Server Deployment, that means double base64 encoded here. (Or single w/ stringData.)\n 1password-credentials.json: |-\n eyJ2ZXJpZmllciI6eyJzYWx0IjoiZXhhbXBsZSIsImxvY2FsSGFzaCI6ImV4YW1wbGUifSwiZW5jQ3JlZGVudGlhbHMiOnsia2lkIjoiZXhhbXBsZSIsImVuYyI6ImV4YW1wbGUiLCJjdHkiOiJleGFtcGxlIiwiaXYiOiJleGFtcGxlIiwiZGF0YSI6ImV4YW1wbGUifSwidmVyc2lvbiI6IjIiLCJkZXZpY2VVdWlkIjoiZXhhbXBsZSIsInVuaXF1ZUtleSI6eyJhbGciOiJleGFtcGxlIiwiZXh0Ijp0cnVlLCJrIjoiZXhhbXBsZSIsImtleV9vcHMiOlsiZW5jcnlwdCIsImRlY3J5cHQiXSwia3R5Ijoib2N0Iiwia2lkIjoiZXhhbXBsZSJ9fQ==\n</code></pre></li> <li>Reference the secret in a Connect Server Deployment <pre><code>---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: onepassword-connect-staging\nspec:\n template:\n spec:\n containers:\n - name: connect-api\n image: 1password/connect-api:1.5.0\n env:\n - name: OP_SESSION\n valueFrom:\n secretKeyRef:\n name: connect-server-credentials\n key: 1password-credentials.json\n ...\n - name: connect-sync\n image: 1password/connect-sync:1.5.0\n env:\n - name: OP_SESSION\n valueFrom:\n secretKeyRef:\n name: connect-server-credentials\n key: 1password-credentials.json\n ...\n ...\n</code></pre></li> </ol>"},{"location":"provider/1password-automation/#deploy-a-connect-server","title":"Deploy a Connect Server","text":"<ul> <li>Follow the remaining instructions in the Quick Start guide.<ul> <li>Deploy at minimum a Deployment and Service for a Connect Server, to go along with the Secret for the Server created in the Setup Authentication section.</li> </ul> </li> <li>The Service's name will be referenced in SecretStores/ClusterSecretStores.</li> <li>Keep in mind the likely need for additional Connect Servers for other Automation Environments when naming objects. For example dev, staging, prod, etc.</li> <li>Unencrypted secret values are passed over the connection between the Operator and the Connect Server. Encrypting the connection is recommended.</li> </ul>"},{"location":"provider/1password-automation/#creating-compatible-1password-items","title":"Creating Compatible 1Password Items","text":"<p>Also see examples below for matching SecretStore and ExternalSecret specs.</p>"},{"location":"provider/1password-automation/#manually-password-type","title":"Manually (Password type)","text":"<ol> <li>Click the plus button to create a new Password type Item.</li> <li>Change the title to what you want <code>remoteRef.key</code> to be.</li> <li>Set what you want <code>remoteRef.property</code> to be in the field sections where is says 'label', and values where it says 'new field'.</li> <li>Click the 'Save' button.</li> </ol>"},{"location":"provider/1password-automation/#manually-document-type","title":"Manually (Document type)","text":"<ul> <li>Click the plus button to create a new Document type Item.</li> <li>Choose the file to upload and upload it.</li> <li>Change the title to match <code>remoteRef.key</code></li> <li>Click the 'Add New File' button to add more files.</li> <li>Click the 'Save' button.</li> </ul>"},{"location":"provider/1password-automation/#scripting-password-type-with-op-cli","title":"Scripting (Password type with op CLI)","text":"<ul> <li>Create <code>file.json</code> with the following contents, swapping in your keys and values. Note: <code>section.name</code>'s and <code>section.title</code>'s values are ignored by the Operator, but cannot be empty for the <code>op</code> CLI <pre><code> {\n \"title\": \"my-title\",\n \"vault\": {\n \"id\": \"vault-id\"\n },\n \"category\": \"LOGIN\",\n \"fields\": [\n {\n \"id\": \"username\",\n \"type\": \"STRING\",\n \"purpose\": \"USERNAME\",\n \"label\": \"username\",\n \"value\": \"a-username\"\n },\n {\n \"id\": \"password\",\n \"type\": \"CONCEALED\",\n \"purpose\": \"PASSWORD\",\n \"label\": \"password\",\n \"password_details\": {\n \"strength\": \"TERRIBLE\"\n },\n \"value\": \"a-password\"\n },\n {\n \"id\": \"notesPlain\",\n \"type\": \"STRING\",\n \"purpose\": \"NOTES\",\n \"label\": \"notesPlain\",\n \"value\": \"notesPlain\"\n },\n {\n \"id\": \"customField\",\n \"type\": \"CONCEALED\",\n \"purpose\": \"custom\",\n \"label\": \"custom\",\n \"value\": \"custom-value\"\n }\n ]\n }\n</code></pre></li> <li>Run <code>op item create --template file.json</code></li> </ul>"},{"location":"provider/1password-automation/#scripting-document-type","title":"Scripting (Document type)","text":"<ul> <li>Unfortunately the <code>op</code> CLI doesn't seem to support uploading multiple files to the same Item, and the current Go lib has a bug. <code>op</code> can be used to create a Document type Item with one file in it, but for now it's necessary to add multiple files to the same Document via the GUI.</li> </ul>"},{"location":"provider/1password-automation/#in-built-field-labeled-password-on-password-type-items","title":"In-built field labeled <code>password</code> on Password type Items","text":"<ul> <li>TL;DR if you need a field labeled <code>password</code>, use the in-built one rather than the one in a fields Section.</li> </ul> <ul> <li>1Password automatically adds a field labeled <code>password</code> on every Password type Item, whether it's created through a GUI or the API or <code>op</code> CLI.</li> <li>There's no problem with using this field just like any other field, just make sure you don't end up with two fields with the same label. (For example, by automating the <code>op</code> CLI to create Items.)</li> <li>The in-built <code>password</code> field is not otherwise special for the purposes of ExternalSecrets. It can be ignored when not in use.</li> </ul>"},{"location":"provider/1password-automation/#examples","title":"Examples","text":"<p>Examples of using the <code>my-env-config</code> and <code>my-cert</code> Items seen above.</p> <ul> <li>Note: with this configuration a 1Password Item titled <code>my-env-config</code> is correlated to a ExternalSecret named <code>my-env-config</code> that results in a Kubernetes secret named <code>my-env-config</code>, all with matching names for the key/value pairs. This is a way to increase comprehensibility. <pre><code>---\napiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: staging\nspec:\n provider:\n onepassword:\n connectHost: https://onepassword-connect-staging\n vaults:\n staging: 1 # look in this vault first\n shared: 2 # next look in here. error if not found\n auth:\n secretRef:\n connectTokenSecretRef:\n name: onepassword-connect-token-staging\n key: token\n</code></pre> <pre><code>---\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: my-env-config\nspec:\n secretStoreRef:\n kind: SecretStore\n name: staging\n target:\n creationPolicy: Owner\n data:\n - secretKey: MY_ENV_VAR1\n remoteRef:\n key: my-env-config\n property: MY_ENV_VAR1\n - secretKey: MY_ENV_VAR2\n remoteRef:\n key: my-env-config\n property: MY_ENV_VAR2\n # OR\n dataFrom:\n - extract:\n key: my-env-config\n property: MY_ENV_VAR1 # optional field Label to match exactly\n # OR\n - find:\n path: my-env-config # optional Item Title to match exactly\n name:\n regexp: \"^MY_ENV_VAR.*\"\n</code></pre> <pre><code>---\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: my-cert\nspec:\n secretStoreRef:\n kind: SecretStore\n name: staging\n target:\n creationPolicy: Owner\n data:\n - secretKey: cert.crt\n remoteRef:\n key: my-cert\n property: cert.crt\n - secretKey: cert.key\n remoteRef:\n key: my-cert\n property: cert.key\n # OR\n dataFrom:\n - extract:\n key: my-cert\n property: cert.key # optional field Label to match exactly\n # OR\n - find:\n path: my-cert # optional Item Title to match exactly\n name:\n regexp: \"^cert.*\"\n</code></pre></li> </ul>"},{"location":"provider/1password-automation/#additional-notes","title":"Additional Notes","text":""},{"location":"provider/1password-automation/#general","title":"General","text":"<ul> <li>It's intuitive to use Document type Items for Kubernetes secrets mounted as files, and Password type Items for ones that will be mounted as environment variables, but either can be used for either. It comes down to what's more convenient.</li> </ul>"},{"location":"provider/1password-automation/#why-no-version-history","title":"Why no version history","text":"<ul> <li>1Password only supports version history on their in-built <code>password</code> field. Therefore, implementing version history in this provider would require one Item in 1Password per <code>remoteRef</code> in an ExternalSecret. Additionally <code>remoteRef.property</code> would be pointless/unusable.</li> <li>For example, a Kubernetes secret with 15 keys (say, used in <code>envFrom</code>,) would require 15 Items in the 1Password vault, instead of 15 Fields in 1 Item. This would quickly get untenable for more than a few secrets, because:<ul> <li>All Items would have to have unique names which means <code>secretKey</code> couldn't match the Item name the <code>remoteRef</code> is targeting.</li> <li>Maintenance, particularly clean up of no longer used secrets, would be significantly more work.</li> <li>A vault would often become a huge list of unorganized entries as opposed to a much smaller list organized by Kubernetes Secret.</li> </ul> </li> <li>To support new and old versions of a secret value at the same time, create a new Item in 1Password with the new value, and point some ExternalSecrets at a time to the new Item.</li> </ul>"},{"location":"provider/1password-automation/#keeping-misconfiguration-from-working","title":"Keeping misconfiguration from working","text":"<ul> <li>One instance of the ExternalSecrets Operator can work with many Connect Server instances, but it may not be the best approach.</li> <li>With one Operator instance per Connect Server instance, namespaces and RBAC can be used to improve security posture, and perhaps just as importantly, it's harder to misconfigure something and have it work (supply env A's secret values to env B for example.)</li> <li>You can run as many 1Password Connect Servers as you need security boundaries to help protect against accidental misconfiguration.</li> </ul>"},{"location":"provider/1password-automation/#patching-externalsecrets-with-kustomize","title":"Patching ExternalSecrets with Kustomize","text":"<ul> <li>An overlay can provide a SecretStore specific to that overlay, and then use JSON6902 to patch all the ExternalSecrets coming from base to point to that SecretStore. Here's an example <code>overlays/staging/kustomization.yaml</code>: <pre><code>---\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\n\nresources:\n- ../../base/something-with-external-secrets\n- secretStore.staging.yaml\n\npatchesJson6902:\n- target:\n kind: ExternalSecret\n name: \".*\"\n patch: |-\n - op: replace\n path: /spec/secretStoreRef/name\n value: staging\n</code></pre></li> </ul>"},{"location":"provider/akeyless/","title":"Akeyless","text":""},{"location":"provider/akeyless/#akeyless-secrets-management-platform","title":"Akeyless Secrets Management Platform","text":"<p>External Secrets Operator integrates with the Akeyless Secrets Management Platform.</p>"},{"location":"provider/akeyless/#create-secret-store","title":"Create Secret Store","text":"<p>SecretStore resource specifies how to access Akeyless. This resource is namespaced.</p> <p>NOTE: Make sure the Akeyless provider is listed in the Kind=SecretStore. If you use a customer fragment, define the value of akeylessGWApiURL as the URL of your Akeyless Gateway in the following format: https://your.akeyless.gw:8080/v2.</p> <p>Akeyelss provide several Authentication Methods:</p>"},{"location":"provider/akeyless/#authentication-with-kubernetes","title":"Authentication with Kubernetes","text":"<p>Options for obtaining Kubernetes credentials include:</p> <ol> <li>Using a service account jwt referenced in serviceAccountRef</li> <li>Using the jwt from a Kind=Secret referenced by the secretRef</li> <li>Using transient credentials from the mounted service account token within the external-secrets operator</li> </ol>"},{"location":"provider/akeyless/#create-the-akeyless-secret-store-provider-with-kubernetes-auth-method","title":"Create the Akeyless Secret Store Provider with Kubernetes Auth-Method","text":"<pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: akeyless-secret-store\nspec:\n provider:\n akeyless:\n # URL of your akeyless API\n akeylessGWApiURL: \"https://api.akeyless.io\"\n authSecretRef:\n kubernetesAuth:\n accessID: \"p-XXXXXX\"\n k8sConfName: \"my-conf-name\"\n\n # Optional service account field containing the name\n # of a kubernetes ServiceAccount\n serviceAccountRef:\n name: \"my-sa\"\n\n # Optional secret field containing a Kubernetes ServiceAccount JWT\n # used for authenticating with Akeyless\n secretRef:\n name: \"my-secret\"\n key: \"token\"\n</code></pre> <p>NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> for <code>serviceAccountRef</code> and <code>secretRef</code> according to the namespaces where the secrets reside.</p>"},{"location":"provider/akeyless/#authentication-with-cloud-identity-or-api-access-key","title":"Authentication With Cloud-Identity or Api-Access-Key","text":"<p>Akeyless providers require an access-id, access-type and access-Type-param To set your SecretStore with an authentication method from Akeyless.</p> <p>The supported auth-methods and their parameters are:</p> accessType accessTypeParam <code>aws_iam</code> - <code>gcp</code> The gcp audience <code>azure_ad</code> azure object id (optional) <code>api_key</code> The access key. <code>k8s</code> The k8s configuration name <p>For more information see Akeyless Authentication Methods</p>"},{"location":"provider/akeyless/#creating-an-akeyless-credentials-secret","title":"Creating an Akeyless Credentials Secret","text":"<p>Create a secret containing your credentials using the following example as a guide:</p> <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: akeyless-secret-creds\ntype: Opaque\nstringData:\n accessId: \"p-XXXX\"\n accessType: # gcp/azure_ad/api_key/k8s/aws_iam\n accessTypeParam: # optional: can be one of the following: gcp-audience/azure-obj-id/access-key/k8s-conf-name\n</code></pre>"},{"location":"provider/akeyless/#create-the-akeyless-secret-store-provider-with-the-credentials-secret","title":"Create the Akeyless Secret Store Provider with the Credentials Secret","text":"<pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: akeyless-secret-store\nspec:\n provider:\n akeyless:\n # URL of your akeyless API\n akeylessGWApiURL: \"https://api.akeyless.io\"\n authSecretRef:\n secretRef:\n accessID:\n name: akeyless-secret-creds\n key: accessId\n accessType:\n name: akeyless-secret-creds\n key: accessType\n accessTypeParam:\n name: akeyless-secret-creds\n key: accessTypeParam\n</code></pre> <p>NOTE: In case of a <code>ClusterSecretStore</code>, be sure to provide <code>namespace</code> for <code>accessID</code>, <code>accessType</code> and <code>accessTypeParam</code> according to the namespaces where the secrets reside.</p>"},{"location":"provider/akeyless/#create-the-akeyless-secret-store-with-cas-for-tls-handshake","title":"Create the Akeyless Secret Store With CAs for TLS handshake","text":"<pre><code>....\nspec:\n provider:\n akeyless:\n akeylessGWApiURL: \"https://your.akeyless.gw:8080/v2\"\n\n # Optional caBundle - PEM/base64 encoded CA certificate\n caBundle: \"&lt;base64 encoded cabundle&gt;\"\n # Optional caProvider:\n # Instead of caBundle you can also specify a caProvider\n # this will retrieve the cert from a Secret or ConfigMap\n caProvider:\n type: \"Secret/ConfigMap\" # Can be Secret or ConfigMap\n name: \"&lt;name of secret or configmap&gt;\"\n key: \"&lt;key inside secret&gt;\"\n # namespace is mandatory for ClusterSecretStore and not relevant for SecretStore\n namespace: \"my-cert-secret-namespace\"\n ....\n</code></pre>"},{"location":"provider/akeyless/#creating-an-external-secret","title":"Creating an external secret","text":"<p>To get a secret from Akeyless and create it as a secret on the Kubernetes cluster, a <code>Kind=ExternalSecret</code> is needed.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: database-credentials\nspec:\n refreshInterval: 1h\n\n secretStoreRef:\n kind: SecretStore\n name: akeyless-secret-store # Must match SecretStore on the cluster\n\n target:\n name: database-credentials # Name for the secret to be created on the cluster\n creationPolicy: Owner\n\n data:\n - secretKey: username # Key given to the secret to be created on the cluster\n remoteRef:\n key: db-username # Full path of the secret on Akeyless\n - secretKey: password # Key given to the secret to be created on the cluster\n remoteRef:\n key: db-password # Full path of the secret on Akeyless\n</code></pre>"},{"location":"provider/akeyless/#using-datafrom","title":"Using DataFrom","text":"<p>DataFrom can be used to get a secret as a JSON string and attempt to parse it.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: database-credentials\nspec:\n refreshInterval: 1h\n\n secretStoreRef:\n kind: SecretStore\n name: akeyless-secret-store # Must match SecretStore on the cluster\n\n target:\n name: database-credentials-json # Name for the secret to be created on the cluster\n creationPolicy: Owner\n\n # for json formatted secrets: each key in the json will be used as the secret key in the SECRET k8s target object\n dataFrom:\n - extract:\n key: database-credentials # Full path of the secret on Akeyless\n</code></pre>"},{"location":"provider/akeyless/#getting-the-kubernetes-secret","title":"Getting the Kubernetes Secret","text":"<p>The operator will fetch the secret and inject it as a <code>Kind=Secret</code>.</p> <pre><code>kubectl get secret database-credentials -o jsonpath='{.data.db-password}' | base64 -d\n</code></pre> <pre><code>kubectl get secret database-credentials-json -o jsonpath='{.data}'\n</code></pre>"},{"location":"provider/akeyless/#pushing-a-secret","title":"Pushing a secret","text":"<p>To push a secret from Kubernetes cluster and create it as a secret to Akeyless, a <code>Kind=PushSecret</code> resource is needed.</p> <p>apiVersion: external-secrets.io/v1alpha1 kind: PushSecret metadata: name: push-secret spec: refreshInterval: 5s updatePolicy: Replace deletionPolicy: Delete secretStoreRefs: - name: akeyless-secret-store kind: SecretStore selector: secret: name: k8s-created-secret data: - match: remoteRef: remoteKey: eso-created/my-secret</p> <p>Then when you create a matching secret as follows:</p> <pre><code>kubectl create secret generic --from-literal=cache-pass=mypassword k8s-created-secret\n</code></pre> <p>Then it will create a secret in akeyless <code>eso-created/my-secret</code> with value <code>{\"cache-pass\":\"mypassword\"}</code></p>"},{"location":"provider/alibaba/","title":"Alibaba Cloud","text":""},{"location":"provider/alibaba/#alibaba-cloud-secrets-manager","title":"Alibaba Cloud Secrets Manager","text":"<p>External Secrets Operator integrates with Alibaba Cloud Key Management Service for secrets and Keys management.</p>"},{"location":"provider/alibaba/#authentication","title":"Authentication","text":"<p>We support Access key and RRSA authentication.</p> <p>To use RRSA authentication, you should follow Use RRSA to authorize pods to access different cloud services to assign the RAM role to external-secrets operator.</p>"},{"location":"provider/alibaba/#access-key-authentication","title":"Access Key authentication","text":"<p>To use <code>accessKeyID</code> and <code>accessKeySecrets</code>, simply create them as a regular <code>Kind: Secret</code> beforehand and associate it with the <code>SecretStore</code>:</p> <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: secret-sample\ndata:\n accessKeyID: bXlhd2Vzb21lYWNjZXNza2V5aWQ=\n accessKeySecret: bXlhd2Vzb21lYWNjZXNza2V5c2VjcmV0\n</code></pre> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: secretstore-sample\nspec:\n provider:\n alibaba:\n regionID: ap-southeast-1\n auth:\n secretRef:\n accessKeyIDSecretRef:\n name: secret-sample\n key: accessKeyID\n accessKeySecretSecretRef:\n name: secret-sample\n key: accessKeySecret\n</code></pre>"},{"location":"provider/alibaba/#rrsa-authentication","title":"RRSA authentication","text":"<p>When using RRSA authentication we manually project the OIDC token file to pod as volume</p> <pre><code>extraVolumes:\n - name: oidc-token\n projected:\n sources:\n - serviceAccountToken:\n path: oidc-token\n expirationSeconds: 7200 # The validity period of the OIDC token in seconds.\n audience: \"sts.aliyuncs.com\"\n\nextraVolumeMounts:\n - name: oidc-token\n mountPath: /var/run/secrets/tokens\n</code></pre> <p>and provide the RAM role ARN and OIDC volume path to the secret store <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: secretstore-sample\nspec:\n provider:\n alibaba:\n regionID: ap-southeast-1\n auth:\n rrsa:\n oidcProviderArn: acs:ram::1234:oidc-provider/ack-rrsa-ce123456\n oidcTokenFilePath: /var/run/secrets/tokens/oidc-token\n roleArn: acs:ram::1234:role/test-role\n sessionName: secrets\n</code></pre></p>"},{"location":"provider/alibaba/#creating-external-secret","title":"Creating external secret","text":"<p>To create a kubernetes secret from the Alibaba Cloud Key Management Service secret a <code>Kind=ExternalSecret</code> is needed.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: secretstore-sample\n kind: SecretStore\n target:\n name: example-secret\n creationPolicy: Owner\n data:\n - secretKey: secret-key\n remoteRef:\n key: ext-secret\n</code></pre>"},{"location":"provider/aws-parameter-store/","title":"AWS Parameter Store","text":""},{"location":"provider/aws-parameter-store/#parameter-store","title":"Parameter Store","text":"<p>A <code>ParameterStore</code> points to AWS SSM Parameter Store in a certain account within a defined region. You should define Roles that define fine-grained access to individual secrets and pass them to ESO using <code>spec.provider.aws.role</code>. This way users of the <code>SecretStore</code> can only access the secrets necessary.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: parameterstore\nspec:\n provider:\n aws:\n service: ParameterStore\n # define a specific role to limit access\n # to certain secrets\n role: arn:aws:iam::123456789012:role/external-secrets\n region: eu-central-1\n auth:\n secretRef:\n accessKeyIDSecretRef:\n name: awssm-secret\n key: access-key\n secretAccessKeySecretRef:\n name: awssm-secret\n key: secret-access-key\n</code></pre> <p>NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>accessKeyIDSecretRef</code> and <code>secretAccessKeySecretRef</code> with the namespaces where the secrets reside.</p> <p>API Pricing &amp; Throttling</p> <p>The SSM Parameter Store API is charged by throughput and is available in different tiers, see pricing. Please estimate your costs before using ESO. Cost depends on the RefreshInterval of your ExternalSecrets.</p>"},{"location":"provider/aws-parameter-store/#iam-policy","title":"IAM Policy","text":""},{"location":"provider/aws-parameter-store/#fetching-parameters","title":"Fetching Parameters","text":"<p>The example policy below shows the minimum required permissions for fetching SSM parameters. This policy permits pinning down access to secrets with a path matching <code>dev-*</code>. Other operations may require additional permission. For example, finding parameters based on tags will also require <code>ssm:DescribeParameters</code> and <code>tag:GetResources</code> permission with <code>\"Resource\": \"*\"</code>. Generally, the specific permission required will be logged as an error if an operation fails.</p> <p>For further information see AWS Documentation.</p> <pre><code>{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"ssm:GetParameter*\",\n ],\n \"Resource\": \"arn:aws:ssm:us-east-2:1234567889911:parameter/dev-*\"\n }\n ]\n}\n</code></pre>"},{"location":"provider/aws-parameter-store/#pushing-parameters","title":"Pushing Parameters","text":"<p>The example policy below shows the minimum required permissions for pushing SSM parameters. Like with the fetching policy it restricts the path in which it can push secrets too.</p> <pre><code>{\n \"Action\": [\n \"ssm:GetParameter*\",\n \"ssm:PutParameter*\",\n \"ssm:AddTagsToResource\",\n \"ssm:ListTagsForResource\"\n ],\n \"Effect\": \"Allow\",\n \"Resource\": \"arn:aws:ssm:us-east-2:1234567889911:parameter/dev-*\"\n}\n</code></pre>"},{"location":"provider/aws-parameter-store/#json-secret-values","title":"JSON Secret Values","text":"<p>You can store JSON objects in a parameter. You can access nested values or arrays using gjson syntax:</p> <p>Consider the following JSON object that is stored in the Parameter Store key <code>friendslist</code>:</p> <pre><code>{\n \"name\": {\"first\": \"Tom\", \"last\": \"Anderson\"},\n \"friends\": [\n {\"first\": \"Dale\", \"last\": \"Murphy\"},\n {\"first\": \"Roger\", \"last\": \"Craig\"},\n {\"first\": \"Jane\", \"last\": \"Murphy\"}\n ]\n}\n</code></pre> <p>This is an example on how you would look up nested keys in the above json object:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: extract-data\nspec:\n # [omitted for brevity]\n data:\n - secretKey: my_name\n remoteRef:\n key: friendslist\n property: name.first # Tom\n - secretKey: first_friend\n remoteRef:\n key: friendslist\n property: friends.1.first # Roger\n\n # metadataPolicy to fetch all the tags in JSON format\n - secretKey: tags\n remoteRef:\n metadataPolicy: Fetch\n key: database-credentials\n\n # metadataPolicy to fetch a specific tag (dev) from the source secret\n - secretKey: developer\n remoteRef:\n metadataPolicy: Fetch\n key: database-credentials\n property: dev\n</code></pre>"},{"location":"provider/aws-parameter-store/#parameter-versions","title":"Parameter Versions","text":"<p>ParameterStore creates a new version of a parameter every time it is updated with a new value. The parameter can be referenced via the <code>version</code> property</p>"},{"location":"provider/aws-parameter-store/#setsecret","title":"SetSecret","text":"<p>The SetSecret method for the Parameter Store allows the user to set the value stored within the Kubernetes cluster to the remote AWS Parameter Store.</p>"},{"location":"provider/aws-parameter-store/#creating-a-push-secret","title":"Creating a Push Secret","text":"<pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: pushsecret-example # Customisable\n namespace: default # Same of the SecretStores\nspec:\n updatePolicy: Replace # Policy to overwrite existing secrets in the provider on sync\n deletionPolicy: Delete # the provider' secret will be deleted if the PushSecret is deleted\n refreshInterval: 10s # Refresh interval for which push secret will reconcile\n secretStoreRefs: # A list of secret stores to push secrets to\n - name: aws-parameterstore\n kind: SecretStore\n selector:\n secret:\n name: pokedex-credentials # Source Kubernetes secret to be pushed\n # Alternatively, you can point to a generator that produces values to be pushed\n generatorRef:\n apiVersion: external-secrets.io/v1alpha1\n kind: ECRAuthorizationToken\n name: prod-registry-credentials\n template:\n metadata:\n annotations: { }\n labels: { }\n data:\n best-pokemon: \"{{ .best-pokemon | toString | upper }} is the really best!\"\n # Uses an existing template from configmap\n # Secret is fetched, merged and templated within the referenced configMap data\n # It does not update the configmap, it creates a secret with: data[\"alertmanager.yml\"] = ...result...\n templateFrom:\n - configMap:\n name: application-config-tmpl\n items:\n - key: config.yml\n data:\n - conversionStrategy: None # Also supports the ReverseUnicode strategy\n match:\n secretKey: best-pokemon # Source Kubernetes secret key to be pushed\n remoteRef:\n remoteKey: my-first-parameter # Remote reference (where the secret is going to be pushed)\n</code></pre>"},{"location":"provider/aws-parameter-store/#additional-metadata-for-pushsecret","title":"Additional Metadata for PushSecret","text":"<p>Optionally, it is possible to configure additional options for the parameter such as <code>Type</code> and encryption Key. To control this behaviour you can set the following provider's <code>metadata</code>:</p> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: pushsecret-example # Customisable\n namespace: default # Same of the SecretStores\nspec:\n deletionPolicy: Delete # the provider' secret will be deleted if the PushSecret is deleted\n refreshInterval: 10s # Refresh interval for which push secret will reconcile\n secretStoreRefs: # A list of secret stores to push secrets to\n - name: aws-parameterstore\n kind: SecretStore\n selector:\n secret:\n name: pokedex-credentials # Source Kubernetes secret to be pushed\n data:\n - match:\n remoteRef:\n remoteKey: my-first-parameter # Remote reference (where the secret is going to be pushed)\n metadata:\n parameterStoreType: \"SecureString\"\n parameterStoreKeyID: \"bb123123-b2b0-4f60-ac3a-44a13f0e6b6c\"\n</code></pre> <p><code>parameterStoreType</code> takes three options. <code>String</code>, <code>StringList</code>, and <code>SecureString</code>, where <code>String</code> is the default.</p> <p><code>parameterStoreKeyID</code> takes a KMS Key <code>$ID</code> or <code>$ARN</code> (in case a key source is created in another account) as a string, where <code>alias/aws/ssm</code> is the default. This property is only used if <code>parameterStoreType</code> is set as <code>SecureString</code>.</p>"},{"location":"provider/aws-parameter-store/#check-successful-secret-sync","title":"Check successful secret sync","text":"<p>To be able to check that the secret has been succesfully synced you can run the following command:</p> <pre><code>kubectl get pushsecret pushsecret-example\n</code></pre> <p>If the secret has synced successfully it will show the status as \"Synced\".</p>"},{"location":"provider/aws-parameter-store/#test-new-secret-using-aws-cli","title":"Test new secret using AWS CLI","text":"<p>To View your parameter on AWS Parameter Store using the AWS CLI, install and login to the AWS CLI using the following guide: AWS CLI.</p> <p>Run the following commands to get your synchronized parameter from AWS Parameter Store:</p> <pre><code>aws ssm get-parameter --name=my-first-parameter --region=us-east-1\n</code></pre> <p>You should see something similar to the following output:</p> <pre><code>{\n \"Parameter\": {\n \"Name\": \"my-first-parameter\",\n \"Type\": \"String\",\n \"Value\": \"charmander\",\n \"Version\": 4,\n \"LastModifiedDate\": \"2022-09-15T13:04:31.098000-03:00\",\n \"ARN\": \"arn:aws:ssm:us-east-1:1234567890123:parameter/my-first-parameter\",\n \"DataType\": \"text\"\n }\n}\n</code></pre>"},{"location":"provider/aws-parameter-store/#aws-authentication","title":"AWS Authentication","text":""},{"location":"provider/aws-parameter-store/#controllers-pod-identity","title":"Controller's Pod Identity","text":"<p>Note: If you are using Parameter Store replace <code>service: SecretsManager</code> with <code>service: ParameterStore</code> in all examples below.</p> <p>This is basicially a zero-configuration authentication method that inherits the credentials from the runtime environment using the aws sdk default credential chain.</p> <p>You can attach a role to the pod using IRSA, kiam or kube2iam. When no other authentication method is configured in the <code>Kind=Secretstore</code> this role is used to make all API calls against AWS Secrets Manager or SSM Parameter Store.</p> <p>Based on the Pod's identity you can do a <code>sts:assumeRole</code> before fetching the secrets to limit access to certain keys in your provider. This is optional.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: team-b-store\nspec:\n provider:\n aws:\n service: SecretsManager\n region: eu-central-1\n # optional: do a sts:assumeRole before fetching secrets\n role: team-b\n</code></pre>"},{"location":"provider/aws-parameter-store/#access-key-id-secret-access-key","title":"Access Key ID &amp; Secret Access Key","text":"<p>You can store Access Key ID &amp; Secret Access Key in a <code>Kind=Secret</code> and reference it from a SecretStore.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: team-b-store\nspec:\n provider:\n aws:\n service: SecretsManager\n region: eu-central-1\n # optional: assume role before fetching secrets\n role: team-b\n auth:\n secretRef:\n accessKeyIDSecretRef:\n name: awssm-secret\n key: access-key\n secretAccessKeySecretRef:\n name: awssm-secret\n key: secret-access-key\n</code></pre> <p>NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>accessKeyIDSecretRef</code>, <code>secretAccessKeySecretRef</code> with the namespaces where the secrets reside.</p>"},{"location":"provider/aws-parameter-store/#eks-service-account-credentials","title":"EKS Service Account credentials","text":"<p>This feature lets you use short-lived service account tokens to authenticate with AWS. You must have Service Account Volume Projection enabled - it is by default on EKS. See EKS guide on how to set up IAM roles for service accounts.</p> <p>The big advantage of this approach is that ESO runs without any credentials.</p> <pre><code>apiVersion: v1\nkind: ServiceAccount\nmetadata:\n annotations:\n eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/team-a\n name: my-serviceaccount\n namespace: default\n</code></pre> <p>Reference the service account from above in the Secret Store:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: secretstore-sample\nspec:\n provider:\n aws:\n service: SecretsManager\n region: eu-central-1\n auth:\n jwt:\n serviceAccountRef:\n name: my-serviceaccount\n</code></pre> <p>NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> for <code>serviceAccountRef</code> with the namespace where the service account resides.</p>"},{"location":"provider/aws-parameter-store/#custom-endpoints","title":"Custom Endpoints","text":"<p>You can define custom AWS endpoints if you want to use regional, vpc or custom endpoints. See List of endpoints for Secrets Manager, Secure Systems Manager and Security Token Service.</p> <p>Use the following environment variables to point the controller to your custom endpoints. Note: All resources managed by this controller are affected.</p> ENV VAR DESCRIPTION AWS_SECRETSMANAGER_ENDPOINT Endpoint for the Secrets Manager Service. The controller uses this endpoint to fetch secrets from AWS Secrets Manager. AWS_SSM_ENDPOINT Endpoint for the AWS Secure Systems Manager. The controller uses this endpoint to fetch secrets from SSM Parameter Store. AWS_STS_ENDPOINT Endpoint for the Security Token Service. The controller uses this endpoint when creating a session and when doing <code>assumeRole</code> or <code>assumeRoleWithWebIdentity</code> calls."},{"location":"provider/aws-secrets-manager/","title":"AWS Secrets Manager","text":""},{"location":"provider/aws-secrets-manager/#secrets-manager","title":"Secrets Manager","text":"<p>A <code>SecretStore</code> points to AWS Secrets Manager in a certain account within a defined region. You should define Roles that define fine-grained access to individual secrets and pass them to ESO using <code>spec.provider.aws.role</code>. This way users of the <code>SecretStore</code> can only access the secrets necessary.</p> <p><pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: aws-secretsmanager\nspec:\n provider:\n aws:\n service: SecretsManager\n # define a specific role to limit access\n # to certain secrets.\n # role is a optional field that\n # can be omitted for test purposes\n role: arn:aws:iam::123456789012:role/external-secrets\n region: eu-central-1\n auth:\n secretRef:\n accessKeyIDSecretRef:\n name: awssm-secret\n key: access-key\n secretAccessKeySecretRef:\n name: awssm-secret\n key: secret-access-key\n</code></pre> NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>accessKeyIDSecretRef</code> and <code>secretAccessKeySecretRef</code> with the namespaces where the secrets reside.</p>"},{"location":"provider/aws-secrets-manager/#iam-policy","title":"IAM Policy","text":"<p>Create a IAM Policy to pin down access to secrets matching <code>dev-*</code>.</p> <pre><code>{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"secretsmanager:GetResourcePolicy\",\n \"secretsmanager:GetSecretValue\",\n \"secretsmanager:DescribeSecret\",\n \"secretsmanager:ListSecretVersionIds\"\n ],\n \"Resource\": [\n \"arn:aws:secretsmanager:us-west-2:111122223333:secret:dev-*\"\n ]\n }\n ]\n}\n</code></pre>"},{"location":"provider/aws-secrets-manager/#permissions-for-pushsecret","title":"Permissions for PushSecret","text":"<p>If you're planning to use <code>PushSecret</code>, ensure you also have the following permissions in your IAM policy:</p> <pre><code>{\n \"Effect\": \"Allow\",\n \"Action\": [\n \"secretsmanager:CreateSecret\",\n \"secretsmanager:PutSecretValue\",\n \"secretsmanager:TagResource\",\n \"secretsmanager:DeleteSecret\"\n ],\n \"Resource\": [\n \"arn:aws:secretsmanager:us-west-2:111122223333:secret:dev-*\"\n ]\n}\n</code></pre> <p>Here's a more restrictive version of the IAM policy:</p> <pre><code>{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"secretsmanager:CreateSecret\",\n \"secretsmanager:PutSecretValue\",\n \"secretsmanager:TagResource\"\n ],\n \"Resource\": [\n \"arn:aws:secretsmanager:us-west-2:111122223333:secret:dev-*\"\n ]\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"secretsmanager:DeleteSecret\"\n ],\n \"Resource\": [\n \"arn:aws:secretsmanager:us-west-2:111122223333:secret:dev-*\"\n ],\n \"Condition\": {\n \"StringEquals\": {\n \"secretsmanager:ResourceTag/managed-by\": \"external-secrets\"\n }\n }\n }\n ]\n}\n</code></pre> <p>In this policy, the DeleteSecret action is restricted to secrets that have the specified tag, ensuring that deletion operations are more controlled and in line with the intended management of the secrets.</p>"},{"location":"provider/aws-secrets-manager/#additional-settings-for-pushsecret","title":"Additional Settings for PushSecret","text":"<p>Additional settings can be set at the <code>SecretStore</code> level to control the behavior of <code>PushSecret</code> when interacting with AWS Secrets Manager.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: aws-secretsmanager\nspec:\n provider:\n aws:\n service: SecretsManager\n role: arn:aws:iam::123456789012:role/external-secrets\n region: eu-central-1\n secretsManager:\n # Additional parameters can be added to the AWS Secrets Manager DeleteSecret API call.\n # These parameters are only relevant when the deletionPolicy is set to Delete.\n # See: https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_DeleteSecret.html#API_DeleteSecret_RequestSyntax\n forceDeleteWithoutRecovery: true\n # recoveryWindowInDays: 9 (conflicts with forceDeleteWithoutRecovery)\n</code></pre>"},{"location":"provider/aws-secrets-manager/#additional-metadata-for-pushsecret","title":"Additional Metadata for PushSecret","text":"<p>It's possible to configure AWS Secrets Manager to either push secrets in <code>binary</code> format or as plain <code>string</code>.</p> <p>To control this behaviour set the following provider metadata:</p> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: pushsecret-example # Customisable\n namespace: teamb # Same of the SecretStores\nspec:\n deletionPolicy: Delete\n refreshInterval: 10s # Refresh interval for which push secret will reconcile\n secretStoreRefs: # A list of secret stores to push secrets to\n - name: teamb-secret-store\n kind: SecretStore\n selector:\n secret:\n name: my-secret # Source Kubernetes secret to be pushed\n data:\n - match:\n secretKey: key1 # Source Kubernetes secret key to be pushed\n remoteRef:\n remoteKey: teamb-my-first-parameter-3 # Remote reference (where the secret is going to be pushed)\n metadata:\n secretPushFormat: string\n</code></pre> <p><code>secretPushFormat</code> takes two options. <code>binary</code> and <code>string</code>, where <code>binary</code> is the default.</p>"},{"location":"provider/aws-secrets-manager/#json-secret-values","title":"JSON Secret Values","text":"<p>SecretsManager supports simple key/value pairs that are stored as json. If you use the API you can store more complex JSON objects. You can access nested values or arrays using gjson syntax:</p> <p>Consider the following JSON object that is stored in the SecretsManager key <code>friendslist</code>: <pre><code>{\n \"name\": {\"first\": \"Tom\", \"last\": \"Anderson\"},\n \"friends\": [\n {\"first\": \"Dale\", \"last\": \"Murphy\"},\n {\"first\": \"Roger\", \"last\": \"Craig\"},\n {\"first\": \"Jane\", \"last\": \"Murphy\"}\n ]\n}\n</code></pre></p> <p>This is an example on how you would look up nested keys in the above json object:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example\nspec:\n refreshInterval: 1m\n secretStoreRef:\n name: aws-secretsmanager\n kind: SecretStore\n target:\n name: friends\n creationPolicy: Owner\n data:\n - secretKey: my_name\n remoteRef:\n key: friendslist\n property: name.first # Tom\n - secretKey: first_friend\n remoteRef:\n key: friendslist\n property: friends.1.first # Roger\n\n # metadataPolicy to fetch all the labels in JSON format\n - secretKey: tags\n remoteRef:\n metadataPolicy: Fetch \n key: database-credentials\n\n # metadataPolicy to fetch a specific label (dev) from the source secret\n - secretKey: developer\n remoteRef:\n metadataPolicy: Fetch \n key: database-credentials\n property: dev\n</code></pre>"},{"location":"provider/aws-secrets-manager/#secret-versions","title":"Secret Versions","text":"<p>SecretsManager creates a new version of a secret every time it is updated. The secret version can be reference in two ways, the <code>VersionStage</code> and the <code>VersionId</code>. The <code>VersionId</code> is a unique uuid which is generated every time the secret changes. This id is immutable and will always refer to the same secret data. The <code>VersionStage</code> is an alias to a <code>VersionId</code>, and can refer to different secret data as the secret is updated. By default, SecretsManager will add the version stages <code>AWSCURRENT</code> and <code>AWSPREVIOUS</code> to every secret, but other stages can be created via the update-secret-version-stage api.</p> <p>The <code>version</code> field on the <code>remoteRef</code> of the ExternalSecret will normally consider the version to be a <code>VersionStage</code>, but if the field is prefixed with <code>uuid/</code>, then the version will be considered a <code>VersionId</code>.</p> <p>So in this example, the operator will request the same secret with different versions: <code>AWSCURRENT</code> and <code>AWSPREVIOUS</code>:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: versioned-api-key\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: aws-secretsmanager\n kind: SecretStore\n target:\n name: versioned-api-key\n creationPolicy: Owner\n data:\n - secretKey: previous-api-key\n remoteRef:\n key: \"production/api-key\"\n version: \"AWSPREVIOUS\"\n - secretKey: current-api-key\n remoteRef:\n key: \"production/api-key\"\n version: \"AWSCURRENT\"\n</code></pre> <p>While in this example, the operator will request the secret with <code>VersionId</code> as <code>abcd-1234</code></p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: versioned-api-key\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: aws-secretsmanager\n kind: SecretStore\n target:\n name: versioned-api-key\n creationPolicy: Owner\n data:\n - secretKey: api-key\n remoteRef:\n key: \"production/api-key\"\n version: \"uuid/123e4567-e89b-12d3-a456-426614174000\"\n</code></pre>"},{"location":"provider/aws-secrets-manager/#aws-authentication","title":"AWS Authentication","text":""},{"location":"provider/aws-secrets-manager/#controllers-pod-identity","title":"Controller's Pod Identity","text":"<p>Note: If you are using Parameter Store replace <code>service: SecretsManager</code> with <code>service: ParameterStore</code> in all examples below.</p> <p>This is basicially a zero-configuration authentication method that inherits the credentials from the runtime environment using the aws sdk default credential chain.</p> <p>You can attach a role to the pod using IRSA, kiam or kube2iam. When no other authentication method is configured in the <code>Kind=Secretstore</code> this role is used to make all API calls against AWS Secrets Manager or SSM Parameter Store.</p> <p>Based on the Pod's identity you can do a <code>sts:assumeRole</code> before fetching the secrets to limit access to certain keys in your provider. This is optional.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: team-b-store\nspec:\n provider:\n aws:\n service: SecretsManager\n region: eu-central-1\n # optional: do a sts:assumeRole before fetching secrets\n role: team-b\n</code></pre>"},{"location":"provider/aws-secrets-manager/#access-key-id-secret-access-key","title":"Access Key ID &amp; Secret Access Key","text":"<p>You can store Access Key ID &amp; Secret Access Key in a <code>Kind=Secret</code> and reference it from a SecretStore.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: team-b-store\nspec:\n provider:\n aws:\n service: SecretsManager\n region: eu-central-1\n # optional: assume role before fetching secrets\n role: team-b\n auth:\n secretRef:\n accessKeyIDSecretRef:\n name: awssm-secret\n key: access-key\n secretAccessKeySecretRef:\n name: awssm-secret\n key: secret-access-key\n</code></pre> <p>NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>accessKeyIDSecretRef</code>, <code>secretAccessKeySecretRef</code> with the namespaces where the secrets reside.</p>"},{"location":"provider/aws-secrets-manager/#eks-service-account-credentials","title":"EKS Service Account credentials","text":"<p>This feature lets you use short-lived service account tokens to authenticate with AWS. You must have Service Account Volume Projection enabled - it is by default on EKS. See EKS guide on how to set up IAM roles for service accounts.</p> <p>The big advantage of this approach is that ESO runs without any credentials.</p> <pre><code>apiVersion: v1\nkind: ServiceAccount\nmetadata:\n annotations:\n eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/team-a\n name: my-serviceaccount\n namespace: default\n</code></pre> <p>Reference the service account from above in the Secret Store:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: secretstore-sample\nspec:\n provider:\n aws:\n service: SecretsManager\n region: eu-central-1\n auth:\n jwt:\n serviceAccountRef:\n name: my-serviceaccount\n</code></pre> <p>NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> for <code>serviceAccountRef</code> with the namespace where the service account resides.</p>"},{"location":"provider/aws-secrets-manager/#custom-endpoints","title":"Custom Endpoints","text":"<p>You can define custom AWS endpoints if you want to use regional, vpc or custom endpoints. See List of endpoints for Secrets Manager, Secure Systems Manager and Security Token Service.</p> <p>Use the following environment variables to point the controller to your custom endpoints. Note: All resources managed by this controller are affected.</p> ENV VAR DESCRIPTION AWS_SECRETSMANAGER_ENDPOINT Endpoint for the Secrets Manager Service. The controller uses this endpoint to fetch secrets from AWS Secrets Manager. AWS_SSM_ENDPOINT Endpoint for the AWS Secure Systems Manager. The controller uses this endpoint to fetch secrets from SSM Parameter Store. AWS_STS_ENDPOINT Endpoint for the Security Token Service. The controller uses this endpoint when creating a session and when doing <code>assumeRole</code> or <code>assumeRoleWithWebIdentity</code> calls."},{"location":"provider/azure-key-vault/","title":"Azure Key Vault","text":""},{"location":"provider/azure-key-vault/#azure-key-vault","title":"Azure Key vault","text":"<p>External Secrets Operator integrates with Azure Key vault for secrets, certificates and Keys management.</p>"},{"location":"provider/azure-key-vault/#authentication","title":"Authentication","text":"<p>We support authentication with Microsoft Entra identities that can be used as Workload Identity or AAD Pod Identity as well as with Service Principal credentials.</p> <p>Since the AAD Pod Identity is deprecated, it is recommended to use the Workload Identity authentication.</p> <p>We support connecting to different cloud flavours azure supports: <code>PublicCloud</code>, <code>USGovernmentCloud</code>, <code>ChinaCloud</code> and <code>GermanCloud</code>. You have to specify the <code>environmentType</code> and point to the correct cloud flavour. This defaults to <code>PublicCloud</code>.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: azure-backend\nspec:\n provider:\n azurekv:\n # PublicCloud, USGovernmentCloud, ChinaCloud, GermanCloud\n environmentType: PublicCloud # default\n</code></pre> <p>Minimum required permissions are <code>Get</code> over secret and certificate permissions. This can be done by adding a Key Vault access policy:</p> <pre><code>KUBELET_IDENTITY_OBJECT_ID=$(az aks show --resource-group &lt;AKS_CLUSTER_RG_NAME&gt; --name &lt;AKS_CLUSTER_NAME&gt; --query 'identityProfile.kubeletidentity.objectId' -o tsv)\naz keyvault set-policy --name kv-name-with-certs --object-id \"$KUBELET_IDENTITY_OBJECT_ID\" --certificate-permissions get --secret-permissions get\n</code></pre>"},{"location":"provider/azure-key-vault/#service-principal-key-authentication","title":"Service Principal key authentication","text":"<p>A service Principal client and Secret is created and the JSON keyfile is stored in a <code>Kind=Secret</code>. The <code>ClientID</code> and <code>ClientSecret</code> or <code>ClientCertificate</code> (in PEM format) should be configured for the secret. This service principal should have proper access rights to the keyvault to be managed by the operator.</p>"},{"location":"provider/azure-key-vault/#managed-identity-authentication","title":"Managed Identity authentication","text":"<p>A Managed Identity should be created in Azure, and that Identity should have proper rights to the keyvault to be managed by the operator.</p> <p>Use aad-pod-identity to assign the identity to external-secrets operator. To add the selector to external-secrets operator, use <code>podLabels</code> in your values.yaml in case of Helm installation of external-secrets.</p> <p>If there are multiple Managed Identities for different keyvaults, the operator should have been assigned all identities via aad-pod-identity, then the SecretStore configuration should include the Id of the identity to be used via the <code>identityId</code> field.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: azure-store\nspec:\n provider:\n # provider type: azure keyvault\n azurekv:\n authType: ManagedIdentity\n # Optionally set the Id of the Managed Identity, if multiple identities are assigned to external-secrets operator\n identityId: \"&lt;MI_clientId&gt;\"\n # URL of your vault instance, see: https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates\n vaultUrl: \"https://my-keyvault-name.vault.azure.net\"\n</code></pre>"},{"location":"provider/azure-key-vault/#workload-identity","title":"Workload Identity","text":"<p>In Microsoft Entra, Workload Identity can be Application, user-assigned Managed Identity and Service Principal.</p> <p>You can use Azure AD Workload Identity Federation to access Azure managed services like Key Vault without needing to manage secrets. You need to configure a trust relationship between your Kubernetes Cluster and Azure AD. This can be done in various ways, for instance using <code>terraform</code>, the Azure Portal or the <code>az</code> cli. We found the azwi cli very helpful. The Azure Workload Identity Quick Start Guide is also good place to get started.</p> <p>This is basically a two step process:</p> <ol> <li>Create a Kubernetes Service Account (guide)</li> </ol> <p><pre><code>azwi serviceaccount create phase sa \\\n --aad-application-name \"${APPLICATION_NAME}\" \\\n --service-account-namespace \"${SERVICE_ACCOUNT_NAMESPACE}\" \\\n --service-account-name \"${SERVICE_ACCOUNT_NAME}\"\n</code></pre> 2. Configure the trust relationship between Azure AD and Kubernetes (guide)</p> <pre><code>azwi serviceaccount create phase federated-identity \\\n --aad-application-name \"${APPLICATION_NAME}\" \\\n --service-account-namespace \"${SERVICE_ACCOUNT_NAMESPACE}\" \\\n --service-account-name \"${SERVICE_ACCOUNT_NAME}\" \\\n --service-account-issuer-url \"${SERVICE_ACCOUNT_ISSUER}\"\n</code></pre> <p>With these prerequisites met you can configure <code>ESO</code> to use that Service Account. You have two options:</p>"},{"location":"provider/azure-key-vault/#mounted-service-account","title":"Mounted Service Account","text":"<p>You run the controller and mount that particular service account into the pod by adding the label <code>azure.workload.identity/use: \"true\"</code>to the pod. That grants everyone who is able to create a secret store or reference a correctly configured one the ability to read secrets. This approach is usually not recommended. But may make sense when you want to share an identity with multiple namespaces. Also see our Multi-Tenancy Guide for design considerations.</p> <pre><code>apiVersion: v1\nkind: ServiceAccount\nmetadata:\n # this service account was created by azwi\n name: workload-identity-sa\n annotations:\n azure.workload.identity/client-id: 7d8cdf74-xxxx-xxxx-xxxx-274d963d358b\n azure.workload.identity/tenant-id: 5a02a20e-xxxx-xxxx-xxxx-0ad5b634c5d8\n---\napiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: azure-store\nspec:\n provider:\n azurekv:\n authType: WorkloadIdentity\n vaultUrl: \"https://xx-xxxx-xx.vault.azure.net\"\n # note: no serviceAccountRef was provided\n</code></pre>"},{"location":"provider/azure-key-vault/#referenced-service-account","title":"Referenced Service Account","text":"<p>You run the controller without service account (effectively without azure permissions). Now you have to configure the SecretStore and set the <code>serviceAccountRef</code> and point to the service account you have just created. This is usually the recommended approach. It makes sense for everyone who wants to run the controller without Azure permissions and delegate authentication via service accounts in particular namespaces. Also see our Multi-Tenancy Guide for design considerations.</p> <pre><code>apiVersion: v1\nkind: ServiceAccount\nmetadata:\n # this service account was created by azwi\n name: workload-identity-sa\n annotations:\n azure.workload.identity/client-id: 7d8cdf74-xxxx-xxxx-xxxx-274d963d358b\n azure.workload.identity/tenant-id: 5a02a20e-xxxx-xxxx-xxxx-0ad5b634c5d8\n---\napiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: azure-store\nspec:\n provider:\n azurekv:\n authType: WorkloadIdentity\n vaultUrl: \"https://xx-xxxx-xx.vault.azure.net\"\n serviceAccountRef:\n name: workload-identity-sa\n</code></pre> <p>In case you don't have the clientId when deploying the SecretStore, such as when deploying a Helm chart that includes instructions for creating a Managed Identity using Azure Service Operator next to the SecretStore definition, you may encounter an interpolation problem. Helm lacks dependency management, which means it can create an issue when the clientId is only known after everything is deployed. Although the Service Account can inject <code>clientId</code> and <code>tenantId</code> into a pod, it doesn't support secretKeyRef/configMapKeyRef. Therefore, you can deliver the clientId and tenantId directly, bypassing the Service Account.</p> <p>The following example demonstrates using the secretRef field to directly deliver the <code>clientId</code> and <code>tenantId</code> to the SecretStore while utilizing Workload Identity authentication.</p> <pre><code>apiVersion: v1\nkind: ServiceAccount\nmetadata:\n # this service account was created by azwi\n name: workload-identity-sa\n annotations: {}\n---\napiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: azure-store\nspec:\n provider:\n azurekv:\n # tenantId spec option #1\n tenantId: \"5a02a20e-xxxx-xxxx-xxxx-0ad5b634c5d8\"\n authType: WorkloadIdentity\n vaultUrl: \"https://xx-xxxx-xx.vault.azure.net\"\n serviceAccountRef:\n name: workload-identity-sa\n authSecretRef:\n clientId:\n name: umi-secret\n key: clientId\n # tenantId spec option #2\n tenantId:\n name: umi-secret\n key: tenantId\n</code></pre>"},{"location":"provider/azure-key-vault/#update-secret-store","title":"Update secret store","text":"<p>Be sure the <code>azurekv</code> provider is listed in the <code>Kind=SecretStore</code></p> <p><pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: azure-store\nspec:\n provider:\n # provider type: azure keyvault\n azurekv:\n # azure tenant ID, see: https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-how-to-find-tenant\n tenantId: \"2ed1d494-6c5a-4c5d-aa24-479446fb844d\"\n # URL of your vault instance, see: https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates\n vaultUrl: \"https://kvtestpushsecret.vault.azure.net\"\n authSecretRef:\n # points to the secret that contains\n # the azure service principal credentials\n clientId:\n name: azure-secret-sp\n key: ClientID\n clientSecret:\n name: azure-secret-sp\n key: ClientSecret\n</code></pre> NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>clientId</code> and <code>clientSecret</code> with the namespaces where the secrets reside.</p> <p>Or in case of Managed Identity authentication:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: azure-store\nspec:\n provider:\n # provider type: azure keyvault\n azurekv:\n authType: ManagedIdentity\n # Optionally set the Id of the Managed Identity, if multiple identities are assigned to external-secrets operator\n identityId: \"&lt;MI_clientId&gt;\"\n # URL of your vault instance, see: https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates\n vaultUrl: \"https://my-keyvault-name.vault.azure.net\"\n</code></pre>"},{"location":"provider/azure-key-vault/#object-types","title":"Object Types","text":"<p>Azure Key Vault manages different object types, we support <code>keys</code>, <code>secrets</code> and <code>certificates</code>. Simply prefix the key with <code>key</code>, <code>secret</code> or <code>cert</code> to retrieve the desired type (defaults to secret).</p> Object Type Return Value <code>secret</code> the raw secret value. <code>key</code> A JWK which contains the public key. Azure Key Vault does not export the private key. You may want to use template functions to transform this JWK into PEM encoded PKIX ASN.1 DER format. <code>certificate</code> The raw CER contents of the x509 certificate. You may want to use template functions to transform this into your desired encoding"},{"location":"provider/azure-key-vault/#creating-external-secret","title":"Creating external secret","text":"<p>To create a Kubernetes secret from the Azure Key vault secret a <code>Kind=ExternalSecret</code> is needed.</p> <p>You can manage keys/secrets/certificates saved inside the keyvault , by setting a \"/\" prefixed type in the secret name, the default type is a <code>secret</code>. Other supported values are <code>cert</code> and <code>key</code>.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: database-credentials\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: azure-store\n\n target:\n name: database-credentials\n creationPolicy: Owner\n\n data:\n # name of the SECRET in the Azure KV (no prefix is by default a SECRET)\n - secretKey: database-username\n remoteRef:\n key: database-username\n\n # explicit type and name of secret in the Azure KV\n - secretKey: database-password\n remoteRef:\n key: secret/database-password\n\n # metadataPolicy to fetch all the tags in JSON format\n - secretKey: database-credentials-metadata\n remoteRef:\n key: database-credentials\n metadataPolicy: Fetch\n\n # metadataPolicy to fetch a specific tag which name must be in property\n - secretKey: database-credentials\n remoteRef:\n key: database-credentials\n metadataPolicy: Fetch\n property: environment\n\n # type/name of certificate in the Azure KV\n # raw value will be returned, use templating features for data processing\n - secretKey: db-client-cert\n remoteRef:\n key: cert/db-client-cert\n\n # type/name of the public key in the Azure KV\n # the key is returned PEM encoded\n - secretKey: encryption-pubkey\n remoteRef:\n key: key/encryption-pubkey\n</code></pre> <p>The operator will fetch the Azure Key vault secret and inject it as a <code>Kind=Secret</code>. Then the Kubernetes secret can be fetched by issuing:</p> <pre><code>kubectl get secret secret-to-be-created -n &lt;namespace&gt; -o jsonpath='{.data.dev-secret-test}' | base64 -d\n</code></pre> <p>To select all secrets inside the key vault or all tags inside a secret, you can use the <code>dataFrom</code> directive:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: all-secrets\nspec:\n refreshInterval: 1h # rate ESO pulls Azure Key Vault\n secretStoreRef:\n kind: SecretStore\n name: azure-store # name of the SecretStore (or kind specified)\n target:\n name: all-secrets # name of the k8s Secret to be created\n creationPolicy: Owner\n dataFrom:\n # find all secrets starting with dev-\n - find:\n name:\n regexp: \"^dev\"\n # find all secrets with tags\n - find:\n tags:\n environment: dev\n\n # extract data from a json value\n - extract:\n key: database-credentials\n\n # fetch tags from `database-credentials`\n # and store them as individual keys in a secret\n - extract:\n key: database-credentials\n metadataPolicy: Fetch\n</code></pre> <p>To get a PKCS#12 certificate from Azure Key Vault and inject it as a <code>Kind=Secret</code> of type <code>kubernetes.io/tls</code>:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: tls-client-credentials\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: azure-store\n target:\n template:\n type: kubernetes.io/tls\n engineVersion: v2\n data:\n tls.crt: \"{{ .tls | b64dec | pkcs12cert }}\"\n tls.key: \"{{ .tls | b64dec | pkcs12key }}\"\n data:\n - secretKey: tls\n remoteRef:\n # Azure Key Vault certificates must be fetched as secret/cert-name\n key: secret/tls-client-credentials\n</code></pre>"},{"location":"provider/azure-key-vault/#creating-a-pushsecret","title":"Creating a PushSecret","text":"<p>You can push secrets to Azure Key Vault into the different <code>secret</code>, <code>key</code> and <code>certificate</code> APIs.</p>"},{"location":"provider/azure-key-vault/#pushing-to-a-secret","title":"Pushing to a Secret","text":"<p>Pushing to a Secret requires no previous setup. with the secret available in Kubernetes, you can simply refer it to a PushSecret object to have it created on Azure Key Vault: <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: source-secret\nstringData:\n source-key: \"my-secret\"\n---\napiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: pushsecret-example\n namespace: default\nspec:\n refreshInterval: 10s # Refresh interval for which push secret will reconcile\n deletionPolicy: Delete\n secretStoreRefs: # A list of secret stores to push secrets to\n - name: azure-store\n kind: SecretStore\n selector:\n secret:\n name: source-secret # Source Kubernetes secret to be pushed\n data:\n - match:\n secretKey: source-key # Source Kubernetes secret key containing the secret\n remoteRef:\n remoteKey: my-azkv-secret-name \n</code></pre></p> <p>Note</p> <p>In order to create a PushSecret targeting keys, <code>CreateSecret</code> and <code>DeleteSecret</code> actions must be granted to the Service Principal/Identity configured on the SecretStore.</p>"},{"location":"provider/azure-key-vault/#pushing-to-a-key","title":"Pushing to a Key","text":"<p>The first step is to generate a valid Private Key. Supported Formats include <code>PRIVATE KEY</code>, <code>RSA PRIVATE KEY</code> AND <code>EC PRIVATE KEY</code> (EC/PKCS1/PKCS8 types). After uploading your key to a Kubernetes Secret, the next step is to create a PushSecret manifest with the following configuration:</p> <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: source-key\ndata:\n tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlKSndJQkFBS0NBZ0VBcTRJTEFXRkZRdXNCMTFtYk1FQ2ZSRjh2WUJWeVhqYmFBczN5SE5RWXBNbUNWNkt0CmxKOVcrMlRMRUc3WnlhN1hwTGNuTlc1QWtOM3FrYW1zWGNiV0dLMUZIK3BKcXlKK2RkaktrMjlXa1RHYnV2THgKdkNWSGp6cndPN0NFdTVGWmIvV2NxcjMzb2l4YWdwNlBFYVZKR0t6U3hJaFMvZDlXR1JuN0MySnhKRnlaWlBLWgpYY01KOEg0TmZ5UDcrWjVZTjJMaWQ4eWdWUlpDWXgzQktadXdsQmdwMkpjMmpkN0x4WmQrYmx3REdGUEw4VHpPCk5LZjFRT2JndmdWY2E4M0NWVTJLZ3p0R0M0YVhkVDR3TkYrV25Hdmgza1JrVlBqMDRsbms4Z001M0ZJZ0dJV2oKalphRVd2b2RBMFJSWEtwL3IyMFI4aFRRNXlZMGJ4ejVSQVJyTEdkY1BlejRJY3FSZG5nUm10VldkQ29ZMzZNMgphdE9HRnNPd0ZCbEpuRVhUY0dxWXlnbnZYQlVzVXRNSmdYY3pDWlB1czlTODZtTGxjajlZK3BNb3FSY0NpMCtOCjBtd3VvNUt3dG1tSjBURnBXR3RLS0VSVUpOZkduNWIxekZrWGxsZSt5ODMzMkN2Nk9yWXNCemNya0pFOGJHRmUKTytZY1lqYytGblJpN3JhWXpwTzRReDJ5dzUxSGRScis3aldxNnFrejEzUlZya3hSQ1NFVW5wbVE1M0RvSTZjWgpDakN0UjZWZ3VVY0xnYndFM2w0dlluV0VXMHVNNmZjenlQem1LVis5M0RFd1U4Q3pXR09neTJrNjBYcmx2YkJwCjYrbFdlZVZnNzJJZjZEb0oyVFZZQStFZUpOWDBpaHVUTmpDNmk3VVZYdm5KRWNhSnFTRXE1QTY4OUs4Q0F3RUEKQVFLQ0FnQWN3S2x0cXN2OHd2OUZCaDJ4UWpReE55L3ZFTWxpcUJsMmZPWkpGUG1vcnF1dVczUjBSUjVFK1FuZQpFR2RzbTJaRmsvcjd4eWNGNGw1UDJ6MHRYNGRIRGMxWDQyUkVUMzBaN3FWUGdFdm4vWVFaSEYrUVprT1A3SmFYCnV5a1ZkUEdraG0ya1prS2Nxb2psK3dVTE5VV0M0SDVaT20ySGFDaTcvcElLdjQ4dVJHUG0rNURnbWpFUlkyQ0oKM3hPQUxwNmxjbXQ3SUJBRkU3MC9kcDZLaGpKZE1ZdmFac2RiazIxZ0M5ekRUYU9yTVdrd1lUeEVzWis1S0x1bQp2NmxWM1dIbUFTRG1qVXBaNWs5LzlWUUpnN2p4TWxqa2RWeklyaEFIM29BMlhub1Z5S0xlMlpDb3pRSVZhbmJ3CnRFUmJuNjNXVUJmQkdPSkl6aXZlTU9KTkY5eUxoOTBrWmszaDR0N3dqWFNodUR2SGp2ZmVaVzhjOStTVTh3VlUKTlRZQzUxaHFKYXNDdWdHa0NVZGp3V0pucXc4QU1VNGZFQkM0V1JBRWpKMTdYMDVJNmt3c2V2ZVRrNjlmOTNWSgoxS3ZVcmpKTkNpeVVXVWVzc0lrWllacGxJZnYrbExJUWNrTmVpOFdRRjV0RTh0Z09heHJLZXBWMW81NlkvT2tUCmFyYjg1Z2VYb0Z0Tm9NMUd6TkxqQnQrZ2pIY2owcExZakZ5L2Jsa2ZrZnRNMW1hN0U3L3ROK0d2bHBhQXE3RUcKNTc3a2xoNXJGWGQza09meVY1U3E3cmFQWDRZOWlPSU5EaXBVblpXcENHYjRHQS8wSFozdWpacTB6SlQ4Z0NyaQpSQndBRFBVY0J0UzYxUzE0WjJhU0Q1R1NKUmFHbFNGdVRoY1lxR0MrK08xcTllbkRpUUtDQVFFQTJjN21EN2FvClRlcExYRklWMzU0Zk5QTFhGYm9JSXZPZHhLVnYvR25NajZhMVhCd3RPdWhlQTlmNlhacUY2ZXViVmtLK1ZobWgKR1k5dm5nWHd2ZHBiZTIzdmN5d2duYWxTSDVYRGZnaE9LZU5ZMDJSYnhtWlVTMEtvWGRhSStHVDA3QWN6ZFFkaQpMRnBYTWtybmQwZC9taHZGNkVxN0t0Mkw2YkVoSXptQU5sTWMyY1lBeEIwY0UzRjJLQTNqV3dyQjRuMUZrRTlQCnMzby9tbmVXNEswMVlMVEsyMGhPOTlNeG5oNzNTV1h1SWFXdlI3T1pRcHFEMWFtYXBGUGlqY0RlRVpQczVUMFIKNEk3aVczNWF4YTl5WncxSkYrMTV5aEhkTTNHZllGaXJudy8zRlpQL282RzBJeW50YUZLNkFGU0dIaHpMcEs1awphSWRMYWVBbWlMYnpmUUtDQVFFQXlaVExET1h5V2VTZjUwV0oxUzVtTHJDMVJUNUI4K1dvZzhiVSsvSWxZTjF6Cm82eTM2QkVJcTlMWGhUUTl6cGp0MlcwNTRHa3FjU1hKcTJtajFHSEE5Q3FCTGNTaldyNHR6ZHFXTzREcnoxN0gKVCtpaEZqZ016R2praXhNSlpkZ2JoWGprQ3RkVEMzdGJhaFBiNjN4TjJGM0d6aE8xRmRUVWZ6bXM3WkVzWmRhYgpTaFZaaUFBOU40dnpmYWYyZ3I2SlB2azZwbEdpV2hvT2xkclRvVG4zSFRPNGJNYWJxc20vSFNTU2FyNUtXTUlXCnZlSVN4YjFoQTFIL1dTMXcvN1dqVHJ1UUZqWDRtU1BkT2lqL3hZblVWWjcrTjhLN3VKREJZNjcrWXVNM2RQNHgKdUJ2RjcvdDdwd3g0b002QnhBbGpQZExwZ2dxRFFLb3drVk9reFZ3b213S0NBUUJJS0pOdmdVUWhEQTRMZCtabgpQeXQzanp4U3BsOHJ0U24vakErZHdDOVZLQlhOZmtnOXk5M1p5Q1BaL3VkK3A5KytwRDRLcUZNRzlNNDF2Q0lWCnc5R3JBckRocHl6bkRzRjJWVmQrMmFHTG54WStjbkUxT1pHVG5YSEtKTmtiOGRaeW03QWdoV0d3Ny8wVFhGMXkKMXUwZlVUUXYwUkpSRVRUWkp5V2pWZGwwSmZUWThSQXY2TFQwZkJKNUVxRFArTEJqS0wxeklkTjEwbnBmNGw3Sgo4SmhPZ1piekx2RjZpUzFYQlV0SHRjMCt1SFZwZThhNm1oWXpJdzFvZzZINjlIcWR1RFF6ZmhmK0hWaEFsNHZiCkVsVUVieEpZS3dTK1BVemJUamxPNGhGNWtRQjYxWjFMeUxhMUw1N0hnU0MrRzBLVGwxYWdLR1o3ZXRjeExHR1gKeVlUQkFvSUJBRms2NWc3VmtzdTc2aFJqc2JtT0NtbE1pMUVWVi9od2hvR2VlQlQyZ1JrNXJjQ2I2ZVJ0OWRxcApRQUdVdUc5RlByUHFKNTV3cnZyYThVUlJSTlgwVjRjOWNXVWpEL1JSRHRGNm10bklIWm56cUdKMDVTbUNzaGVoCnJ0anBHbFhjcllJTm0xUTVNR2Q2dVdKaFhBNEhQaVl5akpnWUhTYUd5WEZ2eEY1OHpweGR2T3UwTzZkNkE1OGMKOGpHRE1obDU0aUxnQzlnbmRxaFB0SGtkSG1UVjFjODFYOE8ydnAyQkpIbndBR2dEeDhFMldQN0FuZkt0KzgyTwpkR3V6TTd2ZFdXYTJtL2RZK0t4Qk5lSlMxN1ZIWjVobkFyMElGRFNFenpZaTlqUXJ4QmFqbHJxYWdLblVOazRoCnRSdnBqWU9MYkVTbm9mbVFVYjFFR0srYnlPb2IrMVVDZ2dFQUJJTFZ0eVV6cFNobW1FN0crZ3I0aGpBb0UxQlgKTDd2SHVIbGdrMStNbFR6RlNLZXpZUDY4RnFsRjRocEFRT2kxTnN3Sy9zaXppdGEycUdUUDJyd1d3NkJUUW9wawplbkdDaEtWNUp0SHRBeDZ2bEZ0aUxUVzE5QTlvUXZEbEllYmNsaFRob2ZWeHV0NFI4RC8vSXZRQXRxbm5jUFFuCnZ5RzRUakl4VCtsWDZqcXdHbUlwRVI4TlpLdjVXU2EzOVVNdlF0ZUJ3Q1hUZEF6Wnlqc0RjRENodlJVRno3S2YKNVlMZ1pVdEt2cEZnbVNYNGF0b2t1TCt5Nm9LYm93Tld6bVdhNzhHbzRLUlhGK2xxUk5OL0dTM0lkM01MdDNmKwovLzRvcWNZa1lyU0dEbjJPenRabGpFcjFrK0NCQ0Rvc3pFMms2b2ZmN2pBck1YUG5McUVXQXkrWDdBPT0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0K\n---\napiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: pushsecret-example\n namespace: default\nspec:\n refreshInterval: 10s # Refresh interval for which push secret will reconcile\n deletionPolicy: Delete\n secretStoreRefs: # A list of secret stores to push secrets to\n - name: azure-store\n kind: SecretStore\n selector:\n secret:\n name: source-key # Source Kubernetes secret to be pushed\n data:\n - match:\n secretKey: tls.key # Source Kubernetes secret key containing the JWK\n remoteRef:\n remoteKey: key/my-azkv-key-name\n</code></pre> <p>Note</p> <p>In order to create a PushSecret targeting keys, <code>ImportKey</code> and <code>DeleteKey</code> actions must be granted to the Service Principal/Identity configured on the SecretStore.</p>"},{"location":"provider/azure-key-vault/#pushing-to-a-certificate","title":"Pushing to a Certificate","text":"<p>The first step is to generate a valid P12 certificate. Currently, only PKCS1/PKCS8 types are supported. Currently only password-less P12 certificates are supported.</p> <p>After uploading your P12 certificate to a Kubernetes Secret, the next step is to create a PushSecret manifest with the following configuration <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: source-certificate\ndata:\n cert.p12: MIIQZgIBAzCCECwGCSqGSIb3DQEHAaCCEB0EghAZMIIQFTCCBi8GCSqGSIb3DQEHBqCCBiAwggYcAgEAMIIGFQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIl69kTzb7QegCAggAgIIF6IOxs3Cr7vl4eT2/YdPNuVoadkQUMO6P5Ad6iuLvY7cDU7D9DO/cga/BVO0/OSIYXgTzbOg3KhreFUcoCTWne7/rbByYi6RHt2AjcZbs6CC6lTraRp5NzppfLGUUAX7v4BR93q55mB0H/j+FNx4QWhgC7sEjSawdvmeNyi+5IrCib0xDYqQ8AvN/g5Vhhp8nAqChx+1n26tRaDh7ULAY+/7D2ffG+gXHNxYn5tM7DGrcCW1FZtEqF53XVzbtyqAqtiWvSyXWYc9CyDN2mqfVG50BDAVGJT3SvuqCs7VO1w8Gs3LbT/eHRfczt2yjVZMLemVuMgHJ6Z3C1W5KjcFRsAhGLzi63d2rj091OnzhWP5YX0QrsAxgLYVeszhsq2GIb/vqIDubwawN0lZQk/guTFRAtcBMb+WDfzqJNPjOElz63/ugxNPTslWNyB7FpNWAtRxjT7qYB28JqnA8nepbzuQc/PZYPcuNFcZJD5YKE0aAhQEgaVOT0ygFdp+/VQ9LsfHgn2AVtsAmDUbt2UaXfyDDwLH19hVs6YPnYGNFiOSRBoTIgCzBreUeo3d/tJ8Ha4CA1TXrdisOGcqO9vszf8bXqgCQQzLl8lxAKZgCYCRoBF9TMkK/4IZ6NeEdxuO4hDhm6bbapIlVw5KsmqPk5i0wYT9TebH6aPyMT4OtYgVdZmTXI8RfkjduKjVxyEDIiX776yTZS0H8F0KtzJdfxX9euwneVg8ap9/7zEZNqfrtj8BGY/12LsXowExbeGLuyb+cgW8F83Pszyilc/EOrXzJOrmEwu3c/fIm93+NhZSoeZ5NwbkhUjOn0qox//FPZF8eSOFkB8Br5gnLuyFl41cOQ0rpVOI0Byz5TFhP4gQ1hH6AuAhRMdGhDWmg4Vot0CAOr3vthbBn/b9B7QQY23UzKlgeog9McrvJ1leM1Jeyl6Az/8tGFJTN7gIZNq91tKuV3bLqLvl6yCKGChy3Hrik+WJFvoaMwLsX38ljgYUYV/+d6gP0Oe87u+9pQ7xnZPaUJ8EJDA3KtFuagfNC2O/F/kZU2KV1Z4Q+3SDZ6O2KGbQestO9BYz/AZAiIfw0qw1Rb0ilskByXH0CLT3FxrefUDMGa57vxQOBeIpJXk91LCg5YDuZ/a8pcnII2dQrXfB+6rK/3fxQdZhliV8KSvQenyw6ZoVqwK+Z1nS1htikfOf3UW/KXHfGsX9L+cS2CA8IaA5EZAZS/boeXxt2ke16LNj2jlfxK8LX051MJ1sTM0I5K9hIp0oNaAKhTmdpWzudbGRRwtZJVhPOaUG4MHaTmrFNQLqOFtUvUDPl6w31fX4LQcPrZncrEahKPoq9vD9AqFvoI+Ku1hfuO+6/pB88fcE/eRtUU824nWB5EU9T7LOQim36fjZrYYAgBZbmwqiERGV68ILnpARbyaA/B/Sj4pIFYmPHo7mhhVWjz8o08QQC3zC4z5R3xisFb/67OCUqxk+ouI0mrM93IBzWVG1INTmmEvz3neeSlSNuUwj40hDOeKaUkUnQCsJWZy9Bx9yIeYfPVhE9GM57qkmzTKnJhM3cCSZEaZuXzvkut6rb7mkorfRI2pMFSK4TjWe743L7TWYXspMtRHe++nsNweZNQCniYvI+S6hVe8GYwbCMxRue+f57I3rBBdcKmBn2npTOcX/5fwYMCgjYEIJdWZZBSXhqEYw2ZEwU2rNvWXpGFcp5cPYwpKWjiD5GpL3eXOTj7Q5u9UHQWhMUQN7Lt/d6Fd9bsoTBhQlRnU6Xe4fdHtCyBMYTjyygqSfa/8XZUp+tZ2tX3zBxCYdw3bepOw4o7skUbqpKKGW0hjEoNgeoB8EFszeM48IY7M75CQY3adFqFzcG+XnTg5K5dJUihcCgn7LwWE1pu8mQTk8FjNkfJjD51Bv/YfEoPTa1XPDumIRZwSJO47mUOdVjg+qUzp3mRz6Gs4/1EJBfTOk3vLkpMUx/YutbzUD6sUZNa8PgICVPEapPbZHQdO/0LgD6DQi2kUsHuhiE2zCCCd4GCSqGSIb3DQEHAaCCCc8EggnLMIIJxzCCCcMGCyqGSIb3DQEMCgECoIIJbjCCCWowHAYKKoZIhvcNAQwBAzAOBAiVo1C5uK6CRwICCAAEgglIfhBryp3NDqqoOhAcaoKj2X2JXamh8KKk7vDW62QfYJVtormTKdnEXHE9f67ZfiB6ippsiTH1Sp1uFWirfiaBb0WhYjoQcUY6vry9Zb/GUd0NnyXnIz6WILFPfE9KC8v1Eo+pxOVj0qRWmf+CGrZCtZbi479k44/aCacBwrut8DaSuaTf9rDc3dgZj1ESYBINkBDXwm0lm/mpObhDbyaoL6+uwloM/EhE8VrtYmZLQ8781EuD6XVfem1GMuHCPiQBL8/23hze2yyB3NnjQzEcC9RLw2yPilWmB+PjfDUzIaCnOty6OUINZZqJ6ivoaA3qS8xh+kZTiCmAlHW/+5RyYXUL/c1bvlBMZz6z9n3lXBjnee3kRVbrQV/aa+069Nd76Mi8WBXhsjkm3+K14fuJksg1x3NohcL3/kW/iYHBXBFug2w6wX8l1T3XcxekBKDDNDfoy/ZExmDmsDAmUfIWb4zonLlaGq6z/9l3LkjrNS9/7C2YYEmh0xmMGD0mjzj1k932LWzvLdPaEIZTm2YsoI4TyraKc2yjXmmQWldGeN4yB/s0RfoaxPrMjkQsO6ZaU+gPqucd0JjL/e9gDVUWB0CL6Wy1T+H60iWBQhj0h5PoXuIbsocVj9PC08zniXmXUiVvbt62AyPm7oYci8BXJIc18WQ/BcO1EzPbQCVqI8DMWkyVCN/XUR7Oufseib//qZyf5XOSqwTHaetWU5tsIVKHcU8vzwPHqiDrFRmkBvn8pmtaQibaartr1XmiTCCkRX5yCzstbWWhjnRB/UD1zTxiMQUEmkmFD3zldLYuXWaaQNpNExog7vyJSMLUuTpff68sElBTRUA5pqqiVua5VsorzWaVMORsdagii4iJ/KQDoSs3KLZ6tXqNHBxoP69Mf6WJF8LZ+3FyYr+Ckpii2zgxx7D274fK6XfQpTS1yxeJPTxPZoEEZs9G03UKkrfi3Uv106akNB4XyAMxsyK26GTbKGkSig1C2gme/oCJfG8ZYin8hhl6QTlGk4ao2RWXT8Rh+qW6PDm+SVA4WJl9NI/eJwEtjmE2U1nt0IfkNy2miug3rHbr1yso4gnfdQUtMsHz055y7GgauJKADGa7N2dUdq7jbK4rbD59QsloYKpkN0TX2g86APMuMlHai33A942bsFnp+IC4ONHpj+LQZHgbr1ygVhI6EQs+x6OAw/0UrEq8fP0KVJBZHR96GJZHGCkVy6z+FVlRGTw4Lgb+dMpjucJeLQw852TLN3zHKsCglsygzGf6dfZhHs4o0tB+NyWr4Pgw/F8n3iXhTQCv95fHoTz9lav/LU1KTxADPhgczNUE6e2zrfZ0724d+eBOZXPY5endc+t2Kci+O2S2xS3XDxt4GDEWEogy6kjQoObjaHEoiOUcplbTfgptpXseivK1y3DU3gJPbNYTE8qJIOnFDwUxYDGYjlUH9h+SguCeRkO8sR5iQrYsjQQbDcPxss3rg6DeytcnsFwKf8bE/mwOpzHOE9CMrWuOoPrmtn7Lad7aTn1YN3hyeaHHVVAWzsbOyhhvEmsX5pifM26ZF57cabEiOU3itt5cYI9qxb90V4hc69NgfONx89RtrgsXd61rIsf8CeQDx3rQmQWZ54Pb0o5WUMnCbui/Z5Nw4RjeKdl38josYB3VZCXBz7g1y3ZWZUpl8GTn6TUZGXtXw8e4g18RJxpgt5OC3d27jY4fsDrVlUlYuZV21fbOG/MyT1YKQvNZlazpNPXXXyHK+Swj+A3H4It0K7IhM4R5+riH3ngcgbtF3M3StIM4lT5KVA84CRUWmDPIUskNbTUJWLw3nhDa5mmgCC9eRrb724leAFWG/FAvlsXmMl5BWWm5KYynu+y0pNpDbLmNNP6PlEBi9Ipms51BaUbQa2Y+LbFXj7dm4MBl07qroxQTOAu/DmUrxkBXU0ElpYhYrYoGbODuH/fD0C2KOJ5d6O8jRg3nN0228A2wrd18p47Q63mHyJlezxKI69o1Um6FNUjTtk6KU1Zp0AtW4mE5jkdKLfRNhlDPrgZAeYoT3OFU9UaPRauw/EJBNhSjmZC6aa4wqu60gmQ8xfnJ6YEd/XayZXqjoAiE9cAC3tF3bO8x3gpp0D0uKFhha5VgtYb9LTVlbE+Kb4DLi5fEkRWyTfywVMXLPgm5HnVE3Pz6SRwH8jHUjNSnqRRbwJfJ4Sb8LzQSzf1y0imoAfGRUcjbIC0tKAitYZ5LduaIzNyi4hBaAwsXLkLEkBClUqtI4LtCf6ETgPNRWmSWYKeiV6vzjyR0xhBi1VixpS8HN4OdA8Te3t41lp6w8nFaJcrD0LnLNPMeotJv5u+6gc3d1Jd/to+DtvxpFulh8J5WMEXCHJOV6nSKRb+rGUFh+2jp9qkSB98XGCcKn3blAFxEGYwtJXqpP53pPxa6Up/f0/KR87a4IWD0y5fZ90+HcvDCnQofuQWsMobpiFWN7ScYttbcO85xv7J6Qs+yUf9hzraN8rLW9o7LKnW+fCT8c0ggTIqTyaW1HwTtYDZtYDUIG9KDj3KY1YZN2yca+ErnS1phfI71m8JqjvH2k/+finxs2IexESmjzRTeqgEKGrhx1BdhwJ5/nd9moF6HuWqR3XCd2UtiLyhQbFt+Lo70vHm3m0Duzu03pKgGGXQQQqa1QM6YIAV6s3TSs/5cYm5KGZCd7UoKlMRzivHst/Nm6Zy+3jckpn626f7RkP/hIfT9Qvrd80PGYeCe2nNvTMfAfScYbczZ225knqeT6Z7vdY8+jgabAjREPLzKvZlL3wS6FquFEsGYn/BNAbkuJ9OhxWBgwqhTVLGaJdTAtl9cgcJqUKE76cclwit9ZF0ucUBdqV9twE2prGB/ujSKmhJ7Qd/FwEr7/UdJwQ8iVbs3+qJHBg91WPhTR9eab0YHzM+62FePZFWpQQ8m9RfP5Ku262YLhGEqmBHAHcOomhWUF/t3fQWewUIADG1Mr4nICeYUbLjsnS3IpASwM2uzFNBgdIe/i/xq5KZMvjtaaEqUviVPkAcHrS96L58DoEnsC+96ljH9lyBwJcJ3q2eT7rQNFY/yANRvNi5ix1mtZV8J6d/HWr2v5P67W3TnbN6yFjIVNwz2vqXOG5tsZ/5AWrctnu7kaanaHvmXgVgIkijHmzW21ZQQANPNgjGBkycGUXZMMUIwGwYJKoZIhvcNAQkUMQ4eDABNAHkAQwBlAHIAdDAjBgkqhkiG9w0BCRUxFgQU59WMkYzN/aRcemeMQJxzpRcC5nwwMTAhMAkGBSsOAwIaBQAEFN17vdeYvqbjC2HcRpRxhBWpv7ydBAgrPrMeGR5G/wICCAA=\n# Alternatively, you could also do it like this:\n#stringData:\n# certPem: |\n# -----BEGIN CERTIFICATE-----\n# ...\n# -----END CERTIFICATE-----\n# -----BEGIN PRIVATE KEY-----\n# ...\n# -----END PRIVATEKEY-----\n\n---\napiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: pushsecret-example\n namespace: default\nspec:\n refreshInterval: 10s # Refresh interval for which push secret will reconcile\n deletionPolicy: Delete\n secretStoreRefs: # A list of secret stores to push secrets to\n - name: azure-store\n kind: SecretStore\n selector:\n secret:\n name: source-certificate # Source Kubernetes secret to be pushed\n data:\n - match:\n secretKey: cert.p12 # Source Kubernetes secret key containing the certificate\n remoteRef:\n remoteKey: cert/my-azkv-cert-name\n</code></pre></p> <p>Note</p> <p>In order to create a PushSecret targeting keys, <code>ImportCertificate</code> and <code>DeleteCertificate</code> actions must be granted to the Service Principal/Identity configured on the SecretStore.</p>"},{"location":"provider/beyondtrust/","title":"BeyondTrust","text":""},{"location":"provider/beyondtrust/#beyondtrust-password-safe","title":"BeyondTrust Password Safe","text":"<p>External Secrets Operator integrates with BeyondTrust Password Safe.</p> <p>Warning: The External Secrets Operator secure usage involves taking several measures. Please see Security Best Practices for more information.</p> <p>Warning: If the BT provider secret is deleted it will still exist in the Kubernetes secrets.</p>"},{"location":"provider/beyondtrust/#prerequisites","title":"Prerequisites","text":"<p>The BT provider supports retrieval of a secret from BeyondInsight/Password Safe versions 23.1 or greater.</p> <p>For this provider to retrieve a secret the Password Safe/Secrets Safe instance must be preconfigured with the secret in question and authorized to read it.</p>"},{"location":"provider/beyondtrust/#authentication","title":"Authentication","text":"<p>BeyondTrust OAuth Authentication.</p> <ol> <li>Create an API access registration in BeyondInsight</li> <li>Create or use an existing Secrets Safe Group</li> <li>Create or use an existing Application User</li> <li>Add API registration to the Application user</li> <li>Add the user to the group</li> <li>Add the Secrets Safe Feature to the group</li> </ol> <p>NOTE: The ClentID and ClientSecret must be stored in a Kubernetes secret in order for the SecretStore to read the configuration.</p> <pre><code>kubectl create secret generic bt-secret --from-literal ClientSecret=\"&lt;your secret&gt;\"\nkubectl create secret generic bt-id --from-literal ClientId=\"&lt;your ID&gt;\"\n</code></pre>"},{"location":"provider/beyondtrust/#client-certificate","title":"Client Certificate","text":"<p>If using <code>retrievalType: MANAGED_ACCOUNT</code>, you will also need to download the pfx certificate from Secrets Safe, extract that certificate and create two Kubernetes secrets.</p> <pre><code>openssl pkcs12 -in client_certificate.pfx -nocerts -out ps_key.pem -nodes\nopenssl pkcs12 -in client_certificate.pfx -clcerts -nokeys -out ps_cert.pem\n\n# Copy the text from the ps_key.pem to a file.\n-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n\n# Copy the text from the ps_cert.pem to a file.\n-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n\nkubectl create secret generic bt-certificate --from-file=ClientCertificate=./ps_cert.pem\nkubectl create secret generic bt-certificatekey --from-file=ClientCertificateKey=./ps_key.pem\n</code></pre>"},{"location":"provider/beyondtrust/#creating-a-secretstore","title":"Creating a SecretStore","text":"<p>You can follow the below example to create a <code>SecretStore</code> resource. You can also use a <code>ClusterSecretStore</code> allowing you to reference secrets from all namespaces. ClusterSecretStore</p> <pre><code>kubectl apply -f secret-store.yml\n</code></pre> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: secretstore-beyondtrust\nspec:\n provider:\n beyondtrust:\n server:\n apiUrl: https://example.com:443/BeyondTrust/api/public/v3/\n retrievalType: MANAGED_ACCOUNT # or SECRET\n verifyCA: true\n clientTimeOutSeconds: 45\n auth: \n certificate: # omit certificates if retrievalType is SECRET\n secretRef:\n name: bt-certificate\n key: ClientCertificate\n certificateKey:\n secretRef:\n name: bt-certificatekey\n key: ClientCertificateKey\n clientSecret:\n secretRef:\n name: bt-secret\n key: ClientSecret\n clientId:\n secretRef:\n name: bt-id\n key: ClientId\n</code></pre>"},{"location":"provider/beyondtrust/#creating-a-externalsecret","title":"Creating a ExternalSecret","text":"<p>You can follow the below example to create a <code>ExternalSecret</code> resource. Secrets can be referenced by path. You can also use a <code>ClusterExternalSecret</code> allowing you to reference secrets from all namespaces.</p> <pre><code>kubectl apply -f external-secret.yml\n</code></pre> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: beyondtrust-external-secret\nspec:\n refreshInterval: 300s\n secretStoreRef:\n kind: SecretStore\n name: secretstore-beyondtrust\n target:\n name: my-beyondtrust-secret # name of secret to create in k8s secrets (etcd)\n creationPolicy: Owner\n data:\n - secretKey: secretKey\n remoteRef:\n key: system01/managed_account01\n</code></pre>"},{"location":"provider/beyondtrust/#get-the-k8s-secret","title":"Get the K8s secret","text":"<pre><code># WARNING: this command will reveal the stored secret in plain text\nkubectl get secret my-beyondtrust-secret -o jsonpath=\"{.data.secretKey}\" | base64 --decode &amp;&amp; echo\n</code></pre>"},{"location":"provider/bitwarden-secrets-manager/","title":"Bitwarden Secrets Manager","text":""},{"location":"provider/bitwarden-secrets-manager/#bitwarden-secrets-manager-provider","title":"Bitwarden Secrets Manager Provider","text":"<p>This section describes how to set up the Bitwarden Secrets Manager provider for External Secrets Operator (ESO).</p>"},{"location":"provider/bitwarden-secrets-manager/#prerequisites","title":"Prerequisites","text":"<p>In order for the bitwarden provider to work, we need a second service. This service is the Bitwarden SDK Server. The Bitwarden SDK is Rust based and requires CGO enabled. In order to not restrict the capabilities of ESO, and the image size ( the bitwarden Rust SDK libraries are over 150MB in size ) it has been decided to create a soft wrapper around the SDK that runs as a separate service providing ESO with a light REST API to pull secrets through.</p>"},{"location":"provider/bitwarden-secrets-manager/#bitwarden-sdk-server","title":"Bitwarden SDK server","text":"<p>The server itself can be installed together with ESO. The ESO Helm Chart packages this service as a dependency. The Bitwarden SDK Server's full name is hardcoded to bitwarden-sdk-server. This is so that the exposed service URL gets a determinable endpoint.</p> <p>In order to install the service install ESO with the following helm directive:</p> <pre><code>helm install external-secrets \\\n external-secrets/external-secrets \\\n -n external-secrets \\\n --create-namespace \\\n --set bitwarden-sdk-server.enabled=true\n</code></pre>"},{"location":"provider/bitwarden-secrets-manager/#certificate","title":"Certificate","text":"<p>The Bitwarden SDK Server NEEDS to run as an HTTPS service. That means that any installation that wants to communicate with the Bitwarden provider will need to generate a certificate. The best approach for that is to use cert-manager. It's easy to set up and can generate a certificate that the store can use to connect with the server.</p> <p>For a sample set up look at the bitwarden sdk server's test setup. It contains a self-signed certificate issuer for cert-manager.</p>"},{"location":"provider/bitwarden-secrets-manager/#external-secret-store","title":"External secret store","text":"<p>With that out of the way, let's take a look at how a secret store would look like.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: bitwarden-secretsmanager\nspec:\n provider:\n bitwardensecretsmanager:\n apiURL: https://api.bitwarden.com\n identityURL: https://identity.bitwarden.com\n auth:\n secretRef:\n credentials:\n key: token\n name: bitwarden-access-token\n bitwardenServerSDKURL: https://bitwarden-sdk-server.default.svc.cluster.local:9998\n caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUQ5akNDQXQ2Z0F3SUJBZ0lRS08vM1J1dXR4YWdOeThCdUcyUTJYREFOQmdrcWhraUc5dzBCQVFzRkFEQkQKTVJ3d0dnWURWUVFLRXhObGVIUmxjbTVoYkMxelpXTnlaWFJ6TG1sdk1TTXdJUVlEVlFRREV4cGpaWEowTFcxaApibUZuWlhJdFltbDBkMkZ5WkdWdUxYUnNjekFlRncweU5EQTJNVGt4TXpJd01EUmFGdzB5TkRBNU1UY3hNekl3Ck1EUmFNRU14SERBYUJnTlZCQW9URTJWNGRHVnlibUZzTFhObFkzSmxkSE11YVc4eEl6QWhCZ05WQkFNVEdtTmwKY25RdGJXRnVZV2RsY2kxaWFYUjNZWEprWlc0dGRHeHpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QQpNSUlCQ2dLQ0FRRUExdlFxaTNCL0NVU01FaUx1b3NkTVdZV25QcWJmQ20xbnZsMWhoUWxjOW1ocDFnSmxDbndjCmE0MmxuTkx0TjNTUmdrZWFNYXppV1RyaDQ5SGdUeTNVQ2xoNDh5RXFvTmJDRUlaL2xxOHNoVzRMd2g0RTdNT08KOVJJMDY2a3JCYllYakZuam1ETjdJV1NLOVVwZjIrOUpLTi9PM3ZWTktLMGZhOERxRkppL3h3VUsyOGRNc05tZAo2NnkreW52TzRFRU51Wm9IRUFieWdrOTQ2cm9yNnNmUkxHZ3ZVYXg5cmd4dEh5TkZqcGkrbjhCUDRlQkRZeGI4CkVsQy93Q0Rza2NBNFF3TXphU3NFbDBwL3gwQm9nTS9nbWJWelNVemhBL2NGdXpMRVJmV0tuanJrbmpoenNFWncKRWlzUmZ6K3MyVnUvcm5YK3pabTBoWTFvSDZYY29mVkhOUUlEQVFBQm80SGxNSUhpTUE0R0ExVWREd0VCL3dRRQpBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJTeUplK1lnUWZQbWFFOEZKSHowbzZ0CjQzeGh4VENCbndZRFZSMFJCSUdYTUlHVWdqOWxlSFJsY201aGJDMXpaV055WlhSekxXSnBkSGRoY21SbGJpMXoKWkdzdGMyVnlkbVZ5TG1SbFptRjFiSFF1YzNaakxtTnNkWE4wWlhJdWJHOWpZV3lDTG1KcGRIZGhjbVJsYmkxegpaR3N0YzJWeWRtVnlMbVJsWm1GMWJIUXVjM1pqTG1Oc2RYTjBaWEl1Ykc5allXeUNDV3h2WTJGc2FHOXpkSWNFCmZ3QUFBWWNRQUFBQUFBQUFBQUFBQUFBQUFBQUFBVEFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBdllYUW5ETEgKczc3N3NJN3cwN2NWMVIrTmZvbGRYblp5ejVtQVpDZkc4T2djZDRGdjRYV3lrRG94MzlkUWo0dTJnOWlVcUNwawp2QzJsbUR1UjNrS2kzbjgySTYyQ1BDN1JmZFd3M2hqaFJOV1NKbVBGeGF6NHkrbnMvMDZ3RFBlMmZwRXpPMXIzCmwxTFdZMHBySVlMME1EYTI1c3BUdlZPdWxyeWlnUnJRRGNEbS9hZ3krSEs4RHB3dWlTTEpsdFM0Q1JVa25mb3kKS00rL213VTd4RzNrSnN5ekR0T2dOZDhZeG1lRU44Q05WSk9JalltRk9OWTJrYU51S2ZnMU1aaXArcllPTEFqUgpJdUNxOFhSSTVST2gxOFJKdVlXcVZ6MUkwbXE4aVgwYlo2WG5WRjliZ0ViQ2d3bXZOWkZha3Z4RVhkWmR2N3VmCkYvRm9PTUFlNTY3L0RBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==\n organizationID: 7c0d21ec-10d9-4972-bdf8-ec52df99cc86\n projectID: 9c713cd6-728c-437a-a783-252b0773a0bb\n</code></pre> <p>The api url and identity url are optional. The secret should contain the token for the Machine account for bitwarden.</p> <p>Note</p> <p>Make sure that the machine account has Read-Write access to the Project that the secrets are in.</p> <p>Note</p> <p>A secret store is organization/project dependent. Meaning a 1 store == 1 organization/project. This is so that we ensure that no other project's secrets can be modified accidentally or intentionally.</p>"},{"location":"provider/bitwarden-secrets-manager/#external-secrets","title":"External Secrets","text":"<p>There are two ways to fetch secrets from the provider.</p>"},{"location":"provider/bitwarden-secrets-manager/#find-by-uuid","title":"Find by UUID","text":"<p>In order to fetch a secret by using its UUID simply provide that as remote key in the external secrets like this:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: bitwarden\nspec:\n refreshInterval: 10s\n secretStoreRef:\n # This name must match the metadata.name in the `SecretStore`\n name: bitwarden-secretsmanager\n kind: SecretStore\n data:\n - secretKey: test\n remoteRef:\n key: \"339062b8-a5a1-4303-bf1d-b1920146a622\"\n</code></pre>"},{"location":"provider/bitwarden-secrets-manager/#find-by-name","title":"Find by Name","text":"<p>To find a secret using its name, we need a bit more information. Mainly, these are the rules to find a secret:</p> <ul> <li>if name is a UUID get the secret</li> <li>if name is NOT a UUID Property is mandatory that defines the projectID to look for</li> <li>if name + projectID + organizationID matches, we return that secret</li> <li>if more than one name exists for the same projectID within the same organization we error</li> </ul> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: bitwarden\nspec:\n refreshInterval: 10s\n secretStoreRef:\n # This name must match the metadata.name in the `SecretStore`\n name: bitwarden-secretsmanager\n kind: SecretStore\n data:\n - secretKey: test\n remoteRef:\n key: \"secret-name\"\n</code></pre>"},{"location":"provider/bitwarden-secrets-manager/#push-secret","title":"Push Secret","text":"<p>Pushing a secret is also implemented. Pushing a secret requires even more restrictions because Bitwarden Secrets Manager allows creating the same secret with the same key multiple times. In order to avoid overwriting, or potentially, returning the wrong secret, we restrict push secret with the following rules:</p> <ul> <li>name, projectID, organizationID and value AND NOTE equal, we won't push it again.</li> <li>name, projectID, organizationID and ONLY the value does not equal ( INCLUDING THE NOTE ) we update</li> <li>any of the above isn't true, we create the secret ( this means that it will create a secret in a separate project )</li> </ul> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: pushsecret-bitwarden # Customisable\nspec:\n refreshInterval: 10s # Refresh interval for which push secret will reconcile\n secretStoreRefs: # A list of secret stores to push secrets to\n - name: bitwarden-secretsmanager\n kind: SecretStore\n selector:\n secret:\n name: my-secret # Source Kubernetes secret to be pushed\n data:\n - match:\n secretKey: key # Source Kubernetes secret key to be pushed\n remoteRef:\n remoteKey: remote-key-name # Remote reference (where the secret is going to be pushed)\n metadata:\n note: \"Note of the secret to add.\"\n</code></pre>"},{"location":"provider/chef/","title":"Chef","text":""},{"location":"provider/chef/#chef","title":"Chef","text":"<p><code>Chef External Secrets provider</code> will enable users to seamlessly integrate their Chef-based secret management with Kubernetes through the existing External Secrets framework.</p> <p>In many enterprises, legacy applications and infrastructure are still tightly integrated with the Chef/Chef Infra Server/Chef Server Cluster for configuration and secrets management. Teams often rely on Chef data bags to securely store sensitive information such as application secrets and infrastructure configurations. These data bags serve as a centralized repository for managing and distributing sensitive data across the Chef ecosystem.</p> <p>NOTE: <code>Chef External Secrets provider</code> is designed only to fetch data from the Chef data bags into Kubernetes secrets, it won't update/delete any item in the data bags. </p>"},{"location":"provider/chef/#authentication","title":"Authentication","text":"<p>Every request made to the Chef Infra server needs to be authenticated. Authentication is done using the Private keys of the Chef Users. The User needs to have appropriate Permissions to the data bags containing the data that they want to fetch using the External Secrets Operator.</p> <p>The following command can be used to create Chef Users: <pre><code>chef-server-ctl user-create USER_NAME FIRST_NAME [MIDDLE_NAME] LAST_NAME EMAIL 'PASSWORD' (options)\n</code></pre></p> <p>More details on the above command are available here Chef User Create Option. The above command will return the default private key (PRIVATE_KEY_VALUE), which we will use for authentication. Additionally, a Chef User with access to specific data bags, a private key pair with an expiration date can be created with the help of the knife user key command.</p>"},{"location":"provider/chef/#create-a-secret-containing-your-private-key","title":"Create a secret containing your private key","text":"<p>We need to store the above User's API key into a secret resource. Example: <pre><code>kubectl create secret generic chef-user-secret -n vivid --from-literal=user-private-key='PRIVATE_KEY_VALUE'\n</code></pre></p>"},{"location":"provider/chef/#creating-clustersecretstore","title":"Creating ClusterSecretStore","text":"<p>The Chef <code>ClusterSecretStore</code> is a cluster-scoped SecretStore that can be referenced by all Chef <code>ExternalSecrets</code> from all namespaces. You can follow the below example to create a <code>ClusterSecretStore</code> resource.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ClusterSecretStore\nmetadata:\n name: vivid-clustersecretstore # name of ClusterSecretStore\nspec:\n provider:\n chef:\n username: user # Chef User name\n serverUrl: https://manage.chef.io/organizations/testuser/ # Chef server URL\n auth:\n secretRef:\n privateKeySecretRef:\n key: user-private-key # name of the key inside Secret resource\n name: chef-user-secret # name of Kubernetes Secret resource containing the Chef User's private key\n namespace: vivid # the namespace in which the above Secret resource resides\n</code></pre>"},{"location":"provider/chef/#creating-secretstore","title":"Creating SecretStore","text":"<p>Chef <code>SecretStores</code> are bound to a namespace and can not reference resources across namespaces. For cross-namespace SecretStores, you must use Chef <code>ClusterSecretStores</code>.</p> <p>You can follow the below example to create a <code>SecretStore</code> resource.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: vivid-secretstore # name of SecretStore\n namespace: vivid # must be required for kind: SecretStore\nspec:\n provider:\n chef:\n username: user # Chef User name\n serverUrl: https://manage.chef.io/organizations/testuser/ # Chef server URL\n auth:\n secretRef:\n privateKeySecretRef:\n name: chef-user-secret # name of Kubernetes Secret resource containing the Chef User's private key\n key: user-private-key # name of the key inside Secret resource\n namespace: vivid # the ns where the k8s secret resource containing Chef User's private key resides\n</code></pre>"},{"location":"provider/chef/#creating-externalsecret","title":"Creating ExternalSecret","text":"<p>The Chef <code>ExternalSecret</code> describes what data should be fetched from Chef Data bags, and how the data should be transformed and saved as a Kind=Secret.</p> <p>You can follow the below example to create an <code>ExternalSecret</code> resource. <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: vivid-external-secrets # name of ExternalSecret\n namespace: vivid # namespace inside which the ExternalSecret will be created\n annotations:\n company/contacts: user.a@company.com, user.b@company.com\n company/team: vivid-dev\n labels:\n app.kubernetes.io/name: external-secrets\nspec:\n refreshInterval: 15m\n secretStoreRef:\n name: vivid-clustersecretstore # name of ClusterSecretStore\n kind: ClusterSecretStore\n data:\n - secretKey: USERNAME\n remoteRef:\n key: vivid_prod/global_user # databagName/dataItemName\n property: username # a json key in dataItem\n - secretKey: PASSWORD\n remoteRef:\n key: vivid_prod/global_user\n property: password\n - secretKey: APIKEY\n remoteRef:\n key: vivid_global/apikey\n property: api_key\n - secretKey: APP_PROPERTIES\n remoteRef:\n key: vivid_global/app_properties # databagName/dataItemName , it will fetch all key-vlaues present in the dataItem\n target:\n name: vivid-credentials # name of kubernetes Secret resource that will be created and will contain the obtained secrets\n creationPolicy: Owner\n template:\n mergePolicy: Replace \n engineVersion: v2\n data:\n secrets.json: |\n {\n \"username\": \"{{ .USERNAME }}\",\n \"password\": \"{{ .PASSWORD }}\",\n \"app_apikey\": \"{{ .APIKEY }}\",\n \"app_properties\": \"{{ .APP_PROPERTIES }}\"\n }\n</code></pre></p> <p>When the above <code>ClusterSecretStore</code> and <code>ExternalSecret</code> resources are created, the <code>ExternalSecret</code> will connect to the Chef Server using the private key and will fetch the data bags contained in the <code>vivid-credentials</code> secret resource.</p> <p>To get all data items inside the data bag, you can use the <code>dataFrom</code> directive: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: vivid-external-secrets # name of ExternalSecret\n namespace: vivid # namespace inside which the ExternalSecret will be created\n annotations:\n company/contacts: user.a@company.com, user.b@company.com\n company/team: vivid-dev\n labels:\n app.kubernetes.io/name: external-secrets\nspec:\n refreshInterval: 15m\n secretStoreRef:\n name: vivid-clustersecretstore # name of ClusterSecretStore\n kind: ClusterSecretStore\n dataFrom:\n - extract:\n key: vivid_global # only data bag name\n target:\n name: vivid_global_all_cred # name of Kubernetes Secret resource that will be created and will contain the obtained secrets\n creationPolicy: Owner\n</code></pre></p> <p>follow : this file for more info</p>"},{"location":"provider/cloak/","title":"Cloak End 2 End Encrypted Secrets","text":""},{"location":"provider/cloak/#cloak","title":"Cloak","text":"<p>Sync secrets from the Cloak Encrypted Secrets Platform to Kubernetes using the External Secrets Operator.</p> <p>Cloak uses the webhook provider built into the External Secrets Operator but also required a proxy service to handle decrypting secrets when they arrive into your cluster.</p>"},{"location":"provider/cloak/#key-setup","title":"Key Setup","text":"<p>From the Cloak user interface create a service account and store the private key on your file system.</p> <p>Now create a kubernetes secret in the same namespace as the External Secrets Operator.</p> <pre><code>HISTIGNORE='*kubectl*' kubectl --namespace=external-secrets \\\n create secret generic cloak-key \\\n --from-file=ecdh_private_key=$LOCATION_OF_YOUR_PEM_FILE\n</code></pre>"},{"location":"provider/cloak/#deploy-the-decryption-proxy","title":"Deploy the decryption proxy","text":"<pre><code># The cloak external secrets proxy\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: cloak-external-secrets\n namespace: external-secrets\nspec:\n selector:\n matchLabels:\n app: cloak-external-secrets\n replicas: 1\n template:\n metadata:\n labels:\n app: cloak-external-secrets\n spec:\n containers:\n - name: cloak-external-secrets\n image: purtontech/cloak-external-secrets:latest\n imagePullPolicy: IfNotPresent\n env: \n - name: ECDH_PRIVATE_KEY \n valueFrom: \n secretKeyRef: \n name: cloak-key \n key: ecdh_private_key \n ports:\n - containerPort: 7105\n</code></pre> <p>And a Kubernetes Service so External Secrets Operator can access the proxy.</p> <pre><code>apiVersion: v1\nkind: Service\nmetadata:\n name: cloak-external-secrets-service\n namespace: external-secrets\nspec:\n selector:\n app: cloak-external-secrets\n ports:\n - protocol: TCP\n port: 7105\n targetPort: 7105\n</code></pre>"},{"location":"provider/cloak/#create-a-secret-store","title":"Create a secret store","text":"<p>You can now place the configuration in any Kubernetes Namespace.</p> <pre><code># An External secrets webhookl\napiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: cloak-backend\nspec:\n provider:\n webhook:\n url: \"http://cloak-external-secrets-service:7105/{{ .remoteRef.key }}\"\n result:\n jsonPath: \"$.value\"\n headers:\n Content-Type: application/json\n</code></pre>"},{"location":"provider/cloak/#connect-a-secret-to-the-provider","title":"Connect a secret to the provider","text":"<p>Each <code>secretKey</code> reference in the yaml should point to the name of the secret as it is stored in Cloak.</p> <pre><code># Access a secret\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: cloak-example\nspec:\n refreshInterval: \"15m\"\n secretStoreRef:\n name: cloak-backend\n kind: SecretStore\n target:\n name: example-sync\n data:\n - secretKey: access-token\n remoteRef:\n key: PULUMI_ACCESS_TOKEN\n - secretKey: do-access-token\n remoteRef:\n key: DIGITALOCEAN_ACCESS_TOKEN\n</code></pre>"},{"location":"provider/conjur/","title":"CyberArk Conjur","text":""},{"location":"provider/conjur/#conjur-provider","title":"Conjur Provider","text":"<p>This section describes how to set up the Conjur provider for External Secrets Operator (ESO). For a working example, see the Accelerator-K8s-External-Secrets repo.</p>"},{"location":"provider/conjur/#prerequisites","title":"Prerequisites","text":"<p>Before installing the Conjur provider, you need:</p> <ul> <li>A running Conjur Server (OSS, Enterprise, or Cloud), with:</li> <li>An accessible Conjur endpoint (for example: <code>https://myapi.example.com</code>).</li> <li>Your configured Conjur authentication info (such as <code>hostid</code>, <code>apikey</code>, or JWT service ID). For more information on configuring Conjur, see Policy statement reference.</li> <li>Support for your authentication method (<code>apikey</code> is supported by default, <code>jwt</code> requires additional configuration).</li> <li>Optional: Conjur server certificate (see below).</li> <li>A Kubernetes cluster with ESO installed.</li> </ul>"},{"location":"provider/conjur/#conjur-server-certificate","title":"Conjur server certificate","text":"<p>If you set up your Conjur server with a self-signed certificate, we recommend that you populate the <code>caBundle</code> field with the Conjur self-signed certificate in the secret-store definition. The certificate CA must be referenced in the secret-store definition using either <code>caBundle</code> or <code>caProvider</code>:</p> <pre><code>....\nspec:\n provider:\n conjur:\n # Service URL\n url: https://myapi.conjur.org\n\n # [OPTIONAL] base64 encoded string of certificate\n caBundle: \"&lt;base64 encoded cabundle&gt;\"\n\n # [OPTIONAL] caProvider:\n # Instead of caBundle you can also specify a caProvider,\n # which retrieves the cert from a Secret or ConfigMap\n caProvider:\n type: \"Secret\" # Can be Secret or ConfigMap\n name: \"&lt;name of secret or configmap&gt;\"\n key: \"&lt;key inside secret or configmap&gt;\"\n # namespace is required for ClusterSecretStore\n # but not relevant for SecretStore\n namespace: \"my-cert-secret-namespace\"\n ....\n</code></pre>"},{"location":"provider/conjur/#external-secret-store","title":"External secret store","text":"<p>The Conjur provider is configured as an external secret store in ESO. The Conjur provider supports these two methods to authenticate to Conjur:</p> <ul> <li><code>apikey</code>: uses a Conjur <code>hostid</code> and <code>apikey</code> to authenticate with Conjur</li> <li><code>jwt</code>: uses a JWT to authenticate with Conjur</li> </ul>"},{"location":"provider/conjur/#option-1-external-secret-store-with-apikey-authentication","title":"Option 1: External secret store with apiKey authentication","text":"<p>This method uses a Conjur <code>hostid</code> and <code>apikey</code> to authenticate with Conjur. It is the simplest method to set up and use because your Conjur instance requires no additional configuration.</p>"},{"location":"provider/conjur/#step-1-define-an-external-secret-store","title":"Step 1: Define an external secret store","text":"<p>Tip</p> <p>Save as the file as: <code>conjur-secret-store.yaml</code></p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: conjur\nspec:\n provider:\n conjur:\n # Service URL\n url: https://myapi.conjur.org\n # [OPTIONAL] base64 encoded string of certificate\n caBundle: OPTIONALxFIELDxxxBase64xCertxString== \n auth:\n apikey:\n # conjur account\n account: conjur\n userRef: # Get this from K8S secret\n name: conjur-creds\n key: hostid\n apiKeyRef: # Get this from K8S secret\n name: conjur-creds\n key: apikey\n</code></pre>"},{"location":"provider/conjur/#step-2-create-kubernetes-secrets-for-conjur-credentials","title":"Step 2: Create Kubernetes secrets for Conjur credentials","text":"<p>To connect to the Conjur server, the ESO Conjur provider needs to retrieve the <code>apikey</code> credentials from K8s secrets.</p> <p>Note</p> <p>For more information about how to create K8s secrets, see Creating a secret.</p> <p>Here is an example of how to create K8s secrets using the <code>kubectl</code> command:</p> <pre><code># This is all one line\nkubectl -n external-secrets create secret generic conjur-creds --from-literal=hostid=MYCONJURHOSTID --from-literal=apikey=MYAPIKEY\n\n# Example:\n# kubectl -n external-secrets create secret generic conjur-creds --from-literal=hostid=host/data/app1/host001 --from-literal=apikey=321blahblah\n</code></pre> <p>Note</p> <p><code>conjur-creds</code> is the <code>name</code> defined in the <code>userRef</code> and <code>apikeyRef</code> fields of the <code>conjur-secret-store.yml</code> file.</p>"},{"location":"provider/conjur/#step-3-create-the-external-secrets-store","title":"Step 3: Create the external secrets store","text":"<p>Important</p> <p>Unless you are using a ClusterSecretStore, credentials must reside in the same namespace as the SecretStore.</p> <pre><code># WARNING: creates the store in the \"external-secrets\" namespace, update the value as needed\n#\nkubectl apply -n external-secrets -f conjur-secret-store.yaml\n\n# WARNING: running the delete command will delete the secret store configuration\n#\n# If there is a need to delete the external secretstore\n# kubectl delete secretstore -n external-secrets conjur\n</code></pre>"},{"location":"provider/conjur/#option-2-external-secret-store-with-jwt-authentication","title":"Option 2: External secret store with JWT authentication","text":"<p>This method uses JWT tokens to authenticate with Conjur. You can use the following methods to retrieve a JWT token for authentication:</p> <ul> <li>JWT token from a referenced Kubernetes service account</li> <li>JWT token stored in a Kubernetes secret</li> </ul>"},{"location":"provider/conjur/#step-1-define-an-external-secret-store_1","title":"Step 1: Define an external secret store","text":"<p>When you use JWT authentication, the following must be specified in the <code>SecretStore</code>:</p> <ul> <li><code>account</code> - The name of the Conjur account</li> <li><code>serviceId</code> - The ID of the JWT Authenticator <code>WebService</code> configured in Conjur that is used to authenticate the JWT token</li> </ul> <p>You can retrieve the JWT token from either a referenced service account or a Kubernetes secret.</p> <p>For example, to retrieve a JWT token from a referenced Kubernetes service account, the following secret store definition can be used:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: conjur\nspec:\n provider:\n conjur:\n # Service URL\n url: https://myapi.conjur.org\n # [OPTIONAL] base64 encoded string of certificate\n caBundle: OPTIONALxFIELDxxxBase64xCertxString==\n auth:\n jwt:\n # conjur account\n account: conjur\n # The authn-jwt service ID\n serviceID: my-jwt-auth-service\n # Service account to retrieve JWT token for\n serviceAccountRef:\n name: my-service-account\n # [OPTIONAL] audiences to include in JWT token\n audiences:\n - https://conjur.company.com\n</code></pre> <p>Important</p> <p>This method is only supported in Kubernetes 1.22 and above as it uses the TokenRequest API to get the JWT token from the referenced service account. Audiences can be defined in the Conjur JWT authenticator.</p> <p>Alternatively, here is an example where a secret containing a valid JWT token is referenced:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: conjur\nspec:\n provider:\n conjur:\n # Service URL\n url: https://myapi.conjur.org\n # [OPTIONAL] base64 encoded string of certificate\n caBundle: OPTIONALxFIELDxxxBase64xCertxString==\n auth:\n jwt:\n # conjur account\n account: conjur\n # The authn-jwt service ID\n serviceID: my-jwt-auth-service\n # Secret containing a valid JWT token\n secretRef:\n name: my-jwt-secret\n key: token\n</code></pre> <p>The JWT token must identify your Conjur host, be compatible with your configured Conjur JWT authenticator, and meet all the Conjur JWT guidelines.</p> <p>You can use an external JWT issuer or the Kubernetes API server to create the token. For example, a Kubernetes service account token can be created with this command:</p> <pre><code>kubectl create token my-service-account --audience='https://conjur.company.com' --duration=3600s\n</code></pre> <p>Save the secret store file as <code>conjur-secret-store.yaml</code>.</p>"},{"location":"provider/conjur/#step-2-create-the-external-secrets-store","title":"Step 2: Create the external secrets store","text":"<pre><code># WARNING: creates the store in the \"external-secrets\" namespace, update the value as needed\n#\nkubectl apply -n external-secrets -f conjur-secret-store.yaml\n\n# WARNING: running the delete command will delete the secret store configuration\n#\n# If there is a need to delete the external secretstore\n# kubectl delete secretstore -n external-secrets conjur\n</code></pre>"},{"location":"provider/conjur/#define-an-external-secret","title":"Define an external secret","text":"<p>After you have configured the Conjur provider secret store, you can fetch secrets from Conjur.</p> <p>Here is an example of how to fetch a single secret from Conjur:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: conjur\nspec:\n refreshInterval: 10s\n secretStoreRef:\n # This name must match the metadata.name in the `SecretStore`\n name: conjur\n kind: SecretStore\n data:\n - secretKey: secret00\n remoteRef:\n key: data/app1/secret00\n</code></pre> <p>Save the external secret file as <code>conjur-external-secret.yaml</code>.</p>"},{"location":"provider/conjur/#find-by-name-and-find-by-tag","title":"Find by Name and Find by Tag","text":"<p>The Conjur provider also supports the Find by Name and Find by Tag ESO features. This means that you can use a regular expression or tags to dynamically fetch multiple secrets from Conjur.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: conjur-find-by-name\nspec:\n refreshInterval: 10s\n secretStoreRef:\n # This name must match the metadata.name in the `SecretStore`\n name: conjur\n kind: SecretStore\n target:\n name: k8s-secret-to-be-created\n dataFrom:\n - find:\n # You can use *either* `name` or `tags` to filter the secrets. Here are basic examples of both:\n name:\n # Match all secrets in the app1 namespace (e.g., `app1/secret00`, `app1/secret01`, etc.)\n regexp: \"^app1\\/.+$\"\n tags:\n # Only fetch Conjur secrets with the following annotations\n environment: \"prod\"\n application: \"app1\"\n</code></pre> <p>If you use these features, we strongly recommend that you limit the permissions of the Conjur host to only the secrets that it needs to access. This is more secure and it reduces the load on both the Conjur server and ESO.</p>"},{"location":"provider/conjur/#create-the-external-secret","title":"Create the external secret","text":"<pre><code># WARNING: creates the external-secret in the \"external-secrets\" namespace, update the value as needed\n#\nkubectl apply -n external-secrets -f conjur-external-secret.yaml\n\n# WARNING: running the delete command will delete the external-secrets configuration\n#\n# If there is a need to delete the external secret\n# kubectl delete externalsecret -n external-secrets conjur\n</code></pre>"},{"location":"provider/conjur/#get-the-k8s-secret","title":"Get the K8s secret","text":"<ul> <li>Log in to your Conjur server and verify that your secret exists</li> <li>Review the value of your Kubernetes secret to verify that it contains the same value as the Conjur server</li> </ul> <pre><code># WARNING: this command will reveal the stored secret in plain text\n#\n# Assuming the secret name is \"secret00\", this will show the value\nkubectl get secret -n external-secrets conjur -o jsonpath=\"{.data.secret00}\" | base64 --decode &amp;&amp; echo\n</code></pre>"},{"location":"provider/conjur/#see-also","title":"See also","text":"<ul> <li>Accelerator-K8s-External-Secrets repo</li> <li>Configure Conjur JWT authentication</li> </ul>"},{"location":"provider/conjur/#license","title":"License","text":"<p>Copyright (c) 2023-2024 CyberArk Software Ltd. All rights reserved.</p> <p>Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at</p> <p>http://www.apache.org/licenses/LICENSE-2.0</p> <p>Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.</p>"},{"location":"provider/delinea/","title":"Delinea","text":""},{"location":"provider/delinea/#delinea-devops-secrets-vault","title":"Delinea DevOps Secrets Vault","text":"<p>External Secrets Operator integrates with Delinea DevOps Secrets Vault.</p> <p>Please note that the Delinea Secret Server product is NOT in scope of this integration.</p>"},{"location":"provider/delinea/#creating-a-secretstore","title":"Creating a SecretStore","text":"<p>You need client ID, client secret and tenant to authenticate with DSV. Both client ID and client secret can be specified either directly in the config, or by referencing a kubernetes secret.</p> <p>To acquire client ID and client secret, refer to the policy management and client management documentation.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: secret-store\nspec:\n provider:\n delinea:\n tenant: &lt;TENANT&gt;\n tld: &lt;TLD&gt;\n clientId:\n value: &lt;CLIENT_ID&gt;\n clientSecret:\n secretRef:\n name: &lt;NAME_OF_KUBE_SECRET&gt;\n key: &lt;KEY_IN_KUBE_SECRET&gt;\n</code></pre> <p>Both <code>clientId</code> and <code>clientSecret</code> can either be specified directly via the <code>value</code> field or can reference a kubernetes secret.</p> <p>The <code>tenant</code> field must correspond to the host name / site name of your DevOps vault. If you selected a region other than the US you must also specify the TLD, e.g. <code>tld: eu</code>.</p> <p>If required, the URL template (<code>urlTemplate</code>) can be customized as well.</p>"},{"location":"provider/delinea/#referencing-secrets","title":"Referencing Secrets","text":"<p>Secrets can be referenced by path. Getting a specific version of a secret is not yet supported.</p> <p>Note that because all DSV secrets are JSON objects, you must specify <code>remoteRef.property</code>. You can access nested values or arrays using gjson syntax.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: secret\nspec:\n refreshInterval: 20s\n secretStoreRef:\n kind: SecretStore\n name: secret-store\n data:\n - secretKey: &lt;KEY_IN_KUBE_SECRET&gt;\n remoteRef:\n key: &lt;SECRET_PATH&gt;\n property: &lt;JSON_PROPERTY&gt;\n</code></pre>"},{"location":"provider/device42/","title":"Device42","text":"<p>External Secrets Operator integrates with Device42 API to sync Device42 secrets into a Kubernetes cluster.</p>"},{"location":"provider/device42/#authentication","title":"Authentication","text":"<p><code>username</code> and <code>password</code> is required to talk to the Device42 API.</p> <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: device42-credentials\ndata:\n username: dGVzdA== # \"test\"\n password: dGVzdA== # \"test\"\n</code></pre>"},{"location":"provider/device42/#creating-a-secretstore","title":"Creating a SecretStore","text":"<pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: device42-secret-store\nspec:\n provider:\n device42:\n host: &lt;DEVICE42_HOSTNAME&gt;\n auth:\n secretRef:\n credentials:\n name: &lt;NAME_OF_KUBE_SECRET&gt;\n key: &lt;KEY_IN_KUBE_SECRET&gt;\n namespace: &lt;kube-system&gt;\n</code></pre>"},{"location":"provider/device42/#referencing-secrets","title":"Referencing Secrets","text":"<p>Secrets can be referenced by defining the <code>key</code> containing the Id of the secret. The <code>password</code> field is return from device42</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: device42-external-secret\nspec:\n refreshInterval: 5m\n secretStoreRef:\n kind: SecretStore\n name: device42-secret-store\n target:\n name: &lt;K8s_SECRET_NAME_TO_MANAGE&gt;\n data:\n - secretKey: &lt;KEY_NAME_WITHIN_KUBE_SECRET&gt;\n remoteRef:\n key: &lt;DEVICE42_SECRET_ID&gt;\n</code></pre>"},{"location":"provider/doppler/","title":"Doppler","text":""},{"location":"provider/doppler/#doppler-secretops-platform","title":"Doppler SecretOps Platform","text":"<p>Sync secrets from the Doppler SecretOps Platform to Kubernetes using the External Secrets Operator.</p>"},{"location":"provider/doppler/#authentication","title":"Authentication","text":"<p>Doppler Service Tokens are recommended as they restrict access to a single config.</p> <p></p> <p>NOTE: Doppler Personal Tokens are also supported but require <code>project</code> and <code>config</code> to be set on the <code>SecretStore</code> or <code>ClusterSecretStore</code>.</p> <p>Create the Doppler Token secret by opening the Doppler dashboard and navigating to the desired Project and Config, then create a new Service Token from the Access tab:</p> <p></p> <p>Create the Doppler Token Kubernetes secret with your Service Token value:</p> <pre><code>HISTIGNORE='*kubectl*' kubectl create secret generic \\\n doppler-token-auth-api \\\n --from-literal dopplerToken=\"dp.st.xxxx\"\n</code></pre> <p>Then to create a generic <code>SecretStore</code>:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: doppler-auth-api\nspec:\n provider:\n doppler:\n auth:\n secretRef:\n dopplerToken:\n name: doppler-token-auth-api\n key: dopplerToken\n</code></pre> <p>NOTE: In case of a <code>ClusterSecretStore</code>, be sure to set <code>namespace</code> in <code>secretRef.dopplerToken</code>.</p>"},{"location":"provider/doppler/#use-cases","title":"Use Cases","text":"<p>The Doppler provider allows for a wide range of use cases:</p> <ol> <li>Fetch</li> <li>Fetch all</li> <li>Filter</li> <li>JSON secret</li> <li>Name transformer</li> <li>Download</li> </ol> <p>Let's explore each use case using a fictional <code>auth-api</code> Doppler project.</p>"},{"location":"provider/doppler/#1-fetch","title":"1. Fetch","text":"<p>To sync one or more individual secrets:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: auth-api-db-url\nspec:\n secretStoreRef:\n kind: SecretStore\n name: doppler-auth-api\n\n target:\n name: auth-api-db-url\n\n data:\n - secretKey: DB_URL\n remoteRef:\n key: DB_URL\n</code></pre> <p></p>"},{"location":"provider/doppler/#2-fetch-all","title":"2. Fetch all","text":"<p>To sync every secret from a config:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: auth-api-all\nspec:\n secretStoreRef:\n kind: SecretStore\n name: doppler-auth-api\n\n target:\n name: auth-api-all\n\n dataFrom:\n - find:\n name:\n regexp: .*\n</code></pre> <p></p>"},{"location":"provider/doppler/#3-filter","title":"3. Filter","text":"<p>To filter secrets by <code>path</code> (path prefix), <code>name</code> (regular expression) or a combination of both:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: auth-api-db\nspec:\n secretStoreRef:\n kind: SecretStore\n name: doppler-auth-api\n\n target:\n name: auth-api-db\n\n dataFrom:\n - find:\n path: DB_\n</code></pre> <p></p>"},{"location":"provider/doppler/#4-json-secret","title":"4. JSON secret","text":"<p>To parse a JSON secret to its key-value pairs:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: auth-api-sa-json\nspec:\n secretStoreRef:\n kind: SecretStore\n name: doppler-auth-api\n\n target:\n name: auth-api-sa-json\n\n dataFrom:\n - extract:\n key: SA_JSON\n</code></pre> <p></p>"},{"location":"provider/doppler/#5-name-transformer","title":"5. Name transformer","text":"<p>Name transformers format keys from Doppler's UPPER_SNAKE_CASE to one of the following alternatives:</p> <ul> <li>upper-camel</li> <li>camel</li> <li>lower-snake</li> <li>tf-var</li> <li>dotnet-env</li> <li>lower-kebab</li> </ul> <p>Name transformers require a specifically configured <code>SecretStore</code>:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: doppler-auth-api-dotnet-env\nspec:\n provider:\n doppler:\n auth:\n secretRef:\n dopplerToken:\n name: doppler-token-auth-api\n nameTransformer: dotnet-env\n</code></pre> <p>Then an <code>ExternalSecret</code> referencing the <code>SecretStore</code>:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: doppler-auth-api-dotnet-env\nspec:\n secretStoreRef:\n kind: SecretStore\n name: doppler-auth-api-dotnet-env\n\n target:\n name: doppler-auth-api-dotnet-env\n creationPolicy: Owner\n\n dataFrom:\n - find:\n name:\n regexp: .*\n</code></pre> <p></p>"},{"location":"provider/doppler/#6-download","title":"6. Download","text":"<p>A single <code>DOPPLER_SECRETS_FILE</code> key is set where the value is the secrets downloaded in one of the following formats:</p> <ul> <li>json</li> <li>dotnet-json</li> <li>env</li> <li>env-no-quotes</li> <li>yaml</li> </ul> <p>Downloading secrets requires a specifically configured <code>SecretStore</code>:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: doppler-auth-api-json-file\nspec:\n provider:\n doppler:\n auth:\n secretRef:\n dopplerToken:\n name: doppler-token-auth-api\n key: dopplerToken\n format: json\n</code></pre> <p>Then an <code>ExternalSecret</code> referencing the <code>SecretStore</code>:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: auth-api-json-file\nspec:\n secretStoreRef:\n kind: SecretStore\n name: doppler-auth-api-json-file\n\n target:\n name: auth-api-json-file\n\n dataFrom:\n - find:\n path: DOPPLER_SECRETS_FILE\n</code></pre> <p></p>"},{"location":"provider/fake/","title":"Fake","text":"<p>We provide a <code>fake</code> implementation to help with testing. This provider returns static key/value pairs and nothing else. To use the <code>fake</code> provider simply create a <code>SecretStore</code> or <code>ClusterSecretStore</code> and configure it like in the following example:</p> <p>Note</p> <p>The provider returns static data configured in <code>value</code>. You can define a <code>version</code>, too. If set the <code>remoteRef</code> from an ExternalSecret must match otherwise no value is returned.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ClusterSecretStore\nmetadata:\n name: fake\nspec:\n provider:\n fake:\n data:\n - key: \"/foo/bar\"\n value: \"HELLO1\"\n version: \"v1\"\n - key: \"/foo/bar\"\n value: \"HELLO2\"\n version: \"v2\"\n - key: \"/foo/baz\"\n value: '{\"john\": \"doe\"}'\n version: \"v1\"\n</code></pre> <p>Please note that <code>value</code> is intended for exclusive use with <code>data</code> for <code>dataFrom</code>. You can use the <code>data</code> to set a <code>JSON</code> compliant value to be used as <code>dataFrom</code>.</p> <p>Here is an example <code>ExternalSecret</code> that displays this behavior:</p> <p>Warning</p> <p>This provider supports specifying different <code>data[].version</code> configurations. However, <code>data[].property</code> is ignored.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: fake\n kind: ClusterSecretStore\n target:\n name: secret-to-be-created\n data:\n - secretKey: foo_bar\n remoteRef:\n key: /foo/bar\n version: v1\n dataFrom:\n - extract:\n key: /foo/baz\n version: v1\n</code></pre> <p>This results in the following secret:</p> <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: secret-to-be-created\n namespace: default\ndata:\n foo_bar: SEVMTE8x # HELLO1 (via data)\n john: ZG9l #doe (via dataFrom)\n</code></pre>"},{"location":"provider/fortanix/","title":"Fortanix","text":""},{"location":"provider/fortanix/#fortanix-dsm-sdkms","title":"Fortanix DSM / SDKMS","text":"<p>Populate kubernetes secrets from OPAQUE or SECRET security objects in Fortanix.</p>"},{"location":"provider/fortanix/#authentication","title":"Authentication","text":"<p>SDKMS Application API Key</p>"},{"location":"provider/fortanix/#creating-a-secretstore","title":"Creating a SecretStore","text":"<pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: secret-store\nspec:\n provider:\n fortanix:\n apiUrl: &lt;HOST_OF_SDKMS_API&gt;\n apiKey:\n secretRef:\n name: &lt;NAME_OF_KUBE_SECRET&gt;\n key: &lt;KEY_IN_KUBE_SECRET&gt;\n</code></pre>"},{"location":"provider/fortanix/#referencing-secrets","title":"Referencing Secrets","text":"<pre><code># Raw stored value\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: secret\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: secret-store\n data:\n - secretKey: &lt;KEY_IN_KUBE_SECRET&gt;\n remoteRef:\n key: &lt;SDKMS_SECURITY_OBJECT_NAME&gt;\n---\n# From stored key-value JSON\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: secret-from-property\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: secret-store\n data:\n - secretKey: &lt;KEY_IN_KUBE_SECRET&gt;\n remoteRef:\n key: &lt;SDKMS_SECURITY_OBJECT_NAME&gt;\n property: &lt;SECURITY_OBJECT_VALUE_INNER_PROPERTY&gt;\n---\n# Extract all keys from stored key-value JSON\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: secret-from-extract\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: secret-store\n dataFrom:\n - extract:\n key: &lt;SDKMS_SECURITY_OBJECT_NAME&gt;\n</code></pre>"},{"location":"provider/gitlab-variables/","title":"GitLab Variables","text":""},{"location":"provider/gitlab-variables/#gitlab-variables","title":"GitLab Variables","text":"<p>External Secrets Operator integrates with GitLab to sync GitLab Project Variables API and/or GitLab Group Variables API to secrets held on the Kubernetes cluster.</p>"},{"location":"provider/gitlab-variables/#configuring-gitlab","title":"Configuring GitLab","text":"<p>The GitLab API requires an access token, project ID and/or groupIDs.</p> <p>To create a new access token, go to your user settings and select 'access tokens'. Give your token a name, expiration date, and select the permissions required (Note 'api' is required).</p> <p></p> <p>Click 'Create personal access token', and your token will be generated and displayed on screen. Copy or save this token since you can't access it again. </p>"},{"location":"provider/gitlab-variables/#access-token-secret","title":"Access Token secret","text":"<p>Create a secret containing your access token:</p> <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: gitlab-secret\n labels: \n type: gitlab\ntype: Opaque \nstringData:\n token: \"**access token goes here**\"\n</code></pre>"},{"location":"provider/gitlab-variables/#configuring-the-secret-store","title":"Configuring the secret store","text":"<p>Be sure the <code>gitlab</code> provider is listed in the <code>Kind=SecretStore</code> and the ProjectID is set. If you are not using <code>https://gitlab.com</code>, you must set the <code>url</code> field as well.</p> <p>In order to sync group variables <code>inheritFromGroups</code> must be true or <code>groupIDs</code> have to be defined.</p> <p>In case you have defined multiple environments in Gitlab, the secret store should be constrained to a specific <code>environment_scope</code>.</p> <p><pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: gitlab-secret-store\nspec:\n provider:\n # provider type: gitlab\n gitlab:\n # url: https://gitlab.mydomain.com/\n auth:\n SecretRef:\n accessToken:\n name: gitlab-secret\n key: token\n projectID: \"**project ID goes here**\"\n groupIDs: \"**groupID(s) go here**\"\n inheritFromGroups: \"**automatically looks for variables in parent groups**\"\n environment: \"**environment scope goes here**\"\n</code></pre> NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>accessToken</code> with the namespace where the secret resides.</p> <p>Your project ID can be found on your project's page. </p>"},{"location":"provider/gitlab-variables/#creating-external-secret","title":"Creating external secret","text":"<p>To sync a GitLab variable to a secret on the Kubernetes cluster, a <code>Kind=ExternalSecret</code> is needed.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: gitlab-external-secret-example\nspec:\n refreshInterval: 1h\n\n secretStoreRef:\n kind: SecretStore\n name: gitlab-secret-store # Must match SecretStore on the cluster\n\n target:\n name: gitlab-secret-to-create # Name for the secret to be created on the cluster\n creationPolicy: Owner\n\n data:\n - secretKey: secretKey # Key given to the secret to be created on the cluster\n remoteRef: \n key: myGitlabVariable # Key of the variable on Gitlab\n</code></pre>"},{"location":"provider/gitlab-variables/#using-datafrom","title":"Using DataFrom","text":"<p>DataFrom can be used to get a variable as a JSON string and attempt to parse it.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: gitlab-external-secret-example\nspec:\n refreshInterval: 1h\n\n secretStoreRef:\n kind: SecretStore\n name: gitlab-secret-store # Must match SecretStore on the cluster\n\n target:\n name: gitlab-secret-to-create # Name for the secret to be created on the cluster\n creationPolicy: Owner\n\n # each secret name in the KV will be used as the secret key in the SECRET k8s target object\n dataFrom:\n - extract:\n key: \"myJsonVariable\" # Key of the variable on Gitlab\n</code></pre>"},{"location":"provider/gitlab-variables/#getting-the-kubernetes-secret","title":"Getting the Kubernetes secret","text":"<p>The operator will fetch the project variable and inject it as a <code>Kind=Secret</code>. <pre><code>kubectl get secret gitlab-secret-to-create -o jsonpath='{.data.secretKey}' | base64 -d\n</code></pre></p>"},{"location":"provider/google-secrets-manager/","title":"Google Cloud Secret Manager","text":""},{"location":"provider/google-secrets-manager/#google-cloud-secret-manager","title":"Google Cloud Secret Manager","text":"<p>External Secrets Operator integrates with GCP Secret Manager for secret management.</p>"},{"location":"provider/google-secrets-manager/#authentication","title":"Authentication","text":""},{"location":"provider/google-secrets-manager/#workload-identity","title":"Workload Identity","text":"<p>Your Google Kubernetes Engine (GKE) applications can consume GCP services like Secrets Manager without using static, long-lived authentication tokens. This is our recommended approach of handling credentials in GCP. ESO offers two options for integrating with GKE workload identity: pod-based workload identity and using service accounts directly. Before using either way you need to create a service account - this is covered below.</p>"},{"location":"provider/google-secrets-manager/#creating-workload-identity-service-accounts","title":"Creating Workload Identity Service Accounts","text":"<p>You can find the documentation for Workload Identity here. We will walk you through how to navigate it here.</p> <p>Search the document for this editable values and change them to your values: Note: If you have installed ESO, a serviceaccount has already been created. You can either patch the existing <code>external-secrets</code> SA or create a new one that fits your needs.</p> <ul> <li><code>CLUSTER_NAME</code>: The name of your cluster</li> <li><code>PROJECT_ID</code>: Your project ID (not your Project number nor your Project name)</li> <li><code>K8S_NAMESPACE</code>: For us following these steps here it will be <code>es</code>, but this will be the namespace where you deployed the external-secrets operator</li> <li><code>KSA_NAME</code>: external-secrets (if you are not creating a new one to attach to the deployment)</li> <li><code>GSA_NAME</code>: external-secrets for simplicity, or something else if you have to follow different naming conventions for cloud resources</li> <li><code>ROLE_NAME</code>: should be <code>roles/secretmanager.secretAccessor</code> - so you make the pod only be able to access secrets on Secret Manager</li> </ul>"},{"location":"provider/google-secrets-manager/#using-service-accounts-directly","title":"Using Service Accounts directly","text":"<p>Let's assume you have created a service account correctly and attached a appropriate workload identity. It should roughly look like this:</p> <pre><code>apiVersion: v1\nkind: ServiceAccount\nmetadata:\n name: external-secrets\n namespace: es\n annotations:\n iam.gke.io/gcp-service-account: example-team-a@my-project.iam.gserviceaccount.com\n</code></pre> <p>You can reference this particular ServiceAccount in a <code>SecretStore</code> or <code>ClusterSecretStore</code>. It's important that you also set the <code>projectID</code>, <code>clusterLocation</code> and <code>clusterName</code>. The Namespace on the <code>serviceAccountRef</code> is ignored when using a <code>SecretStore</code> resource. This is needed to isolate the namespaces properly.</p> <p>When filling <code>clusterLocation</code> parameter keep in mind if it is Regional or Zonal cluster.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ClusterSecretStore\nmetadata:\n name: gcp-store\nspec:\n provider:\n gcpsm:\n projectID: alphabet-123\n auth:\n workloadIdentity:\n # name of the cluster Location, region or zone\n clusterLocation: europe-central2\n # name of the GKE cluster\n clusterName: alpha-cluster-42\n # projectID of the cluster (if omitted defaults to spec.provider.gcpsm.projectID)\n clusterProjectID: my-cluster-project\n # reference the sa from above\n serviceAccountRef:\n name: team-a\n namespace: team-a\n</code></pre> <p>You need to give the Google service account the <code>roles/iam.serviceAccountTokenCreator</code> role so it can generate a service account token for you (not necessary in the Pod-based Workload Identity bellow)</p>"},{"location":"provider/google-secrets-manager/#using-pod-based-workload-identity","title":"Using Pod-based Workload Identity","text":"<p>You can attach a Workload Identity directly to the ESO pod. ESO then has access to all the APIs defined in the attached service account policy. You attach the workload identity by (1) creating a service account with a attached workload identity (described above) and (2) using this particular service account in the pod's <code>serviceAccountName</code> field.</p> <p>For this example we will assume that you installed ESO using helm and that you named the chart installation <code>external-secrets</code> and the namespace where it lives <code>es</code> like:</p> <pre><code>helm install external-secrets external-secrets/external-secrets --namespace es\n</code></pre> <p>Then most of the resources would have this name, the important one here being the k8s service account attached to the external-secrets operator deployment:</p> <pre><code># ...\n containers:\n - image: ghcr.io/external-secrets/external-secrets:vVERSION\n name: external-secrets\n ports:\n - containerPort: 8080\n protocol: TCP\n restartPolicy: Always\n schedulerName: default-scheduler\n serviceAccount: external-secrets\n serviceAccountName: external-secrets # &lt;--- here\n</code></pre> <p>The pod now has the identity. Now you need to configure the <code>SecretStore</code>. You just need to set the <code>projectID</code>, all other fields can be omitted.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: gcp-store\nspec:\n provider:\n gcpsm:\n projectID: alphabet-123\n</code></pre>"},{"location":"provider/google-secrets-manager/#gcp-service-account-authentication","title":"GCP Service Account authentication","text":"<p>You can use GCP Service Account to authenticate with GCP. These are static, long-lived credentials. A GCP Service Account is a JSON file that needs to be stored in a <code>Kind=Secret</code>. ESO will use that Secret to authenticate with GCP. See here how you manage GCP Service Accounts. After creating a GCP Service account go to <code>IAM &amp; Admin</code> web UI, click <code>ADD ANOTHER ROLE</code> button, add <code>Secret Manager Secret Accessor</code> role to this service account. The <code>Secret Manager Secret Accessor</code> role is required to access secrets.</p> <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: gcpsm-secret\n labels:\n type: gcpsm\ntype: Opaque\nstringData:\n secret-access-credentials: |-\n {\n \"type\": \"service_account\",\n \"project_id\": \"external-secrets-operator\",\n \"private_key_id\": \"\",\n \"private_key\": \"-----BEGIN PRIVATE KEY-----\\nA key\\n-----END PRIVATE KEY-----\\n\",\n \"client_email\": \"test-service-account@external-secrets-operator.iam.gserviceaccount.com\",\n \"client_id\": \"client ID\",\n \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n \"token_uri\": \"https://oauth2.googleapis.com/token\",\n \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/test-service-account%40external-secrets-operator.iam.gserviceaccount.com\"\n }\n</code></pre>"},{"location":"provider/google-secrets-manager/#update-secret-store","title":"Update secret store","text":"<p>Be sure the <code>gcpsm</code> provider is listed in the <code>Kind=SecretStore</code></p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: gcp-store\n namespace: example\nspec:\n provider:\n gcpsm: # gcpsm provider\n auth:\n secretRef:\n secretAccessKeySecretRef:\n name: gcpsm-secret # secret name containing SA key\n key: secret-access-credentials # key name containing SA key\n projectID: alphabet-123 # name of Google Cloud project\n</code></pre> <p>NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> for <code>SecretAccessKeyRef</code> with the namespace of the secret that we just created.</p>"},{"location":"provider/google-secrets-manager/#creating-external-secret","title":"Creating external secret","text":"<p>To create a kubernetes secret from the GCP Secret Manager secret a <code>Kind=ExternalSecret</code> is needed.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: database-credentials\nspec:\n refreshInterval: 1h # rate SecretManager pulls GCPSM\n secretStoreRef:\n kind: SecretStore\n name: gcp-store # name of the SecretStore (or kind specified)\n target:\n name: database-credentials # name of the k8s Secret to be created\n creationPolicy: Owner\n data:\n - secretKey: database_username\n remoteRef:\n key: database_username # name of the GCPSM secret key\n - secretKey: database_password\n remoteRef:\n key: database_password # name of the GCPSM secret key\n</code></pre> <p>The operator will fetch the GCP Secret Manager secret and inject it as a <code>Kind=Secret</code> <pre><code>kubectl get secret secret-to-be-created -n &lt;namespace&gt; -o jsonpath='{.data.dev-secret-test}' | base64 -d\n</code></pre></p>"},{"location":"provider/hashicorp-vault/","title":"HashiCorp Vault","text":""},{"location":"provider/hashicorp-vault/#hashicorp-vault","title":"Hashicorp Vault","text":"<p>External Secrets Operator integrates with HashiCorp Vault for secret management.</p> <p>The KV Secrets Engine is the only one supported by this provider. For other secrets engines, please refer to the Vault Generator.</p>"},{"location":"provider/hashicorp-vault/#example","title":"Example","text":"<p>First, create a SecretStore with a vault backend. For the sake of simplicity we'll use a static token <code>root</code>:</p> <p><pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: vault-backend\nspec:\n provider:\n vault:\n server: \"http://my.vault.server:8200\"\n path: \"secret\"\n # Version is the Vault KV secret engine version.\n # This can be either \"v1\" or \"v2\", defaults to \"v2\"\n version: \"v2\"\n auth:\n # points to a secret that contains a vault token\n # https://www.vaultproject.io/docs/auth/token\n tokenSecretRef:\n name: \"vault-token\"\n key: \"token\"\n---\napiVersion: v1\nkind: Secret\nmetadata:\n name: vault-token\ndata:\n token: cm9vdA== # \"root\"\n</code></pre> NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> for <code>tokenSecretRef</code> with the namespace of the secret that we just created.</p> <p>Then create a simple k/v pair at path <code>secret/foo</code>:</p> <pre><code>vault kv put secret/foo my-value=s3cr3t\n</code></pre> <p>Can check kv version using following and check for <code>Options</code> column, it should indicate [version:2]:</p> <pre><code>vault secrets list -detailed\n</code></pre> <p>If you are using version: 1, just remember to update your SecretStore manifest appropriately</p> <p>Now create a ExternalSecret that uses the above SecretStore:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: vault-example\nspec:\n refreshInterval: \"15s\"\n secretStoreRef:\n name: vault-backend\n kind: SecretStore\n target:\n name: example-sync\n data:\n - secretKey: foobar\n remoteRef:\n key: foo\n property: my-value\n\n # metadataPolicy to fetch all the labels in JSON format\n - secretKey: tags\n remoteRef:\n metadataPolicy: Fetch\n key: foo\n\n # metadataPolicy to fetch a specific label (dev) from the source secret\n - secretKey: developer\n remoteRef:\n metadataPolicy: Fetch\n key: foo\n property: dev\n\n---\n# That will automatically create a Kubernetes Secret with:\n# apiVersion: v1\n# kind: Secret\n# metadata:\n# name: example-sync\n# data:\n# foobar: czNjcjN0\n</code></pre> <p>Keep in mind that fetching the labels with <code>metadataPolicy: Fetch</code> only works with KV sercrets engine version v2.</p>"},{"location":"provider/hashicorp-vault/#fetching-raw-values","title":"Fetching Raw Values","text":"<p>You can fetch all key/value pairs for a given path If you leave the <code>remoteRef.property</code> empty. This returns the json-encoded secret value for that path.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: vault-example\nspec:\n # ...\n data:\n - secretKey: foobar\n remoteRef:\n key: /dev/package.json\n</code></pre>"},{"location":"provider/hashicorp-vault/#nested-values","title":"Nested Values","text":"<p>Vault supports nested key/value pairs. You can specify a gjson expression at <code>remoteRef.property</code> to get a nested value.</p> <p>Given the following secret - assume its path is <code>/dev/config</code>: <pre><code>{\n \"foo\": {\n \"nested\": {\n \"bar\": \"mysecret\"\n }\n }\n}\n</code></pre></p> <p>You can set the <code>remoteRef.property</code> to point to the nested key using a gjson expression. <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: vault-example\nspec:\n # ...\n data:\n - secretKey: foobar\n remoteRef:\n key: /dev/config\n property: foo.nested.bar\n---\n# creates a secret with:\n# foobar=mysecret\n</code></pre></p> <p>If you would set the <code>remoteRef.property</code> to just <code>foo</code> then you would get the json-encoded value of that property: <code>{\"nested\":{\"bar\":\"mysecret\"}}</code>.</p>"},{"location":"provider/hashicorp-vault/#multiple-nested-values","title":"Multiple nested Values","text":"<p>You can extract multiple keys from a nested secret using <code>dataFrom</code>.</p> <p>Given the following secret - assume its path is <code>/dev/config</code>: <pre><code>{\n \"foo\": {\n \"nested\": {\n \"bar\": \"mysecret\",\n \"baz\": \"bang\"\n }\n }\n}\n</code></pre></p> <p>You can set the <code>remoteRef.property</code> to point to the nested key using a gjson expression. <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: vault-example\nspec:\n # ...\n dataFrom:\n - extract:\n key: /dev/config\n property: foo.nested\n</code></pre></p> <p>That results in a secret with these values: <pre><code>bar=mysecret\nbaz=bang\n</code></pre></p>"},{"location":"provider/hashicorp-vault/#getting-multiple-secrets","title":"Getting multiple secrets","text":"<p>You can extract multiple secrets from Hashicorp vault by using <code>dataFrom.Find</code></p> <p>Currently, <code>dataFrom.Find</code> allows users to fetch secret names that match a given regexp pattern, or fetch secrets whose <code>custom_metadata</code> tags match a predefined set.</p> <p>Warning</p> <p>The way hashicorp Vault currently allows LIST operations is through the existence of a secret metadata. If you delete the secret, you will also need to delete the secret's metadata or this will currently make Find operations fail.</p> <p>Given the following secret - assume its path is <code>/dev/config</code>: <pre><code>{\n \"foo\": {\n \"nested\": {\n \"bar\": \"mysecret\",\n \"baz\": \"bang\"\n }\n }\n}\n</code></pre></p> <p>Also consider the following secret has the following <code>custom_metadata</code>: <pre><code>{\n \"environment\": \"dev\",\n \"component\": \"app-1\"\n}\n</code></pre></p> <p>It is possible to find this secret by all the following possibilities: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: vault-example\nspec:\n # ...\n dataFrom:\n - find: #will return every secret with 'dev' in it (including paths)\n name:\n regexp: dev\n - find: #will return every secret matching environment:dev tags from dev/ folder and beyond\n tags:\n environment: dev\n</code></pre> will generate a secret with: <pre><code>{\n \"dev_config\":\"{\\\"foo\\\":{\\\"nested\\\":{\\\"bar\\\":\\\"mysecret\\\",\\\"baz\\\":\\\"bang\\\"}}}\"\n}\n</code></pre></p> <p>Currently, <code>Find</code> operations are recursive throughout a given vault folder, starting on <code>provider.Path</code> definition. It is recommended to narrow down the scope of search by setting a <code>find.path</code> variable. This is also useful to automatically reduce the resulting secret key names: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: vault-example\nspec:\n # ...\n dataFrom:\n - find: #will return every secret from dev/ folder\n path: dev\n name:\n regexp: \".*\"\n - find: #will return every secret matching environment:dev tags from dev/ folder\n path: dev\n tags:\n environment: dev\n</code></pre> Will generate a secret with: <pre><code>{\n \"config\":\"{\\\"foo\\\": {\\\"nested\\\": {\\\"bar\\\": \\\"mysecret\\\",\\\"baz\\\": \\\"bang\\\"}}}\"\n}\n</code></pre></p>"},{"location":"provider/hashicorp-vault/#authentication","title":"Authentication","text":"<p>We support five different modes for authentication: token-based, appRole, kubernetes-native, ldap, userPass, jwt/oidc, awsAuth and tlsCert, each one comes with it's own trade-offs. Depending on the authentication method you need to adapt your environment.</p> <p>If you're using Vault namespaces, you can authenticate into one namespace and use the vault token against a different namespace, if desired.</p>"},{"location":"provider/hashicorp-vault/#token-based-authentication","title":"Token-based authentication","text":"<p>A static token is stored in a <code>Kind=Secret</code> and is used to authenticate with vault.</p> <p><pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: vault-backend\n namespace: example\nspec:\n provider:\n vault:\n server: \"https://vault.acme.org\"\n path: \"secret\"\n version: \"v2\"\n auth:\n # points to a secret that contains a vault token\n # https://www.vaultproject.io/docs/auth/token\n tokenSecretRef:\n name: \"my-secret\"\n key: \"vault-token\"\n</code></pre> NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>tokenSecretRef</code> with the namespace where the secret resides.</p>"},{"location":"provider/hashicorp-vault/#approle-authentication-example","title":"AppRole authentication example","text":"<p>AppRole authentication reads the secret id from a <code>Kind=Secret</code> and uses the specified <code>roleId</code> to aquire a temporary token to fetch secrets.</p> <p><pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: vault-backend\n namespace: example\nspec:\n provider:\n vault:\n server: \"https://vault.acme.org\"\n path: \"secret\"\n version: \"v2\"\n auth:\n # VaultAppRole authenticates with Vault using the\n # App Role auth mechanism\n # https://www.vaultproject.io/docs/auth/approle\n appRole:\n # Path where the App Role authentication backend is mounted\n path: \"approle\"\n # RoleID configured in the App Role authentication backend\n roleId: \"db02de05-fa39-4855-059b-67221c5c2f63\"\n # Reference to a key in a K8 Secret that contains the App Role SecretId\n secretRef:\n name: \"my-secret\"\n key: \"secret-id\"\n</code></pre> NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>secretRef</code> with the namespace where the secret resides.</p>"},{"location":"provider/hashicorp-vault/#kubernetes-authentication","title":"Kubernetes authentication","text":"<p>Kubernetes-native authentication has three options of obtaining credentials for vault:</p> <ol> <li>by using a service account jwt referenced in <code>serviceAccountRef</code></li> <li>by using the jwt from a <code>Kind=Secret</code> referenced by the <code>secretRef</code></li> <li>by using transient credentials from the mounted service account token within the external-secrets operator</li> </ol> <p>Vault validates the service account token by using the TokenReview API. \u26a0\ufe0f You have to bind the <code>system:auth-delegator</code> ClusterRole to the service account that is used for authentication. Please follow the Vault documentation.</p> <p><pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: vault-backend\n namespace: example\nspec:\n provider:\n vault:\n server: \"https://vault.acme.org\"\n path: \"secret\"\n version: \"v2\"\n auth:\n # Authenticate against Vault using a Kubernetes ServiceAccount\n # token stored in a Secret.\n # https://www.vaultproject.io/docs/auth/kubernetes\n kubernetes:\n # Path where the Kubernetes authentication backend is mounted in Vault\n mountPath: \"kubernetes\"\n # A required field containing the Vault Role to assume.\n role: \"demo\"\n # Optional service account field containing the name\n # of a kubernetes ServiceAccount\n serviceAccountRef:\n name: \"my-sa\"\n # Optional secret field containing a Kubernetes ServiceAccount JWT\n # used for authenticating with Vault\n secretRef:\n name: \"my-secret\"\n key: \"vault\"\n</code></pre> NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>serviceAccountRef</code> or in <code>secretRef</code>, if used.</p>"},{"location":"provider/hashicorp-vault/#ldap-authentication","title":"LDAP authentication","text":"<p>LDAP authentication uses username/password pair to get an access token. Username is stored directly in a <code>Kind=SecretStore</code> or <code>Kind=ClusterSecretStore</code> resource, password is stored in a <code>Kind=Secret</code> referenced by the <code>secretRef</code>.</p> <p><pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: vault-backend\n namespace: example\nspec:\n provider:\n vault:\n server: \"https://vault.acme.org\"\n path: \"secret\"\n version: \"v2\"\n auth:\n # VaultLdap authenticates with Vault using the LDAP auth mechanism\n # https://www.vaultproject.io/docs/auth/ldap\n ldap:\n # Path where the LDAP authentication backend is mounted\n path: \"ldap\"\n # LDAP username\n username: \"username\"\n secretRef:\n name: \"my-secret\"\n key: \"ldap-password\"\n</code></pre> NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>secretRef</code> with the namespace where the secret resides.</p>"},{"location":"provider/hashicorp-vault/#userpass-authentication","title":"UserPass authentication","text":"<p>UserPass authentication uses username/password pair to get an access token. Username is stored directly in a <code>Kind=SecretStore</code> or <code>Kind=ClusterSecretStore</code> resource, password is stored in a <code>Kind=Secret</code> referenced by the <code>secretRef</code>.</p> <p><pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: vault-backend\n namespace: example\nspec:\n provider:\n vault:\n server: \"https://vault.acme.org\"\n path: \"secret\"\n version: \"v2\"\n auth:\n # VaultUserPass authenticates with Vault using the UserPass auth mechanism\n # https://www.vaultproject.io/docs/auth/userpass\n userPass:\n # Path where the UserPass authentication backend is mounted\n path: \"userpass\"\n username: \"username\"\n secretRef:\n name: \"my-secret\"\n key: \"password\"\n</code></pre> NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>secretRef</code> with the namespace where the secret resides.</p>"},{"location":"provider/hashicorp-vault/#jwtoidc-authentication","title":"JWT/OIDC authentication","text":"<p>JWT/OIDC uses either a JWT token stored in a <code>Kind=Secret</code> and referenced by the <code>secretRef</code> or a temporary Kubernetes service account token retrieved via the <code>TokenRequest</code> API. Optionally a <code>role</code> field can be defined in a <code>Kind=SecretStore</code> or <code>Kind=ClusterSecretStore</code> resource.</p> <p><pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: vault-backend\n namespace: example\nspec:\n provider:\n vault:\n server: \"https://vault.acme.org\"\n path: \"secret\"\n version: \"v2\"\n auth:\n # VaultJwt authenticates with Vault using the JWT/OIDC auth mechanism\n # https://www.vaultproject.io/docs/auth/jwt\n jwt:\n # Path where the JWT authentication backend is mounted\n path: \"jwt\"\n # JWT role configured in a Vault server, optional.\n role: \"vault-jwt-role\"\n\n # Retrieve JWT token from a Kubernetes secret\n secretRef:\n name: \"my-secret\"\n key: \"jwt-token\"\n\n # ... or retrieve a Kubernetes service account token via the `TokenRequest` API\n kubernetesServiceAccountToken:\n serviceAccountRef:\n name: \"my-sa\"\n # `audiences` defaults to `[\"vault\"]` it not supplied\n audiences:\n - vault\n # `expirationSeconds` defaults to 10 minutes if not supplied\n expirationSeconds: 600\n</code></pre> NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>secretRef</code> with the namespace where the secret resides.</p>"},{"location":"provider/hashicorp-vault/#aws-iam-authentication","title":"AWS IAM authentication","text":"<p>AWS IAM uses either a set of AWS Programmatic access credentials stored in a <code>Kind=Secret</code> and referenced by the <code>secretRef</code> or by getting the authentication token from an IRSA enabled service account</p>"},{"location":"provider/hashicorp-vault/#tls-certificates-authentication","title":"TLS certificates authentication","text":"<p>TLS certificates auth method allows authentication using SSL/TLS client certificates which are either signed by a CA or self-signed. SSL/TLS client certificates are defined as having an ExtKeyUsage extension with the usage set to either ClientAuth or Any.</p>"},{"location":"provider/hashicorp-vault/#mutual-authentication-mtls","title":"Mutual authentication (mTLS)","text":"<p>Under specific compliance requirements, the Vault server can be set up to enforce mutual authentication from clients across all APIs by configuring the server with <code>tls_require_and_verify_client_cert = true</code>. This configuration differs fundamentally from the TLS certificates auth method. While the TLS certificates auth method allows the issuance of a Vault token through the <code>/v1/auth/cert/login</code> API, the mTLS configuration solely focuses on TLS transport layer authentication and lacks any authorization-related capabilities. It's important to note that the Vault token must still be included in the request, following any of the supported authentication methods mentioned earlier.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: vault-backend\n namespace: example\nspec:\n provider:\n vault:\n server: \"https://vault.acme.org\"\n path: \"secret\"\n version: \"v2\"\n\n # client TLS related configuration\n caBundle: \"...\"\n tls:\n clientCert:\n name: \"my-cert-secret\"\n key: \"tls.crt\"\n secretRef:\n name: \"my-cert-secret\"\n key: \"tls.key\"\n\n # the authentication methods are not really related to the client TLS configuration\n auth:\n ...\n</code></pre>"},{"location":"provider/hashicorp-vault/#access-key-id-secret-access-key","title":"Access Key ID &amp; Secret Access Key","text":"<p>You can store Access Key ID &amp; Secret Access Key in a <code>Kind=Secret</code> and reference it from a SecretStore.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: vault-backend-aws-iam\nspec:\n provider:\n vault:\n server: \"http://my.vault.server:8200\"\n path: secret\n version: v2\n namespace: &lt;vault_namespace&gt;\n auth:\n iam:\n # Path where the AWS auth method is enabled in Vault, e.g: \"aws/\". Defaults to aws\n path: aws\n # AWS Region. Defaults to us-east-1\n region: us-east-1\n # optional: assume role before fetching secrets\n role: arn:aws:iam::1234567890:role/role-a\n # Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine\n vaultRole: vault-role-for-aws-iam-auth\n # Optional. Placeholder to supply header X-Vault-AWS-IAM-Server-ID. It is an additional (optional) header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws\n vaultAwsIamServerID: example-vaultAwsIamServerID\n secretRef: #Use this method when you have static AWS creds.\n accessKeyIDSecretRef:\n name: vault-iam-creds-secret\n key: access-key\n secretAccessKeySecretRef:\n name: vault-iam-creds-secret\n key: secret-access-key\n sessionTokenSecretRef:\n name: vault-iam-creds-secret\n key: secret-session-token\n</code></pre> <p>NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>accessKeyIDSecretRef</code>, <code>secretAccessKeySecretRef</code> with the namespaces where the secrets reside.</p>"},{"location":"provider/hashicorp-vault/#eks-service-account-credentials","title":"EKS Service Account credentials","text":"<p>This feature lets you use short-lived service account tokens to authenticate with AWS. You must have Service Account Volume Projection enabled - it is by default on EKS. See EKS guide on how to set up IAM roles for service accounts.</p> <p>The big advantage of this approach is that ESO runs without any credentials.</p> <pre><code>apiVersion: v1\nkind: ServiceAccount\nmetadata:\n annotations:\n eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-irsa-enabled-role\n name: my-serviceaccount\n namespace: default\n</code></pre> <p>Reference the service account from above in the Secret Store:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: vault-backend-aws-iam\nspec:\n provider:\n vault:\n server: \"http://my.vault.server:8200\"\n path: secret\n version: v2\n namespace: &lt;vault_namespace&gt;\n auth:\n iam:\n # Path where the AWS auth method is enabled in Vault, e.g: \"aws/\". Defaults to aws\n path: aws\n # AWS Region. Defaults to us-east-1\n region: us-east-1\n # Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine\n vaultRole: vault-role-for-aws-iam-auth\n # Optional. Placeholder to supply header X-Vault-AWS-IAM-Server-ID. It is an additional (optional) header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws\n vaultAwsIamServerID: example-vaultAwsIamServerID\n jwt:\n serviceAccountRef:\n name: my-serviceaccount #Provide service account with IRSA enabled\n</code></pre>"},{"location":"provider/hashicorp-vault/#controllers-pod-identity","title":"Controller's Pod Identity","text":"<p>This is basicially a zero-configuration authentication approach that inherits the credentials from the controller's pod identity</p> <p>This approach assumes that appropriate IRSA setup is done controller's pod (i.e. IRSA enabled IAM role is created appropriately and controller's service account is annotated appropriately with the annotation \"eks.amazonaws.com/role-arn\" to enable IRSA)</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: vault-backend-aws-iam\nspec:\n provider:\n vault:\n server: \"http://my.vault.server:8200\"\n path: secret\n version: v2\n namespace: &lt;vault_namespace&gt;\n auth:\n iam:\n # Path where the AWS auth method is enabled in Vault, e.g: \"aws/\". Defaults to aws\n path: aws\n # AWS Region. Defaults to us-east-1\n region: us-east-1\n # Vault Role. In vault, a role describes an identity with a set of permissions, groups, or policies you want to attach a user of the secrets engine\n vaultRole: vault-role-for-aws-iam-auth\n # Optional. Placeholder to supply header X-Vault-AWS-IAM-Server-ID. It is an additional (optional) header used by Vault IAM auth method to mitigate against different types of replay attacks. More details here: https://developer.hashicorp.com/vault/docs/auth/aws\n vaultAwsIamServerID: example-vaultAwsIamServerID\n</code></pre> <p>NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> for <code>serviceAccountRef</code> with the namespace where the service account resides.</p> <p><pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: vault-backend\n namespace: example\nspec:\n provider:\n vault:\n server: \"https://vault.acme.org\"\n path: \"secret\"\n version: \"v2\"\n auth:\n # VaultJwt authenticates with Vault using the JWT/OIDC auth mechanism\n # https://www.vaultproject.io/docs/auth/jwt\n jwt:\n # Path where the JWT authentication backend is mounted\n path: \"jwt\"\n # JWT role configured in a Vault server, optional.\n role: \"vault-jwt-role\"\n\n # Retrieve JWT token from a Kubernetes secret\n secretRef:\n name: \"my-secret\"\n key: \"jwt-token\"\n\n # ... or retrieve a Kubernetes service account token via the `TokenRequest` API\n kubernetesServiceAccountToken:\n serviceAccountRef:\n name: \"my-sa\"\n # `audiences` defaults to `[\"vault\"]` it not supplied\n audiences:\n - vault\n # `expirationSeconds` defaults to 10 minutes if not supplied\n expirationSeconds: 600\n</code></pre> NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>secretRef</code> with the namespace where the secret resides.</p>"},{"location":"provider/hashicorp-vault/#pushsecret","title":"PushSecret","text":"<p>Vault supports PushSecret features which allow you to sync a given Kubernetes secret key into a Hashicorp vault secret. To do so, it is expected that the secret key is a valid JSON object or that the <code>property</code> attribute has been specified under the <code>remoteRef</code>. To use PushSecret, you need to give <code>create</code>, <code>read</code> and <code>update</code> permissions to the path where you want to push secrets for both <code>data</code> and <code>metadata</code> of the secret. Use it with care!</p> <p>Note</p> <p>Since Vault KV v1 API is not supported with storing secrets metadata, PushSecret will add a <code>custom_metadata</code> map to each secret in Vault that he will manage. It means pushing secret keys named <code>custom_metadata</code> is not supported with Vault KV v1.</p> <p>Here is an example of how to set up <code>PushSecret</code>:</p> <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: source-secret\n namespace: default\nstringData:\n source-key1: \"{\\\"foo\\\":\\\"bar\\\"}\" # Needs to be a JSON\n source-key2: bar # Could be a plain string\n---\napiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: pushsecret-example\n namespace: default\nspec:\n refreshInterval: 10s\n secretStoreRefs:\n - name: vault-secretstore\n kind: SecretStore\n selector:\n secret:\n name: source-secret\n data:\n - match:\n secretKey: source-key1\n remoteRef:\n remoteKey: vault/secret1\n - match:\n secretKey: source-key2\n remoteRef:\n remoteKey: vault/secret2\n property: foo\n</code></pre> <p>Note that in this example, we are generating two secrets in the target vault with the same structure but using different input formats.</p>"},{"location":"provider/hashicorp-vault/#vault-enterprise","title":"Vault Enterprise","text":""},{"location":"provider/hashicorp-vault/#eventual-consistency-and-performance-standby-nodes","title":"Eventual Consistency and Performance Standby Nodes","text":"<p>When using Vault Enterprise with performance standby nodes, any follower can handle read requests immediately after the provider has authenticated. Since Vault becomes eventually consistent in this mode, these requests can fail if the login has not yet propagated to each server's local state.</p> <p>Below are two different solutions to this scenario. You'll need to review them and pick the best fit for your environment and Vault configuration.</p>"},{"location":"provider/hashicorp-vault/#vault-namespaces","title":"Vault Namespaces","text":"<p>Vault namespaces are an enterprise feature that support multi-tenancy. You can specify a vault namespace using the <code>namespace</code> property when you define a SecretStore:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: vault-backend\nspec:\n provider:\n vault:\n server: \"http://my.vault.server:8200\"\n # See https://www.vaultproject.io/docs/enterprise/namespaces\n namespace: \"ns1\"\n path: \"secret\"\n version: \"v2\"\n auth:\n # ...\n</code></pre>"},{"location":"provider/hashicorp-vault/#authenticating-into-a-different-namespace","title":"Authenticating into a different namespace","text":"<p>In some situations your authentication backend may be in one namespace, and your secrets in another. You can authenticate into one namespace, and use that token against another, by setting <code>provider.vault.namespace</code> and <code>provider.vault.auth.namespace</code> to different values. If <code>provider.vault.auth.namespace</code> is unset but <code>provider.vault.namespace</code> is, it will default to the <code>provider.vault.namespace</code> value.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: vault-backend\nspec:\n provider:\n vault:\n server: \"http://my.vault.server:8200\"\n # See https://www.vaultproject.io/docs/enterprise/namespaces\n namespace: \"app-team\"\n path: \"secret\"\n version: \"v2\"\n auth:\n namespace: \"kubernetes-team\"\n # ...\n</code></pre>"},{"location":"provider/hashicorp-vault/#read-your-writes","title":"Read Your Writes","text":"<p>Vault 1.10.0 and later encodes information in the token to detect the case when a server is behind. If a Vault server does not have information about the provided token, Vault returns a 412 error so clients know to retry.</p> <p>A method supported in versions Vault 1.7 and later is to utilize the <code>X-Vault-Index</code> header returned on all write requests (including logins). Passing this header back on subsequent requests instructs the Vault client to retry the request until the server has an index greater than or equal to that returned with the last write. Obviously though, this has a performance hit because the read is blocked until the follower's local state has caught up.</p>"},{"location":"provider/hashicorp-vault/#forward-inconsistent","title":"Forward Inconsistent","text":"<p>Vault also supports proxying inconsistent requests to the current cluster leader for immediate read-after-write consistency.</p> <p>Vault 1.10.0 and later support a replication configuration that detects when forwarding should occur and does it transparently to the client.</p> <p>In Vault 1.7 forwarding can be achieved by setting the <code>X-Vault-Inconsistent</code> header to <code>forward-active-node</code>. By default, this behavior is disabled and must be explicitly enabled in the server's replication configuration.</p>"},{"location":"provider/ibm-secrets-manager/","title":"IBM Secrets Manager","text":""},{"location":"provider/ibm-secrets-manager/#ibm-cloud-secret-manager","title":"IBM Cloud Secret Manager","text":"<p>External Secrets Operator integrates with IBM Cloud Secret Manager for secret management.</p>"},{"location":"provider/ibm-secrets-manager/#authentication","title":"Authentication","text":"<p>We support API key and trusted profile container authentication for this provider.</p>"},{"location":"provider/ibm-secrets-manager/#api-key-secret","title":"API key secret","text":"<p>To generate your key (for test purposes we are going to generate from your user), first got to your (Access IAM) page:</p> <p></p> <p>On the left, click \"API Keys\", then click on \"Create\"</p> <p></p> <p>Pick a name and description for your key:</p> <p></p> <p>You have created a key. Press the eyeball to show the key. Copy or save it because keys can't be displayed or downloaded twice.</p> <p></p> <p>Create a secret containing your apiKey:</p> <pre><code>kubectl create secret generic ibm-secret --from-literal=apiKey='API_KEY_VALUE'\n</code></pre>"},{"location":"provider/ibm-secrets-manager/#trusted-profile-container-auth","title":"Trusted Profile Container Auth","text":"<p>To create the trusted profile, first got to your (Access IAM) page:</p> <p></p> <p>On the left, click \"Access groups\":</p> <p></p> <p>Pick a name and description for your group:</p> <p></p> <p>Click on \"Access\", and then on \"Assign\":</p> <p></p> <p>Click on \"Assign Access\", select \"IAM services\", and pick \"Secrets Manager\" from the pick-list:</p> <p></p> <p>Scope to \"All resources\" or \"Resources based on selected attributes\":</p> <p></p> <p>Select the \"SecretsReader\" service access policy:</p> <p></p> <p>Click \"Add\" and \"Assign\" to save the access group.</p> <p>Next, on the left, click \"Trusted profiles\":</p> <p></p> <p>Press \"Create\" and pick a name and description for your profile:</p> <p></p> <p>Scope the profile's access.</p> <p>The compute service type will be \"Red Hat OpenShift on IBM Cloud\". Additional restriction can be configured based on cloud or cluster metadata, or if \"Specific resources\" is selected, restriction to a specific cluster.</p> <p></p> <p>Click \"Add\" next to the previously created access group and then \"Create\", to associate the necessary service permissions.</p> <p></p> <p>To use the container-based authentication, it is necessary to map the API server <code>serviceAccountToken</code> auth token to the \"external-secrets\" and \"external-secrets-webhook\" deployment descriptors. Example below:</p> <pre><code>...\nspec:\n ...\n template:\n ...\n spec:\n containers:\n ...\n volumeMounts:\n - mountPath: /var/run/secrets/tokens\n name: sa-token\n ...\n volumes:\n - name: sa-token\n projected:\n defaultMode: 420\n sources:\n - serviceAccountToken:\n audience: iam\n expirationSeconds: 3600\n path: sa-token\n...\n</code></pre>"},{"location":"provider/ibm-secrets-manager/#update-secret-store","title":"Update secret store","text":"<p>Be sure the <code>ibm</code> provider is listed in the <code>Kind=SecretStore</code></p> <p><pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: ibm-store\nspec:\n provider:\n ibm:\n serviceUrl: \"https://&lt;SECRETS_MANAGER_ID&gt;.&lt;REGION&gt;.secrets-manager.appdomain.cloud\"\n auth:\n containerAuth:\n profile: \"test container auth profile\"\n tokenLocation: \"/var/run/secrets/tokens/sa-token\"\n iamEndpoint: \"https://iam.cloud.ibm.com\"\n secretRef:\n secretApiKeySecretRef:\n name: ibm-secret\n key: apiKey\n</code></pre> NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>secretApiKeySecretRef</code> with the namespace where the secret resides.</p> <p>NOTE: Only <code>secretApiKeySecretRef</code> or <code>containerAuth</code> should be specified, depending on authentication method being used.</p> <p>To find your <code>serviceURL</code>, under your Secrets Manager resource, go to \"Endpoints\" on the left.</p> <p>See here for a list of publicly available endpoints.</p> <p></p>"},{"location":"provider/ibm-secrets-manager/#secret-types","title":"Secret Types","text":"<p>We support the following secret types of IBM Secrets Manager:</p> <ul> <li><code>arbitrary</code></li> <li><code>username_password</code></li> <li><code>iam_credentials</code></li> <li><code>service_credentials</code></li> <li><code>imported_cert</code></li> <li><code>public_cert</code></li> <li><code>private_cert</code></li> <li><code>kv</code></li> </ul> <p>To define the type of secret you would like to sync you need to prefix the secret id with the desired type. If the secret type is not specified it is defaulted to <code>arbitrary</code>:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: ibm-sample\nspec:\n # [...]\n data:\n - secretKey: test\n remoteRef:\n # defaults to type=arbitrary\n key: xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n - secretKey: usr_pass\n remoteRef:\n key: username_password/yyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy\n property: username\n - secretKey: iam_cred\n remoteRef:\n key: iam_credentials/zzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz\n - secretKey: srv_cred\n remoteRef:\n key: service_credentials/zzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz\n - secretKey: imp_cert\n remoteRef:\n key: imported_cert/zzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz\n property: certificate\n - secretKey: pub_cert\n remoteRef:\n key: public_cert/zzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz\n property: certificate\n - secretKey: prvt_cert\n remoteRef:\n key: private_cert/zzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz\n property: certificate\n - secretKey: kv_without_key\n remoteRef:\n key: kv/zzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz\n - secretKey: kv_key\n remoteRef:\n key: kv/zzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz\n property: 'keyid'\n - secretKey: kv_key_with_path\n remoteRef:\n key: kv/zzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz\n property: 'key.path'\n</code></pre> <p>The behavior for the different secret types is as following:</p>"},{"location":"provider/ibm-secrets-manager/#arbitrary","title":"arbitrary","text":"<ul> <li><code>remoteRef</code> retrieves a string from secrets manager and sets it for specified <code>secretKey</code></li> <li><code>dataFrom</code> retrieves a string from secrets manager and tries to parse it as JSON object setting the key:values pairs in resulting Kubernetes secret if successful</li> </ul>"},{"location":"provider/ibm-secrets-manager/#username_password","title":"username_password","text":"<ul> <li><code>remoteRef</code> requires a <code>property</code> to be set for either <code>username</code> or <code>password</code> to retrieve respective fields from the secrets manager secret and set in specified <code>secretKey</code></li> <li><code>dataFrom</code> retrieves both <code>username</code> and <code>password</code> fields from the secrets manager secret and sets appropriate key:value pairs in the resulting Kubernetes secret</li> </ul>"},{"location":"provider/ibm-secrets-manager/#iam_credentials","title":"iam_credentials","text":"<ul> <li><code>remoteRef</code> retrieves an apikey from secrets manager and sets it for specified <code>secretKey</code></li> <li><code>dataFrom</code> retrieves an apikey from secrets manager and sets it for the <code>apikey</code> Kubernetes secret key</li> </ul>"},{"location":"provider/ibm-secrets-manager/#service_credentials","title":"service_credentials","text":"<ul> <li><code>remoteRef</code> retrieves the credentials object from secrets manager and sets it for specified <code>secretKey</code></li> <li><code>dataFrom</code> retrieves the credential object as a map from secrets manager and sets appropriate key:value pairs in the resulting Kubernetes secret</li> </ul>"},{"location":"provider/ibm-secrets-manager/#imported_cert-public_cert-and-private_cert","title":"imported_cert, public_cert, and private_cert","text":"<ul> <li><code>remoteRef</code> requires a <code>property</code> to be set for either <code>certificate</code>, <code>private_key</code> or <code>intermediate</code> to retrieve respective fields from the secrets manager secret and set in specified <code>secretKey</code></li> <li><code>dataFrom</code> retrieves all <code>certificate</code>, <code>private_key</code> and <code>intermediate</code> fields from the secrets manager secret and sets appropriate key:value pairs in the resulting Kubernetes secret</li> </ul>"},{"location":"provider/ibm-secrets-manager/#kv","title":"kv","text":"<ul> <li>An optional <code>property</code> field can be set to <code>remoteRef</code> to select requested key from the KV secret. If not set, the entire secret will be returned</li> <li><code>dataFrom</code> retrieves a string from secrets manager and tries to parse it as JSON object setting the key:values pairs in resulting Kubernetes secret if successful. It could be either used with the methods</li> <li><code>Extract</code> to extract multiple key/value pairs from one secret (with optional <code>property</code> field being supported as well)</li> <li><code>Find</code> to find secrets based on tags or regular expressions and allows finding multiple external secrets and map them into a single Kubernetes secret</li> </ul> <pre><code>{\n \"key1\": \"val1\",\n \"key2\": \"val2\",\n \"key3\": {\n \"keyA\": \"valA\",\n \"keyB\": \"valB\"\n },\n \"special.key\": \"special-content\"\n}\n</code></pre> <pre><code>data:\n- secretKey: key3_keyB\n remoteRef:\n key: 'kv/aaaaa-bbbb-cccc-dddd-eeeeee'\n property: 'key3.keyB'\n- secretKey: special_key\n remoteRef:\n key: 'kv/aaaaa-bbbb-cccc-dddd-eeeeee'\n property: 'special.key'\n- secretKey: key_all\n remoteRef:\n key: 'kv/aaaaa-bbbb-cccc-dddd-eeeeee'\n</code></pre> <pre><code>dataFrom:\n - extract:\n key: 'kv/fffff-gggg-iiii-dddd-eeeeee' #mandatory\n decodingStrategy: Base64 #optional\n</code></pre> <pre><code>dataFrom:\n - find:\n name: #matches any secret name ending in foo-bar\n regexp: \"key\" #assumption that secrets are stored like /comp/key1, key2/trigger, and comp/trigger/keygen within the secret manager\n - find:\n tags: #matches any secrets with the following metadata labels\n environment: \"dev\"\n application: \"BFF\"\n</code></pre> <p>results in</p> <pre><code>data:\n # secrets from data\n key3_keyB: ... #valB\n special_key: ... #special-content\n key_all: ... #{\"key1\":\"val1\",\"key2\":\"val2\", ...\"special.key\":\"special-content\"}\n\n # secrets from dataFrom with extract method\n keyA: ... #1st key-value pair from JSON object\n keyB: ... #2nd key-value pair from JSON object\n keyC: ... #3rd key-value pair from JSON object\n\n # secrets from dataFrom with find regex method\n _comp_key1: ... #secret value for /comp/key1\n key2_trigger: ... #secret value for key2/trigger\n _comp_trigger_keygen: ... #secret value for comp/trigger/keygen\n\n # secrets from dataFrom with find tags method\n bffA: ...\n bffB: ...\n bffC: ...\n</code></pre>"},{"location":"provider/ibm-secrets-manager/#creating-external-secret","title":"Creating external secret","text":"<p>To create a kubernetes secret from the IBM Secrets Manager, a <code>Kind=ExternalSecret</code> is needed. Below example creates a kubernetes secret based on ID of the secret in Secrets Manager.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: database-credentials\nspec:\n refreshInterval: 60m\n secretStoreRef:\n name: ibm-store\n kind: SecretStore\n target:\n name: database-credentials\n creationPolicy: Owner\n data:\n - secretKey: username\n remoteRef:\n key: username_password/&lt;SECRET_ID&gt;\n property: username\n - secretKey: password\n remoteRef:\n key: username_password/&lt;SECRET_ID&gt;\n property: password\n</code></pre> <p>Alternatively, the secret name along with its secret group name can be specified instead of secret ID to fetch the secret.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: database-credentials\nspec:\n refreshInterval: 60m\n secretStoreRef:\n name: ibm-store\n kind: SecretStore\n target:\n name: database-credentials\n creationPolicy: Owner\n data:\n - secretKey: username\n remoteRef:\n key: &lt;SECRET_GROUP_NAME&gt;/username_password/&lt;SECRET_NAME&gt;\n property: username\n - secretKey: password\n remoteRef:\n key: &lt;SECRET_GROUP_NAME&gt;/username_password/&lt;SECRET_NAME&gt;\n property: password\n</code></pre>"},{"location":"provider/ibm-secrets-manager/#getting-the-kubernetes-secret","title":"Getting the Kubernetes secret","text":"<p>The operator will fetch the IBM Secret Manager secret and inject it as a <code>Kind=Secret</code> <pre><code>kubectl get secret secret-to-be-created -n &lt;namespace&gt; | -o jsonpath='{.data.test}' | base64 -d\n</code></pre></p>"},{"location":"provider/ibm-secrets-manager/#populating-the-kubernetes-secret-with-metadata-from-ibm-secrets-manager-provider","title":"Populating the Kubernetes secret with metadata from IBM Secrets Manager Provider","text":"<p>ESO can add metadata while creating or updating a Kubernetes secret to be reflected in its labels or annotations. The metadata could be any of the fields that are supported and returned in the response by IBM Secrets Manager.</p> <p>In order for the user to opt in to adding metadata to secret, an existing optional field <code>spec.dataFrom.extract.metadataPolicy</code> can be set to <code>Fetch</code>, its default value being <code>None</code>. In addition to this, templating provided be ESO can be leveraged to specify the key-value pairs of the resultant secrets' labels and annotation.</p> <p>In order for the required metadata to be populated in the Kubernetes secret, combination of below should be provided in the External Secrets resource: 1. The required metadata should be specified under <code>template.metadata.labels</code> or <code>template.metadata.annotations</code>. 2. The required secret data should be specified under <code>template.data</code>. 3. The spec.dataFrom.extract should be specified with details of the Secrets Manager secret with <code>spec.dataFrom.extract.metadataPolicy</code> set to <code>Fetch</code>. Below is an example, where <code>secret_id</code> and <code>updated_at</code> are the metadata of a secret in IBM Secrets Manager:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: database-credentials\n namespace: external-secrets\nspec:\n dataFrom:\n - extract:\n key: username_password/&lt;SECRET_ID&gt;\n metadataPolicy: Fetch # leveraging optional parameter, defaults to None\n secretKey: username\n secretStoreRef:\n kind: SecretStore\n name: ibm-store\n target:\n name: database-credentials\n template:\n engineVersion: v2\n data:\n secret: \"{{ .password }}\"\n metadata:\n annotations:\n secret_id: \"{{ .id }}\" # adding metadata key whose value would be added to the secret as a label\n updated_at: \"{{ .updated_at }}\"\n</code></pre> <p>While the secret is being reconciled, it will have the secret data along with the required annotations. Below is the example of the secret after reconciliation:</p> <pre><code>apiVersion: v1\ndata:\n secret: OHE0MFV5MGhQb2FmRjZTOGVva3dPQjRMeVZXeXpWSDlrSWgyR1BiVDZTMyc=\nimmutable: false\nkind: Secret\nmetadata:\n annotations:\n reconcile.external-secrets.io/data-hash: 02217008d13ed228e75cf6d26fe74324\n creationTimestamp: \"2023-05-04T08:41:24Z\"\n secret_id: \"1234\"\n updated_at: 2023-05-04T08:57:19Z\n name: database-credentials\n namespace: external-secrets\n ownerReferences:\n - apiVersion: external-secrets.io/v1beta1\n blockOwnerDeletion: true\n controller: true\n kind: ExternalSecret\n name: database-credentials\n uid: c2a018e7-1ac3-421b-bd3b-d9497204f843\n #resourceVersion: \"1803567\" #immutable for a user\n #uid: f5dff604-611b-4d41-9d65-b860c61a0b8d #immutable for a user\ntype: Opaque\n</code></pre>"},{"location":"provider/infisical/","title":"Infisical","text":"<p>Sync secrets from Infisical to your Kubernetes cluster using External Secrets Operator.</p>"},{"location":"provider/infisical/#authentication","title":"Authentication","text":"<p>In order for the operator to fetch secrets from Infisical, it needs to first authenticate with Infisical.</p> <p>To authenticate, you can use Universal Auth from Machine identities.</p> <p>Follow the guide here to learn how to create and obtain a pair of Client Secret and Client ID.</p>"},{"location":"provider/infisical/#storing-your-machine-identity-secrets","title":"Storing Your Machine Identity Secrets","text":"<p>Once you have generated a pair of <code>Client ID</code> and <code>Client Secret</code>, you will need to store these credentials in your cluster as a Kubernetes secret.</p> <p>Note</p> <p>Remember to replace with your own Machine Identity credentials.</p> <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: universal-auth-credentials\ntype: Opaque\n\nstringData:\n clientId: &lt;machine identity client id&gt;\n clientSecret: &lt;machine identity client secret&gt;\n</code></pre>"},{"location":"provider/infisical/#secret-store","title":"Secret Store","text":"<p>You will then need to create a generic <code>SecretStore</code>. An sample <code>SecretStore</code> has been is shown below.</p> <p>Tip</p> <p>To get your project slug from Infisical, head over to the project settings and click the button <code>Copy Project Slug</code>.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: infisical\nspec:\n provider:\n infisical:\n auth:\n universalAuthCredentials:\n clientId:\n key: clientId\n namespace: default\n name: universal-auth-credentials\n clientSecret:\n key: clientSecret\n namespace: default\n name: universal-auth-credentials\n # Details to pull secrets from\n secretsScope:\n projectSlug: first-project-fujo\n environmentSlug: dev # \"dev\", \"staging\", \"prod\", etc..\n # optional\n secretsPath: / # Root is \"/\"\n # optional\n recursive: true # Default is false\n # optional\n hostAPI: https://app.infisical.com\n</code></pre> <p>Note</p> <p>For <code>ClusterSecretStore</code>, be sure to set <code>namespace</code> in <code>universalAuthCredentials.clientId</code> and <code>universalAuthCredentials.clientSecret</code>.</p>"},{"location":"provider/infisical/#fetch-individual-secrets","title":"Fetch Individual Secret(s)","text":"<p>To sync one or more secrets individually, use the following YAML:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: infisical-managed-secrets\nspec:\n secretStoreRef:\n kind: SecretStore\n name: infisical\n\n target:\n name: auth-api\n\n data:\n - secretKey: API_KEY\n remoteRef:\n key: API_KEY\n</code></pre>"},{"location":"provider/infisical/#fetch-all-secrets","title":"Fetch All Secrets","text":"<p>To sync all secrets from an Infisical , use the following YAML:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: infisical-managed-secrets\nspec:\n secretStoreRef:\n kind: SecretStore\n name: infisical\n\n target:\n name: auth-api\n\n dataFrom:\n - find:\n name:\n regexp: .*\n</code></pre>"},{"location":"provider/infisical/#filter-by-prefixname","title":"Filter By Prefix/Name","text":"<p>To filter secrets by <code>path</code> (path prefix) and <code>name</code> (regular expression).</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: infisical-managed-secrets\nspec:\n secretStoreRef:\n kind: SecretStore\n name: infisical\n\n target:\n name: auth-api\n\n dataFrom:\n - find:\n path: DB_\n</code></pre>"},{"location":"provider/keeper-security/","title":"Keeper Security","text":""},{"location":"provider/keeper-security/#keeper-security","title":"Keeper Security","text":"<p>External Secrets Operator integrates with Keeper Security for secret management by using Keeper Secrets Manager.</p>"},{"location":"provider/keeper-security/#authentication","title":"Authentication","text":""},{"location":"provider/keeper-security/#secrets-manager-configuration-smc","title":"Secrets Manager Configuration (SMC)","text":"<p>KSM can authenticate using One Time Access Token or Secret Manager Configuration. In order to work with External Secret Operator we need to configure a Secret Manager Configuration.</p>"},{"location":"provider/keeper-security/#creating-secrets-manager-configuration","title":"Creating Secrets Manager Configuration","text":"<p>You can find the documentation for the Secret Manager Configuration creation here. Make sure you add the proper permissions to your device in order to be able to read and write secrets</p> <p>Once you have created your SMC, you will get a config.json file or a base64 json encoded string containing the following keys:</p> <ul> <li><code>hostname</code></li> <li><code>clientId</code></li> <li><code>privateKey</code></li> <li><code>serverPublicKeyId</code></li> <li><code>appKey</code></li> <li><code>appOwnerPublicKey</code></li> </ul> <p>This base64 encoded jsong string will be required to create your secretStores</p>"},{"location":"provider/keeper-security/#important-note-about-this-documentation","title":"Important note about this documentation","text":"<p>The KepeerSecurity calls the entries in vaults 'Records'. These docs use the same term.</p>"},{"location":"provider/keeper-security/#update-secret-store","title":"Update secret store","text":"<p>Be sure the <code>keepersecurity</code> provider is listed in the <code>Kind=SecretStore</code></p> <pre><code>---\napiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: keeper\nspec:\n provider:\n keepersecurity:\n authRef: # Refer to a kubernetes secret which holds the base64 encoded json string for the configuration\n name: keeper-configuration\n key: auth\n folderID: 1qdsiewFW-U # Folder ID where the secrets can be pushed. It requires write permissions\n</code></pre> <p>NOTE 1: <code>folderID</code> target the folder ID where the secrets should be pushed to. It requires write permissions within the folder</p> <p>NOTE 2: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> for <code>SecretAccessKeyRef</code> with the namespace of the secret that we just created.</p>"},{"location":"provider/keeper-security/#external-secrets","title":"External Secrets","text":""},{"location":"provider/keeper-security/#behavior","title":"Behavior","text":"<ul> <li>How a Record is equated to an ExternalSecret:<ul> <li><code>remoteRef.key</code> is equated to a Record's ID</li> <li><code>remoteRef.property</code> is equated to one of the following options:<ul> <li>Fields: Record's field's Type</li> <li>CustomFields: Record's field's Label</li> <li>Files: Record's file's Name</li> <li>If empty, defaults to the complete Record in JSON format</li> </ul> </li> <li><code>remoteRef.version</code> is currently not supported.</li> </ul> </li> <li><code>dataFrom</code>:<ul> <li><code>find.path</code> is currently not supported.</li> <li><code>find.name.regexp</code> is equated to one of the following options:<ul> <li>Fields: Record's field's Type</li> <li>CustomFields: Record's field's Label</li> <li>Files: Record's file's Name</li> </ul> </li> <li><code>find.tags</code> are not supported at this time.</li> </ul> </li> </ul> <p>NOTE: For complex types, like name, phone, bankAccount, which does not match with a single string value, external secrets will return the complete json string. Use the json template functions to decode.</p>"},{"location":"provider/keeper-security/#creating-external-secret","title":"Creating external secret","text":"<p>To create a kubernetes secret from Keeper Secret Manager secret a <code>Kind=ExternalSecret</code> is needed.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example\nspec:\n refreshInterval: 1h # rate SecretManager pulls KeeperSrucity\n secretStoreRef:\n kind: SecretStore\n name: example # name of the SecretStore (or kind specified)\n target:\n name: secret-to-be-created # name of the k8s Secret to be created\n creationPolicy: Owner\n dataFrom:\n - extract:\n key: OqPt3Vd37My7G8rTb-8Q # ID of the Keeper Record\n---\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: regcred\n namespace: external-secrets\nspec:\n refreshInterval: 1m\n secretStoreRef:\n name: keeper\n kind: ClusterSecretStore\n target:\n name: regcred\n creationPolicy: Owner\n template:\n engineVersion: v2\n type: kubernetes.io/dockerconfigjson\n data:\n .dockerconfigjson: \"{\\\"auths\\\":{\\\"registry.example.com\\\":{\\\"username\\\":\\\"{{ .username }}\\\",\\\"password\\\":\\\"{{ .password }}\\\",\\\"auth\\\":\\\"{{(printf \\\"%s:%s\\\" .username .password) | b64enc }}\\\"}}}\"\n data:\n - secretKey: username\n remoteRef:\n key: OqPt3Vd37My7G8rTb-8Q\n property: login\n - secretKey: password\n remoteRef:\n key: OqPt3Vd37My7G8rTb-8Q\n property: password\n---\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: config\n namespace: external-secrets\nspec:\n refreshInterval: 1m\n secretStoreRef:\n name: keeper\n kind: ClusterSecretStore\n target:\n name: credentials\n creationPolicy: Owner\n template:\n engineVersion: v2\n data:\n username: \"{{ .login }}\"\n password: \"{{ .password }}\"\n data:\n - secretKey: login\n remoteRef:\n key: OqPt3Vd37My7G8rTb-8Q\n property: login\n - secretKey: password\n remoteRef:\n key: OqPt3Vd37My7G8rTb-8Q\n property: password\n---\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example\nspec:\n refreshInterval: 1h # rate SecretManager pulls KeeperSrucity\n secretStoreRef:\n kind: SecretStore\n name: example # name of the SecretStore (or kind specified)\n target:\n name: secret-to-be-created # name of the k8s Secret to be created\n creationPolicy: Owner\n template:\n engineVersion: v2\n data:\n username: \"{{ (fromJson .name).first }} {{ (fromJson .name).middle }} {{ (fromJson .name).last }}\" # decode json string into vars\n dataFrom:\n - extract:\n key: OqPt3Vd37My7G8rTb-8Q # ID of the Keeper Record\n</code></pre> <p>The operator will fetch the Keeper Secret Manager secret and inject it as a <code>Kind=Secret</code> <pre><code>kubectl get secret secret-to-be-created -n &lt;namespace&gt; | -o jsonpath='{.data.dev-secret-test}' | base64 -d\n</code></pre></p>"},{"location":"provider/keeper-security/#limitations","title":"Limitations","text":"<p>There are some limitations using this provider.</p> <ul> <li>Keeper Secret Manager does not work with <code>General</code> Records types nor legacy non-typed records</li> <li>Using tags <code>find.tags</code> is not supported by KSM</li> <li>Using path <code>find.path</code> is not supported at the moment</li> </ul>"},{"location":"provider/keeper-security/#push-secrets","title":"Push Secrets","text":"<p>Push Secret will only work with a custom KeeperSecurity Record type <code>ExternalSecret</code></p>"},{"location":"provider/keeper-security/#behavior_1","title":"Behavior","text":"<ul> <li><code>selector</code>:</li> <li><code>secret.name</code>: name of the kubernetes secret to be pushed</li> <li><code>data.match</code>:</li> <li><code>secretKey</code>: key on the selected secret to be pushed</li> <li><code>remoteRef.remoteKey</code>: Secret and key to be created on the remote provider<ul> <li>Format: SecretName/SecretKey</li> </ul> </li> </ul>"},{"location":"provider/keeper-security/#creating-push-secret","title":"Creating push secret","text":"<p>To create a Keeper Security record from kubernetes a <code>Kind=PushSecret</code> is needed.</p> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: example\nspec:\n secretStoreRefs:\n - name: keeper\n kind: SecretStore\n refreshInterval: \"1h\"\n deletionPolicy: Delete\n selector:\n secret:\n name: secret-name # k8s secret to be pushed\n data:\n - match:\n secretKey: secret-key # k8s key within the secret to be pushed\n remoteRef:\n remoteKey: remote-secret-name/remote-secret-key # This will create a record called \"remote-secret-name\" with a key \"remote-secret-key\"\n</code></pre>"},{"location":"provider/keeper-security/#limitations_1","title":"Limitations","text":"<ul> <li>Only possible to push one key per secret at the moment</li> <li>If the record with the selected name exists but the key does not exists the record can not be updated. See Ability to add custom fields to existing secret #17</li> </ul>"},{"location":"provider/kubernetes/","title":"Kubernetes","text":"<p>External Secrets Operator allows to retrieve secrets from a Kubernetes Cluster - this can be either a remote cluster or the local one where the operator runs in.</p> <p>A <code>SecretStore</code> points to a specific namespace in the target Kubernetes Cluster. You are able to retrieve all secrets from that particular namespace given you have the correct set of RBAC permissions.</p> <p>The <code>SecretStore</code> reconciler checks if you have read access for secrets in that namespace using <code>SelfSubjectRulesReview</code>. See below on how to set that up properly.</p>"},{"location":"provider/kubernetes/#external-secret-spec","title":"External Secret Spec","text":"<p>This provider supports the use of the <code>Property</code> field. With it you point to the key of the remote secret. If you leave it empty it will json encode all key/value pairs.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: database-credentials\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: k8s-store # name of the SecretStore (or kind specified)\n target:\n name: database-credentials # name of the k8s Secret to be created\n data:\n - secretKey: username\n remoteRef:\n key: database-credentials\n property: username\n\n - secretKey: password\n remoteRef:\n key: database-credentials\n property: password\n\n # metadataPolicy to fetch all the labels and annotations in JSON format\n - secretKey: tags\n remoteRef:\n metadataPolicy: Fetch\n key: database-credentials\n\n # metadataPolicy to fetch all the labels in JSON format\n - secretKey: labels\n remoteRef:\n metadataPolicy: Fetch\n key: database-credentials\n property: labels\n\n # metadataPolicy to fetch a specific label (dev) from the source secret\n - secretKey: developer\n remoteRef:\n metadataPolicy: Fetch\n key: database-credentials\n property: labels.dev\n</code></pre>"},{"location":"provider/kubernetes/#find-by-tag-name","title":"find by tag &amp; name","text":"<p>You can fetch secrets based on labels or names matching a regexp:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: fetch-tls-and-nginx\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: k8s-store\n target:\n name: fetch-tls-and-nginx\n dataFrom:\n - find:\n name:\n # match secret name with regexp\n regexp: \"tls-.*\"\n - find:\n tags:\n # fetch secrets based on label combination\n app: \"nginx\"\n</code></pre>"},{"location":"provider/kubernetes/#target-api-server-configuration","title":"Target API-Server Configuration","text":"<p>The servers <code>url</code> can be omitted and defaults to <code>kubernetes.default</code>. You have to provide a CA certificate in order to connect to the API Server securely. For your convenience, each namespace has a ConfigMap <code>kube-root-ca.crt</code> that contains the CA certificate of the internal API Server (see <code>RootCAConfigMap</code> feature gate). Use that if you want to connect to the same API server. If you want to connect to a remote API Server you need to fetch it and store it inside the cluster as ConfigMap or Secret. You may also define it inline as base64 encoded value using the <code>caBundle</code> property.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: k8s-store-default-ns\nspec:\n provider:\n kubernetes:\n # with this, the store is able to pull only from `default` namespace\n remoteNamespace: default\n server:\n url: \"https://myapiserver.tld\"\n caProvider:\n type: ConfigMap\n name: kube-root-ca.crt\n key: ca.crt\n</code></pre>"},{"location":"provider/kubernetes/#authentication","title":"Authentication","text":"<p>It's possible to authenticate against the Kubernetes API using client certificates, a bearer token or service account. The operator enforces that exactly one authentication method is used. You can not use the service account that is mounted inside the operator, this is by design to avoid reading secrets across namespaces.</p> <p>NOTE: <code>SelfSubjectRulesReview</code> permission is required in order to validation work properly. Please use the following role as reference:</p> <pre><code>apiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n namespace: default\n name: eso-store-role\nrules:\n- apiGroups: [\"\"]\n resources:\n - secrets\n verbs:\n - get\n - list\n - watch\n- apiGroups:\n - authorization.k8s.io\n resources:\n - selfsubjectrulesreviews\n verbs:\n - create\n</code></pre>"},{"location":"provider/kubernetes/#authenticating-with-bearertoken","title":"Authenticating with BearerToken","text":"<p>Create a Kubernetes secret with a client token. There are many ways to acquire such a token, please refer to the Kubernetes Authentication docs.</p> <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: my-token\ndata:\n token: \"....\"\n</code></pre> <p>Create a SecretStore: The <code>auth</code> section indicates that the type <code>token</code> will be used for authentication, it includes the path to fetch the token. Set <code>remoteNamespace</code> to the name of the namespace where your target secrets reside.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: k8s-store-token-auth\nspec:\n provider:\n kubernetes:\n # with this, the store is able to pull only from `default` namespace\n remoteNamespace: default\n server:\n # ...\n auth:\n token:\n bearerToken:\n name: my-token\n key: token\n</code></pre>"},{"location":"provider/kubernetes/#authenticating-with-serviceaccount","title":"Authenticating with ServiceAccount","text":"<p>Create a Kubernetes Service Account, please refer to the Service Account Tokens Documentation on how they work and how to create them.</p> <pre><code>$ kubectl create serviceaccount my-store\n</code></pre> <p>This Service Account needs permissions to read <code>Secret</code> and create <code>SelfSubjectRulesReview</code> resources. Please see the above role.</p> <pre><code>$ kubectl create rolebinding my-store --role=eso-store-role --serviceaccount=default:my-store\n</code></pre> <p>Create a SecretStore: the <code>auth</code> section indicates that the type <code>serviceAccount</code> will be used for authentication.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: k8s-store-sa-auth\nspec:\n provider:\n kubernetes:\n # with this, the store is able to pull only from `default` namespace\n remoteNamespace: default\n server:\n # ...\n auth:\n serviceAccount:\n name: \"my-store\"\n</code></pre>"},{"location":"provider/kubernetes/#authenticating-with-client-certificates","title":"Authenticating with Client Certificates","text":"<p>Create a Kubernetes secret which contains the client key and certificate. See Generate Certificates Documentations on how to create them.</p> <pre><code>$ kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key\n</code></pre> <p>Reference the <code>tls-secret</code> in the SecretStore</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: k8s-store-cert-auth\nspec:\n provider:\n kubernetes:\n # with this, the store is able to pull only from `default` namespace\n remoteNamespace: default\n server:\n # ...\n auth:\n cert:\n clientCert:\n name: \"tls-secret\"\n key: \"tls.crt\"\n clientKey:\n name: \"tls-secret\"\n key: \"tls.key\"\n</code></pre>"},{"location":"provider/kubernetes/#pushsecret","title":"PushSecret","text":"<p>The PushSecret functionality facilitates the replication of a Kubernetes Secret from one namespace or cluster to another. This feature proves useful in scenarios where you need to share sensitive information, such as credentials or configuration data, across different parts of your infrastructure.</p> <p>To configure the PushSecret resource, you need to specify the following parameters:</p> <ul> <li> <p>Selector: Specify the selector that identifies the source Secret to be replicated. This selector allows you to target the specific Secret you want to share.</p> </li> <li> <p>SecretKey: Set the SecretKey parameter to indicate the key within the source Secret that you want to replicate. This ensures that only the relevant information is shared.</p> </li> <li> <p>RemoteRef.Property: In addition to the above parameters, the Kubernetes provider requires you to set the <code>remoteRef.property</code> field. This field specifies the key of the remote Secret resource where the replicated value should be stored.</p> </li> </ul> <p>Here's an example:</p> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: example\nspec:\n refreshInterval: 10s\n secretStoreRefs:\n - name: k8s-store-remote-ns\n kind: SecretStore\n selector:\n secret:\n name: pokedex-credentials\n data:\n - match:\n secretKey: best-pokemon\n remoteRef:\n remoteKey: remote-best-pokemon\n property: best-pokemon\n</code></pre> <p>To utilize the PushSecret feature effectively, the referenced <code>SecretStore</code> requires specific permissions on the target cluster. In particular it requires <code>create</code>, <code>read</code>, <code>update</code> and <code>delete</code> permissions on the Secret resource:</p> <pre><code>apiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n namespace: remote\n name: eso-store-push-role\nrules:\n- apiGroups: [\"\"]\n resources:\n - secrets\n verbs:\n - get\n - list\n - watch\n - create\n - update\n - patch\n - delete\n- apiGroups:\n - authorization.k8s.io\n resources:\n - selfsubjectrulesreviews\n verbs:\n - create\n</code></pre>"},{"location":"provider/kubernetes/#pushsecret-metadata","title":"PushSecret Metadata","text":"<p>The Kubernetes provider is able to manage both <code>metadata.labels</code> and <code>metadata.annotations</code> of the secret on the target cluster.</p> <p>Users have different preferences on what metadata should be pushed. ESO by default pushes both labels and annotations to the target secret and merges them with the existing metadata.</p> <p>You can specify the metadata in the <code>spec.template.metadata</code> section if you want to decouple it from the existing secret.</p> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: example\nspec:\n # ...\n template:\n metadata:\n labels:\n app.kubernetes.io/part-of: argocd\n data:\n mysql_connection_string: \"mysql://{{ .hostname }}:3306/{{ .database }}\"\n data:\n - match:\n secretKey: mysql_connection_string\n remoteRef:\n remoteKey: backend_secrets\n property: mysql_connection_string\n</code></pre> <p>Further, you can leverage the <code>.data[].metadata</code> section to fine-tine the behaviour of the metadata merge strategy. The metadata section is a versioned custom-resource alike structure, the behaviour is detailed below.</p> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: example\nspec:\n # ...\n data:\n - match:\n secretKey: example-1\n remoteRef:\n remoteKey: example-remote-secret\n property: url\n\n metadata:\n apiVersion: kubernetes.external-secrets.io/v1alpha1\n kind: PushSecretMetadata\n spec:\n sourceMergePolicy: Merge # or Replace\n targetMergePolicy: Merge # or Replace / Ignore\n labels:\n color: red\n annotations:\n yes: please\n</code></pre> Field Type Description sourceMergePolicy string: <code>Merge</code>, <code>Replace</code> The sourceMergePolicy defines how the metadata of the source secret is merged. <code>Merge</code> will merge the metadata of the source secret with the metadata defined in <code>.data[].metadata</code>. With <code>Replace</code>, the metadata in <code>.data[].metadata</code> replaces the source metadata. targetMergePolicy string: <code>Merge</code>, <code>Replace</code>, <code>Ignore</code> The targetMergePolicy defines how ESO merges the metadata produced by the sourceMergePolicy with the target secret. With <code>Merge</code>, the source metadata is merged with the existing metadata from the target secret. <code>Replace</code> will replace the target metadata with the metadata defined in the source. <code>Ignore</code> leaves the target metadata as is. labels <code>map[string]string</code> The labels. annotations <code>map[string]string</code> The annotations."},{"location":"provider/kubernetes/#implementation-considerations","title":"Implementation Considerations","text":"<p>When utilizing the PushSecret feature and configuring the permissions for the SecretStore, consider the following:</p> <ul> <li> <p>RBAC Configuration: Ensure that the Role-Based Access Control (RBAC) configuration for the SecretStore grants the appropriate permissions for creating, reading, and updating resources in the target cluster.</p> </li> <li> <p>Least Privilege Principle: Adhere to the principle of least privilege when assigning permissions to the SecretStore. Only provide the minimum required permissions to accomplish the desired synchronization between Secrets.</p> </li> <li> <p>Namespace or Cluster Scope: Depending on your specific requirements, configure the SecretStore to operate at the desired scope, whether it is limited to a specific namespace or encompasses the entire cluster. Consider the security and access control implications of your chosen scope.</p> </li> </ul>"},{"location":"provider/onboardbase/","title":"Onboardbase","text":""},{"location":"provider/onboardbase/#onboardbase-secret-management","title":"Onboardbase Secret Management","text":"<p>Sync secrets from Onboardbase to Kubernetes using the External Secrets Operator.</p>"},{"location":"provider/onboardbase/#authentication","title":"Authentication","text":""},{"location":"provider/onboardbase/#get-an-onboardbase-api-key","title":"Get an Onboardbase API Key.","text":"<p>Create the Onboardbase API by opening the organization tab under your account settings:</p> <p></p> <p>And view them under the team name in your Account settings</p> <p></p> <p>Create an Onboardbase API secret with your API Key and Passcode value:</p> <pre><code>HISTIGNORE='*kubectl*' \\\n kubectl create secret generic onboardbase-auth-secret \\\n --from-literal=API_KEY=*****VZYKYJNMMEMK***** \\\n --from-literal=PASSCODE=api-key-passcode\n</code></pre> <p>Then to create a generic <code>SecretStore</code>:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: onboardbase-external-secret-store\nspec:\n provider:\n onboardbase:\n project: project-name # can be altered from here\n environment: development # can be altered from here\n auth:\n apiKey:\n name: onboardbase-auth-secret\n key: onboardbase-api-key \n passcode:\n name: onboardbase-auth-secret\n key: onboardbase-passcode\n</code></pre>"},{"location":"provider/onboardbase/#use-cases","title":"Use Cases","text":"<p>The below operations are possible with the Onboardbase provider:</p> <ol> <li>Fetch</li> <li>Fetch all</li> <li>Filter</li> </ol> <p>Let's explore each use case using a fictional <code>auth-api</code> Onboardbase project.</p>"},{"location":"provider/onboardbase/#1-fetch","title":"1. Fetch","text":"<p>To sync one or more individual secrets:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: service-name-secrets\nspec:\n refreshInterval: 10m\n secretStoreRef:\n name: onboardbase-external-secret-store\n kind: SecretStore\n target:\n name: service-name-secrets\n data:\n - secretKey: DATABASE_URI\n remoteRef: \n key: DATABASE_URI\n</code></pre>"},{"location":"provider/onboardbase/#2-fetch-all","title":"2. Fetch all","text":"<p>To sync every secret from a config:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: service-name-secrets\nspec:\n refreshInterval: 10m\n secretStoreRef:\n name: onboardbase-external-secret-store\n kind: SecretStore\n target:\n name: service-name-secrets\n dataFrom:\n - find:\n name:\n regexp: .*\n</code></pre>"},{"location":"provider/onboardbase/#3-filter","title":"3. Filter","text":"<p>To filter secrets by <code>path</code> (path prefix), <code>name</code> (regular expression) or a combination of both:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: service-name-secrets\nspec:\n refreshInterval: 10m\n secretStoreRef:\n name: onboardbase-external-secret-store\n kind: SecretStore\n target:\n name: service-name-secrets\n dataFrom:\n - find:\n path: DATABASE_\n</code></pre>"},{"location":"provider/oracle-vault/","title":"Oracle Vault","text":""},{"location":"provider/oracle-vault/#oracle-vault","title":"Oracle Vault","text":"<p>External Secrets Operator integrates with the Oracle Cloud Infrastructure (OCI) REST API to manage secrets in Oracle Vault. All secret operations exposed by External Secrets Operator are supported by the Oracle provider.</p> <p>For more information on managing OCI Vaults and OCI Vault Secrets, see the following documentation:</p> <ul> <li>Managing Vaults</li> <li>Managing Vault Secrets</li> </ul>"},{"location":"provider/oracle-vault/#authentication","title":"Authentication","text":"<p>External Secrets Operator may authenticate to OCI Vault using User Principal, Instance Principal, or Workload Identity.</p> <p>To specify the authenticating principal in a secret store, set the <code>spec.provider.oracle.principalType</code> value. Note that the value of <code>principalType</code> defaults <code>InstancePrincipal</code> if not set.</p> <p>apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: my-secret-store spec: provider: oracle: # May be UserPrincipal, InstancePrincipal, or Workload principalType:"},{"location":"provider/oracle-vault/#user-principal-authentication","title":"User Principal Authentication","text":"<p>For user principal authentication, region, user OCID, tenancy OCID, private key, and fingerprint are required. The private key and fingerprint must be supplied in a Kubernetes secret, while the user OCID, tenancy OCID, and region should be set in the secret store.</p> <p>To get your user principal information, find url for the OCI region you are accessing. </p> <p>Select tenancy in the top right to see your tenancy OCID as shown below. </p> <p>Select your user in the top right to see your user OCID as shown below. </p> <p>Your fingerprint will be attatched to your API key, once it has been generated. Private keys can be created or uploaded on the same page as the your user OCID. </p> <p>Once you click \"Add API Key\" you will be shown the following, where you can download the key in the necessary PEM format for API requests. Creating a private key will automatically generate a fingerprint. </p> <p>Next, create a secret containing your private key and fingerprint:</p> <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: oracle-secret\n labels: \n type: oracle\ntype: Opaque\nstringData:\n privateKey: \n fingerprint: \n</code></pre> <p>After creating the credentials secret, the secret store can be configured:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: example-auth\nspec:\n provider:\n oracle:\n vault: # The vault OCID\n region: # The vault region\n principalType: UserPrincipal\n auth:\n user: # A user OCID\n tenancy: # A user's tenancy\n secretRef:\n privatekey:\n name: oracle-secret\n key: privateKey\n fingerprint:\n name: oracle-secret\n key: fingerprint\n</code></pre> <p>NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>privatekey</code> and <code>fingerprint</code> with the namespaces where the secrets reside.</p>"},{"location":"provider/oracle-vault/#instance-principal-authentication-oci","title":"Instance Principal Authentication (OCI)","text":"<p>Instance Principal uses a pod's instance principal to authenticate to OCI Vault. Ensure your cluster instances have the appropriate policies to use Instance Principal.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: my-secret-store\nspec:\n provider:\n oracle:\n vault: # The vault OCID\n principalType: InstancePrincipal\n</code></pre>"},{"location":"provider/oracle-vault/#workload-identity-authentication-ocioke","title":"Workload Identity Authentication (OCI/OKE)","text":"<p>Workload Identity can be used to grant the External Secrets Operator pod policy driven access to OCI Vault when running on Oracle Container Engine for Kubernetes (OKE).</p> <p>Note that if a service account is not provided in the secret store, the Oracle provider will authenticate using the service account token of the External Secrets Operator.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: my-secret-store\nspec:\n provider:\n oracle:\n vault: # The vault OCID\n principalType: Workload\n # If serviceAccountRef is not specified, the Oracle provider will authenticate using the service account token of the External Secrets Operator.\n serviceAccountRef:\n # If using a namespaced secret store, this service account must exist in the same namespace as the secret store.\n # namespace: service account namespace. Required if using ClusterSecretStore, otherwise cannot be specified.\n name: # The service account name to use for authentication.\n</code></pre>"},{"location":"provider/oracle-vault/#creating-an-external-secret","title":"Creating an External Secret","text":"<p>To create a Kubernetes secret from an OCI Vault secret a <code>Kind=ExternalSecret</code> is needed. The External Secret will reference an OCI Vault instance containing secrets with either JSON or plaintext data.</p>"},{"location":"provider/oracle-vault/#external-secret-targeting-json-data","title":"External Secret targeting JSON data","text":"<pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example\nspec:\n refreshInterval: 0.03m\n secretStoreRef:\n kind: SecretStore\n name: example # Must match SecretStore on the cluster\n target:\n name: secret-to-be-created # Name for the secret on the cluster\n creationPolicy: Owner\n dataFrom:\n - extract:\n key: the-secret-name\n</code></pre>"},{"location":"provider/oracle-vault/#external-secret-targeting-plaintext-data","title":"External Secret targeting plaintext data","text":"<pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example\nspec:\n refreshInterval: 0.03m\n secretStoreRef:\n kind: SecretStore\n name: example # Must match SecretStore on the cluster\n target:\n name: secret-to-be-created # Name for the secret on the cluster\n creationPolicy: Owner\n data:\n - secretKey: key\n remoteRef:\n key: my-eso-secret\n</code></pre>"},{"location":"provider/oracle-vault/#getting-the-kubernetes-secret","title":"Getting the Kubernetes secret","text":"<p>The operator will fetch the OCI Vault Secret and inject it as a <code>Kind=Secret</code>. <pre><code>kubectl get secret oracle-secret-to-create -o jsonpath='{.data.dev-secret-test}' | base64 -d\n</code></pre></p>"},{"location":"provider/oracle-vault/#pushsecrets-and-retrieving-multiple-secrets","title":"PushSecrets and retrieving multiple secrets.","text":"<p>When using PushSecrets, the compartment OCID and encryption key OCID must be specified in the Oracle SecretStore. You can find your compartment and encrpytion key OCIDs in the OCI console.</p> <p>If retrieving multiple secrets by tag or regex, only the compartment OCID must be specified.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: example-instance-principal\nspec:\n provider:\n oracle:\n vault: # The vault OCID\n compartment: # The compartment OCID where the vault is located. Required when using PushSecrets or retrieving multiple secrets.\n encryptionKey: # The OCID of the master encryption key that will be used for PushSecret encryption. Must exist in the vault, required when using PushSecrets.\n principalType: Workload\n</code></pre>"},{"location":"provider/passbolt/","title":"Passbolt","text":"<p>External Secrets Operator integrates with Passbolt API to sync Passbolt to secrets held on the Kubernetes cluster.</p>"},{"location":"provider/passbolt/#creating-a-passbolt-secret-store","title":"Creating a Passbolt secret store","text":"<p>Be sure the <code>passbolt</code> provider is listed in the <code>Kind=SecretStore</code> and auth and host are set. The API requires a password and private key provided in a secret.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: passbolt\nspec:\n provider:\n passbolt:\n host: https://passbolt.passbolt.svc.cluster.local\n auth:\n passwordSecretRef:\n key: password\n name: passbolt-credentials\n privateKeySecretRef:\n key: privateKey\n name: passbolt-credentials\n</code></pre>"},{"location":"provider/passbolt/#creating-an-external-secret","title":"Creating an external secret","text":"<p>To sync a Passbolt secret to a Kubernetes secret, a <code>Kind=ExternalSecret</code> is needed. By default the secret contains name, username, uri, password and description.</p> <p>To only select a single property add the <code>property</code> key.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: passbolt-example-simple\nspec:\n refreshInterval: \"15s\"\n secretStoreRef:\n name: passbolt\n kind: SecretStore\n target:\n name: passbolt-example\n data:\n - secretKey: full_secret\n remoteRef:\n key: e22487a8-feb8-4591-95aa-14b193930cb4 # Replace with ID of exising Passbolt secret\n - secretKey: password_only\n remoteRef:\n key: e22487a8-feb8-4591-95aa-14b193930cb4 # Replace with ID of exising Passbolt secret\n property: password # You can limit the secret to only display one property\n</code></pre> <p>The above external secret will lead to the creation of a secret in the following form:</p> <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: passbolt-example\ndata:\n full_secret: '{\"name\":\"passbolt-secret\",\"username\":\"some-username\",\"password\":\"supersecretpassword\",\"uri\":\"passbolt.com\",\"description\":\"some description\"}'\n password_only: supersecretpassword\ntype: Opaque\n</code></pre>"},{"location":"provider/passbolt/#finding-a-secret-by-name","title":"Finding a secret by name","text":"<p>Instead of retrieving secrets by ID you can also use <code>dataFrom</code> to search for secrets by name.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: passbolt-example\nspec:\n refreshInterval: \"15s\"\n secretStoreRef:\n name: passbolt\n kind: SecretStore\n target:\n name: passbolt-example\n dataFrom:\n - find:\n name:\n regexp: \".*\"\n</code></pre>"},{"location":"provider/previder/","title":"Previder","text":""},{"location":"provider/previder/#previder-secret-vault-manager","title":"Previder Secret Vault Manager","text":"<p>External Secrets Operator integrates with Previder Secrets Vault for secure secret management.</p>"},{"location":"provider/previder/#authentication","title":"Authentication","text":"<p>We support Access Token authentication using a Secrets Vault ReadWrite or ReadOnly token.</p> <p>This token can be created with the vault-cli using an Environment token which can be acquired via the Previder Portal.</p>"},{"location":"provider/previder/#access-token-authentication","title":"Access Token authentication","text":"<p>To use the access token, first create it as a regular Kubernetes Secret and then associate it with the Previder Secret Store.</p> <pre><code>apiVersion: v1\nkind: Secret\nmetadata:\n name: previder-vault-sample-secret\ndata:\n previder-vault-token: cHJldmlkZXIgdmF1bHQgZXhhbXBsZQ==\n</code></pre> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: previder-secretstore-sample\nspec:\n provider:\n previder:\n auth:\n secretRef:\n accessToken:\n name: previder-vault-sample-secret\n key: previder-vault-token\n</code></pre>"},{"location":"provider/previder/#creating-external-secret","title":"Creating external secret","text":"<p>To create a kubernetes secret from the Previder Secret Vault, create an ExternalSecret with a reference to a Vault secret.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: previder-secretstore-sample\n kind: SecretStore\n target:\n name: example-secret\n creationPolicy: Owner\n data:\n - secretKey: local-secret-key\n remoteRef:\n key: token-name-or-id\n</code></pre>"},{"location":"provider/pulumi/","title":"Pulumi ESC","text":""},{"location":"provider/pulumi/#pulumi-esc","title":"Pulumi ESC","text":"<p>Sync environments, configs and secrets from Pulumi ESC to Kubernetes using the External Secrets Operator.</p> <p></p> <p>More information about setting up Pulumi ESC can be found in the Pulumi ESC documentation.</p>"},{"location":"provider/pulumi/#authentication","title":"Authentication","text":"<p>Pulumi Access Tokens are recommended to access Pulumi ESC.</p>"},{"location":"provider/pulumi/#creating-a-secretstore","title":"Creating a SecretStore","text":"<p>A Pulumi <code>SecretStore</code> can be created by specifying the <code>organization</code>, <code>project</code> and <code>environment</code> and referencing a Kubernetes secret containing the <code>accessToken</code>.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: secret-store\nspec:\n provider:\n pulumi:\n organization: &lt;NAME_OF_THE_ORGANIZATION&gt;\n project: &lt;NAME_OF_THE_PROJECT&gt;\n environment: &lt;NAME_OF_THE_ENVIRONMENT&gt;\n accessToken:\n secretRef:\n name: &lt;NAME_OF_KUBE_SECRET&gt;\n key: &lt;KEY_IN_KUBE_SECRET&gt;\n</code></pre> <p>If required, the API URL (<code>apiUrl</code>) can be customized as well. If not specified, the default value is <code>https://api.pulumi.com/api/esc</code>.</p>"},{"location":"provider/pulumi/#creating-a-clustersecretstore","title":"Creating a ClusterSecretStore","text":"<p>Similarly, a <code>ClusterSecretStore</code> can be created by specifying the <code>namespace</code> and referencing a Kubernetes secret containing the <code>accessToken</code>.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ClusterSecretStore\nmetadata:\n name: secret-store\nspec:\n provider:\n pulumi:\n organization: &lt;NAME_OF_THE_ORGANIZATION&gt;\n project: &lt;NAME_OF_THE_PROJECT&gt;\n environment: &lt;NAME_OF_THE_ENVIRONMENT&gt;\n accessToken:\n secretRef:\n name: &lt;NAME_OF_KUBE_SECRET&gt;\n key: &lt;KEY_IN_KUBE_SECRET&gt;\n namespace: &lt;NAMESPACE&gt;\n</code></pre>"},{"location":"provider/pulumi/#referencing-secrets","title":"Referencing Secrets","text":"<p>Secrets can be referenced by defining the <code>key</code> containing the JSON path to the secret. Pulumi ESC secrets are internally organized as a JSON object.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: secret\nspec:\n refreshInterval: 5m\n secretStoreRef:\n kind: SecretStore\n name: secret-store\n data:\n - secretKey: &lt;KEY_IN_KUBE_SECRET&gt;\n remoteRef:\n key: &lt;PULUMI_PATH_SYNTAX&gt;\n</code></pre> <p>Note: <code>key</code> is not following the JSON Path syntax, but rather the Pulumi path syntax.</p>"},{"location":"provider/pulumi/#examples","title":"Examples","text":"<ul> <li>root</li> <li>root.nested</li> <li>root[\"nested\"]</li> <li>root.double.nest</li> <li>root[\"double\"].nest</li> <li>root[\"double\"][\"nest\"]</li> <li>root.array[0]</li> <li>root.array[100]</li> <li>root.array[0].nested</li> <li>root.array[0][1].nested</li> <li>root.nested.array[0].double[1]</li> <li>root[\"key with \\\"escaped\\\" quotes\"]</li> <li>root[\"key with a .\"]</li> <li>[\"root key with \\\"escaped\\\" quotes\"].nested</li> <li>[\"root key with a .\"][100]</li> <li>root.array[*].field</li> <li>root.array[\"*\"].field</li> </ul> <p>See Pulumi's documentation for more information.</p>"},{"location":"provider/pulumi/#pushsecrets","title":"PushSecrets","text":"<p>With the latest release of Pulumi ESC, secrets can be pushed to the Pulumi service. This can be done by creating a <code>PushSecrets</code> object.</p> <p>Here is a basic example of how to define a <code>PushSecret</code> object:</p> <pre><code>apiVersion: external-secrets.io/v1alpha1\nkind: PushSecret\nmetadata:\n name: push-secret-example\nspec:\n refreshInterval: 10s\n selector:\n secret:\n name: &lt;NAME_OF_KUBE_SECRET&gt;\n secretStoreRefs:\n - kind: ClusterSecretStore\n name: secret-store\n data:\n - match:\n secretKey: &lt;KEY_IN_KUBE_SECRET&gt;\n remoteRef:\n remoteKey: &lt;PULUMI_PATH_SYNTAX&gt;\n</code></pre> <p>This will then push the secret to the Pulumi service. If the secret already exists, it will be updated.</p>"},{"location":"provider/pulumi/#limitations","title":"Limitations","text":"<p>Currently, the Pulumi provider only supports nested objects up to a depth of 1. Any nested objects beyond this depth will be stored as a string with the JSON representation.</p> <p>This Pulumi ESC example:</p> <pre><code>values:\n backstage:\n my: test\n test: hello\n test22:\n my: hello\n test33:\n world: true\n x: true\n num: 42\n</code></pre> <p>Will result in the following Kubernetes secret:</p> <pre><code>my: test\nnum: \"42\"\ntest: hello\ntest22: '{\"my\":{\"trace\":{\"def\":{\"begin\":{\"byte\":72,\"column\":11,\"line\":6},\"end\":{\"byte\":77,\"column\":16,\"line\":6},\"environment\":\"tgif-demo\"}},\"value\":\"hello\"}}'\ntest33: '{\"world\":{\"trace\":{\"def\":{\"begin\":{\"byte\":103,\"column\":14,\"line\":8},\"end\":{\"byte\":107,\"column\":18,\"line\":8},\"environment\":\"tgif-demo\"}},\"value\":true}}'\nx: \"true\"\n</code></pre>"},{"location":"provider/scaleway/","title":"Scaleway","text":""},{"location":"provider/scaleway/#scaleway-secret-manager","title":"Scaleway Secret Manager","text":"<p>External Secrets Operator integrates with Scaleway's Secret Manager.</p>"},{"location":"provider/scaleway/#creating-a-secretstore","title":"Creating a SecretStore","text":"<p>You need an api key (access key + secret key) to authenticate with the secret manager. Both access and secret keys can be specified either directly in the config, or by referencing a kubernetes secret.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: secret-store\nspec:\n provider:\n scaleway:\n region: &lt;REGION&gt;\n projectId: &lt;PROJECT_UUID&gt;\n accessKey:\n value: &lt;ACCESS_KEY&gt;\n secretKey:\n secretRef:\n name: &lt;NAME_OF_KUBE_SECRET&gt;\n key: &lt;KEY_IN_KUBE_SECRET&gt;\n</code></pre>"},{"location":"provider/scaleway/#referencing-secrets","title":"Referencing Secrets","text":"<p>Secrets can be referenced by name, id or path, using the prefixes <code>\"name:\"</code>, <code>\"id:\"</code> and <code>\"path:\"</code> respectively.</p> <p>A PushSecret resource can only use a name reference.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: secret\nspec:\n refreshInterval: 20s\n secretStoreRef:\n kind: SecretStore\n name: secret-store\n data:\n - secretKey: &lt;KEY_IN_KUBE_SECRET&gt;\n remoteRef:\n key: id:&lt;SECRET_UUID&gt;\n version: latest_enabled\n</code></pre>"},{"location":"provider/secretserver/","title":"Delinea Secret Server","text":"<p>External Secrets Operator integration with Delinea Secret Server.</p>"},{"location":"provider/secretserver/#creating-a-secretstore","title":"Creating a SecretStore","text":"<p>You need a username, password and a fully qualified Secret Server tenant URL to authenticate i.e. <code>https://yourTenantName.secretservercloud.com</code>.</p> <p>Both username and password can be specified either directly in your <code>SecretStore</code> yaml config, or by referencing a kubernetes secret.</p> <p>To acquire a username and password, refer to the Secret Server user management documentation.</p> <p>Both <code>username</code> and <code>password</code> can either be specified directly via the <code>value</code> field (example below)</p> <p>spec.provider.secretserver.username.value: \"yourusername\" spec.provider.secretserver.password.value: \"yourpassword\" </p> <p>Or you can reference a kubernetes secret (password example below).</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: secret-server-store\nspec:\n provider:\n secretserver:\n serverURL: \"https://yourtenantname.secretservercloud.com\"\n username:\n value: \"yourusername\"\n password:\n secretRef:\n name: &lt;NAME_OF_K8S_SECRET&gt;\n key: &lt;KEY_IN_K8S_SECRET&gt;\n</code></pre>"},{"location":"provider/secretserver/#referencing-secrets","title":"Referencing Secrets","text":"<p>Secrets may be referenced by secret ID or secret name.</p> <p>Please note if using the secret name the name field must not contain spaces or control characters. If multiple secrets are found, <code>only the first found secret will be returned</code>.</p> <p>Please note: <code>Retrieving a specific version of a secret is not yet supported.</code></p> <p>Note that because all Secret Server secrets are JSON objects, you must specify the <code>remoteRef.property</code> in your ExternalSecret configuration. You can access nested values or arrays using gjson syntax.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: secret-server-external-secret\nspec:\n refreshInterval: 15s\n secretStoreRef:\n kind: SecretStore\n name: secret-server-store\n data:\n - secretKey: SecretServerValue #&lt;SECRET_VALUE_RETURNED_HERE&gt;\n remoteRef:\n key: \"52622\" #&lt;SECRET_ID&gt;\n property: \"array.0.value\" #&lt;GJSON_PROPERTY&gt; * an empty property will return the entire secret\n</code></pre>"},{"location":"provider/secretserver/#preparing-your-secret","title":"Preparing your secret","text":"<p>You can either retrieve your entire secret or you can use a JSON formatted string stored in your secret located at Items[0].ItemValue to retrieve a specific value. See example JSON secret below.</p>"},{"location":"provider/secretserver/#examples","title":"Examples","text":"<p>Using the json formatted secret below:</p> <ul> <li>Lookup a single top level property using secret ID.</li> </ul> <p>spec.data.remoteRef.key = 52622 (id of the secret) spec.data.remoteRef.property = \"user\" (Items.0.ItemValue user attribute) returns: marktwain@hannibal.com</p> <ul> <li>Lookup a nested property using secret name.</li> </ul> <p>spec.data.remoteRef.key = \"external-secret-testing\" (name of the secret) spec.data.remoteRef.property = \"books.1\" (Items.0.ItemValue books.1 attribute) returns: huckleberryFinn</p> <ul> <li>Lookup by secret ID (secret name will work as well) and return the entire secret.</li> </ul> <p>spec.data.remoteRef.key = \"52622\" (id of the secret) spec.data.remoteRef.property = \"\" returns: The entire secret in JSON format as displayed below</p> <pre><code>{\n \"Name\": \"external-secret-testing\",\n \"FolderID\": 73,\n \"ID\": 52622,\n \"SiteID\": 1,\n \"SecretTemplateID\": 6098,\n \"SecretPolicyID\": -1,\n \"PasswordTypeWebScriptID\": -1,\n \"LauncherConnectAsSecretID\": -1,\n \"CheckOutIntervalMinutes\": -1,\n \"Active\": true,\n \"CheckedOut\": false,\n \"CheckOutEnabled\": false,\n \"AutoChangeEnabled\": false,\n \"CheckOutChangePasswordEnabled\": false,\n \"DelayIndexing\": false,\n \"EnableInheritPermissions\": true,\n \"EnableInheritSecretPolicy\": true,\n \"ProxyEnabled\": false,\n \"RequiresComment\": false,\n \"SessionRecordingEnabled\": false,\n \"WebLauncherRequiresIncognitoMode\": false,\n \"Items\": [\n {\n \"ItemID\": 280265,\n \"FieldID\": 439,\n \"FileAttachmentID\": 0,\n \"FieldName\": \"Data\",\n \"Slug\": \"data\",\n \"FieldDescription\": \"json text field\",\n \"Filename\": \"\",\n \"ItemValue\": \"{ \\\"user\\\": \\\"marktwain@hannibal.com\\\", \\\"occupation\\\": \\\"author\\\",\\\"books\\\":[ \\\"tomSawyer\\\",\\\"huckleberryFinn\\\",\\\"Pudd'nhead Wilson\\\"] }\",\n \"IsFile\": false,\n \"IsNotes\": false,\n \"IsPassword\": false\n }\n ]\n}\n</code></pre>"},{"location":"provider/senhasegura-dsm/","title":"senhasegura DevOps Secrets Management (DSM)","text":""},{"location":"provider/senhasegura-dsm/#senhasegura-devops-secrets-management-dsm","title":"senhasegura DevOps Secrets Management (DSM)","text":"<p>External Secrets Operator integrates with senhasegura DevOps Secrets Management (DSM) module to sync application secrets to secrets held on the Kubernetes cluster.</p>"},{"location":"provider/senhasegura-dsm/#authentication","title":"Authentication","text":"<p>Authentication in senhasegura uses DevOps Secrets Management (DSM) application authorization schema</p> <p>You need to create an Kubernetes Secret with desired auth parameters, for example:</p> <p>Instructions to setup authorizations and secrets in senhasegura DSM can be found at senhasegura docs for DSM and senhasegura YouTube channel</p> <pre><code>---\napiVersion: v1\nkind: Secret\nmetadata:\n name: senhasegura-dsm-auth\nstringData:\n CLIENT_SECRET: \"CHANGEME\"\n</code></pre>"},{"location":"provider/senhasegura-dsm/#examples","title":"Examples","text":"<p>To sync secrets between senhasegura and Kubernetes with External Secrets, we need to define an SecretStore or ClusterSecretStore resource with senhasegura provider, setting authentication in DSM module with Secret defined before</p>"},{"location":"provider/senhasegura-dsm/#secretstore","title":"SecretStore","text":"<pre><code>---\napiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: senhasegura\nspec:\n provider:\n senhasegura:\n url: \"https://senhasegura.changeme.com\"\n module: DSM # Select senhasegura DSM module to sync secrets\n auth:\n clientId: \"CHANGEME\"\n clientSecretSecretRef:\n name: senhasegura-dsm-auth\n key: CLIENT_SECRET\n ignoreSslCertificate: false # Optional\n</code></pre>"},{"location":"provider/senhasegura-dsm/#clustersecretstore","title":"ClusterSecretStore","text":"<pre><code>---\napiVersion: external-secrets.io/v1beta1\nkind: ClusterSecretStore\nmetadata:\n name: senhasegura\nspec:\n provider:\n senhasegura:\n url: \"https://senhasegura.changeme.com\"\n module: DSM # Select senhasegura DSM module to sync secrets\n auth:\n clientId: \"CHANGEME\"\n clientSecretSecretRef:\n name: senhasegura-dsm-auth\n key: CLIENT_SECRET\n namespace: senhasegura # Namespace of Secret \"senhasegura-dsm-auth\"\n ignoreSslCertificate: false # Optional\n</code></pre>"},{"location":"provider/senhasegura-dsm/#syncing-secrets","title":"Syncing secrets","text":"<p>In examples below, consider that three secrets (api-settings, db-settings and hsm-settings) are defined in senhasegura DSM</p> <p>**Secret Identifier: ** api-settings</p> <p>Secret data: </p> <pre><code>URL=https://example.com/api/example\nTOKEN=example-token-value\n</code></pre> <p>**Secret Identifier: ** db-settings</p> <p>Secret data: </p> <pre><code>DB_HOST='db.example'\nDB_PORT='5432'\nDB_USERNAME='example'\nDB_PASSWORD='example'\n</code></pre> <p>**Secret Identifier: ** hsm-settings</p> <p>Secret data: </p> <pre><code>HSM_ADDRESS='hsm.example'\nHSM_PORT='9223'\n</code></pre>"},{"location":"provider/senhasegura-dsm/#sync-dsm-secrets-using-secret-identifiers","title":"Sync DSM secrets using Secret Identifiers","text":"<p>You can fetch all key/value pairs for a given secret identifier If you leave the remoteRef.property empty. This returns the json-encoded secret value for that path.</p> <p>If you only need a specific key, you can select it using remoteRef.property as the key name.</p> <p>In this method, you can overwrites data name in Kubernetes Secret object (e.g API_SETTINGS and API_SETTINGS_TOKEN)</p> <pre><code>---\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example-secret\nspec:\n refreshInterval: \"30s\"\n secretStoreRef:\n name: senhasegura\n kind: SecretStore\n target:\n name: example-secret\n data:\n # Define API_SETTINGS Kubernetes Secret key, with json-encoded values from senhasegura secret with identifier \"api-settings\"\n - secretKey: API_SETTINGS\n remoteRef:\n key: api-settings # Secret Identifier in senhasegura\n # Define API_SETTINGS_TOKEN Kubernetes Secret key, with single secret key (TOKEN) from senhasegura as string\n - secretKey: API_SETTINGS_TOKEN\n remoteRef:\n key: api-settings # Secret Identifier in senhasegura\n property: TOKEN # Optional, Key name within secret\n</code></pre> <p>Kubernetes Secret will be create with follow <code>.data.X</code></p> <pre><code>API_SETTINGS='[{\"TOKEN\":\"example-token-value\",\"URL\":\"https://example.com/api/example\"}]'\nAPI_SETTINGS_TOKEN='example-token-value'\n</code></pre>"},{"location":"provider/senhasegura-dsm/#sync-dsm-secrets-using-secret-identifiers-with-automatically-name-assignments","title":"Sync DSM secrets using Secret Identifiers with automatically name assignments","text":"<p>If your app requires multiples secrets, it is not required to create multiple ExternalSecret resources, you can aggregate secrets using a single ExternalSecret resource</p> <p>In this method, every secret data in senhasegura creates an Kubernetes Secret <code>.data.X</code> field</p> <pre><code>---\napiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: example-secret\nspec:\n refreshInterval: \"30s\"\n secretStoreRef:\n name: senhasegura\n kind: SecretStore\n target:\n name: example-secret\n dataFrom:\n # Define Kubernetes Secret key with any k/v pair in senhasegura Secret with identifier \"api-settings\" or \"db-settings\"\n - extract:\n key: api-settings\n - extract:\n key: db-settings\n</code></pre> <p>Kubernetes Secret will be create with follow <code>.data.X</code></p> <pre><code>URL='https://example.com/api/example'\nTOKEN='example-token-value'\nDB_HOST='db.example'\nDB_PORT='5432'\nDB_USERNAME='example'\nDB_PASSWORD='example'\n</code></pre>"},{"location":"provider/webhook/","title":"Webhook","text":""},{"location":"provider/webhook/#generic-webhook","title":"Generic Webhook","text":"<p>External Secrets Operator can integrate with simple web apis by specifying the endpoint</p>"},{"location":"provider/webhook/#example","title":"Example","text":"<p>First, create a SecretStore with a webhook backend. We'll use a static user/password <code>root</code>:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: webhook-backend\nspec:\n provider:\n webhook:\n url: \"http://httpbin.org/get?parameter={{ .remoteRef.key }}\"\n result:\n jsonPath: \"$.args.parameter\"\n headers:\n Content-Type: application/json\n Authorization: Basic {{ print .auth.username \":\" .auth.password | b64enc }}\n secrets:\n - name: auth\n secretRef:\n name: webhook-credentials\n---\napiVersion: v1\nkind: Secret\nmetadata:\n name: webhook-credentials\ndata:\n username: dGVzdA== # \"test\"\n password: dGVzdA== # \"test\"\n</code></pre> <p>NB: This is obviously not practical because it just returns the key as the result, but it shows how it works</p> <p>NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in all <code>secrets</code> references with the namespaces where the secrets reside.</p> <p>Now create an ExternalSecret that uses the above SecretStore:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: webhook-example\nspec:\n refreshInterval: \"15s\"\n secretStoreRef:\n name: webhook-backend\n kind: SecretStore\n target:\n name: example-sync\n data:\n - secretKey: foobar\n remoteRef:\n key: secret\n---\n# will create a secret with:\nkind: Secret\nmetadata:\n name: example-sync\ndata:\n foobar: c2VjcmV0\n</code></pre>"},{"location":"provider/webhook/#limitations","title":"Limitations","text":"<p>Webhook does not support authorization, other than what can be sent by generating http headers</p> <p>Note</p> <p>If a webhook endpoint for a given <code>ExternalSecret</code> returns a 404 status code, the secret is considered to have been deleted. This will trigger the <code>deletionPolicy</code> set on the <code>ExternalSecret</code>.</p>"},{"location":"provider/webhook/#templating","title":"Templating","text":"<p>Generic WebHook provider uses the templating engine to generate the API call. It can be used in the url, headers, body and result.jsonPath fields.</p> <p>The provider inserts the secret to be retrieved in the object named <code>remoteRef</code>.</p> <p>In addition, secrets can be added as named objects, for example to use in authorization headers. Each secret has a <code>name</code> property which determines the name of the object in the templating engine.</p>"},{"location":"provider/webhook/#all-parameters","title":"All Parameters","text":"<pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ClusterSecretStore\nmetadata:\n name: statervault\nspec:\n provider:\n webhook:\n # Url to call. Use templating engine to fill in the request parameters\n url: &lt;url&gt;\n # http method, defaults to GET\n method: &lt;method&gt;\n # Timeout in duration (1s, 1m, etc)\n timeout: 1s\n result:\n # [jsonPath](https://jsonpath.com) syntax, which also can be templated\n jsonPath: &lt;jsonPath&gt;\n # Map of headers, can be templated\n headers:\n &lt;Header-Name&gt;: &lt;header contents&gt;\n # Body to sent as request, can be templated (optional)\n body: &lt;body&gt;\n # List of secrets to expose to the templating engine\n secrets:\n # Use this name to refer to this secret in templating, above\n - name: &lt;name&gt;\n secretRef:\n namespace: &lt;namespace&gt; # Only used in ClusterSecretStores\n name: &lt;name&gt;\n # Add CAs here for the TLS handshake\n caBundle: &lt;base64 encoded cabundle&gt;\n caProvider:\n type: Secret or ConfigMap\n name: &lt;name of secret or configmap&gt;\n namespace: &lt;namespace&gt; # Only used in ClusterSecretStores\n key: &lt;key inside secret&gt;\n</code></pre>"},{"location":"provider/webhook/#webhook-as-generators","title":"Webhook as generators","text":"<p>You can also leverage webhooks as generators, following the same syntax. The only difference is that the webhook generator needs its source secrets to be labeled, as opposed to webhook secretstores. Please see the generator-webhook documentation for more information. </p>"},{"location":"provider/yandex-certificate-manager/","title":"Yandex Certificate Manager","text":""},{"location":"provider/yandex-certificate-manager/#yandex-certificate-manager","title":"Yandex Certificate Manager","text":"<p>External Secrets Operator integrates with Yandex Certificate Manager for secret management.</p>"},{"location":"provider/yandex-certificate-manager/#prerequisites","title":"Prerequisites","text":"<ul> <li>External Secrets Operator installed</li> <li>Yandex.Cloud CLI installed</li> </ul>"},{"location":"provider/yandex-certificate-manager/#authentication","title":"Authentication","text":"<p>At the moment, authorized key authentication is only supported:</p> <ul> <li>Create a service account in Yandex.Cloud: <pre><code>yc iam service-account create --name eso-service-account\n</code></pre></li> <li>Create an authorized key for the service account and save it to <code>authorized-key.json</code> file: <pre><code>yc iam key create \\\n --service-account-name eso-service-account \\\n --output authorized-key.json\n</code></pre></li> <li>Create a k8s secret containing the authorized key saved above: <pre><code>kubectl create secret generic yc-auth --from-file=authorized-key=authorized-key.json\n</code></pre></li> <li>Create a SecretStore pointing to <code>yc-auth</code> k8s secret: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: secret-store\nspec:\n provider:\n yandexcertificatemanager:\n auth:\n authorizedKeySecretRef:\n name: yc-auth\n key: authorized-key\n</code></pre></li> </ul> <p>NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in all <code>authorizedKeySecretRef</code> with the namespace where the secret resides.</p>"},{"location":"provider/yandex-certificate-manager/#creating-external-secret","title":"Creating external secret","text":"<p>To make External Secrets Operator sync a k8s secret with a Certificate Manager certificate:</p> <ul> <li>Create a Certificate Manager certificate (follow the instructions), if not already created.</li> <li>Assign the <code>certificate-manager.certificates.downloader</code> role for accessing the certificate content to the service account used for authentication (<code>*****</code> is the certificate ID): <pre><code>yc cm certificate add-access-binding \\\n --id ***** \\\n --service-account-name eso-service-account \\\n --role certificate-manager.certificates.downloader\n</code></pre> Run the following command to ensure that the correct access binding has been added: <pre><code>yc cm certificate list-access-bindings --id *****\n</code></pre></li> <li>Create an ExternalSecret pointing to <code>secret-store</code> and the certificate in Certificate Manager: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: external-secret\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: secret-store\n kind: SecretStore\n target:\n name: k8s-secret # the target k8s secret name\n template:\n type: kubernetes.io/tls\n data:\n - secretKey: tls.crt # the target k8s secret key\n remoteRef:\n key: ***** # the certificate ID\n property: chain\n - secretKey: tls.key # the target k8s secret key\n remoteRef:\n key: ***** # the certificate ID\n property: privateKey\n</code></pre> The following property values are possible:<ul> <li><code>chain</code> \u2013 to fetch PEM-encoded certificate chain</li> <li><code>privateKey</code> \u2013 to fetch PEM-encoded private key</li> <li><code>chainAndPrivateKey</code> or missing property \u2013 to fetch both chain and private key</li> </ul> </li> </ul> <p>The operator will fetch the Yandex Certificate Manager certificate and inject it as a <code>Kind=Secret</code> <pre><code>kubectl get secret k8s-secret -ojson | jq '.\"data\".\"tls.crt\"' -r | base64 --decode\nkubectl get secret k8s-secret -ojson | jq '.\"data\".\"tls.key\"' -r | base64 --decode\n</code></pre></p>"},{"location":"provider/yandex-lockbox/","title":"Yandex Lockbox","text":""},{"location":"provider/yandex-lockbox/#yandex-lockbox","title":"Yandex Lockbox","text":"<p>External Secrets Operator integrates with Yandex Lockbox for secret management.</p>"},{"location":"provider/yandex-lockbox/#prerequisites","title":"Prerequisites","text":"<ul> <li>External Secrets Operator installed</li> <li>Yandex.Cloud CLI installed</li> </ul>"},{"location":"provider/yandex-lockbox/#authentication","title":"Authentication","text":"<p>At the moment, authorized key authentication is only supported:</p> <ul> <li>Create a service account in Yandex.Cloud: <pre><code>yc iam service-account create --name eso-service-account\n</code></pre></li> <li>Create an authorized key for the service account and save it to <code>authorized-key.json</code> file: <pre><code>yc iam key create \\\n --service-account-name eso-service-account \\\n --output authorized-key.json\n</code></pre></li> <li>Create a k8s secret containing the authorized key saved above: <pre><code>kubectl create secret generic yc-auth --from-file=authorized-key=authorized-key.json\n</code></pre></li> <li>Create a SecretStore pointing to <code>yc-auth</code> k8s secret: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: secret-store\nspec:\n provider:\n yandexlockbox:\n auth:\n authorizedKeySecretRef:\n name: yc-auth\n key: authorized-key\n</code></pre></li> </ul> <p>NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in all <code>authorizedKeySecretRef</code> with the namespace where the secret resides.</p>"},{"location":"provider/yandex-lockbox/#creating-external-secret","title":"Creating external secret","text":"<p>To make External Secrets Operator sync a k8s secret with a Lockbox secret:</p> <ul> <li>Create a Lockbox secret, if not already created: <pre><code>yc lockbox secret create \\\n --name lockbox-secret \\\n --payload '[{\"key\": \"password\",\"textValue\": \"p@$$w0rd\"}]'\n</code></pre></li> <li>Assign the <code>lockbox.payloadViewer</code> role for accessing the <code>lockbox-secret</code> payload to the service account used for authentication: <pre><code>yc lockbox secret add-access-binding \\\n --name lockbox-secret \\\n --service-account-name eso-service-account \\\n --role lockbox.payloadViewer\n</code></pre> Run the following command to ensure that the correct access binding has been added: <pre><code>yc lockbox secret list-access-bindings --name lockbox-secret\n</code></pre></li> <li>Create an ExternalSecret pointing to <code>secret-store</code> and <code>lockbox-secret</code>: <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: external-secret\nspec:\n refreshInterval: 1h\n secretStoreRef:\n name: secret-store\n kind: SecretStore\n target:\n name: k8s-secret # the target k8s secret name\n data:\n - secretKey: password # the target k8s secret key\n remoteRef:\n key: ***** # ID of lockbox-secret\n property: password # (optional) payload entry key of lockbox-secret\n</code></pre></li> </ul> <p>The operator will fetch the Yandex Lockbox secret and inject it as a <code>Kind=Secret</code> <pre><code>kubectl get secret k8s-secret -n &lt;namespace&gt; | -o jsonpath='{.data.password}' | base64 -d\n</code></pre></p>"},{"location":"snippets/provider-aws-access/","title":"Provider aws access","text":""},{"location":"snippets/provider-aws-access/#aws-authentication","title":"AWS Authentication","text":""},{"location":"snippets/provider-aws-access/#controllers-pod-identity","title":"Controller's Pod Identity","text":"<p>Note: If you are using Parameter Store replace <code>service: SecretsManager</code> with <code>service: ParameterStore</code> in all examples below.</p> <p>This is basicially a zero-configuration authentication method that inherits the credentials from the runtime environment using the aws sdk default credential chain.</p> <p>You can attach a role to the pod using IRSA, kiam or kube2iam. When no other authentication method is configured in the <code>Kind=Secretstore</code> this role is used to make all API calls against AWS Secrets Manager or SSM Parameter Store.</p> <p>Based on the Pod's identity you can do a <code>sts:assumeRole</code> before fetching the secrets to limit access to certain keys in your provider. This is optional.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: team-b-store\nspec:\n provider:\n aws:\n service: SecretsManager\n region: eu-central-1\n # optional: do a sts:assumeRole before fetching secrets\n role: team-b\n</code></pre>"},{"location":"snippets/provider-aws-access/#access-key-id-secret-access-key","title":"Access Key ID &amp; Secret Access Key","text":"<p>You can store Access Key ID &amp; Secret Access Key in a <code>Kind=Secret</code> and reference it from a SecretStore.</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: team-b-store\nspec:\n provider:\n aws:\n service: SecretsManager\n region: eu-central-1\n # optional: assume role before fetching secrets\n role: team-b\n auth:\n secretRef:\n accessKeyIDSecretRef:\n name: awssm-secret\n key: access-key\n secretAccessKeySecretRef:\n name: awssm-secret\n key: secret-access-key\n</code></pre> <p>NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> in <code>accessKeyIDSecretRef</code>, <code>secretAccessKeySecretRef</code> with the namespaces where the secrets reside.</p>"},{"location":"snippets/provider-aws-access/#eks-service-account-credentials","title":"EKS Service Account credentials","text":"<p>This feature lets you use short-lived service account tokens to authenticate with AWS. You must have Service Account Volume Projection enabled - it is by default on EKS. See EKS guide on how to set up IAM roles for service accounts.</p> <p>The big advantage of this approach is that ESO runs without any credentials.</p> <pre><code>apiVersion: v1\nkind: ServiceAccount\nmetadata:\n annotations:\n eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/team-a\n name: my-serviceaccount\n namespace: default\n</code></pre> <p>Reference the service account from above in the Secret Store:</p> <pre><code>apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: secretstore-sample\nspec:\n provider:\n aws:\n service: SecretsManager\n region: eu-central-1\n auth:\n jwt:\n serviceAccountRef:\n name: my-serviceaccount\n</code></pre> <p>NOTE: In case of a <code>ClusterSecretStore</code>, Be sure to provide <code>namespace</code> for <code>serviceAccountRef</code> with the namespace where the service account resides.</p>"},{"location":"snippets/provider-aws-access/#custom-endpoints","title":"Custom Endpoints","text":"<p>You can define custom AWS endpoints if you want to use regional, vpc or custom endpoints. See List of endpoints for Secrets Manager, Secure Systems Manager and Security Token Service.</p> <p>Use the following environment variables to point the controller to your custom endpoints. Note: All resources managed by this controller are affected.</p> ENV VAR DESCRIPTION AWS_SECRETSMANAGER_ENDPOINT Endpoint for the Secrets Manager Service. The controller uses this endpoint to fetch secrets from AWS Secrets Manager. AWS_SSM_ENDPOINT Endpoint for the AWS Secure Systems Manager. The controller uses this endpoint to fetch secrets from SSM Parameter Store. AWS_STS_ENDPOINT Endpoint for the Security Token Service. The controller uses this endpoint when creating a session and when doing <code>assumeRole</code> or <code>assumeRoleWithWebIdentity</code> calls."}]}