Kubernetes Secrets vs ConfigMaps - kubernetes

Have been using Kubernetes secrets up to date.
Now we have ConfigMaps as well.
What is the preferred way forward - secrets or config maps?
P.S. After a few iterations we have stabilised at the following rule:
configMaps are per solution domain (can be shared across microservices within the domain, but ultimately are single purpose config entries)
secrets are shared across solution domains, usually represent third party systems or databases

I'm the author of both of these features. The idea is that you should:
Use Secrets for things which are actually secret like API keys, credentials, etc
Use ConfigMaps 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. In general, we like intent-based APIs, and the intent is definitely different for secret data vs. plain old configs.

One notable difference in the implementation is that kubectl apply -f:
ConfigMaps are "unchanged" if the data hasn't changed.
Secrets are always "configured" - even if the file hasn't changed

Both, ConfigMaps and Secrets store data as a key value pair. The major difference is, Secrets store data in base64 format meanwhile ConfigMaps store data in a plain text.
If you have some critical data like, keys, passwords, service accounts credentials, db connection string, etc then you should always go for Secrets rather than Configs.
And if you want to do some application configuration using environment variables which you don't want to keep secret/hidden like, app theme, base platform url, etc then you can go for ConfigMaps

Related

How to merge a K8s Configmap to a Secret (or two secrets together)

I am using Helm w/ Kubernetes and am trying to add data that I have in an existing Configmap to an existing secret. The reason for this, is that there is a property on a CRD that I need to set which only takes in a single secret key ref. The existing secret is created by Vault, and the existing Configmap is configured in the Helm chart in plain text. For reasons that I won't get into, we cannot include the content of the configmap into the Vault secret entry, so I MUST be able to merge these two into a secret.
I've tried searching for this, but most answers I see involve creating an initContainer and setting up a volume, but unfortunately I don't think this will work for my situation. I just need a single secret that I can reference in a CRD and problem solved. Is this possible using Kubernetes/Helm?
My fallback plan is to create my own CRD and associated controller to merge the configmap data and the secret's data and basically create a new secret, but it seems like overkill.
As far as I am aware of there is not way to do this in kubernetes.
The only solution that I can see would be to implement some tool yourself. With something like kopf you could implement a simple operator that listen for the creation/update of a specific secret and configmap, get their data and merge it into a new secret.
Using an operator allows you to handle all the cases that might occur during the life of your resources, such as when your new secret is deleted or updated, etc.

Encrypting secrets in config maps

Is there any way to encrypt secrets in configmaps for kubernetes deployments? I'm using flux so I need all of my deployment files to be stored in git, I encrypt all the secrets' manifests using kubeseal but I haven't found a good solution for protecting secrets in configmaps (usually config files contain stuff like username/password).
There is no straightforward way to reference secrets in k8s.
You can use the workaround offered here to load a secret as an environment variable and reference it in your configmap, but keep in mind loading secrets as environment variable is not recommended.
Caution: ConfigMap does not provide secrecy or encryption. If the data you want to store are confidential, use a Secret rather than a ConfigMap, or use additional (third party) tools to keep your data private.
From: https://kubernetes.io/docs/concepts/configuration/configmap/

What is the point of Kubernetes secrets if I can decode them?

I can easily get the secrets stored in Kubernetes.
$ kubectl get secret my-app-secrets -o yaml
Select secret value from output that I want to decode.
Example ZXhwb3NlZC1wYXNzd29yZAo=
$ echo ZXhwb3NlZC1wYXNzd29yZAo= | base64 --decode
> exposed-password
I'm not sure I understand the effectiveness of the secrets resources in Kubernetes ecosystem since it's easy to obtain this.
base64 is encoding, not encryption, it allows you to simply encode information in a convenient way.
The data that you encode may contain many unrecognized characters, line feeds, etc., so it is convenient to encode them.
In kubernetes, you can enable encryption using this instruction.
But kubernetes should not be the only source of truth, rather kubernetes loads these secrets from an external vault that you need to select, such as hashicorp's vault, as indicated in the comments.
In addition to hashicorp vault, there are various ways to store secrets in git:
Helm secrets
Kamus
Sealed secrets
git-crypt
You may also be interested in the kubesec project, which can be used to analyze kubernetes resources for security risks.
The point is that in Kubernetes, the secret allows you to protect your password (what you want to do by encrypting it) by controlling the access to the secret, instead of by encrypting it.
There are several mechanisms for it:
Secrets can only by accessed by those of their very same namespace.
Secrets have permissions as any other file, so you choose who has access to it.
They are only sent to pods whenever required, not before.
They're not written in local disk storage.
That said, in case something goes wrong, solutions as Sealed Secrets created by Bitnami or others solutions (see Mokrecov answer) have arisen to give even more robustness to the matter, just in case someone undesired gained access to your secret.
Secrets in kubernetes are separate manifests NOT to protect your secret data, but to separate your secret data from your deployment/pod configuration.
Then it's up to you how to secure your secrets, there are many options with it's pros and cons (see Mokrecov's answer). There is also some advantages of secrets compared to other types. Like namespace restriction, seperate access management, not available in pod before it's needed and they are not written in the local disc storage.
Let's think other way around, let's imagine there wasn't any Secrets in kubernetes. Now, your secret data will be inside your deployment/pod/configmap. You have several problems. For example:
You want to give access to deployment manifest to all users but restrict access to Secrets to person A and B only. How do you do that?
If you want to encrypt secrets, you will have to encrypt all data together with deployment data which will make maintenance impossible. Or you can encrypt each secret value but you have to come up with some decryption mechanism for each of them, and keys to decrypt will be unvailed in that phase anyway.
You can use ConfigMap to seperate secret data from configuration. But then when you want to add encryption mechanism, or some access restrictions to it, you will be restricted by characteristics of ConfigMap, because it's intention is only to store non secret data. With Secrets you have easy options to add encryption/restrictions.

Secret management in Helm Charts

I am trying to use Helm charts to install applications in Kubernetes clusters. Can someone please suggest what could be a better solution to manage secrets? Using helm secrets would be a good idea or Hashicorp Vault?
Vault is technically awesome, but it can be an administrative burden. You can get strong protection of "secrets", whatever they may be; you can avoid ever sharing magic secrets like the your central database password by generating single-use passwords; if you need something signed or encrypted, you can ask Vault to do that for you and avoid ever having to know the cryptographic secret yourself. The big downsides are that it's a separate service to manage, getting secrets out of it is not totally seamless, and you occasionally need to have an administrator party to unseal it if you need to restart the server.
Kubernetes secrets are really just ConfigMaps with a different name. With default settings it's very easy for an operator to get out the value of a Secret (kubectl get secret ... -o yaml, then base64 decode the strings), so they're not actually that secret. If you have an interesting namespace setup, you generally can't access a Secret in a different namespace, which could mean being forced to copy around Secrets a lot. Using only native tools like kubectl to manage Secrets is also a little clumsy.
Pushing credentials in via Helm is probably the most seamless path – it's very easy to convert from a Helm value to a Secret object to push into a container, and very easy to push in values from somewhere like a CI system – but also the least secure. In addition to being able to dump out the values via kubectl you can also helm get values on a Helm release to find out the values.
So it's a question of how important keeping your secrets really secret is, and how much effort you want to put in. If you want seamless integration and can limit access to your cluster to authorized operators and effectively use RBAC, a Helm value might be good enough. If you can invest in the technically best and also most complex solution and you want some of its advanced capabilities, Vault works well. Maintaining a plain Kubernetes secret is kind of a middle ground, it's a little more secure than using Helm but not nearly as manageable.

Kubernetes when to use secrets instead of configmap?

What are the differences between secrets and configmap in term of security?
In which cases would I want to use secret instead of configmap?
Secrets are stored encoded and over time will become more protected (e.g. limited access, encrypted at rest, etc). Secrets existed before ConfigMap was created, so until recently it was common to store configuration data in secrets (e.g. conf2kube).
You should use secrets for sensitive data (database passwords, private keys) and ConfigMaps for non-sensitive configuration data.
Most importantly secrets are stored in tmpfs, an in memory file system, and are never persisted to a node file system.
Conversely they consume RAM.
You can compare
Secrets with Password Manager.
ConfigMap with TextFile.
Obviously, Secrets are safer than ConfigMaps as they are encoded.