From kube-dc
Creates and manages per-project encryption keys backed by OpenBao Transit for encrypting payloads up to 64 KiB directly or envelope-encrypting larger blobs. Plaintext never leaves OpenBao; workloads reference keys.
How this skill is triggered — by the user, by Claude, or both
Slash command
/kube-dc:manage-kmsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
- Target project must exist and be Ready
{org}-{project}enable_openbao=true)deletionPolicy: retain) even when the CRD is deleted, so backup envelopes wrapping old DEKs remain decryptable.application (your code; the default), etcd (managed-K8s etcd encryption), or backup (snapshot wrapping). Filters in the UI + drives lifecycle guards.aes256-gcm96 (default) or chacha20-poly1305. Both are symmetric AEAD; pick the default unless told otherwise.min_decryption_version is manually advanced (irreversible operator action — never auto).retain (default; survives CRD delete) or schedule (30-day countdown; cancellable until expiry).| Need | Use |
|---|---|
| Encrypt an API token to put in a database field | KMS direct encrypt (≤ 64 KiB) |
| Encrypt a large file or message-queue payload before storing | KMS envelope encryption (Go / Python helpers below) |
| Store a credential the platform syncs into a K8s Secret | manage-secrets |
| TLS server / mTLS / code-signing certs | manage-certificates |
| Database username + password with rotation | create-database |
apiVersion: security.kube-dc.com/v1alpha1
kind: KMSKey
metadata:
name: {key-name}
namespace: {project-namespace} # {org}-{project}
spec:
purpose: application # application | etcd | backup
algorithm: aes256-gcm96 # aes256-gcm96 | chacha20-poly1305
rotation:
enabled: true # opt-in
interval: 90d # KubeDC duration; d|h|m|s only (no w)
deletionPolicy: retain # retain | schedule
See @kmskey-template.yaml for a fully-annotated template.
# Default (purpose=application, no rotation)
kube-dc kms keys create {key-name}
# With scheduled rotation
kube-dc kms keys create {key-name} --rotation=90d
# Backup-purpose with schedule-delete enabled
kube-dc kms keys create archive-2026 \
--purpose=backup --deletion-policy=schedule
kube-dc kms keys list
kube-dc kms keys describe {key-name}
# NAME PURPOSE ALGORITHM VERSION ROTATION
# {name} application aes256-gcm96 3 enabled (90d)
# Or via kubectl
kubectl get kmskey -n {project-namespace}
kubectl describe kmskey {key-name} -n {project-namespace}
For short payloads — API tokens, configuration secrets, single database fields:
# Inline plaintext
kube-dc kms encrypt {key-name} --plaintext="hunter2"
# vault:v3:hQH7+t9xZ...
# From a file
kube-dc kms encrypt {key-name} --plaintext-file=./token.txt > token.enc
# Decrypt back
kube-dc kms decrypt {key-name} --ciphertext-file=./token.enc
# hunter2
The ciphertext is an opaque vault:vN:... string — store it anywhere; only the project's KMS can decrypt it.
For files, database fields, or message-queue payloads, generate a per-payload data key, encrypt locally with the data key, store the wrapped data key next to the ciphertext.
The wire format Kube-DC uses (matching the managed-K8s etcd backup envelope):
NONCE (12B) || CIPHERTEXT || GCM_TAG (16B)
+ wrappedDek = "vault:vN:..." (stored next to the ciphertext)
See @envelope-encryption-go.md for the Go helper and @envelope-encryption-py.md for the Python helper. Both authenticate against OpenBao via the projected SA token (audience=openbao), so a workload pod needs:
spec:
containers:
- name: app
volumeMounts:
- name: bao-token
mountPath: /var/run/secrets/openbao
readOnly: true
volumes:
- name: bao-token
projected:
sources:
- serviceAccountToken:
audience: openbao
path: token
expirationSeconds: 3600
# Add a new key version. Old versions remain alive for decryption.
kube-dc kms keys rotate {key-name}
Or schedule via spec:
kubectl patch kmskey {key-name} -n {project-namespace} \
--type=merge -p '{"spec":{"rotation":{"enabled":true,"interval":"90d"}}}'
After rotation:
encrypt call uses the new version (the vault:vN: prefix increments).To force old ciphertexts to become unreadable (e.g. a compromised version):
kube-dc kms keys set-min-decryption-version {key-name} {version}
This is irreversible. Anything still wrapped with a sub-{version} DEK stops decrypting forever. The CLI walks through a confirmation prompt; confirm with the user first that everything important has been re-wrapped or aged out.
Automation NEVER does this — it's always a human action. Workloads using the KMSKey have encrypt + decrypt permissions but NOT set-min-decryption-version.
Default deletionPolicy: retain keeps the underlying Transit key even after the CRD is deleted. To actually destroy key material:
# Step 1 — flip the policy to schedule (30-day countdown, cancellable)
kube-dc kms keys schedule-delete {key-name}
# Step 2 — cancel at any time before expiry
kube-dc kms keys cancel-delete {key-name}
# Step 3 — the controller hard-deletes after 30 days
OpenBao's own deletion_allowed=false flag prevents accidental destruction even by platform admins.
After creating a KMSKey:
# 1. KMSKey is Ready
kubectl get kmskey {key-name} -n {project-namespace} \
-o jsonpath='{.status.conditions[?(@.type=="Ready")].status}'
# Expected: True
# 2. status.keyId points at the OpenBao Transit path
kubectl get kmskey {key-name} -n {project-namespace} \
-o jsonpath='{.status.keyId}'
# Expected: <org>/transit/keys/<org>-<project>-<key-name>
# 3. status.currentVersion is at least 1
kubectl get kmskey {key-name} -n {project-namespace} \
-o jsonpath='{.status.currentVersion}'
# Expected: 1 (or higher after rotations)
# 4. Round-trip test
echo -n "test" | kube-dc kms encrypt {key-name} --plaintext-file=/dev/stdin \
| kube-dc kms decrypt {key-name} --ciphertext-file=/dev/stdin
# Expected: test
deletionPolicy: retain is the default for a reason: a deleted Transit key would make every existing ciphertext (and every backup envelope wrapping a DEK with that key) unrecoverable. Don't schedule deletion without confirming nothing references the key.<cluster>-etcd KMSKey with purpose=etcd. Do NOT delete that key, schedule it for deletion, or advance its min_decryption_version — every etcd row + every encrypted backup depends on it. See the manage-cluster skill for KEK rotation on those keys.npx claudepluginhub kube-dc/kube-dc-public --plugin kube-dcGuides encryption key lifecycle with envelope encryption, cloud KMS, rotation schedules, and HSM-backed storage to prevent long-lived plaintext keys.
Creates and manages Kube-DC ManagedSecrets backed by OpenBao, with optional sync to Kubernetes Secrets via External Secrets Operator. Use for API tokens, OAuth secrets, signing keys, third-party credentials.
Gates Cloud KMS key version destruction and key ring deletion with a full CMEK dependency audit, preventing irreversible data loss by enumerating all dependent resources and requiring explicit approval.