Skip to main content
Version: v5.7.0

opschain admin encryption reencrypt

Included from Basic tier

Rewrites every at-rest envelope that is not sealed under the current key — the v2 SystemService.ReencryptAtRest write. Server-side, the run:

  1. Refuses by name when any stored envelope references a key this server does not carry (<table>.<column> holds N envelope(s) under key <id> — this server does not carry that key), before touching a row: list the key in OPSCHAIN_PREVIOUS_KEYS on every replica and rerun.
  2. Takes the cluster-wide lock (a PostgreSQL advisory lock; a second concurrent run anywhere in the estate is refused as already in progress).
  3. Resumes an unfinished run for the same target key (status partial or failed) or opens a new progress row.
  4. Selects pending rows set-wise per column (ORDER BY ctid / rowid keyset cursor, LIMIT --batch-size), decrypts under the ring, re-encrypts under the current key and writes each batch in one transaction, guarded by the value it read (a row changed under the run is skipped and picked up by the next pass). Counts land in the progress row after every batch — never a value.
  5. On a clean full pass with nothing pending, retires every other registered key (retired_at, retired_by = <run id>): they may then be removed from OPSCHAIN_PREVIOUS_KEYS on every replica.
  6. Records the api:encryption:reencrypt audit event with the run id, target key id, status and counts.

The run is idempotent: a converted row no longer matches the selection, so a rerun finds nothing to do and answers completed with converted 0.

Flags​

FlagMeaning
--batch-size <n>Rows per transaction (default 500 server-side, capped at 5000).
--limit <n>Stop after this many rows; the run stays partial and the next invocation resumes it (0 = run to completion). Use it to spread a very large estate over several windows.
--server <url>Server base URL (default: the active context / OPSCHAIN_SERVER).
--auth-token <token>Admin bearer token override (default: your opschain login session, then $OPSCHAIN_ADMIN_TOKEN, then the token stored by opschain admin login).

Under -o json / -o yaml the run document is printed verbatim (id, target_key_id, status, started_at, updated_at, finished_at, converted, failed, skipped, resumed, columns[], retired_key_ids, error); the exit code still reflects the status.

Run statuses​

StatusMeaningExit
completedA full pass found nothing left; superseded keys retired.0
partial--limit stopped the run; rerun to resume.1
completed_with_failuresfailed rows could not be decrypted under any configured key (the count is the latest pass's, not a running sum); no key is retired while they remain.1
failedA statement error stopped the run (error names it); rerun to resume.1

Exit codes​

CodeMeaning
0The run completed.
1The run is partial or failed, the run was refused (missing key, already in progress, no encryption configured), the request failed, or the token was rejected.
2Usage error — a negative flag, no server or no credential resolvable.

Examples​

opschain admin encryption reencrypt
opschain admin encryption reencrypt --batch-size 1000 --limit 200000
opschain admin encryption reencrypt -o json | jq '.status, .retired_key_ids'

See also​

  • opschain docs cli/admin-encryption-status — the census before and after; pending must read 0 and the old key retired.
  • The encryption key rotation runbook in the operations runbooks — the rotation drill.