- Notifications
You must be signed in to change notification settings - Fork404
Integrate external secret management systems with Kubernetes
License
external-secrets/kubernetes-external-secrets
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
This project has beendeprecated.Please take a look at ESO (External Secrets Operator) insteadhttps://github.com/external-secrets/external-secrets
This project was moved from theGoDaddy to theexternal-secrets GitHub organization in an effort to consolidate different projects with the same objective. More informationhere.
Kubernetes External Secrets allows you to use external secretmanagement systems, likeAWS Secrets Manager orHashiCorp Vault, to securely add secrets inKubernetes. Read more about the design and motivation for KubernetesExternal Secrets on theGoDaddy EngineeringBlog.
The community and maintainers of this project and related Kubernetessecret management projects use the#external-secrets
channel on the Kubernetes slack for discussion and brainstorming.
The project extends the Kubernetes API by adding anExternalSecrets
object usingCustom Resource Definition and a controller to implement the behavior of the object itself.
AnExternalSecret
declares how to fetch the secret data, while the controller converts allExternalSecrets
toSecrets
.The conversion is completely transparent toPods
that can accessSecrets
normally.
By defaultSecrets
are not encrypted at rest and are open to attack, either via theetcd
server or via backups ofetcd
data.To mitigate this risk, use anexternal secret management system with a KMS pluginto encryptSecrets
stored inetcd
.
ExternalSecrets
are added in the cluster (e.g.,kubectl apply -f external-secret-example.yml
)- Controller fetches
ExternalSecrets
using the Kubernetes API - Controller uses
ExternalSecrets
to fetch secret data from external providers (e.g, AWS Secrets Manager) - Controller upserts
Secrets
Pods
can accessSecrets
normally
The officialhelm chart can be used to create thekubernetes-external-secrets
resources andDeployment
on aKubernetes cluster using theHelm package manager.
$ helm repo add external-secrets https://external-secrets.github.io/kubernetes-external-secrets/$ helm install [RELEASE_NAME] external-secrets/kubernetes-external-secrets
For more details about configuration see thehelm chart docs
If you don't want to install helm on your cluster and just want to usekubectl
to installkubernetes-external-secrets
, you could get thehelm
client cli first and then use the following sample command to generate kubernetes manifests:
$ helm template --include-crds --output-dir ./output_dir external-secrets/kubernetes-external-secrets
The generated kubernetes manifests will be in./output_dir
and can be applied to deploykubernetes-external-secrets
to the cluster.
Forkubernetes-external-secrets
to be able to retrieve your secrets it will need access to your secret backend.
Access to AWS secrets backends (SSM & secrets manager) can be granted in various ways:
Granting your nodes explicit access to your secrets using thenode instance role (easy for experimentation, not recommended)
Directly provide AWS access credentials to the
kubernetes-external-secrets
pod by environmental variables.
Optionally configure custom endpoints using environment variables
- AWS_SM_ENDPOINT - Useful to set endpoints for FIPS compliance.
- AWS_STS_ENDPOINT - Useful to set endpoints for FIPS compliance or regional latency.
- AWS_SSM_ENDPOINT - Useful to set endpoints for FIPS compliance or custom VPC endpoint.
SetAWS_ACCESS_KEY_ID
andAWS_SECRET_ACCESS_KEY
env vars in thekubernetes-external-secrets
session/pod.You can useenvVarsFromSecret
in the helm chart to create these env vars from existing k8s secrets.
Additionally, you can specify aroleArn
which will be assumed before retrieving the secret.You can limit the range of roles which can be assumed by this particularnamespace by using annotations on the namespace resource. The annotation key is configurable (seeabove). The annotation value is evaluated as a regular expression and tries to match theroleArn
.
kind:Namespacemetadata:name:iam-exampleannotations:# annotation key is configurableiam.amazonaws.com/permitted:"arn:aws:iam::123456789012:role/.*"
Add your secret data to your backend. For example, AWS Secrets Manager:
aws secretsmanager create-secret --name hello-service/password --secret-string "1234"
AWS Parameter Store:
aws ssm put-parameter --name "/hello-service/password" --type "String" --value "1234"
and then create ahello-service-external-secret.yml
file:
apiVersion:"kubernetes-client.io/v1"kind:ExternalSecretmetadata:name:hello-servicespec:backendType:secretsManager# optional: specify role to assume when retrieving the dataroleArn:arn:aws:iam::123456789012:role/test-roledata: -key:hello-service/passwordname:password# optional: specify a template with any additional markup you would like added to the downstream Secret resource.# This template will be deep merged without mutating any existing fields. For example: you cannot override metadata.name.template:metadata:annotations:cat:cheeselabels:dog:farfel
or
apiVersion:"kubernetes-client.io/v1"kind:ExternalSecretmetadata:name:hello-servicespec:backendType:systemManagerdata: -key:/hello-service/passwordname:password
The following IAM policy allows a user or role to access parameters matchingprod-*
.
{"Version":"2012-10-17","Statement": [ {"Effect":"Allow","Action":"ssm:GetParameter","Resource":"arn:aws:ssm:us-west-2:123456789012:parameter/prod-*" } ]}
The IAM policy for Secrets Manager is similar (see docs):
{"Version":"2012-10-17","Statement": [ {"Effect":"Allow","Action": ["secretsmanager:GetResourcePolicy","secretsmanager:GetSecretValue","secretsmanager:DescribeSecret","secretsmanager:ListSecretVersionIds" ],"Resource": ["arn:aws:secretsmanager:us-west-2:111122223333:secret:aes128-1a2b3c","arn:aws:secretsmanager:us-west-2:111122223333:secret:aes192-4D5e6F","arn:aws:secretsmanager:us-west-2:111122223333:secret:aes256-7g8H9i" ] } ]}
Save the file and run:
kubectl apply -f hello-service-external-secret.yml
Wait a few minutes and verify that the associatedSecret
has been created:
kubectl get secret hello-service -o=yaml
TheSecret
created by the controller should look like:
apiVersion:v1kind:Secretmetadata:name:hello-serviceannotations:cat:cheeselabels:dog:farfeltype:Opaquedata:password:MTIzNA==
You can overrideExternalSecret
type usingtemplate
, for example:
apiVersion:kubernetes-client.io/v1kind:ExternalSecretmetadata:name:hello-dockerspec:backendType:systemManagertemplate:type:kubernetes.io/dockerconfigjsondata: -key:/hello-service/hello-dockername:.dockerconfigjson
Kubernetes External Secrets supports templating inExternalSecret
usinglodash.template.
Template is applied to allExternalSecret.template
sections of the manifest.Data retrieved from secure backend is available via thedata
variable.Additonal objectyaml
of instance ofjs-yaml is available inlodash
templates.It can be leveraged for easier YAML content manipulation.
Templating can be used for:
- Generating K8S
Secret
keys:- upserting plain text via
ExternalSecret.template.stringData
- upserting base64 encoded content
ExternalSecret.template.data
- upserting plain text via
- For creating dynamic labels, annotations and other fields available in K8S
Secret
object.
To demonstrate templating functionality let's assume the secure backend, e.g. Hashicorp Vault, contains the following data
kv/extsec/secret1 | kv/extsec/secret2 |
---|---|
{"intKey":11,"objKey": {"strKey":"hello world" }} | {"arrKey": [1,2,3]} |
Then, one could create the followingExternalSecret
apiVersion:kubernetes-client.io/v1kind:ExternalSecretmetadata:name:tmpl-ext-secspec:backendType:vaultdata: -key:kv/data/extsec/secret1name:s1 -key:kv/data/extsec/secret2name:s2kvVersion:2template:data:file.txt:| <%= Buffer.from(JSON.stringify(JSON.parse(data.s1).objKey)).toString("base64")%>metadata:labels:label1:<%= JSON.parse(data.s1).intKey %>label2:<%= JSON.parse(data.s1).objKey.strKey.replace(" ", "-") %>stringData:file.yaml:| <%= yaml.dump(JSON.parse(data.s1))%> <% let s2 = JSON.parse(data.s2)%><% s2.arrKey.forEach((e, i) => {%>arr_<%= i%>: <%= e%> <% })%>`vaultMountPoint:kubernetesvaultRole:demo
After applying thisExternalSecret
to the K8S cluster, the operator will generate followingSecret
apiVersion:v1data:file.txt:eyJzdHJLZXkiOiJoZWxsbyB3b3JsZCJ9file.yaml:aW50S2V5OiAxMQpvYmpLZXk6CiAgc3RyS2V5OiBoZWxsbyB3b3JsZAoKYXJyXzA6IDEKYXJyXzE6IDIKYXJyXzI6IDMKYAo=s1:eyJpbnRLZXkiOjExLCJvYmpLZXkiOnsic3RyS2V5IjoiaGVsbG8gd29ybGQifX0=s2:eyJhcnJLZXkiOlsxLDIsM119kind:Secretmetadata:name:tmpl-ext-seclabels:label1:"11"label2:hello-worldtype:Opaque
ResultingSecret
could be inspected to see that result is generated bylodash
templating engine
$ kubectl get secret/tmpl-ext-sec -ogo-template='{{ index .data "s1" | base64decode }}'{"intKey":11,"objKey":{"strKey":"hello world"}}$ kubectl get secret/tmpl-ext-sec -ogo-template='{{ index .data "s2" | base64decode }}'{"arrKey":[1,2,3]}$ kubectl get secret/tmpl-ext-sec -ogo-template='{{ index .data "file.txt" | base64decode }}'{"strKey":"hello world"}$ kubectl get secret/tmpl-ext-sec -ogo-template='{{ index .data "file.yaml" | base64decode }}'intKey: 11objKey: strKey: hello worldarr_0: 1arr_1: 2arr_2: 3$ kubectl get secret/tmpl-ext-sec -ogo-template='{{ .metadata.labels }}'map[label1:11 label2:hello-world]
Enforcing naming conventions for backend keys could be done by using namespace annotations.By default anExternalSecret
may access arbitrary keys from the backend e.g.
data: -key:/dev/cluster1/core-namespace/hello-service/passwordname:password
An enforced naming convention helps to keep the structure tidy and limits the access accordingto your naming schema.
Configure the schema as a regular expression in the namespace using an annotation.This allowsExternalSecrets
incore-namespace
only access to secrets that start with/dev/cluster1/core-namespace/
:
kind:Namespacemetadata:name:core-namespaceannotations:# annotation key is configurableexternalsecrets.kubernetes-client.io/permitted-key-name:"/dev/cluster1/core-namespace/.*"
ExternalSecret config allows scoping the access of kubernetes-external-secrets controller.This allows deployment of multiple kubernetes-external-secrets instances in the same clusterand each instance can access a set of predefined namespaces.
To enable this option, set the env var in the controller side to a list of namespaces:
env:WATCHED_NAMESPACES:"default,qa,dev"
ExternalSecret manifest allows scoping the access of kubernetes-external-secrets controller.This allows deployment of multiple kubernetes-external-secrets instances at the same clusterand each instance can access a set of ExternalSecrets.
To enable this option, set the env var in the controller side:
env:INSTANCE_ID:"dev-team-instance"
And in ExternalSecret side:
apiVersion:kubernetes-client.io/v1kind:ExternalSecretmetadata:name:foospec:controllerId:'dev-team-instance'[...]
Please note
Scoping access by ExternalSecret config provides only a logical separation and it doesn't cover the security aspects.i.e it assumes that the security side is managed by another component like Kubernetes Network policiesor Open Policy Agent.
A few properties have changed name overtime, we still maintain backwards compatbility with these but they will eventually be removed, and they are not validated using the CRD validation.
Old | New |
---|---|
secretDescriptor | spec |
spec.type | spec.template.type |
spec.properties | spec.data |
backendType: secretManager | backendType: secretsManager |
kubernetes-external-secrets supports AWS Secrets Manager, AWS System Manager, Akeyless, Hashicorp Vault, Azure Key Vault, Google Secret Manager and Alibaba Cloud KMS Secret Manager.
kubernetes-external-secrets supports both JSON objects ("Secretkey/value" in the AWS console) or strings ("Plaintext" in the AWSconsole). Using JSON objects is useful when you need to atomicallyupdate multiple values. For example, when rotating a clientcertificate and private key.
When writing an ExternalSecret for a JSON object you must specify theproperties to use. For example, if we add our hello-servicecredentials as a single JSON object:
aws secretsmanager create-secret --region us-west-2 --name hello-service/credentials --secret-string '{"username":"admin","password":"1234"}'
We can declare which properties we want fromhello-service/credentials
:
apiVersion:kubernetes-client.io/v1kind:ExternalSecretmetadata:name:hello-servicespec:backendType:secretsManager# optional: specify role to assume when retrieving the dataroleArn:arn:aws:iam::123456789012:role/test-role# optional: specify regionregion:us-east-1data: -key:hello-service/credentialsname:passwordproperty:password -key:hello-service/credentialsname:usernameproperty:username -key:hello-service/credentialsname:password_previous# Version Stage in Secrets ManagerversionStage:AWSPREVIOUSproperty:password -key:hello-service/credentialsname:password_versioned# Version ID in Secrets ManagerversionId:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxproperty:password
alternatively you can usedataFrom
and get all the values fromhello-service/credentials
:
apiVersion:kubernetes-client.io/v1kind:ExternalSecretmetadata:name:hello-servicespec:backendType:secretsManager# optional: specify role to assume when retrieving the dataroleArn:arn:aws:iam::123456789012:role/test-role# optional: specify regionregion:us-east-1dataFrom: -hello-service/credentials
dataFrom
by default retrieves the latest (AWSCURRENT
) version of the backend secret, if you want to get values in bulk of a specific version, you can usedataFromWithOptions
:
apiVersion:kubernetes-client.io/v1kind:ExternalSecretmetadata:name:hello-servicespec:backendType:secretsManager# optional: specify role to assume when retrieving the dataroleArn:arn:aws:iam::123456789012:role/test-role# optional: specify regionregion:us-east-1dataFromWithOptions: -key:hello-service/credentialsversionStage:AWSPREVIOUS -key:hello-service/credentialsversionId:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
data
,dataFrom
anddataFromWithOptions
can of course be combined, any naming conflicts will use the last defined.
In the below exampledata
takes precedence overdataFromWithOptions
anddataFrom
.
apiVersion:kubernetes-client.io/v1kind:ExternalSecretmetadata:name:hello-servicespec:backendType:secretsManager# optional: specify role to assume when retrieving the dataroleArn:arn:aws:iam::123456789012:role/test-role# optional: specify regionregion:us-east-1dataFrom: -hello-service/credentialsdataFromWithOptions: -key:hello-service/credentialsversionId:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxdata: -key:hello-service/migration-credentialsname:passwordproperty:password
You can scrape values from SSM Parameter Store individually or by providing a path to fetch all keys inside.
When fetching all keys by path, you can also recursively scrape all the sub paths (child paths) if you need to. The default is not to scrape child paths.
apiVersion:kubernetes-client.io/v1kind:ExternalSecretmetadata:name:hello-servicespec:backendType:systemManager# optional: specify role to assume when retrieving the dataroleArn:arn:aws:iam::123456789012:role/test-role# optional: specify regionregion:us-east-1data: -key:/foo/namename:fooName -path:/extra-people/recursive:false
data
anddataFrom
retrieve the latest version of the parameter by default. If you want to get values for a specific version, you can append the version number to the key:
apiVersion:kubernetes-client.io/v1kind:ExternalSecretmetadata:name:hello-servicespec:backendType:systemManager# optional: specify role to assume when retrieving the dataroleArn:arn:aws:iam::123456789012:role/test-role# optional: specify regionregion:us-east-1dataFrom: -hello-service/credentials:3data: -key:/foo/namename:fooName:5
kubernetes-external-secrets supports fetching secrets fromAkeyless Vault, .You will need to set the following environment variables:
env:#akeyless rest-v2 endpointAKEYLESS_API_ENDPOINT:https://api.akeyless.ioAKEYLESS_ACCESS_ID:#AKEYLESS_ACCESS_TYPE can be one of the following: aws_iam/azure_ad/gcp/access_keyAKEYLESS_ACCESS_TYPE:#AKEYLESS_ACCESS_TYPE_PARAM can be one of the following: gcp-audience/azure-obj-id/access-key#AKEYLESS_ACCESS_TYPE_PARAM:
Once you have kubernetes-external-secrets installed, you can create an external secret with YAML like the following:
apiVersion:'kubernetes-client.io/v1'kind:ExternalSecretmetadata:name:hello-secretspec:backendType:akeylessdata: -key:path/secret-namename:password
kubernetes-external-secrets supports fetching secrets fromHashicorp Vault, using theKubernetes authentication method.
env:VAULT_ADDR:https://vault.domain.tldDEFAULT_VAULT_MOUNT_POINT:"k8s-auth"# optional, default value to be used if not specified in the ExternalSecretDEFAULT_VAULT_ROLE:"k8s-auth-role"# optional, default value to be used if not specified in the ExternalSecret
You will need to set theVAULT_ADDR
environment variables so that kubernetes-external-secrets knows which endpoint to connect to, then createExternalSecret
definitions as follows:
apiVersion:"kubernetes-client.io/v1"kind:ExternalSecretmetadata:name:hello-vault-servicespec:backendType:vault# Your authentication mount point, e.g. "kubernetes"# Overrides cluster DEFAULT_VAULT_MOUNT_POINTvaultMountPoint:my-kubernetes-vault-mount-point# The vault role that will be used to fetch the secrets# This role will need to be bound to kubernetes-external-secret's ServiceAccount; see Vault's documentation:# https://www.vaultproject.io/docs/auth/kubernetes.html# Overrides cluster DEFAULT_VAULT_ROLEvaultRole:my-vault-roledata: -name:password# The full path of the secret to read, as in `vault read secret/data/hello-service/credentials`key:secret/data/hello-service/credentialsproperty:password# Vault values are matched individually. If you have several keys in your Vault secret, you will need to add them all separately -name:api-keykey:secret/data/hello-service/credentialsproperty:api-key
If you use Vault Namespaces (a Vault Enterprise feature) you can set the namespace to interact with via theVAULT_NAMESPACE
environment variable.
The Vault token obtained by Kubernetes authentication will be renewed as needed. By default the token will be renewed three poller intervals (POLLER_INTERVAL_MILLISECONDS) before the token TTL expires. The default should be acceptable in most cases but the token renew threshold can also be customized by setting theVAULT_TOKEN_RENEW_THRESHOLD
environment variable. The token renew threshold value is specified in seconds and tokens with remaining TTL less than this number of seconds will be renewed. In order to minimize token renewal load on the Vault server it is suggested that Kubernetes auth tokens issued by Vault have a TTL of at least ten times the poller interval so that they are renewed less frequently. A longer token TTL results in a lower token renewal load on Vault.
If Vault uses a certificate issued by a self-signed CA you will need to provide that certificate:
# Create secret with CAkubectl create secret generic vault-ca --from-file=./ca.pem
# values.yamlenv:VAULT_ADDR:https://vault.domain.tldNODE_EXTRA_CA_CERTS:"/usr/local/share/ca-certificates/ca.pem"filesFromSecret:certificate-authority:secret:vault-camountPath:/usr/local/share/ca-certificates
kubernetes-external-secrets supports fetching secrets fromAzure Key vault
You will need to set these env vars in the deployment of kubernetes-external-secrets:
AZURE_TENANT_ID
AZURE_CLIENT_ID
AZURE_CLIENT_SECRET
The SP configured will require get and list access policies on theAZURE_KEYVAULT_NAME
.
apiVersion:kubernetes-client.io/v1kind:ExternalSecretmetadata:name:hello-keyvault-servicespec:backendType:azureKeyVaultkeyVaultName:hello-worlddata: -key:hello-service/credentialsname:password
kubernetes-external-secrets supports fetching secrets fromAlibaba Cloud KMS Secret Manager
create secret by using thealiyun-cli command below:
# you need to configure aliyun-cli with a valid RAM user and proper permissionaliyun kms CreateSecret --SecretName my_secret --SecretData P@ssw0rd --VersionId 001
You will need to set these env vars in the deployment of kubernetes-external-secrets:
ALICLOUD_ACCESS_KEY_ID
ALICLOUD_ACCESS_KEY_SECRET
ALICLOUD_ENDPOINT
apiVersion:kubernetes-client.io/v1kind:ExternalSecretmetadata:name:hello-servicespec:backendType:alicloudSecretsManager# optional: specify role to assume using provided access key ID and access key secret when retrieving the dataroleArn:acs:ram::{UID}:role/demodata: -key:hello-credentials1name:password -key:hello-credentials2name:username# Version Stage in Alibaba Cloud KMS Secrets Manager. Optional, default value is ACSCurrentversionStage:ACSCurrent
kubernetes-external-secrets supports fetching secrets fromGCP Secret Manager
The external secret will poll for changes to the secret according to the value set forPOLLER_INTERVAL_MILLISECONDS
in env. Depending on the time interval this is set to you may incur additional charges as Google Secret Managercharges per a set number of API calls.
A service account is required to grant the controller access to pull secrets.
Add your secret data to your backend using GCP SDK :
echo -n '{"value": "my-secret-value"}' | gcloud secrets create my-gsm-secret-name --replication-policy="automatic" --data-file=-
If the secret needs to be updated :
echo -n '{"value": "my-secret-value-with-update"}' | gcloud secrets versions add my-gsm-secret-name --data-file=-
Instructions are here:Enable Workload Identity. To enable workload identity on an existing cluster (which is not covered in that document), first enable it on the cluster like so:
gcloud container clusters update $CLUSTER_NAME --workload-pool=$PROJECT_NAME.svc.id.goog
Next enable workload metadata config on the node pool in which the pod will run:
gcloud beta container node-pools update $POOL --cluster $CLUSTER_NAME --workload-metadata-from-node=GKE_METADATA_SERVER
If enabling it only for a particular pool, make sure to add any relevant tolerations or affinities:
tolerations: - key: "name" operator: "Equal" effect: "NoExecute" value: "node-pool-taint" - key: "name" operator: "Equal" effect: "NoSchedule" value: "node-pool-taint"affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: cloud.google.com/gke-nodepool operator: In values: - node-pool
You can add an annotation which is needed for workload identity by passing it in via Helm:
serviceAccount: annotations: iam.gke.io/gcp-service-account: my-secrets-sa@$PROJECT.iam.gserviceaccount.com
Create the policy binding:
gcloud iam service-accounts add-iam-policy-binding --role roles/iam.workloadIdentityUser --member "serviceAccount:$CLUSTER_PROJECT.svc.id.goog[$SECRETS_NAMESPACE/kubernetes-external-secrets]" my-secrets-sa@$PROJECT.iam.gserviceaccount.com
Grant GCP service account access to secrets:
gcloud projects add-iam-policy-binding $PROJECT_ID --member=serviceAccount:my-secrets-sa@$PROJECT.iam.gserviceaccount.com --role=roles/secretmanager.secretAccessor
Alternatively you can create and mount a kubernetes secret containing google service account credentials and set theGOOGLE_APPLICATION_CREDENTIALS
env variable.
Create a Kubernetes secret called gcp-creds with a JSON keyfile from a service account with necessary credentials to access the secrets:
apiVersion: v1kind: Secretmetadata: name: mysecrettype: OpaquestringData: gcp-creds.json: |- $KEYFILE_CONTENT
UncommentGOOGLE_APPLICATION_CREDENTIALS
in the values file as well as the following section:
env: AWS_REGION: us-west-2 POLLER_INTERVAL_MILLISECONDS: 10000 # Caution, setting this frequency may incur additional charges on some platforms LOG_LEVEL: info METRICS_PORT: 3001 VAULT_ADDR: http://127.0.0.1:8200 GOOGLE_APPLICATION_CREDENTIALS: /app/gcp-creds/gcp-creds.json filesFromSecret: gcp-creds: secret: gcp-creds mountPath: /app/gcp-creds
This will mount the secret at/app/gcp-creds/gcp-creds.json
and make it available via theGOOGLE_APPLICATION_CREDENTIALS
environment variable.
Once you have kubernetes-external-secrets installed, you can create an external secret with YAML like the following:
apiVersion:kubernetes-client.io/v1kind:ExternalSecretmetadata:name:gcp-secrets-manager-example# name of the k8s external secret and the k8s secretspec:backendType:gcpSecretsManagerprojectId:my-gsm-secret-projectdata: -key:my-gsm-secret-name# name of the GCP secretname:my-kubernetes-secret-name# key name in the k8s secretversion:latest# version of the GCP secretproperty:value# name of the field in the GCP secret
The field "key" is the name of the secret in Google Secret Manager. The field "name" is the name of the Kubernetes secret this external secret will generate. The metadata "name" field is the name of the external secret in Kubernetes.
To retrieve external secrets, you can use the following command:
kubectl get externalsecrets -n $NAMESPACE
To retrieve the secrets themselves, you can use the regular:
kubectl get secrets -n $NAMESPACE
To retrieve an individual secret's content, use the following where "mysecret" is the key to the secret content under the "data" field:
kubectl get secret my-secret -o 'go-template={{index .data "mysecret"}}' | base64 -D
The secrets will persist even if the helm installation is removed, although they will no longer sync to Google Secret Manager.
kubernetes-external-secrets supports fetching secrets fromIBM Cloud Secrets Manager.
Create username_password secret by using theUI, CLI or API.The CLI option is illustrated below:
# You need to configure ibm cloud cli with a valid endpoint.# If you're using plug-in version 0.0.8 or later, export the following variable.export SECRETS_MANAGER_URL=https://{instanceid}.{region}.secrets-manager.appdomain.cloud# If you're using plug-in version 0.0.6 or earlier, export the following variable.export IBM_CLOUD_SECRETS_MANAGER_API_URL=https://{instance_ID}.{region}.secrets-manager.appdomain.cloudibmcloud secrets-manager secret-create --secret-type username_password \ --metadata'{"collection_type": "application/vnd.ibm.secrets-manager.secret+json", "collection_total": 1}' \ --resources'[{"name": "example-username-password-secret","description": "Extended description for my secret.","username": "user123","password": "cloudy-rainy-coffee-book"}]'
You will need to set these env vars in the deployment of kubernetes-external-secrets:
IBM_CLOUD_SECRETS_MANAGER_API_APIKEY
IBM_CLOUD_SECRETS_MANAGER_API_ENDPOINT
IBM_CLOUD_SECRETS_MANAGER_API_AUTH_TYPE
apiVersion:kubernetes-client.io/v1kind:ExternalSecretmetadata:name:ibmcloud-secrets-manager-examplespec:backendType:ibmcloudSecretsManagerdata:# The guid id of the secret -key:<guid>name:usernameproperty:usernamesecretType:username_password
Alternately, you can usekeyByName
on the spec to interpret keys as secret names, instead of IDs.Using names is slightly less efficient than using IDs, but it makes your ExternalSecrets more robust, as they are not tied to a particular instance of a secret in a particular instance of Secrets Manager:
apiVersion:kubernetes-client.io/v1kind:ExternalSecretmetadata:name:ibmcloud-secrets-manager-examplespec:backendType:ibmcloudSecretsManagerkeyByName:truedata:# The name of the secret -key:my-credsname:usernameproperty:usernamesecretType:username_password
Most backends do not treat binary secrets any differently than text secrets. Since you typically store a binary secret as a base64-encoded string in the backend, you need to explicitly let the ExternalSecret know that the secret is binary, otherwise it will be encoded in base64 again.You can do that with theisBinary
field on the key. This is necessary for certificates and other secret binary files.
apiVersion:kubernetes-client.io/v1kind:ExternalSecretmetadata:name:hello-servicespec:backendType:anySupportedBackend# ...data: -key:hello-service/archives/secrets_zipname:secrets.zipisBinary:true# Default: false# also works with `property` -key:hello-service/certificatesname:cert.p12property:cert.p12isBinary:true
AWS Secrets Manager is a notable exception to this. If you create/update a secret usingSecretBinary parameter of the API, then AWS API will return the secret data asSecretBinary
in the response and ExternalSecret will handle it accordingly. In that case, you do not need to use theisBinary
field.
Note thatSecretBinary
parameter is not available when using the AWS Secrets Manager console. For any binary secrets (represented by a base64-encoded strings) created/updated via the AWS console, or stored in key-value pairs instead of text strings, you can just use theisBinary
field explicitly as above.
kubernetes-external-secrets exposes the following metrics over a prometheus endpoint:
Metric | Type | Description | Example |
---|---|---|---|
kubernetes_external_secrets_sync_calls_count | Counter | Number of sync operations by backend, secret name and status | kubernetes_external_secrets_sync_calls_count{name="foo",namespace="example",backend="foo",status="success"} 1 |
kubernetes_external_secrets_last_sync_call_state | Gauge | State of last sync call of external secret, where -1 means the last sync_call was an error and 1 means the last sync_call was a success | kubernetes_external_secrets_last_sync_call_state{name="foo",namespace="example",backend="foo"} 1 |
Minikube is a tool that makes it easy to run a Kubernetes cluster locally.
Start minikube and the daemon. This creates theCustomerResourceDefinition
, and starts to processExternalSecrets
:
minikube startnpm run nodemon
Localstack mocks AWS services locally so you can test without connecting to AWS.
Run localstack in a separate terminal window
npm run localstack
Start minikube as above
minikube start
Run the daemon with localstack
npm runlocal
Add secrets using the AWS cli (example)
AWS_ACCESS_KEY_ID=foobar AWS_SECRET_ACCESS_KEY=foobar aws --region=us-west-2 --endpoint-url=http://localhost:4584 secretsmanager create-secret --name hello-service/password --secret-string"1234"
khcheck-external-secrets is akuberhealthy check that monitors if the external secrets operator is functional.
About
Integrate external secret management systems with Kubernetes
Topics
Resources
License
Code of conduct
Security policy
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.