In most enterprise systems where software release cycles consist of separate environments like dev, stage, live, having multiple environments that can be dynamically configured is common. An application may have three different sets of database credentials for authentication. Each set of credentials would be respective to an instance for a particular environment. This approach essentially allows software developers to interact with a developer-friendly database when carrying out their day-to-day coding.
Kubernetes secrets is used to store very sensitive data in your Kubernetes cluster. Secrets are native Kubernetes resources saved in the cluster data store (i.e., etcd database) and can be made available to your containers at runtime. Managing these secrets is a challenging process so in this guide we will explore how to use External Secrets to simplify that.
Kubernetes External Secrets allows you to use external secret management systems like GCP Secrets manager, AWS Secrets Manager or HashiCorp Vault, to securely add secrets in Kubernetes.
An ExternalSecret
declares how to fetch the secret data, while the controller converts all ExternalSecrets
to Secrets
. The conversion is completely transparent to Pods
that can access Secrets
normally. By default Secrets
are not encrypted at rest and are open to attack, either via the etcd
server or via backups of etcd
data. To mitigate this risk, use an external secret management system with a KMS plugin to encrypt Secrets
stored in etcd
.
This is the workflow of how the External Secrets work:
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, GCP Secrets Manager) - Controller upserts
Secrets
Pods
can accessSecrets
normally
Checkout related content:
- How to create and manage Secrets in GCP Secret Manager using Terraform
- How to Create a Service Account for Terraform in GCP
- How to use Terraform to create a vpc network and a Cloud SQL in GCP
- How to use Terraform to create a vpc network and a GKE in GCP
Installing External Secrets
External secrets is available officially as a helm chart in this repo. To add the repo and install it as external-secrets
in our cluster, use this:
|
|
You can also install it with kubectl
if you don’t want to use helm in your cluster by generating the manifests then applying:
|
|
The generated kubernetes manifests will be in ./output_dir
and can be applied to deploy kubernetes-external-secrets
to the cluster.
Ensure you are logged in to GCP
External secrets supports fetching secrets from GCP Secret Manager. The external secrets will poll for changes of the secret according to the value set for POLLER_INTERVAL_MILLISECONDS
in env. Depending on the time interval this is set to you may incur additional charges as Google Secret Manager charges per a set number of API calls. A service account is required to grant the controller access to pull secrets.
To do this, first ensure you are logged in to gcp
|
|
If you have multiple project ensure you are in the right one
|
|
Then enable GCP secret manager:
|
|
Creating a Service account
A service account is required to grant the controller access to pull secrets. To add a service account, use this command:
|
|
Create service account keys:
|
|
Make sure to grant permissions to the created sa:
|
|
Keys will be generated as sm-key.json
and saved in the current directory.
Create a kubernetes secret with the service account credentials to be used to fetch the secrets:
|
|
Adding a secret to GCP Secret manager
Let us add some secret data to the secret manager backend using GCP SDK. You can do this in the Cloud Console as well, it will work just fine.
We are adding a database connection.
|
|
You should see an output similar to this:
|
|
If the secret needs to be updated, you can do so using this command:
|
|
You can also create the secret as json. A json can hold multiple key value pairs. This is how you could create a json secret:
|
|
You should get the same output as shown above. If for any reason you want to confirm that the secret has been set successfully, you can retrieve the latest version using this command:
|
|
Deploy Secret store
A Secret Store is a namespaced resource that determines how your external Secret will be accessed from an authentication perspective. It contains references to Secrets that have the credentials to access the external API. External Secrets also has a ClusterSecretStore which is a global or cluster-wide SecretStore that can be referenced from all namespaces to provide a central gateway to your secrets manager. In our case we will use a SecretStore.
Let us create a Secret store called google-secret-manager
that will use the earlier defined secret gcp-sm-sa-secret
.
|
|
We can confirm the secret store creation with this command:
|
|
Creating External Secrets
An ExternalSecret is a resource that declares the data you want to fetch from the external secrets manager. It will reference the SecretStore to know how to access sensitive data.
Let us create an external secret for our db secret. Here we are accessing the secret sm-citizix-db-secret
and creating a target citizix-db-secret
secret in kubernetes with a key db-url
:
|
|
We can confirm that the defined external secret is working as expected:
|
|
We can also check that it has created the respective kubernetes secret:
|
|
To confirm the content of the created secret, describe the secret:
|
|
Extracting json values
We can extract json key values as secret data. External secret provides the dataFrom attribute that does just that:
|
|
We can confirm that the defined external secret is working as expected:
|
|
We can also check that it has created the respective kubernetes secret:
|
|
To confirm the content of the created secret, describe the secret:
|
|
Conclusion
In this guide, we learnt what External Secrets are and how we can leverage them to populate our kubernetes secrets from GCP secret manager.