Encryption at rest with Kustomizer and Age
Kustomizer has builtin support for encrypting and decrypting Kubernetes configuration (packaged as OCI artifacts) using Actually Good Encryption (age) asymmetric keys. Age is a modern and secure encryption tool with small explicit keys that is a viable alternative to PGP.
This guide shows you how to securely distribute sensitive Kubernetes configuration to trusted consumers. When publishing OCI artifacts to a container registry, you can opt to encrypt the artifacts content using your consumers public keys.
Before you begin
- Install the Kustomizer CLI by the following instructions in the Installation guide.
- Install the age key generator CLI e.g.
brew install age.
Assuming you want to publish sensitive Kubernetes configuration that can be accessed only by a set of trusted users, first you'll need to acquire their public keys.
Generate key pairs
Generate a X25519 key pair using age keygen CLI:
age-keygen -o id_age
Extract the public key to a separate file:
age-keygen -y id_age > id_age.pub
Create the recipients file
Collect the public keys from your users and save them in a file (one key per line):
touch recipients.txt cat user1/id_age.pub >> recipients.txt cat user2/id_age.pub >> recipients.txt
For testing purposes, add your own public key to the recipients file:
cat id_age.pub >> recipients.txt
Publish encrypted artifacts
To encrypt Kubernetes configuration with your users' public keys, you can point Kustomizer at the recipients file when pushing artifacts to a container registry:
kustomizer push artifact oci://ghcr.io/my-org/my-app:1.0.0 \ -k ./examples/demo-app \ --age-recipients ./recipients.txt
Now if you try to inspect the artifact, Kustomizer will fail to access the artifact content:
$ kustomizer inspect artifact oci://ghcr.io/my-org/my-app:1.0.0 ✗ pulling ghcr.io/my-org/my-app:1.0.0 failed: encrypted artifact, you need to supply a private key for decryption
Consume encrypted artifacts
To make use of encrypted artifacts, you'll need to point Kustomizer to a local file with one or more private keys (age identities).
To inspect an artifact encrypted with your public key:
$ kustomizer inspect artifact oci://ghcr.io/my-org/my-app:1.0.0 \ --age-identities ./id_age Artifact: oci://ghcr.io/my-org/my-app@sha256:1801d42d5459e81119dad543a7f1080ed2aadc92dcbb7c9dabf282692d6bf29d BuiltBy: kustomizer/v2.0.0 CreatedAt: 2021-12-29T08:35:40Z EncryptedWith: age-encryption.org/v1 Checksum: 5b8c45af6951e977581122b7848b490f25b43ffd44ed7a82fd574eff6aac06be Resources: - Namespace/kustomizer-demo-app - ConfigMap/kustomizer-demo-app/redis-config-bd2fcfgt6k - Service/kustomizer-demo-app/backend - Service/kustomizer-demo-app/cache - Service/kustomizer-demo-app/frontend - Deployment/kustomizer-demo-app/backend - ghcr.io/stefanprodan/podinfo:6.0.0 - Deployment/kustomizer-demo-app/cache - public.ecr.aws/docker/library/redis:6.2.0 - Deployment/kustomizer-demo-app/frontend - ghcr.io/stefanprodan/podinfo:6.0.0 - HorizontalPodAutoscaler/kustomizer-demo-app/backend - HorizontalPodAutoscaler/kustomizer-demo-app/frontend
All Kustomizer commands that pull artifacts from container registries expose the
--age-identities flag, e.g.:
kustomizer apply inventory sensitive-app --wait --prune \ --artifact oci://ghcr.io/my-org/app-frontend:1.0.0 \ --artifact oci://ghcr.io/my-org/app-backend:1.0.0 \ --age-identities ./id_age