Structured Secrets

Multi-field secrets in SikkerKey -- storing related credentials as named key-value pairs.

A structured secret stores multiple named fields as a single encrypted unit. Use this when a secret has several related values that belong together, like database credentials (host, username, password) or an OAuth config (client ID, client secret, redirect URL).

The fields are serialized to JSON and encrypted as a single blob with the same envelope encryption as regular secrets. The field names are stored as unencrypted metadata so the dashboard can display them. The field values are encrypted.

Creating a Structured Secret

From the secrets page, click + New Secret and select Structured Secret.

Add field name/value pairs:

FieldValue
hostdb.example.com
usernameadmin
passwordhunter2

Field names must be unique within the secret.

Via the CLI:

sikkerkey create --name DB_CREDS \
  --field host db.example.com \
  --field username admin \
  --field password hunter2

If you omit a field's value, it is auto-generated:

sikkerkey create --name DB_CREDS \
  --field host db.example.com \
  --field username admin \
  --field password

Reading Fields

Machines read structured secrets using getFields() to get all fields, or getField() to get a single one.

val db = sk.getFields("sk_db_prod")
val host = db["host"]       // "db.example.com"
val user = db["username"]   // "admin"
val pass = db["password"]   // "hunter2"
db, _ := sk.GetFields("sk_db_prod")
host := db["host"]
db = sk.get_fields("sk_db_prod")
password = sk.get_field("sk_db_prod", "password")
# Get all fields (prints JSON)
sikkerkey get sk_db_prod

# Get a single field
sikkerkey get sk_db_prod password

Calling getSecret() on a structured secret returns the raw JSON string.

Replacing Values

Click a secret to expand it. You get labeled inputs for each field. Change the values you need and confirm.

Replacing updates all fields at once, encrypts with a new data key, and creates a new version.

Updating a Single Field

To change one field without touching the others, use the CLI or SDK:

sikkerkey set sk_db_prod --field password --value "new_password_here"
sk.setField("sk_db_prod", "password", "new_password_here")

This is an atomic operation -- one round trip, no read-modify-write.

Rotating Fields

Click Rotate on a structured secret. You select which fields to rotate. Unselected fields keep their current values.

# Rotate only the password field
sikkerkey rotate sk_db_prod --field password

# Rotate multiple fields
sikkerkey rotate sk_db_prod --field password --field api_key --length 48
val updated = sk.rotateFields("sk_db_prod", "password", length = 32)

Available charsets: symbols (default), alphanumeric, numbers, uuid.

Automatic Rotation

When creating a structured secret, you can check Enable automatic rotation. When enabled:

  • You mark which fields should rotate and which stay static
  • Fields marked for rotation have their values auto-generated (you don't provide values for them)
  • Static fields require values upfront
  • You configure the rotation interval (minimum 5 minutes), generated length, and charset
  • Only the marked fields change on each rotation
  • Manual replace and rotate are disabled while rotation is active

Example: a database credential where host and username are static, and password rotates every 6 hours.

Via the CLI:

sikkerkey create --name DB_CREDS --dynamic --interval 6h \
  --field host db.example.com \
  --field username admin \
  --field password --rotate

The --rotate flag marks the preceding field for rotation. Its value is auto-generated.

From the secrets list, expanding a rotating structured secret shows the schedule editor where you can pause, resume, change the interval, or modify which fields rotate.

Exporting

Structured secrets are flattened when exported. Field names are uppercased and joined with underscores:

sikkerkey export --format env

Output:

DB_CREDS_HOST=db.example.com
DB_CREDS_USERNAME=admin
DB_CREDS_PASSWORD=hunter2

The same flattening applies to sikkerkey run, which injects secrets as environment variables:

sikkerkey run -- ./my-app
# my-app sees DB_CREDS_HOST, DB_CREDS_USERNAME, DB_CREDS_PASSWORD in its environment

Everything Else

Version history, deletion, machine access, and dashboard display work identically to single-value secrets. The only differences are the multi-field UI and the per-field rotation options.