{"id":13521775,"url":"https://github.com/ricoberger/vault-secrets-operator","last_synced_at":"2025-05-15T04:03:11.690Z","repository":{"id":35447357,"uuid":"204312226","full_name":"ricoberger/vault-secrets-operator","owner":"ricoberger","description":"Create Kubernetes secrets from Vault for a secure GitOps based workflow.","archived":false,"fork":false,"pushed_at":"2025-04-05T13:13:48.000Z","size":1002,"stargazers_count":652,"open_issues_count":19,"forks_count":105,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-04-06T23:11:27.916Z","etag":null,"topics":["crd","gitops","helm-chart","kubernetes","kubernetes-secrets","operator-sdk","secret","secrets","vault"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ricoberger.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["ricoberger"],"custom":["https://www.paypal.me/ricoberger"]}},"created_at":"2019-08-25T15:20:01.000Z","updated_at":"2025-04-05T13:13:51.000Z","dependencies_parsed_at":"2023-10-16T08:50:01.276Z","dependency_job_id":"1fdeb424-6fcd-407f-bfed-86e0596ae9ca","html_url":"https://github.com/ricoberger/vault-secrets-operator","commit_stats":{"total_commits":415,"total_committers":53,"mean_commits":7.830188679245283,"dds":"0.40963855421686746","last_synced_commit":"7fe05fc1bc32ab85ee9f1d72fcfe9a3b457b61b2"},"previous_names":[],"tags_count":78,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ricoberger%2Fvault-secrets-operator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ricoberger%2Fvault-secrets-operator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ricoberger%2Fvault-secrets-operator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ricoberger%2Fvault-secrets-operator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ricoberger","download_url":"https://codeload.github.com/ricoberger/vault-secrets-operator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248819380,"owners_count":21166477,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crd","gitops","helm-chart","kubernetes","kubernetes-secrets","operator-sdk","secret","secrets","vault"],"created_at":"2024-08-01T06:00:37.922Z","updated_at":"2025-05-15T04:03:11.669Z","avatar_url":"https://github.com/ricoberger.png","language":"Go","funding_links":["https://github.com/sponsors/ricoberger","https://www.paypal.me/ricoberger"],"categories":["Secret Management","kubernetes","Secrets management","Go","Tools","Open Source Projects","Kubernetes Operators","Ancillary Tools"],"sub_categories":["Regex","Kubernetes","Secrets"],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"./assets/logo.png?\" width=\"20%\" /\u003e\n  \u003cbr\u003e\u003cbr\u003e\n\nCreate Kubernetes secrets from Vault for a secure GitOps based workflow.\n\n  \u003cimg src=\"./assets/gitops.png?\" width=\"100%\" /\u003e\n\u003c/div\u003e\n\nThe **Vault Secrets Operator** creates Kubernetes secrets from Vault. The idea\nbehind the Vault Secrets Operator is to manage secrets in Kubernetes cluster\nusing a secure GitOps based workflow. For more information about a secure GitOps\nbased workflow I recommend the article\n[\"Managing Secrets in Kubernetes\"](https://www.weave.works/blog/managing-secrets-in-kubernetes)\nfrom [Weaveworks](https://www.weave.works). With the help of the Vault Secrets\nOperator you can commit your secrets to your git repository using a custom\nresource. If you apply these secrets to your Kubernetes cluster the Operator\nwill lookup the real secret in Vault and creates the corresponding Kubernetes\nsecret. If you are using something like\n[Sealed Secrets](http://github.com/bitnami-labs/sealed-secrets) for this\nworkflow the Vault Secrets Operator can be used as replacement for this.\n\n## Installation\n\nThe Vault Secrets Operator can be installed via Helm. A list of all configurable\nvalues can be found [here](./charts/README.md). The chart assumes a vault server\nrunning at `http://vault:8200`, but can be overidden by specifying\n`--set vault.address=https://vault.example.com`\n\n```sh\nhelm upgrade --install vault-secrets-operator oci://ghcr.io/ricoberger/charts/vault-secrets-operator --version \u003cVERSION\u003e\n```\n\n### Prepare Vault\n\nThe Vault Secrets Operator supports the **KV Secrets Engine - Version 1** and\n**KV Secrets Engine - Version 2**. To create a new secret engine under a path\nnamed `kvv1` and `kvv2`, you can run the following command:\n\n```sh\nvault secrets enable -path=kvv1 -version=1 kv\nvault secrets enable -path=kvv2 -version=2 kv\n```\n\nAfter you have enabled the secret engine, create a new policy for the Vault\nSecrets Operator. The operator only needs read access to the paths you want to\nuse for your secrets. To create a new policy with the name\n`vault-secrets-operator` and read access to the `kvv1` and `kvv2` path, you can\nrun the following command:\n\n```sh\ncat \u003c\u003cEOF | vault policy write vault-secrets-operator -\npath \"kvv1/*\" {\n  capabilities = [\"read\"]\n}\n\npath \"kvv2/data/*\" {\n  capabilities = [\"read\"]\n}\nEOF\n```\n\nTo access Vault, the operator can choose between:\n\n- **[Token Auth Method](https://www.vaultproject.io/docs/auth/token.html)**\n- **[Kubernetes Auth Method](https://www.vaultproject.io/docs/auth/kubernetes.html)**\n- **[AppRole Auth Method](https://www.vaultproject.io/docs/auth/approle.html)**\n- **[Username \u0026 Password Auth Method](https://www.vaultproject.io/docs/auth/userpass.html)**\n- **[AWS Auth Method](https://www.vaultproject.io/docs/auth/aws.html)**\n- **[Azure Auth Method](https://www.vaultproject.io/docs/auth/azure.html)**\n- **[GCP Auth Method](https://www.vaultproject.io/docs/auth/gcp.html)**\n\nIn the next sections you can find the instructions to setup Vault for the\nauthentication methods.\n\n#### Token Auth Method\n\nTo use Token auth method for the authentication against the Vault API, you need\nto create a token. A token with the previously created policy can be created as\nfollows:\n\n```sh\nvault token create -period=24h -policy=vault-secrets-operator\n```\n\nTo use the created token you need to pass the token as an environment variable\nto the operator. For security reasons the operator only supports the passing of\nenvironment variables via a Kubernetes secret. The secret with the keys\n`VAULT_TOKEN` and `VAULT_TOKEN_LEASE_DURATION` (as well as optional keys\n`VAULT_TOKEN_RENEWAL_INTERVAL` and `VAULT_TOKEN_RENEWAL_RETRY_INTERVAL` to\ncontrol timings for token renewals, if required. `VAULT_RENEW_TOKEN` can also be\nset to `\"false\"` to disable the operators token renew loop) can be created with\nthe following command:\n\n```sh\nexport VAULT_TOKEN=\nexport VAULT_TOKEN_LEASE_DURATION=86400\n\ncat \u003c\u003cEOF | kubectl apply -f -\napiVersion: v1\nkind: Secret\nmetadata:\n  name: vault-secrets-operator\ntype: Opaque\ndata:\n  VAULT_TOKEN: $(echo -n \"$VAULT_TOKEN\" | base64)\n  VAULT_TOKEN_LEASE_DURATION: $(echo -n \"$VAULT_TOKEN_LEASE_DURATION\" | base64)\nEOF\n```\n\nThis creates a secret named `vault-secrets-operator`. To use this secret in the\nHelm chart modify the `values.yaml` file as follows:\n\n```yaml\nenvironmentVars:\n  - name: VAULT_TOKEN\n    valueFrom:\n      secretKeyRef:\n        name: vault-secrets-operator\n        key: VAULT_TOKEN\n  - name: VAULT_TOKEN_LEASE_DURATION\n    valueFrom:\n      secretKeyRef:\n        name: vault-secrets-operator\n        key: VAULT_TOKEN_LEASE_DURATION\n```\n\n#### Kubernetes Auth Method\n\nThe recommended way to authenticate is the Kubernetes auth method, which\nrequires a service account for communication between Vault and the Vault Secrets\nOperator. If you installed the operator via Helm this service account is created\nfor you. The name of the created service account is `vault-secrets-operator`.\nUse the following commands to set the environment variables for the activation\nof the Kubernetes auth method:\n\n```sh\nexport VAULT_SECRETS_OPERATOR_NAMESPACE=$(kubectl get sa vault-secrets-operator -o jsonpath=\"{.metadata.namespace}\")\nexport VAULT_SECRET_NAME=$(kubectl get secret vault-secrets-operator -o jsonpath=\"{.metadata.name}\")\nexport SA_JWT_TOKEN=$(kubectl get secret $VAULT_SECRET_NAME -o jsonpath=\"{.data.token}\" | base64 --decode; echo)\nexport SA_CA_CRT=$(kubectl get secret $VAULT_SECRET_NAME -o jsonpath=\"{.data['ca\\.crt']}\" | base64 --decode; echo)\nexport K8S_HOST=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')\n\n# Verify the environment variables\nenv | grep -E 'VAULT_SECRETS_OPERATOR_NAMESPACE|VAULT_SECRET_NAME|SA_JWT_TOKEN|SA_CA_CRT|K8S_HOST'\n\n# To discover the service account issuer the following commands can be used:\nkubectl proxy\ncurl --silent http://127.0.0.1:8001/api/v1/namespaces/default/serviceaccounts/default/token -H \"Content-Type: application/json\" -X POST -d '{\"apiVersion\": \"authentication.k8s.io/v1\", \"kind\": \"TokenRequest\"}' | jq -r '.status.token' | cut -d . -f2 | base64 -D\n```\n\nEnable the Kubernetes auth method at the default path (`auth/kubernetes`) and\nfinish the configuration of Vault:\n\n```sh\nvault auth enable kubernetes\n\n# Tell Vault how to communicate with the Kubernetes cluster\nvault write auth/kubernetes/config \\\n  issuer=\"https://kubernetes.default.svc.cluster.local\" \\\n  token_reviewer_jwt=\"$SA_JWT_TOKEN\" \\\n  kubernetes_host=\"$K8S_HOST\" \\\n  kubernetes_ca_cert=\"$SA_CA_CRT\"\n\n# Create a role named, 'vault-secrets-operator' to map Kubernetes Service Account to Vault policies and default token TTL\nvault write auth/kubernetes/role/vault-secrets-operator \\\n  bound_service_account_names=\"vault-secrets-operator\" \\\n  bound_service_account_namespaces=\"$VAULT_SECRETS_OPERATOR_NAMESPACE\" \\\n  policies=vault-secrets-operator \\\n  ttl=24h\n\n# If you're running Vault inside Kubernetes, you can alternatively exec into any Vault pod and run this...\n# In modern versions of vault, the token / host / CA cert will be fetched automatically.\n# https://github.com/hashicorp/vault-plugin-auth-kubernetes/issues/121#issuecomment-1046949951\n# vault write auth/kubernetes/config \\\n#   kubernetes_host=https://${KUBERNETES_PORT_443_TCP_ADDR}:443\n```\n\nWhen you deploy the Vault Secrets Operator via Helm chart you have to set the\n`vault.authMethod` property to `kubernetes` in the `values.yaml` file, to use\nthe Kubernetes auth method instead of the default Token auth methods.\n\n```yaml\nvault:\n  authMethod: kubernetes\n```\n\n#### AppRole Auth Method\n\nTo use AppRole auth method for the authentication against the Vault API, you\nneed to create a new AppRole.\n\n```sh\n# Enable AppRole auth method:\nvault auth enable approle\n\n# AppRole with the previously created policy can be created as follows:\nvault write auth/approle/role/vault-secrets-operator \\\n  token_policies=vault-secrets-operator\n\n# Get AppRole ID:\nvault read auth/approle/role/vault-secrets-operator/role-id\n\n# Create a new secret for AppRole:\nvault write -f auth/approle/role/vault-secrets-operator/secret-id\n```\n\nUse the following commands to set the environment variables for the activation\nof the AppRole auth method:\n\n```shell\nexport VAULT_AUTH_METHOD=approle\nexport VAULT_ROLE_ID=\nexport VAULT_SECRET_ID=\nexport VAULT_TOKEN_MAX_TTL=86400\n```\n\nWhen you deploy the Vault Secrets Operator via Helm chart you have to set the\n`vault.authMethod` property to `approle` in the `values.yaml` file, to use the\nAppRole auth method instead of the default Token auth method.\n\n```yaml\nvault:\n  authMethod: approle\n```\n\nSet `VAULT_TOKEN_MAX_TTL` (default: 16 days) same or lower than the\n`token_max_ttl` of the AppRole (Vault default: 32 days) to ensure\nreauthentication in time. Mounting the vault ROLE_ID and SECRET_ID secrets as\nvolumes is supported. It requires `image.volumeMounts` to be populated,\n`VAULT_ROLE_ID_PATH` and `VAULT_SECRET_ID_PATH` to be set in\n`environmentVars`(or `export` as shell variables), and `volumes` to be\npopulated. See example below:\n\nNOTE: `image.volumeMounts[].mountPath` must match `environmentVars[].value` for\nthe respective ROLE_ID or SECRET_ID. Reference\n[Kubernetes: Using Secrets as files from a Pod](https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-files-from-a-pod)\n\n```yaml\nimage:\n  volumeMounts:\n    - name: vault-role-id\n      mountPath: \"/etc/vault/role/\"\n      readOnly: true\n    - name: vault-secret-id\n      mountPath: \"/etc/vault/secret/\"\n      readOnly: true\nenvironmentVars:\n  - name: VAULT_ROLE_ID_PATH\n    value: \"/etc/vault/role/id\"\n  - name: VAULT_SECRET_ID_PATH\n    value: \"/etc/vault/secret/id\"\nvolumes:\n  - name: vault-role-id\n    secret:\n      secretName: vault-secrets-operator\n      items:\n        - key: VAULT_ROLE_ID\n          path: \"id\"\n  - name: vault-secret-id\n    secret:\n      secretName: vault-secrets-operator\n      items:\n        - key: VAULT_SECRET_ID\n          path: \"id\"\n```\n\n### Username and Password\n\nTo use username and password auth method for the authentication against the\nVault API, you need to create a new user.\n\n```sh\n# Enable userpass auth method\nvault auth enable userpass\n\n# Create a user if not already created\nvault write auth/userpass/users/\u003cusername\u003e password=\u003cpassword\u003e policies=\u003cpolicies\u003e\n```\n\nUse the following commands to set the environment variables for the activation\nof the UserPass auth method:\n\n```shell\nexport VAULT_AUTH_METHOD=userpass\nexport VAULT_USER=\nexport VAULT_PASSWORD=\nexport VAULT_TOKEN_MAX_TTL=120\n```\n\nWhen you deploy the Vault Secrets Operator via Helm chart you have to set the\n`vault.authMethod` property to `userpass` in the `values.yaml` file, to use the\nUserPass auth method instead of the default Token auth method.\n\n```yaml\nvault:\n  authMethod: userpass\n```\n\n### AWS Auth Method\n\nYou can use either ec2 or iam auth types on eks clusters to authenticate against\nthe Vault API. [here](https://www.vaultproject.io/docs/auth/aws) Then you can\nenable the auth method with the following environment variables:\n\n```shell\nexport VAULT_AUTH_METHOD=aws\nexport VAULT_AWS_PATH=auth/aws\nexport VAULT_AWS_ROLE=vault-secrets-operator\nexport VAULT_AWS_AUTH_TYPE=iam\n```\n\nIf you deploy the Vault Secrets Operator via Helm you have to set the\n`vault.authMethod`, `vault.awsPath`, `vault.awsRole` and `vault.awsAuthType`\nvalues in the `values.yaml` file.\n\n### Azure Auth Method\n\nYou can use the managed system identity provided on aks cluster to authenticate\nagainst the Vault API, to do that you will need to setup an auth backend as\ndescribed [here](https://www.vaultproject.io/docs/auth/azure) Then you can setup\nthe auth method with the following environment variables:\n\n```shell\nexport VAULT_AUTH_METHOD=azure\nexport VAULT_AZURE_PATH=auth/azure\nexport VAULT_AZURE_ROLE=default\nexport VAULT_AZURE_ISSCALESET=true # Set this to true if the kubernetes nodes are in a vmss and not isolated vm (default in aks)\n```\n\nIf you deploy the Vault Secrets Operator via Helm you have to set the\n`vault.authMethod`, `vault.azurepath`, `vault.azureRole`, `vault.azureScaleset`\nvalues in the `values.yaml` file.\n\n### GCP Auth Method\n\nYou can use either gce or iam auth types on gke clusters to authenticate against\nthe Vault API. [here](https://www.vaultproject.io/docs/auth/gcp) Then you can\nenable the auth method with the following environment variables:\n\n```shell\nexport VAULT_AUTH_METHOD=gcp\nexport VAULT_GCP_PATH=auth/gcp\nexport VAULT_GCP_ROLE=vault-secrets-operator\nexport VAULT_GCP_AUTH_TYPE=iam\n```\n\nIf you deploy the Vault Secrets Operator via Helm you have to set the\n`vault.authMethod`, `vault.gcpPath`, `vault.gcpRole` and `vault.gcpAuthType`\nvalues in the `values.yaml` file.\n\n## Usage\n\n### Secret Engine\n\nCreate two Vault secrets `example-vaultsecret`:\n\n```sh\nvault kv put kvv1/example-vaultsecret foo=bar hello=world\n\nvault kv put kvv2/example-vaultsecret foo=bar\nvault kv put kvv2/example-vaultsecret hello=world\nvault kv put kvv2/example-vaultsecret foo=bar hello=world\n```\n\nDeploy the custom resource `kvv1-example-vaultsecret` to your Kubernetes\ncluster:\n\n```yaml\napiVersion: ricoberger.de/v1alpha1\nkind: VaultSecret\nmetadata:\n  name: kvv1-example-vaultsecret\nspec:\n  keys:\n    - foo\n  path: kvv1/example-vaultsecret\n  type: Opaque\n```\n\nThe Vault Secrets Operator creates a Kubernetes secret named\n`kvv1-example-vaultsecret` with the type `Opaque` from this CR:\n\n```yaml\napiVersion: v1\ndata:\n  foo: YmFy\nkind: Secret\nmetadata:\n  labels:\n    created-by: vault-secrets-operator\n  name: kvv1-example-vaultsecret\ntype: Opaque\n```\n\nYou can also omit the `keys` spec to create a Kubernetes secret which contains\nall keys from the Vault secret:\n\n```yaml\napiVersion: v1\ndata:\n  foo: YmFy\n  hello: d29ybGQ=\nkind: Secret\nmetadata:\n  labels:\n    created-by: vault-secrets-operator\n  name: kvv1-example-vaultsecret\ntype: Opaque\n```\n\nTo deploy a custom resource `kvv2-example-vaultsecret`, which uses the secret\nfrom the KV Secrets Engine - Version 2 you can use the following:\n\n```yaml\napiVersion: ricoberger.de/v1alpha1\nkind: VaultSecret\nmetadata:\n  name: kvv2-example-vaultsecret\nspec:\n  path: kvv2/example-vaultsecret\n  type: Opaque\n```\n\nThe Vault Secrets Operator will create a secret which looks like the following:\n\n```yaml\napiVersion: v1\ndata:\n  foo: YmFy\n  hello: d29ybGQ=\nkind: Secret\nmetadata:\n  labels:\n    created-by: vault-secrets-operator\n  name: kvv2-example-vaultsecret\ntype: Opaque\n```\n\nFor secrets using the KVv2 secret engine you can also specify the version of the\nsecret you want to deploy:\n\n```yaml\napiVersion: ricoberger.de/v1alpha1\nkind: VaultSecret\nmetadata:\n  name: kvv2-example-vaultsecret\nspec:\n  path: kvv2/example-vaultsecret\n  type: Opaque\n  version: 2\n```\n\nThe resulting Kubernetes secret will be:\n\n```yaml\napiVersion: v1\ndata:\n  hello: d29ybGQ=\nkind: Secret\nmetadata:\n  labels:\n    created-by: vault-secrets-operator\n  name: kvv2-example-vaultsecret\ntype: Opaque\n```\n\nThe `spec.type` and `spec.keys` fields are handled in the same way for both\nversions of the KV secret engine. The `spec.version` field is only processed,\nwhen the secret is saved under a KVv2 secret engine. If you specified the\n`VAULT_RECONCILIATION_TIME` environment variable with a value greater than `0`\nevery secret is reconciled after the given time (in seconds). This means, when\nyou do not specify `spec.version`, the Kubernetes secret will be automatically\nupdated if the Vault secret changes. To set the `VAULT_RECONCILIATION_TIME`\nenvironment variable in the Helm chart the `vault.reconciliationTime` value can\nbe used.\n\nThe binary data stored in vault requires\n[base64 encoding](https://github.com/hashicorp/vault/issues/1423#issuecomment-219525845).\nthe `spec.isBinary` can be used to prevent such data get base64 encoded again\nwhen store as secret in k8s.\n\nFor example, let's set `foo` to the `bar` in base64 encoded format (i.e.\nYmFyCg==).\n\n```sh\nvault kv put kvv1/example-vaultsecret foo=YmFyCg==\n```\n\nYou can specify `spec.isBinary` to indicate this is a binary data which is\nalready in base64 encoded format:\n\n```yaml\napiVersion: ricoberger.de/v1alpha1\nkind: VaultSecret\nmetadata:\n  name: kvv1-example-vaultsecret\nspec:\n  keys:\n    - foo\n  isBinary: true\n  path: kvv1/example-vaultsecret\n  type: Opaque\n```\n\nThe resulting Kubernetes secret will be:\n\n```yaml\napiVersion: v1\ndata:\n  foo: YmFyCg==\nkind: Secret\nmetadata:\n  labels:\n    created-by: vault-secrets-operator\n  name: kvv1-example-vaultsecret\ntype: Opaque\n```\n\nThe value for `foo` stays as `YmFyCg==` which does not get base64 encoded again.\n\nIt is also possible to change the default reconciliation strategy from `Replace`\nto `Merge` via the `reconcileStrategy` key in the CRD. For the default `Replace`\nstrategy the complete secret is replaced. If you have an existing secret you can\nchoose the `Merge` strategy to add the keys from Vault to the existing secret.\n\n### Using templated secrets\n\nWhen straight-forward secrets are not sufficient, and the target secrets need to\nbe formatted in a certain way, you can use basic templating to format the\nsecrets. There are multiple uses for this:\n\n- Generate URIs which contain secrets\n- Format secrets in a specific way, for example when using the\n  [Helm Operator](https://docs.fluxcd.io/projects/helm-operator/) which\n  [can use secrets as a source](https://docs.fluxcd.io/projects/helm-operator/en/stable/helmrelease-guide/values/#secrets)\n  for its Helm chart parameterisation, but they have to be in YAML format\n  wrapped inside a secret, like\n  [`secretGenerator`](https://kubernetes-sigs.github.io/kustomize/api-reference/kustomization/secretegenerator/)\n  from [Kustomize](https://kustomize.io) also generates.\n\nTo do this, specify keys under `spec.templates`, containing a valid template\nstring. When `templates` is defined, the standard generation of secrets is\ndisabled, and only the defined templates will be generated.\n\nThe templating uses the standard Go templating engine, also used in tools such\nas [Helm](https://helm.sh) or [Gomplate](https://gomplate.ca). The main\ndifferentiator here is that the `{%` and `%}` delimiters are used to prevent\nconflicts with standard Go templating tools such as Helm, which use `{{` and\n`}}` for this.\n\nThe available functions during templating are the set offered by the\n[Sprig library](http://masterminds.github.io/sprig/) (similar to\n[Helm](https://helm.sh/docs/chart_template_guide/function_list/), but different\nfrom [Gomplate](https://docs.gomplate.ca)), excluding the following functions\nfor security-reasons or their non-idempotent nature to avoid reconciliation\nproblems:\n\n- `genPrivateKey`\n- `genCA`\n- `genSelfSignedCert`\n- `genSignedCert`\n- `htpasswd`\n- `getHostByName`\n- Random functions\n- Date/time functionality\n- Environment variable functions (for security reasons)\n\n#### Templating context\n\nThe context available in the templating engine contains the following items:\n\n- `.Secrets`: Map with all the secrets fetched from vault. Key = secret name,\n  Value = secret value\n- `.Vault`: Contains misc info about the Vault setup\n  - `.Vault.Address`: configured address of the Vault instance\n  - `.Vault.Path`: path of the Vault secret that was fetched\n- `.Namespace`: Namespace where the custom resource instance was deployed.\n- `.Labels`: access to the labels of the custom resource instance\n- `.Annotations`: access to the annotations of the custom resource instance\n\n#### Examples\n\nAn example of a URI formatting secret:\n\n```yaml\napiVersion: ricoberger.de/v1alpha1\nkind: VaultSecret\nmetadata:\n  name: kvv1-example-vaultsecret\n  annotations:\n    redisdb: \"0\"\nspec:\n  keys:\n    - foo\n    - bar\n  path: kvv1/example-vaultsecret\n  templates:\n    fooUri: \"https://user:{% .Secrets.foo %}@{% .Namespace %}.somesite.tld/api\"\n    barUri: \"redis://{% .Secrets.bar %}@redis/{% .Annotations.redisdb %}\"\n  type: Opaque\n```\n\nThe resulting secret will look like:\n\n```yaml\napiVersion: v1\ndata:\n  fooUri: aHR0cHM6Ly91c2VyOmZvb0BuYW1lc3BhY2UuLnNvbWVzaXRlLnRsZC9hcGkK\n  barUri: cmVkaXM6Ly9iYXJAcmVkaXMvMAo=\nkind: Secret\nmetadata:\n  labels:\n    created-by: vault-secrets-operator\n  name: kvv1-example-vaultsecret\ntype: Opaque\n```\n\nThis is a more advanced example for a secret that can be used by\n[HelmOperator](https://docs.fluxcd.io/projects/helm-operator/) as\n[`valuesFrom[].secretKeyRef`](https://docs.fluxcd.io/projects/helm-operator/en/stable/helmrelease-guide/values/#secrets):\n\n```yaml\napiVersion: ricoberger.de/v1alpha1\nkind: VaultSecret\nmetadata:\n  name: kvv1-example-vaultsecret\nspec:\n  keys:\n    - foo\n    - bar\n    - baz\n  path: kvv1/example-vaultsecret\n  templates:\n    values.yaml: |-\n      secrets:\n      {%- range $k, $v := .Secrets %}\n        {% $k %}: {% $v | quote -%}\n      {% end %}\n  type: Opaque\n```\n\nThis will loop over all secrets fetched from Vault, and set the `vault.yaml` key\nto a string like this:\n\n```yaml\nsecrets:\n  foo: \"foovalue\"\n  bar: \"barvalue\"\n  baz: \"bazvalue\n```\n\n#### Notes on templating\n\n- All secrets data is converted to string before being passed to the templating\n  engine, so using binary data will not work well, or at least be unpredictable.\n\n### PKI Engine\n\nYou can generate certificates using the PKI Engine like so:\n\n```yaml\napiVersion: ricoberger.de/v1alpha1\nkind: VaultSecret\nmetadata:\n  name: test-pki\nspec:\n  path: pki\n  secretEngine: pki\n  role: example-dot-com\n  engineOptions:\n    common_name: www.my-website.com\n    ttl: \"5d\"\n  type: Opaque\n```\n\nYou can pass any of the parameters supported by the PKI engine in\n`engineOptions`. A list is available here:\n[https://www.vaultproject.io/api-docs/secret/pki#parameters-15](https://www.vaultproject.io/api-docs/secret/pki#parameters-15)\n\nThis will generate the following secret:\n\n```yaml\napiVersion: v1\nkind: Secret\nmetadata:\n  name: test-pki\ndata:\n  certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tLi4u\n  expiration: MTY0OTc2OTIwMg==\n  issuing_ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tLi4u\n  private_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLS4uLg==\n  private_key_type: cnNh\n  serial_number: MDA6MDA6MDA6MDA6MDA6MDA6MDA6MDA6MDA6MDA6MDA6MDA6MDA6MDA6MDA6MDA6MDA6MDA6MDA6MDA6MDA=\ntype: Opaque\n```\n\nLike with the secret engine, you can template the resulting Kubernetes secret:\n\n```yaml\napiVersion: ricoberger.de/v1alpha1\nkind: VaultSecret\nmetadata:\n  name: test-pki\nspec:\n  path: pki\n  secretEngine: pki\n  role: example-dot-com\n  engineOptions:\n    common_name: www.my-website.com\n  templates:\n    tls.crt: \"{% .Secrets.certificate %}\"\n    tls.key: \"{% .Secrets.private_key %}\"\n    ca.crt: \"{% .Secrets.issuing_ca %}\"\n  type: Opaque\n```\n\nThe following fields are available:\n\n- `certificate`\n- `expiration`\n- `issuing_ca`\n- `private_key`\n- `private_key_type`\n- `serial_number`\n\n#### Certificate Renewal\n\nCertificate are renewed before expiration. You can set how long before\nexpiration you want to renew by setting the `VAULT_PKI_RENEW` environment\nvariable. The default is 1 hour.\n\n### Using specific Vault Role for secrets\n\nIt is possible to not set the `VAULT_KUBERNETES_ROLE` (`vault.kubernetesRole`\nvalue in the Helm chart) and instead specify the Vault Role at the CR. This\nallows you to to use different Vault Roles within one Vault Secrets Operator\ninstance.\n\nThe Vault Role is set via the `vaultRole` property in the VaultSecret CR:\n\n```yaml\napiVersion: ricoberger.de/v1alpha1\nkind: VaultSecret\nmetadata:\n  name: kvv1-example-vaultsecret\nspec:\n  vaultRole: my-custom-vault-role\n  path: kvv1/example-vaultsecret\n  type: Opaque\n```\n\n\u003e **Note:** This option is only available for the kubernetes auth method and all\n\u003e roles must be added to the auth method before they are used by the operator.\n\n### Using Vault Namespaces\n\n[Vault Namespaces](https://www.vaultproject.io/docs/enterprise/namespaces) is a\nset of features within Vault Enterprise that allows Vault environments to\nsupport Secure Multi-tenancy (or SMT) within a single Vault infrastructure.\n\nThe Vault Namespace, which should be used for the authentication of the operator\nagainst Vault can be specified via the `VAULT_NAMESPACE` environment variable.\nIn the Helm chart this value can be provided as follows:\n\n```yaml\nenvironmentVars:\n  - name: VAULT_NAMESPACE\n    value: \"my/root/ns\"\n```\n\nThe operator also supports nested Namespaces. When the `VAULT_NAMESPACE` is set,\nit is also possible to specify a namespace via the `vaultNamespace` field in the\nVaultSecret CR:\n\n```yaml\napiVersion: ricoberger.de/v1alpha1\nkind: VaultSecret\nmetadata:\n  name: kvv1-example-vaultsecret\nspec:\n  vaultNamespace: team1\n  path: kvv1/example-vaultsecret\n  type: Opaque\n```\n\nThe Vault Namespace, which is used to get the secret in the above example will\nbe `my/root/ns/team1`.\n\nThe operator can also be restricted to only reconcile secrets where the\n`spec.vaultNamespace` field is the same as the `VAULT_NAMESPACE` environment\nvariable. For this the `VAULT_RESTRICT_NAMESPACE` environment variable must be\nset to `true`. When this feature is enabled the operator can not be used with\nnested namespaces.\n\n### Propagating labels\n\nThe operator will propagate all labels found on the `VaultSecret` to the actual\nsecret. So if a given label is needed on the resulting secret it can be added\nlike in the following example:\n\n```yaml\napiVersion: ricoberger.de/v1alpha1\nkind: VaultSecret\nmetadata:\n  name: example-vaultsecret\n  labels:\n    my-custom-label: my-custom-label-value\nspec:\n  path: path/to/example-vaultsecret\n  type: Opaque\n```\n\nThis would result in the following secret:\n\n```yaml\napiVersion: v1\ndata: ...\nkind: Secret\nmetadata:\n  labels:\n    created-by: vault-secrets-operator\n    my-custom-label: my-custom-label-value\n  name: example-vaultsecret\ntype: Opaque\n```\n\n## Development\n\nAfter modifying the `*_types.go` file always run the following command to update\nthe generated code for that resource type:\n\n```sh\nmake generate\n```\n\nThe above Makefile target will invoke the\n[controller-gen](https://sigs.k8s.io/controller-tools) utility to update the\n`api/v1alpha1/zz_generated.deepcopy.go` file to ensure our API's Go type\ndefinitons implement the `runtime.Object` interface that all Kind types must\nimplement.\n\nOnce the API is defined with spec/status fields and CRD validation markers, the\nCRD manifests can be generated and updated with the following command:\n\n```sh\nmake manifests\n```\n\nThis Makefile target will invoke controller-gen to generate the CRD manifest at\n`charts/vault-secrets-operator/crds/ricoberger.de_vaultsecrets.yaml`.\n\nDeploy the CRD and run the operator locally with the default Kubernetes config\nfile present at `$HOME/.kube/config`:\n\n```sh\nexport VAULT_ADDRESS=\nexport VAULT_AUTH_METHOD=token\nexport VAULT_TOKEN=\nexport VAULT_TOKEN_LEASE_DURATION=86400\nexport VAULT_RECONCILIATION_TIME=180\n\nmake run\n```\n\n## Links\n\n- [Managing Secrets in Kubernetes](https://www.weave.works/blog/managing-secrets-in-kubernetes)\n- [Operator SDK](https://github.com/operator-framework/operator-sdk)\n- [Vault](https://www.vaultproject.io)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fricoberger%2Fvault-secrets-operator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fricoberger%2Fvault-secrets-operator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fricoberger%2Fvault-secrets-operator/lists"}