| name | manage-secrets |
| description | Create and manage Kube-DC ManagedSecrets — project-scoped secrets backed by OpenBao, optionally projected into a Kubernetes Secret via External Secrets Operator. Use this for storing API tokens, OAuth client secrets, signing keys, third-party credentials. For rotated database passwords use manage-database-credentials (the parent KdcDatabase comes from create-database). For encryption keys use manage-kms. For TLS certificates use manage-certificates. |
Prerequisites
- Target project must exist and be Ready
- Project namespace:
{org}-{project}
- OpenBao must be enabled on the cluster (check with
kubectl -n kube-dc get secret master-config -o jsonpath='{.data.enable_openbao}' | base64 -d → expect true)
Key Concepts
- ManagedSecret — Project-scoped CRD describing intent: name, type, optional sync to a Kubernetes Secret. Values are stored in OpenBao under
<org>/kv-<project>/<name> and never live in the CRD.
- Sync — When enabled (default), the platform projects the values into a regular Kubernetes Secret your workloads mount via
envFrom / volumeMounts. The Secret is rewritten in place on every value update.
- Types —
opaque (default), password, api-key, tls, db-static. The shape drives UI rendering and permission policy.
Create a Secret
Empty secret with default sync (target Secret name = ManagedSecret name)
apiVersion: security.kube-dc.com/v1alpha1
kind: ManagedSecret
metadata:
name: {secret-name}
namespace: {project-namespace}
spec:
type: opaque
description: "What this secret is for"
sync:
enabled: true
refreshInterval: 1h
See @managed-secret-template.yaml for a fully-annotated template.
Seed initial values (CLI is the only way; CRD never holds values)
kube-dc secrets create {secret-name} \
--from-literal=API_KEY={value} \
--from-literal=API_SECRET={value}
kube-dc secrets create {secret-name} --from-env-file=./app.env
kube-dc secrets create {secret-name} --sync-disabled
Read / Update Values
kube-dc secrets list
kube-dc secrets get {secret-name} --value
kube-dc secrets put {secret-name} --from-literal=API_KEY={new-value}
kube-dc secrets unset {secret-name} --key=OLD_KEY
Updates trigger an ESO refresh; the synced Kubernetes Secret reflects the change within ~refreshInterval. For instant rollout, kick the workload (kubectl rollout restart deploy/{name}).
Use in a Workload
The synced Secret name defaults to the ManagedSecret name. Mount it like any Secret:
spec:
containers:
- name: app
image: my-app
envFrom:
- secretRef:
name: {secret-name}
Or selectively:
env:
- name: API_KEY
valueFrom:
secretKeyRef:
name: {secret-name}
key: API_KEY
Import an Existing Kubernetes Secret
kube-dc secrets import {secret-name} --from-secret={existing-k8s-secret}
The platform takes over lifecycle. The original Secret is rewritten with the synced values; existing references continue to work.
Verification
After creating a ManagedSecret:
kubectl get managedsecret {name} -n {project-namespace} \
-o jsonpath='{.status.conditions[?(@.type=="Ready")].status}'
kubectl get secret {name} -n {project-namespace}
kubectl get externalsecret -n {project-namespace} | grep {name}
Success: ManagedSecret Ready, Kubernetes Secret present with values, ExternalSecret reports SyncedToTarget.
Failure:
- Stuck
Ready=False / OpenBaoUnavailable: cluster doesn't have OpenBao enabled or the platform reconciler can't reach it. Check kubectl -n kube-dc get deploy kube-dc-manager is Running.
- Synced Secret never appears: External Secrets Operator may be down; check
kubectl get pods -n external-secrets-system.
Delete
kube-dc secrets delete {name}
kube-dc secrets delete {name} --destroy
--destroy is irreversible — there is no platform recovery path for destroyed values. Confirm with the user before invoking.
Safety
- ManagedSecret values NEVER live in the CRD spec — only intent does. Don't put a
data field in there; it's not a Secret.
- Don't
kubectl edit the synced Kubernetes Secret directly. The next ESO reconcile (~refreshInterval) will overwrite your edits.
- Before deleting with
--destroy, run kube-dc secrets consumers {name} to list every workload mounting the synced Secret. Their pods will fail to restart after destruction.
- For TLS certificates use the
manage-certificates skill instead — it owns renewal lifecycle.
- For rotated database passwords use the
manage-database-credentials skill — it sets up DatabaseCredentialPolicy CRs that rotate the DB user's password on a schedule and project credentials into a K8s Secret. (Create the underlying KdcDatabase first via create-database.)
- For encryption keys (encrypt/decrypt opaque payloads, envelope encryption) use the
manage-kms skill — those are NOT secrets-to-store.