Kapitan can manage references and secrets with the following key management services:
- GPG
- Google Cloud KMS (beta)
- AWS KMS (beta)
- Azure KMS (beta)
- Environment
- Vaultkv (read only support)
If you want to get started with secrets but don't have a GPG or KMS setup, you can also use the base64
reference type. Note that base64
is not encrypted and is intended for development purposes only. Do not use base64 if you're storing sensitive information!
The usual flow of creating and using an encrypted secret with kapitan is:
This is done in the inventory under parameters.kapitan.secrets
.
Just like any other inventory parameters, this can be inherited from a common class or defined per target. For example, common.yml
may contain:
parameters:
kapitan:
vars:
target: ${target_name}
namespace: ${target_name}
secrets:
gpg:
recipients:
- name: [email protected]
fingerprint: D9234C61F58BEB3ED8552A57E28DC07A3CBFAE7C
gkms:
key: 'projects/<project>/locations/<location>/keyRings/<keyRing>/cryptoKeys/<key>'
awskms:
key: 'alias/nameOfKey'
azkms:
key: 'https://<keyvault-name>.vault.azure.net/keys/<object-name>/<object-version>'
vaultkv:
VAULT_ADDR: http://127.0.0.1:8200
auth: token
$ kapitan refs --write <secret_type>:path/to/secret/file -t <target_name> -f <secret_file>
where <secret_type>
can be any of:
plain
: plain - directly written on the disk in plain text (good for random string generation on kapitan level). Not suitable for secrets.base64
: base64 (not encrypted!). Not suitable for secrets.gpg
: GPGgkms
: Google Cloud KMSawskms
: AWS KMSazkms
: Azure KMSvaultkv
: Hashicorp Vault with kv/kv-v2 secret engine
Kapitan will inherit the secrets configuration for the specified target, and encrypt and save your secret into <path/to/secret/file>
.
When referencing your secret in the inventory during compile, you can use the following functions to automatically generate, encrypt and save your secret:
randomstr
- Generates a random string. You can optionally pass the length you want i.e.||randomstr:32
base64
- base64 encodes your secret; to be used as a secondary function i.e.||randomstr|base64
sha256
- sha256 hashes your secret; to be used as a secondary function i.e.||randomstr|sha256
. You can optionally pass a salt i.e||randomstr|sha256:salt
-> becomessha256("salt:<generated random string>")
reveal
- Decrypts a secret; to be used as a secondary function, useful for reuse of a secret like for different encodings i.e||reveal:path/to/secret|base64
rsa
- Generates an RSA 4096 private key (PKCS#8). You can optionally pass the key size i.e.||rsa:2048
ed25519
- Generates a ed25519 private key (PKCS#8).publickey
- Derives the public key from a revealed private key i.e.||reveal:path/to/encrypted_private_key|publickey
rsapublic
- Derives an RSA public key from a revealed private key i.e.||reveal:path/to/encrypted_private_key|rsapublic
(deprecated, usepublickey
instead)
Note: The first operator here ||
is more similar to a logical OR. If the secret file doesn't exist, kapitan will generate it and apply the functions after the ||
. If the secret file already exists, no functions will run.
Note: If you use |reveal:/path/secret
, when changing the /path/secret
file make sure you also delete any secrets referencing /path/secret
so kapitan can regenerate them.
Note: vaultkv
can't be used to generate secrets automatically for now, manually create the secret using the command line.
Secrets can be referenced in the format ?{<secret_type>:path/to/secret/file}
.
For example, assume for now that your GPG-encrypted secret is already stored in a file at targets/secrets/mysql_password
. This can be referenced in the inventory in the following format:
users:
root:
# If 'secrets/targets/${target_name}/mysql/password' doesn't exist, we can automatically generate a random b64-encoded password as follows
password: ?{gpg:targets/${target_name}/mysql/password|randomstr|base64}
During compile, kapitan will search for the path targets/${target_name}/mysql/password
. Should it not exist, then it will automatically generate a random base64 password and save it to that path.
You can reveal the secrets referenced in the outputs of kapitan compile
via:
$ kapitan refs --reveal -f path/to/rendered/template
For example, compiled/minikube-mysql/manifests/mysql_secret.yml
with the following content:
apiVersion: v1
data:
MYSQL_ROOT_PASSWORD: ?{gpg:targets/minikube-mysql/mysql/password:ec3d54de}
MYSQL_ROOT_PASSWORD_SHA256: ?{gpg:targets/minikube-mysql/mysql/password_sha256:122d2732}
kind: Secret
metadata:
annotations: {}
labels:
name: example-mysql
name: example-mysql
namespace: minikube-mysql
type: Opaque
can be revealed as follows:
$ kapitan refs --reveal -f compiled/minikube-mysql/manifests/mysql_secret.yml
This will substitute the referenced secrets with the actual decrypted secrets stored at the referenced paths and display the file content.
You can also use:
$ kapitan refs --reveal --ref-file refs/targets/all-glob/mysql/password
or
$ kapitan refs --reveal --tag "?{base64:targets/all-glob/mysql/password}"
$ # or
$ kapitan refs --reveal --tag "?{base64:targets/all-glob/mysql/password:3192c15c}"
for more convenience.
This allows revealing compiled files without needing access to ref files by using:
$ kapitan compile --embed-refs
Compiled files containing refs will now have the references embedded in the compiled file under the following format (gkms backend used as an example):
?{gkms:ReallyLongBase64HereZ2FyZ2FiZQo=:embedded}
Which means that compiled outputs can now be completely distributed (e.g. in CI/CD systems that apply changes) without the need to access the refs directory.
You can also check out Tesoro for Kubernetes which will reveal embedded secret refs in the cluster.
As illustrated above, one file corresponds to one secret. It is now possible for users who would like to reduce the decryption overhead to manually create a yaml file that contains multiple secrets, each of which can be referenced by its object key. For example, consider the secret file refs/mysql_secrets
:
mysql_passwords:
secret_foo: hello_world
secret_bar: 54321password
This can be manually encrypted by:
$ kapitan refs --write gpg:components/secrets/mysql_secrets -t prod -f secrets/mysql_secrets
To reference secret_foo
inside this file, you can specify it in the inventory as follows:
secret_foo: ${gpg:components/secrets/mysql_secrets@mysql_passwords.secret_foo}
It may be useful in some occasions when revealing references to have the values for the reference dynamically
come from the environment in which Kapitan is executing. This backend provides such functionality. It will attempt
to locate a value for a reference from the environment using a prefixed variable $KAPITAN_VAR_*
convention
and use this value with the refs command.
$ echo "my_default_value" | kapitan refs --write env:path/to/secret_inside_kapitan -t <target_name> -f -
When this reference is created and then referred to in the parameters, it will use the last path component, from a split, to locate a variable in the current environment to use as the value. If this variable cannot be found in the environment, it will use the default value written to the refs file on the filesystem.
parameters:
mysql_passwordS:
secret_foo: ?{env:my/mysql/mysql_secret_foo}
secret_bar: ?{env:my/mysql/mysql_secret_bar}
When using the above parameters reference, values would be consulted in the environment from the following variables:
$KAPITAN_VAR_mysql_secret_foo
$KAPITAN_VAR_mysql_secret_bar
Considering a key-value pair like my_key
:my_secret
in the path secret/foo/bar
in a kv-v2(KV version 2) secret engine on the vault server, to use this as a secret use:
$ echo "foo/bar:my_key" | kapitan refs --write vaultkv:path/to/secret_inside_kapitan -t <target_name> -f -
Parameters in the secret file are collected from the inventory of the target we gave from CLI -t <target_name>
. If target isn't provided then kapitan will identify the variables from the environment when revealing secret.
Environment variables that can be defined in kapitan inventory are VAULT_ADDR
, VAULT_NAMESPACE
, VAULT_SKIP_VERIFY
, VAULT_CLIENT_CERT
, VAULT_CLIENT_KEY
, VAULT_CAPATH
& VAULT_CACERT
.
Extra parameters that can be defined in inventory are:
auth
: specify which authentication method to use liketoken
,userpass
,ldap
,github
&approle
mount
: specify the mount point of key's path. e.g if path=alpha-secret/foo/bar
thenmount: alpha-secret
(defaultsecret
)engine
: secret engine used, eitherkv-v2
orkv
(defaultkv-v2
) Environment variables cannot be defined in inventory areVAULT_TOKEN
,VAULT_USERNAME
,VAULT_PASSWORD
,VAULT_ROLE_ID
,VAULT_SECRET_ID
.
parameters:
kapitan:
secrets:
vaultkv:
auth: userpass
engine: kv-v2
mount: team-alpha-secret
VAULT_ADDR: http://127.0.0.1:8200
VAULT_NAMESPACE: CICD-alpha
VAULT_SKIP_VERIFY: false
VAULT_CLIENT_KEY: /path/to/key
VAULT_CLIENT_CERT: /path/to/cert
To encrypt secrets using keys stored in Azure's Key Vault, a key_id
is required to identify an Azure key object uniquely.
It should be of the form https://{keyvault-name}.vault.azure.net/{object-type}/{object-name}/{object-version}
.
This is done in the inventory under parameters.kapitan.secrets
.
parameters:
kapitan:
vars:
target: ${target_name}
namespace: ${target_name}
secrets:
azkms:
key: 'https://<keyvault-name>.vault.azure.net/keys/<object-name>/<object-version>'
The key can also be specified using the --key
flag
Secrets can be created using any of the methods described in the "creating your secret" section.
For example, if the key is defined in the prod
target file
$ echo "my_encrypted_secret" | kapitan refs --write azkms:path/to/secret_inside_kapitan -t prod -f -
Using the --key
flag and a key_id
$ echo "my_encrypted_secret" | kapitan refs --write azkms:path/to/secret_inside_kapitan --key=<key_id> -f -
Secrets can be referenced and revealed in any of the ways described above.
For example, to reveal the secret stored at path/to/secret_inside_kapitan
$ kapitan refs --reveal --tag "?{azkms:path/to/secret_inside_kapitan}"
Note: Cryptographic algorithm used for encryption is rsa-oaep-256.