Runbooks / Secrets And Dpapi

Secrets and DPAPI

This document covers how IdentityMesh stores connector secrets, the constraints DPAPI imposes on the deployment, and what to do when those constraints bite.

TL;DR

Where secrets live

Secrets are stored in a SQL table on the IdentityMesh database. Each row carries a name (the secret reference) and an encrypted-value blob. A secretscli command-line tool ships with the engine for provisioning and rotation.

A connector configuration does not carry the cleartext secret. It carries a ref string like secret://ad/svc/password. The engine resolves the ref at sync time, decrypts the blob locally, and uses the value to authenticate to the source system.

Why LocalMachine scope

LocalMachine lets the secret blob be read by any account on the host that has access to the database, without coupling the secret to a specific service account. If it were CurrentUser, the secret would only be readable by the exact user that wrote it — restarting the service under a different identity (for example, switching from an interactive user to a managed service account) would break every secret on the box.

The trade-off is the host-binding constraint described above.

Operational consequences

Host migration

You cannot lift-and-shift the IdentityMesh SQL database to a new Windows host and have the existing secret blobs work. The blobs are unreadable on the new machine.

When migrating:

  1. Inventory the connectors that have a PasswordSecretRef / ClientSecretRef.
  2. Stand up the new host with the IdentityMesh service installed and pointed at the database.
  3. On the new host, run secretscli set <ref> <value> for each affected secret. The set operation re-encrypts under the new host’s DPAPI key.
  4. Verify by running a sync and checking that authentication succeeds.

Disaster recovery

A SQL backup-and-restore to a different host has the same problem as migration: the row contents are restored intact, but the DPAPI blobs are unreadable on the new host. The fix is the same: re-provision via secretscli set.

If you need true DR portability, two options:

Service account changes

If the IdentityMesh service runs under, say, LOCALSYSTEM initially and is later changed to a domain service account, secrets written under the first identity are still readable because of the LocalMachine scope. This is the main reason LocalMachine was chosen over CurrentUser.

Decryption failures

When the engine cannot decrypt a stored secret, it throws an InvalidOperationException with a message indicating the secretRef. The exception surfaces in the run history and in the Windows EventLog. If you see this exception, the host’s DPAPI key has changed relative to when the secret was written — re-provision.

How to add or rotate a secret

secretscli set <ref> <plaintext>

Examples:

secretscli set secret://ad/svc-imadmin/password "S3cr3tP@ss"
secretscli set secret://sql/hr-source/password "OtherP@ss"

The set operation upserts the row. To read back (for verification):

secretscli get <ref>
secretscli exists <ref>

get prints the plaintext to the console — only run interactively, never with output captured to a file or log.