5 KiB
Application secret grants
Maidn stores secret values in OpenBao. Git contains only references and access policy. A repository does not get OpenBao access: one named workload identity gets one reviewed grant.
Grant classes
| Consumer | OpenBao path | Kubernetes namespace | Intended use |
|---|---|---|---|
build |
declared apps/<app>/<secret> entries |
tekton-pipelines |
Read-only dependency credentials |
publish |
declared apps/<app>/<secret> entries |
tekton-pipelines |
One app's artifact repository credential |
runtime |
declared apps/<app>/<secret> entries |
<app>-<environment> |
Service runtime credentials |
| shared | shared/<name>/* |
Granted consumer only | Deliberately shared broker, database, or API credentials |
build code is repository-controlled. Anything granted to it is readable by a
pull request author. Do not grant deployment, production, Git write, or
administrator credentials to a build.
Bootstrap configuration
Declare access in the private bootstrap configuration. This declaration has no secret values and is reviewed with the platform configuration:
secretGrants:
- application: orders-api
consumer: publish
secrets:
- registry
shared:
- internal-npm
- application: orders-api
consumer: runtime
environment: staging
secrets:
- database-staging
shared:
- rabbitmq
- application: orders-api
consumer: runtime
environment: production
secrets:
- database-production
shared:
- rabbitmq
MaidnCLI validates application, consumer, environment, application-secret, and shared-grant names. It creates one OpenBao policy and Kubernetes-auth role for every declaration. The role names are deterministic:
maidn-<app>-build
maidn-<app>-publish
maidn-<app>-runtime-<environment>
The policy permits only the exact apps/<app>/<secret> paths and
shared/<name>/* paths listed in its declaration. The CLI stores one property
named value at each apps/<app>/<secret> or shared/<group>/<secret> path.
A shared value is stored once, for example at shared/rabbitmq/password, and
each service requiring it declares that shared grant. Do not copy it into
application paths.
GitOps resources
The application environment manifests create the matching ServiceAccount,
SecretStore, and ExternalSecret. These resources are reviewed GitOps content;
never create them with kubectl apply.
For orders-api staging, use the matching identity and namespace:
apiVersion: v1
kind: ServiceAccount
metadata:
name: maidn-orders-api-runtime-staging
namespace: orders-api-staging
---
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
name: openbao-orders-api-staging
namespace: orders-api-staging
spec:
provider:
vault:
server: http://openbao.openbao.svc:8200
path: secret
version: v2
auth:
kubernetes:
mountPath: kubernetes
role: maidn-orders-api-runtime-staging
serviceAccountRef:
name: maidn-orders-api-runtime-staging
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: orders-api-rabbitmq
namespace: orders-api-staging
spec:
refreshInterval: 1h
secretStoreRef:
name: openbao-orders-api-staging
kind: SecretStore
target:
name: orders-api-rabbitmq
creationPolicy: Owner
data:
- secretKey: value
remoteRef:
key: shared/rabbitmq/password
property: value
The workload references only orders-api-rabbitmq in its own namespace. Each
application/environment needs a separate namespace; do not put runtime
secrets in shared staging or production namespaces.
Artifact repositories
Create one credential per application and artifact target. Its upstream
permissions must be limited to the exact package, hosted repository, or object
prefix. Examples: one npm scope, one Maven hosted repository, one OCI image,
or S3 PutObject for one prefix.
Use publish for credentials needed to upload a completed artifact. Use
build only for credentials that a build must read, such as a private package
registry. A custom build upload is an exception: it exposes the token to build
code and therefore requires a narrowly scoped, disposable credential.
Operations
- Create the least-privilege upstream credential.
- Write its value with
cicd-tool app secret setusing stdin,--file, or--generate. Use a least-privilege--token-fileor a bootstrap-provisioned--identity; never put a value or token in YAML, a URL, a command argument, output, or Git. - Add the reviewed grant and GitOps resources.
- Bootstrap or reconcile to create the OpenBao role and policy.
- Verify the target ExternalSecret becomes Ready without printing its Secret.
- On revocation, remove the grant and ExternalSecret, revoke the upstream credential, then restart affected workloads.
See secrets.md for encrypted operational-material rules and runbooks/credential-rotation.md for rotation.