Skip to content

Setting Secure Parameters

A secure parameter holds its value one of two ways. It is either sealed inside DRP with the owning object's key, or it holds a reference — a LookupUri naming an external secret store such as Vault — so the value lives outside DRP and DRP keeps only the pointer.

How set decides where the value goes

set resolves the parameter before it writes

Every set first resolves the parameter across the inheritance chain — the object, its profiles, its stage, and finally global.

  • If that resolves to a LookupUri, the value is written into the external store and the object is left untouched.
  • If it resolves to anything else, or to nothing at all, the value is written onto the object you named, sealed if the parameter is Secure.

The reference does not have to be on the object you are setting. One inherited from a profile is followed just the same.

Stated as a table:

Parameter resolves to Where the value lands Object's parameters
A LookupUri External store, via the plugin's encrypt action unchanged
A sealed value On the addressed object, sealed key added or replaced
A non-secure value On the addressed object, plaintext key added or replaced
Nothing found On the addressed object, sealed if Secure key added

Only the first row redirects the write. Every other case writes the object you named — never the profile the value happened to resolve from.

Writing a secure parameter requires the updateSecure object action, whether it lands in DRP or in an external store.

For how resolution order works, see Parameter Precedence.

Storing a value in DRP

With no reference anywhere in the chain, set seals the value onto the object:

Bash
drpcli machines set Name:node1 param auth/password to '"s3cret"'
JSON
{
  "Key": "MXu22clcGB9OLkjUveRQSH2KgXbnUg9xh45UKMvh2Us=",
  "Nonce": "f26EqUiuN1P7WGMwCbta2ucyQRqcikDQ",
  "Payload": "KSWP45zxZYIdRuRnSfr9VoNClZ+jlFg="
}

Read it back with --decode, which requires the getSecure object action:

Bash
drpcli machines get Name:node1 param auth/password --decode
# "s3cret"

Storing a value in an external store

Establishing a reference

Point the parameter at the store by setting it to a SecureData object containing a LookupUri:

Bash
drpcli machines set Name:node1 param auth/password \
  to '{"LookupUri":"vault://password?path=testing"}'

Nothing resolved to a reference yet, so by the rule above this is an ordinary write onto the object. The external store is not contacted. A plain read returns the pointer:

Bash
drpcli machines get Name:node1 param auth/password
JSON
{
  "Key": null,
  "LookupUri": "vault://password?path=testing",
  "Nonce": null,
  "Payload": null
}

URI structure

The general shape is:

Text Only
<plugin-instance-name>://<key>?<plugin-specific-options>

The scheme is the Name of the plugin instance, not the provider it was created from. An instance named my-vault is addressed as my-vault:// even though its provider is vault. That is how one endpoint talks to several stores at once — vault-prod:// and vault-dr:// are two instances of the same provider pointing at different servers.

Everything after the scheme is interpreted by that plugin — Vault reads path=, format=json, and prefix=, while the others take their own. For the exact fields, see the page for the store you are using, listed under Secret stores below.

A LookupUri may contain template expansions, in the scheme or anywhere else. They are evaluated against the machine each time the URI is used, not when it is stored.

Writing through the reference

Now that the parameter resolves to a LookupUri, the same set command writes to the store instead of the object:

Bash
drpcli machines set Name:node1 param auth/password to '"s3cret"'

It echoes the reference back rather than a sealed value, because nothing was stored on the machine:

JSON
{
  "Key": null,
  "LookupUri": "vault://password?path=testing",
  "Nonce": null,
  "Payload": null
}

The secret is now in the store:

Bash
vault kv get -mount=secret testing
# password    s3cret

Writing through a reference never creates one. It only follows a reference that already exists.

Inherited references

A reference defined once on a profile applies to every object using it, and set follows it:

Bash
drpcli profiles set prod param auth/password \
  to '{"LookupUri":"vault://password?path=shared"}'
drpcli machines addprofile Name:node1 prod

drpcli machines set Name:node1 param auth/password to '"s3cret"'
drpcli machines get Name:node1 param auth/password
# null      <- nothing is stored on the machine
drpcli machines get Name:node1 param auth/password --aggregate --decode
# "s3cret"

Use --aggregate on reads when the reference is inherited. Without it, a plain get looks only at the object's own parameters and returns null.

A constant URI is shared state

vault://password?path=shared resolves to the same location for every machine using the profile, so one machine's write changes the secret all of them read. Template the URI when each object should own its own secret:

Bash
drpcli profiles set prod param auth/password \
  to '{"LookupUri":"vault://password?path=perhost/{{.Machine.Name}}"}' \
  --no-write-through

Each machine then writes and reads its own path.

Resolve a machine-templated reference through the machine

A templated URI renders against the object you address. {{.Machine.Name}} has a value on a machine, but not on the profile holding the reference — so read and write it through the machine:

Bash
drpcli machines set Name:node1 param auth/password to '"s3cret"'
drpcli machines get Name:node1 param auth/password --aggregate --decode

The same commands against the profile fail. The reference names one location per machine, and the command names no machine:

Bash
drpcli profiles set prod param auth/password to '"s3cret"'
Text Only
Error: param auth/password: cannot expand LookupUri
"vault://password?path=perhost/{{.Machine.Name}}" from profiles prod: ...

Storing or repointing the reference is unaffected — that is a plain value, and --no-write-through skips resolution entirely. A URI with no template, or one templated on something the object does have ({{.Param "..."}}), has a single destination and resolves from the profile as normal.

Writing only locally: --no-write-through

--no-write-through skips the resolution step and writes the addressed object's own parameters. The external store is never contacted.

Use it to pin a local value that shadows an inherited reference:

Bash
drpcli machines set Name:node1 param auth/password \
  to '"local-override"' --no-write-through

The machine now holds a sealed value that wins precedence over the profile's reference, and the store is unchanged.

Use it also to change a pointer. Without the flag the parameter already resolves to a reference, so the URI text would be written into the store as if it were the secret:

Bash
drpcli machines set Name:node1 param auth/password \
  to '{"LookupUri":"vault://password?path=elsewhere"}' --no-write-through

add and remove

Neither resolves the chain, so neither writes through.

add always writes the addressed object and fails if the key is already present there. It succeeds when an object only inherits a value, storing a local one that shadows the inherited reference.

remove deletes the object's own value. It never deletes anything from the external store, and it returns not-found if the object only inherits the parameter.

REST equivalents

Text Only
GET   /api/v3/machines/{uuid}/params/{key}?aggregate=true&decode=true
POST  /api/v3/machines/{uuid}/params/{key}
POST  /api/v3/machines/{uuid}/params/{key}?no-write-through=true

Endpoints that resolve before writing advertise the secure-param-write-through feature flag in GET /api/v3/info.

Secret stores

Each store is provided by a plugin, installed from the catalog and configured by an administrator. The plugin's Name is the URI scheme; its page documents the fields that follow.

  • Vault — HashiCorp Vault. Reading and writing cover the URI fields (path=, format=json, prefix=).
  • AWS SecmanAWS Secrets Manager, using the AWS credential file on the DRP host.
  • Azure KeyVault — Azure Key Vault secrets and certificates, using Azure CLI credentials on the DRP host.
  • Command KeyVault — any CLI-accessible store, via named shell commands set in cmdvault/commands.

Secure Parameter Store is the administrator's overview of the four.

References