开源软件名称(OpenSource Name):bitnami-labs/sealed-secrets开源软件地址(OpenSource Url):https://github.com/bitnami-labs/sealed-secrets开源编程语言(OpenSource Language):Go 57.5%开源软件介绍(OpenSource Introduction):"Sealed Secrets" for KubernetesProblem: "I can manage all my K8s config in git, except Secrets." Solution: Encrypt your Secret into a SealedSecret, which is safe to store - even to a public repository. The SealedSecret can be decrypted only by the controller running in the target cluster and nobody else (not even the original author) is able to obtain the original Secret from the SealedSecret.
OverviewSealed Secrets is composed of two parts:
The These encrypted secrets are encoded in a apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: mysecret
namespace: mynamespace
spec:
encryptedData:
foo: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq..... Once unsealed this will produce a secret equivalent to this: apiVersion: v1
kind: Secret
metadata:
name: mysecret
namespace: mynamespace
data:
foo: bar # <- base64 encoded "bar" This normal kubernetes secret will appear in the cluster
after a few seconds you can use it as you would use any secret that you would have created directly (e.g. reference it from a Jump to the Installation section to get up and running. The Usage section explores in more detail how you craft SealedSecrets as templates for secretsThe previous example only focused on the encrypted secret items themselves, but the relationship between a In particular, the annotations and labels of a To capture this distinction, the This includes metadata such as labels or annotations, but also things like the apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: mysecret
namespace: mynamespace
annotations:
"kubectl.kubernetes.io/last-applied-configuration": ....
spec:
encryptedData:
.dockerconfigjson: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq.....
template:
type: kubernetes.io/dockerconfigjson
# this is an example of labels and annotations that will be added to the output secret
metadata:
labels:
"jenkins.io/credentials-type": usernamePassword
annotations:
"jenkins.io/credentials-description": credentials from Kubernetes The controller would unseal that into something like: apiVersion: v1
kind: Secret
metadata:
name: mysecret
namespace: mynamespace
labels:
"jenkins.io/credentials-type": usernamePassword
annotations:
"jenkins.io/credentials-description": credentials from Kubernetes
ownerReferences:
- apiVersion: bitnami.com/v1alpha1
controller: true
kind: SealedSecret
name: mysecret
uid: 5caff6a0-c9ac-11e9-881e-42010aac003e
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: ewogICJjcmVk... As you can see, the generated Public key / CertificateThe key certificate (public key portion) is used for sealing secrets,
and needs to be available wherever
An alternative workflow
is to store the certificate somewhere (e.g. local disk) with
Since v0.9.x certificates get automatically renewed every 30 days. It's good practice that you and your team
update your offline certificate periodically. To help you with that, since v0.9.2 kubeseal --cert https://your.intranet.company.com/sealed-secrets/your-cluster.cert It also recognizes the
ScopesSealedSecrets are from the POV of an end user a "write only" device. The idea is that the SealedSecret can be decrypted only by the controller running in the target cluster and nobody else (not even the original author) is able to obtain the original Secret from the SealedSecret. The user may or may not have direct access to the target cluster. More specifically, the user might or might not have access to the Secret unsealed by the controller. There are many ways to configure RBAC on k8s, but it's quite common to forbid low-privilege users from reading Secrets. It's also common to give users one or more namespaces where they have higher privileges, which would allow them to create and read secrets (and/or create deployments that can reference those secrets). Encrypted SealedSecret resources are designed to be safe to be looked at without gaining any knowledge about the secrets it conceals. This implies that we cannot allow users to read a SealedSecret meant for a namespace they wouldn't have access to and just push a copy of it in a namespace where they can read secrets from. Sealed-secrets thus behaves as if each namespace had its own independent encryption key and thus once you seal a secret for a namespace, it cannot be moved in another namespace and decrypted there. We don't technically use an independent private key for each namespace, but instead we include the namespace name during the encryption process, effectively achieving the same result. Furthermore, namespaces are not the only level at which RBAC configurations can decide who can see which secret. In fact, it's possible that users can access a secret called That said, there are many scenarios where you might not care about this level of protection. For example, the only people who have access to your clusters are either admins or they cannot read any secret resource at all. You might have a use case for moving a sealed secret to other namespaces (e.g. you might not know the namespace name upfront), or you might not know the name of the secret (e.g. it could contain a unique suffix based on the hash of the contents etc). These are the possible scopes:
In contrast to the restrictions of name and namespace, secret items (i.e. JSON object keys like The scope is selected with the kubeseal --scope cluster-wide <secret.yaml >sealed-secret.json It's also possible to request a scope via annotations in the input secret you pass to
The lack of any of such annotations means
InstallationSee https://github.com/bitnami-labs/sealed-secrets/releases for the latest release and detailed installation instructions. Cloud platform specific notes and instructions: ControllerOnce you deploy the manifest it will create the After a few moments, the controller will start, generate a key pair, and be ready for operation. If it does not, check the controller logs. KustomizeThe official controller manifest installation mechanism is just a YAML file. In some cases you might need to apply your own customizations, like set a custom namespace or set some env variables.
Helm ChartThe Sealed Secrets helm chart is now official supported and hosted in this GitHub repo. helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets NOTE: The versioning scheme of the helm chart differs from the versioning scheme of the sealed secrets project itself. Originally the helm chart was maintained by the community and the first version adopted a major version of 1 while the sealed secrets project itself is still at major 0. This is ok because the version of the helm chart itself is not meant to be necessarily the version of the app itself. However this is confusing, so our current versioning rule is:
There can be thus multiple revisions of the helm chart, with fixes that apply only to the helm chart without affecting the static YAML manifests or the controller image itself. NOTE: the helm chart readme still contains a deprecation notice, but it's no longer reflects reality and will be removed upon next release. NOTE: the helm chart by default installs the controller with the name kubeseal --controller-name sealed-secrets <args> Alternatively, you can set helm install sealed-secrets -n kube-system --set-string fullnameOverride=sealed-secrets-controller sealed-secrets/sealed-secrets HomebrewThe brew install kubeseal MacPortsThe port install kubeseal NixpkgsThe nix-env -iA nixpkgs.kubeseal Installation from sourceIf you just want the latest client tool, it can be installed into
go install github.com/bitnami-labs/sealed-secrets/cmd/kubeseal@main You can specify a release tag or a commit SHA instead of The $(go env GOPATH)/bin/kubeseal UpgradeDon't forget to check the release notes for guidance about possible breaking changes when you upgrade the client tool and/or the controller. Usage# Create a json/yaml-encoded Secret somehow:
# (note use of `--dry-run` - this is just a local file!)
echo -n bar | kubectl create secret generic mysecret --dry-run=client --from-file=foo=/dev/stdin -o json >mysecret.json
# This is the important bit:
# (note default format is json!)
kubeseal <mysecret.json >mysealedsecret.json
# mysealedsecret.json is safe to upload to github, post to twitter,
# etc. Eventually:
kubectl create -f mysealedsecret.json
# Profit!
kubectl get secret mysecret Note the
By design, this scheme does not authenticate the user. In other
words, anyone can create a Managing existing secretsIf you want Update existing secretsIf you want to add or update existing sealed secrets without having the cleartext for the other items, you can just copy&paste the new encrypted data items and merge it into an existing sealed secret. You must take care of sealing the updated items with a compatible name and namespace (see note about scopes above). You can use the echo -n bar | kubectl create secret generic mysecret --dry-run=client --from-file=foo=/dev/stdin -o json \
| kubeseal > mysealedsecret.json
echo -n baz | kubectl create secret generic mysecret --dry-run=client --from-file=bar=/dev/stdin -o json \
| kubeseal --merge-into mysealedsecret.json Raw mode (experimental)Creating temporary Secret with the It can also be useful as a building block for editor/IDE integrations. The downside is that you have to be careful to be consistent with the sealing scope, the namespace and the name. See Scopes
$ echo -n foo | kubeseal --raw --from-file=/dev/stdin --namespace bar --name mysecret
AgBChHUWLMx...
$ echo -n foo | kubeseal --raw --from-file=/dev/stdin --namespace bar --scope namespace-wide
AgAbbFNkM54... Include the metadata:
annotations:
sealedsecrets.bitnami.com/namespace-wide: "true"
$ echo -n foo | kubeseal --raw --from-file=/dev/stdin --scope cluster-wide
AgAjLKpIYV+... Include the metadata:
annotations:
sealedsecrets.bitnami.com/cluster-wide: "true" Secret RotationYou should always rotate your secrets. But since your secrets are encrypted with another secret, you need to understand how these two layers relate in order to take the right decisions. TL;DR:
Sealing key renewalSealing keys are automatically renewed every 30 days. Which means a new sealing key is created and appended to the set of active sealing keys the controller can use to unseal Sealed Secret resources. The most recently created sealing key is the one used to seal new secrets when you use The renewal time of 30d is a reasonable default, but it can be tweaked as needed
with the A value of
A common misunderstanding is that key renewal is often thought of as a form of key rotation, where the old key is not only obsolete but actually bad and that you thus want to get rid of it. It doesn't help that this feature has been historically called "key rotation", which can add to the confusion. Sealed secrets are not automatically rotated and old keys are not deleted when new keys are generated. Old sealed secrets resources can be still decrypted (that's because old sealing keys are not deleted). User secret rotationThe sealing key renewal and SealedSecret rotation are not a substitute for rotating your actual secrets. A core value proposition of this tool is:
If you store anything in a version control storage, and in a public one in particular, you must assume you cannot ever delete that information. If a sealing key somehow leaks out of the cluster you must consider all your SealedSecret resources encrypted with that key as compromised. No amount of sealing key rotation in the cluster or even re-encryption of existing SealedSecrets files can change that. The best practice is to periodically rotate all your actual secrets (e.g. change the password) and craft new SealedSecret resource with those new secrets. But if the sealed secrets controller were not renewing the sealing key that rotation would be moot, since the attacker could just decrypt the new secrets as well. Thus, you need to do both: periodically renew the sealing key and rotate your actual secrets! Early key renewalIf you know or suspect a sealing key has been compromised you should renew the key ASAP before you start sealing your new rotated secrets, otherwise you'll be giving attackers access to your new secrets as well. A key can be generated early by passing the current timestamp to the controller into a flag called Common misconceptions about key renewalSealed secrets sealing keys are not access control keys (e.g. like a password); they are more like the GPG key you might use to read encrypted mail sent to you. Let's continue with the email analogy for a bit: Imagine you have reasons to believe your private GPG key might have been compromised. You'd have more to lose than to gain if the first thing you do is to just delete your private key. All the previous emails sent with that key are no longer accessible to you (unless you have a decrypted copy of those emails), nor are new emails sent by your friends whom you have not yet managed to tell to use the new key. Sure, the content of those encrypted emails is not secure, as an attacker might now be able to decrypt them, but what's done is done. Your sudden loss of ability to read those emails surely doesn't undo the damage; if anything, it's worse because you no longer know for sure what secret the attacker got to know. What you really want to do is to make sure that your friend stops using your old key and that from now on all further communication is encrypted with a new key pair (i.e. your friend must know about that new key). The same logic applies to SealedSecrets. The ultimate goal is securing your actual "user" secrets. The "sealing" secrets are just a mechanism, an "envelope". If a secret is leaked there is no going back; what's done is done. You first need to ensure that new secrets don't get encrypted with that old compromised key (in the email analogy above that's: create a new key pair and give all your friends your new public key). The second logical step is to neutralize the damage, which depends on the nature of the secret. A simple example is a database password: if you accidentally leak your database password, the thing you're supposed to do is simply to change your database password (on the database; and revoke the old one!) and update the SealedSecret resource with the new password (i.e. running Both steps are described in the previous sections, albeit in a less verbose way. There is no shame in reading them again, now that you have a more in-depth grasp of the underlying rationale. Manual key management (advanced)The sealed secrets controller and the associated workflow is designed to keep old sealing keys around and periodically add new ones. You should not delete old keys unless you know what you're doing. That said, if you want you can manually manage (create, move, delete) sealing keys. They are just normal k8s secrets living in the same namespace where the sealed secret controller lives (usually There are advanced use cases that you can address by creative management of the sealing keys. For example, you can share the same sealing key among a few clusters so that you can apply exactly the same sealed secret in multiple clusters. Since sealing keys are just normal k8s secrets you can even use sealed secrets itself and use a GitOps workflow to manage your sealing keys (useful when you want to share the same key among different clusters)! Labelling a sealing key secret with anything other than NOTE Sealed secrets currently does not automatically pick up manually created, deleted or relabeled sealing keys, an admin must restart the controller before the effect will apply. Re-encryption (advanced)Before you can get rid of some old sealing keys you need to re-encrypt your SealedSecrets with the latest private key. kubeseal --re-encrypt <my_sealed_secret.json >tmp.json \
&& mv tmp.json my_sealed_secret.json The invocation above will produce a new sealed secret file freshly encrypted with
the latest key, without making the secrets leave the cluster to the client. You can then save that file
in your version control system ( Currently, old keys are not garbage collected automatically. It's a good idea to periodically re-encrypt your SealedSecrets. But as mentioned above, don't lull yourself in a false sense of security: you must assume the old version of the SealedSecret (the one encrypted with a key you think of as dead) is still potentially around and accessible to attackers. I.e. re-encryption is not a substitute for periodically rotating your actual secrets. Details (advanced)This controller adds a new The controller maintains a set of private/public key pairs as kubernetes
secrets. Keys are labelled with
CryptoMore details about crypto can be found
2023-10-27 2022-08-15 2022-08-17 2022-09-23 2022-08-13 |
请发表评论