Improve SOPS GPG guide key management
- Switch to batch GPG key creation - Accurately name the cluster's decryption key - Suggest password-manager backup - Optionally cleanup secret key from generating machine - Optionally commit the public key to the repo for team members - Document SOPS limitations decryption required for editing / appending fields Signed-off-by: leigh capili <leigh@null.net>
This commit is contained in:
@@ -19,24 +19,30 @@ brew install gnupg sops
|
||||
|
||||
## Generate a GPG key
|
||||
|
||||
Generate a GPG key with OpenPGP without specifying a passphrase:
|
||||
Generate a GPG/OpenPGP key with no passphrase (`%no-protection`):
|
||||
|
||||
```console
|
||||
$ gpg --full-generate-key
|
||||
|
||||
Real name: stefanprodan
|
||||
Email address: stefanprodan@users.noreply.github.com
|
||||
Comment:
|
||||
You selected this USER-ID:
|
||||
"stefanprodan <stefanprodan@users.noreply.github.com>"
|
||||
gpg --batch --full-generate-key <<EOF
|
||||
%no-protection
|
||||
Key-Type: 1
|
||||
Key-Length: 4096
|
||||
Subkey-Type: 1
|
||||
Subkey-Length: 4096
|
||||
Expire-Date: 0
|
||||
Name-Comment: flux secrets
|
||||
Name-Real: cluster0.yourdomain.com
|
||||
EOF
|
||||
```
|
||||
|
||||
Retrieve the GPG key ID (second row of the sec column):
|
||||
The above configuration creates an rsa4096 key that does not expire.
|
||||
For a full list of options to consider for your environment, see [Unattended GPG key generation](https://www.gnupg.org/documentation/manuals/gnupg/Unattended-GPG-key-generation.html).
|
||||
|
||||
Retrieve the GPG key fingerprint (second row of the sec column):
|
||||
|
||||
```console
|
||||
$ gpg --list-secret-keys stefanprodan@users.noreply.github.com
|
||||
$ gpg --list-secret-keys cluster0.yourdomain.com
|
||||
|
||||
sec rsa3072 2020-09-06 [SC]
|
||||
sec rsa4096 2020-09-06 [SC]
|
||||
1F3D1CED2F865F5E59CA564553241F147E7C5FA4
|
||||
```
|
||||
|
||||
@@ -51,6 +57,98 @@ kubectl create secret generic sops-gpg \
|
||||
--from-file=sops.asc=/dev/stdin
|
||||
```
|
||||
|
||||
It's a good idea to back up this secret-key/k8s-Secret with a password manager or offline storage.
|
||||
Also consider deleting the secret decryption key from you machine:
|
||||
|
||||
```console
|
||||
gpg --delete-secret-keys 1F3D1CED2F865F5E59CA564553241F147E7C5FA4
|
||||
```
|
||||
|
||||
## Configure in-cluster secrets decryption
|
||||
|
||||
Register the Git repository on your cluster:
|
||||
|
||||
```sh
|
||||
flux create source git my-secrets \
|
||||
--url=https://github.com/my-org/my-secrets
|
||||
```
|
||||
|
||||
Create a kustomization for reconciling the secrets on the cluster:
|
||||
|
||||
```sh
|
||||
flux create kustomization my-secrets \
|
||||
--source=my-secrets \
|
||||
--path=./clusters/cluster0 \
|
||||
--prune=true \
|
||||
--interval=10m \
|
||||
--decryption-provider=sops \
|
||||
--decryption-secret=sops-gpg
|
||||
```
|
||||
|
||||
Note that the `sops-gpg` can contain more than one key, sops will try to decrypt the
|
||||
secrets by iterating over all the private keys until it finds one that works.
|
||||
|
||||
## Optional: Export the public key into the git directory
|
||||
|
||||
Commit the public key to the repository so that team members who clone the repo can encrypt new files:
|
||||
|
||||
```console
|
||||
gpg --export \
|
||||
--armor 1F3D1CED2F865F5E59CA564553241F147E7C5FA4 > ./clusters/cluster0/.sops.pub.asc
|
||||
```
|
||||
|
||||
Check the file contents to ensure it's the public key before adding it to the repo and committing.
|
||||
|
||||
```console
|
||||
git add ./clusters/cluster0/.sops.pub.asc
|
||||
git commit -am 'Share GPG public key for secrets generation'
|
||||
```
|
||||
|
||||
Team members can then import this key when they pull the git repository:
|
||||
|
||||
```console
|
||||
gpg --import ./clusters/cluster0/.sops.pub.asc
|
||||
```
|
||||
|
||||
!!! hint
|
||||
The public key is sufficient for creating brand new files.
|
||||
The secret key is required for decrypting and editing existing files because SOPS computes a MAC on all values.
|
||||
When using solely the public key to add or remove a field, the whole file should be deleted and recreated.
|
||||
|
||||
## Configure the git directory for encryption
|
||||
|
||||
Write a [sops config file](https://github.com/mozilla/sops#using-sops-yaml-conf-to-select-kms-pgp-for-new-files) to the specific cluster or namespace directory used
|
||||
to store encrypted objects with this particular GPG key's fingerprint.
|
||||
|
||||
```yaml
|
||||
# ./clusters/cluster0/.sops.yaml
|
||||
creation_rules:
|
||||
- path_regex: .*.yaml
|
||||
encrypted_regex: ^(data|stringData)$
|
||||
pgp: 1F3D1CED2F865F5E59CA564553241F147E7C5FA4
|
||||
```
|
||||
|
||||
This config applies recursively to all sub-directories.
|
||||
Multiple directories can use separate sops configs.
|
||||
Contributors using the `sops` CLI to create and encrypt files
|
||||
won't have to worry about specifying the proper key for the target cluster or namespace.
|
||||
|
||||
`encrypted_regex` helps encrypt the the proper `data` and `stringData` fields for Secrets.
|
||||
You may wish to add other fields if you are encrypting other types of Objects.
|
||||
|
||||
!!! hint
|
||||
Note that you should encrypt only the `data` or `stringData` section. Encrypting the Kubernetes
|
||||
secret metadata, kind or apiVersion is not supported by kustomize-controller.
|
||||
|
||||
Ignore all `.sops.yaml` files in a [`.sourceignore`](../components/source/gitrepositories#excluding-files) file at the root of your repo.
|
||||
|
||||
```sh
|
||||
touch .sourceignore
|
||||
echo '**/.sops.yaml' >> .sourceignore
|
||||
```
|
||||
|
||||
You can now commit your SOPS config.
|
||||
|
||||
## Encrypt secrets
|
||||
|
||||
Generate a Kubernetes secret manifest with kubectl:
|
||||
@@ -66,44 +164,14 @@ kubectl -n default create secret generic basic-auth \
|
||||
Encrypt the secret with sops using your GPG key:
|
||||
|
||||
```sh
|
||||
sops --encrypt \
|
||||
--pgp=1F3D1CED2F865F5E59CA564553241F147E7C5FA4 \
|
||||
--encrypted-regex '^(data|stringData)$' \
|
||||
--in-place basic-auth.yaml
|
||||
sops --encrypt --in-place basic-auth.yaml
|
||||
```
|
||||
|
||||
!!! hint
|
||||
Note that you should encrypt only the `data` section. Encrypting the Kubernetes
|
||||
secret metadata, kind or apiVersion is not supported by kustomize-controller.
|
||||
|
||||
You can now commit the encrypted secret to your Git repository.
|
||||
|
||||
!!! hint
|
||||
Note that you shouldn't apply the encrypted secrets onto the cluster with kubectl. SOPS encrypted secrets are designed to be consumed by kustomize-controller.
|
||||
|
||||
## Configure secrets decryption
|
||||
|
||||
Registry the Git repository on your cluster:
|
||||
|
||||
```sh
|
||||
flux create source git my-secrets \
|
||||
--url=https://github.com/my-org/my-secrets
|
||||
```
|
||||
|
||||
Create a kustomization for reconciling the secrets on the cluster:
|
||||
|
||||
```sh
|
||||
flux create kustomization my-secrets \
|
||||
--source=my-secrets \
|
||||
--prune=true \
|
||||
--interval=10m \
|
||||
--decryption-provider=sops \
|
||||
--decryption-secret=sops-gpg
|
||||
```
|
||||
|
||||
Note that the `sops-gpg` can contain more than one key, sops will try to decrypt the
|
||||
secrets by iterating over all the private keys until it finds one that works.
|
||||
|
||||
### Using various cloud providers
|
||||
|
||||
When using AWS/GCP KMS, you don't have to include the gpg `secretRef` under
|
||||
|
||||
Reference in New Issue
Block a user