6.2 KiB
Managing secrets
-
Sometimes our code needs sensitive information:
-
passwords
-
API tokens
-
TLS keys
-
...
-
-
Secrets can be used for that purpose
-
Secrets and ConfigMaps are very similar
Similarities between ConfigMap and Secrets
-
ConfigMap and Secrets are key-value maps
(a Secret can contain zero, one, or many key-value pairs)
-
They can both be exposed with the downward API or volumes
-
They can both be created with YAML or with a CLI command
(
kubectl create configmap/kubectl create secret)
ConfigMap and Secrets are different resources
-
They can have different RBAC permissions
(e.g. the default
viewrole can read ConfigMaps but not Secrets) -
They indicate a different intent:
"You should use secrets for things which are actually secret like API keys, credentials, etc., and use config map for not-secret configuration data."
"In the future there will likely be some differentiators for secrets like rotation or support for backing the secret API w/ HSMs, etc."
(Source: the author of both features)
Secrets have an optional type
-
The type indicates which keys must exist in the secrets, for instance:
kubernetes.io/tlsrequirestls.crtandtls.keykubernetes.io/basic-authrequiresusernameandpasswordkubernetes.io/ssh-authrequiresssh-privatekeykubernetes.io/dockerconfigjsonrequires.dockerconfigjsonkubernetes.io/service-account-tokenrequirestoken,namespace,ca.crt(the whole list is in the documentation)
-
This is merely for our (human) convenience:
“Ah yes, this secret is a ...”
Accessing private repositories
-
Let's see how to access an image on private registry!
-
These images are protected by a username + password
(on some registries, it's token + password, but it's the same thing)
-
To access a private image, we need to:
-
create a secret
-
reference that secret in a Pod template
-
or reference that secret in a ServiceAccount used by a Pod
-
In practice
-
Let's try to access an image on a private registry!
- image = docker-registry.enix.io/jpetazzo/private:latest
- user = reader
- password = VmQvqdtXFwXfyy4Jb5DR
.exercise[
-
Create a Deployment using that image:
kubectl create deployment priv \ --image=docker-registry.enix.io/jpetazzo/private -
Check that the Pod won't start:
kubectl get pods --selector=app=priv
]
Creating a secret
- Let's create a secret with the information provided earlier
.exercise[
- Create the registry secret:
kubectl create secret docker-registry enix \ --docker-server=docker-registry.enix.io \ --docker-username=reader \ --docker-password=VmQvqdtXFwXfyy4Jb5DR
]
Why do we have to specify the registry address?
If we use multiple sets of credentials for different registries, it prevents leaking the credentials of one registry to another registry.
Using the secret
-
The first way to use a secret is to add it to
imagePullSecrets(in the
specsection of a Pod template)
.exercise[
- Patch the
privDeployment that we created earlier:kubectl patch deploy priv --patch=' spec: template: spec: imagePullSecrets: - name: enix '
]
Checking the results
.exercise[
- Confirm that our Pod can now start correctly:
kubectl get pods --selector=app=priv
]
Another way to use the secret
-
We can add the secret to the ServiceAccount
-
This is convenient to automatically use credentials for all pods
(as long as they're using a specific ServiceAccount, of course)
.exercise[
- Add the secret to the ServiceAccount:
kubectl patch serviceaccount default --patch=' imagePullSecrets: - name: enix '
]
Secrets are displayed with base64 encoding
-
When shown with e.g.
kubectl get secrets -o yaml, secrets are base64-encoded -
Likewise, when defining it with YAML,
datavalues are base64-encoded -
Example:
kind: Secret apiVersion: v1 metadata: name: pin-codes data: onetwothreefour: MTIzNA== zerozerozerozero: MDAwMA== -
Keep in mind that this is just encoding, not encryption
-
It is very easy to automatically extract and decode secrets
class: extra-details
Using stringData
-
When creating a Secret, it is possible to bypass base64
-
Just use
stringDatainstead ofdata:kind: Secret apiVersion: v1 metadata: name: pin-codes stringData: onetwothreefour: 1234 zerozerozerozero: 0000 -
It will show up as base64 if you
kubectl get -o yaml -
No
typewas specified, so it defaults toOpaque
class: extra-details
Encryption at rest
-
It is possible to encrypted secrets at rest
-
This means that secrets will be safe if someone ...
-
steals our etcd servers
-
steals our backups
-
snoops the e.g. iSCSI link between our etcd servers and SAN
-
-
However, starting the API server will now require human intervention
(to provide the decryption keys)
-
This is only for extremely regulated environments (military, nation states...)
class: extra-details
Immutable ConfigMaps and Secrets
-
Since Kubernetes 1.19, it is possible to mark a ConfigMap or Secret as immutable
kubectl patch configmap xyz --patch='{"immutable": true}' -
This brings performance improvements when using lots of ConfigMaps and Secrets
(lots = tens of thousands)
-
Once a ConfigMap or Secret has been marked as immutable:
- its content cannot be changed anymore
- the
immutablefield can't be changed back either - the only way to change it is to delete and re-create it
- Pods using it will have to be re-created as well
???
:EN:- Handling passwords and tokens safely
:FR:- Manipulation de mots de passe, clés API etc.