Managing Secrets
DeclaREST keeps sensitive values out of Git repository files by combining metadata declarations, payload placeholders, and a secret store.
How the model works
- Metadata declares which attributes are secrets (
resource.secretAttributes). - Payloads store placeholders instead of plaintext values.
- Secret store holds the actual values (encrypted file or HashiCorp Vault).
- Remote workflows resolve placeholders before sending API requests.
Declaring secret attributes
Add JSON Pointer paths to resource.secretAttributes in metadata:
{
"resource": {
"secretAttributes": [
"/credentials/password",
"/config/bindCredential/0",
"/clientSecret"
]
}
}
Place declarations at the widest safe metadata scope (collection level) so all child resources inherit them.
Placeholder syntax
Two forms are supported in resource payload files:
| Placeholder | Key derivation |
|---|---|
{{secret .}} |
Derived from logical path + attribute path (recommended) |
{{secret custom-key}} |
Uses logical path + custom key suffix |
Example in a resource file:
credentials:
password: "{{secret .}}"
apiToken: "{{secret service-api-token}}"
Prefer {{secret .}} unless you need a stable custom key name.
Configuring a secret store
Set up either backend in your context configuration:
File-backed (encrypted, default):
secretStore:
file:
baseDir: /path/to/secrets # defaults to ~/.declarest/secrets/
passphrase:
prompt: true
HashiCorp Vault:
secretStore:
vault:
address: https://vault.example.com
mountPath: secret
auth:
token:
credentialsRef:
name: vault-token
Then initialize the store:
declarest secret init
See Configuration reference for full schema details.
Safe save workflow
The recommended way to import resources containing secrets:
declarest resource save /corporations/acme --secret-attributes
DeclaREST will:
- Detect plaintext secret candidates based on metadata declarations.
- Store values in the secret store.
- Replace them with
{{secret .}}placeholders in the repository file.
Variants:
# handle only specific attributes
declarest resource save /corporations/acme --secret-attributes /clientSecret,/apiKey
# bypass plaintext guard (local testing only, do not commit)
declarest resource save /corporations/acme --allow-plaintext
Detecting and fixing secrets in existing repositories
Scan for likely plaintext secrets and persist declarations into metadata:
# scan a subtree
declarest secret detect /customers/
# auto-fix: persist detected attributes into metadata
declarest secret detect --fix /customers/
# fix one specific attribute
declarest secret detect --fix --secret-attribute /clientSecret /customers/
# scan from a payload before saving
cat payload.json | declarest secret detect --fix --path /corporations/acme
Secret store operations
declarest secret init # initialize store
declarest secret set /corporations/acme /apiToken super-secret # set a value
declarest secret list /corporations/acme # list keys for a path
declarest secret list /projects --recursive # list recursively
declarest secret get /corporations/acme /apiToken # retrieve a value
Inspecting secrets
View resolved plaintext only when explicitly needed:
declarest resource get /corporations/acme --show-secrets
Use sparingly -- avoid in logs or shared terminals.
Troubleshooting
Save fails with plaintext-secret warning
Possible causes:
- Metadata does not declare the secret attribute yet.
- Secret store is not configured or initialized.
- Some detected secrets were left unhandled.
Fix order:
- Declare
secretAttributesin metadata. - Ensure secret store works:
secret init,secret list. - Retry
resource save --secret-attributes.
One-off plaintext import
Use --allow-plaintext only for temporary local testing. Do not commit the result.