Migrate GPG keypairs
This chapter provides scripts for migrating GPG master keypairs and their secret keyrings, including the master key and all associated subkeys, between Signing Manager accounts or environments.
Nota
These migration scripts support only GPG disk-based keypairs. They do not support HSM-based keypairs.
Contact your DigiCert account manager to obtain the migration scripts.
Importante
Team-restricted keys: GPG secret keyring export is refused outright while the master key belongs to a team, because team membership triggers a multi-person approval flow (1, 2, 3, or more approvers, depending on team configuration). If your keypairs are team-restricted, run Step 0 first as laid out in the below section.
These Windows PoweShell scripts are intended specifically for GPG keypairs and support migrating GPG master keypairs and their secret keyring.
The migration follows a strict five-step workflow across three personas.
Step | Script | Persona | Environment | Purpose |
|---|---|---|---|---|
0 (Optional | | Requester/Admin | Source | Open the key to skip the multi-person team approval flow (falls back to single-approver) |
1 | | Requester | Source | Resolve alias, verify eligibility, request export |
2 | | Approver (different user) | Source | Approve (or reject) the export request |
3 | | Requester (same as step 1) | Source | One-shot download of the encrypted secret keyring |
4 | | Importer | Destination | Inspect, derive aliases, import master with all subkeys |
You supply only the master keypair's UUID. The scripts resolve the alias, discover every subkey, and derive deterministic import aliases automatically. No manual subkey bookkeeping is required.
PowerShell 5.1+ (included with Windows 10/11. No
curl, jq, opensslrequired. ). The scripts use native .NETSystem.Net.Http.HttpClientandSystem.Security.Cryptography.X509Certificates.Client certificate (
.p12/.pfx) and API key for each persona (requester, approver, importer — these can be the same person only where noted below).Permissions per persona:
Requester:
VIEW_SM_KEYPAIR(alias lookup) andREQUEST_SM_KEYPAIR_EXPORT.Approver:
APPROVE_SM_KEYPAIR_EXPORT. Must be a different user from the requester, unless the account has exactly one eligible administrator.Importer:
IMPORT_SM_KEYPAIR. VIEW_SM_KEYPAIRis optional — when present it enables the alias-availability pre-check and lets the ledger record the target keypair id; without it those checks degrade gracefully.
Execution policy
If you get an error about script execution being disabled, run the following command in an elevated (Admin) PowerShell:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Create a CSV with a single column, master_keypair_id.
master_keypair_id aafc011e-f7ff-433b-94ae-8673996fe121 8733dd09-a5e6-421c-ac24-48bedb4be8c9
Only master keypair ids are accepted. If you supply a subkey id, step 1 refuses it locally with a message identifying the parent master key.
How to find your master keypair id
Use the Signing Manager UI under GPG Keypairs, or use the API:
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("C:\path\to\cert.p12", "<password>")
Invoke-RestMethod -Uri "https://<clientauth-host>/signingmanager/api/v1/gpg-keypairs?account_id=<account-id>" `
-Headers @{"x-api-key"="<your-api-key>"} -Certificate $cert | ConvertTo-JsonEvery script accepts:
-ClientCert <path-to-cert.p12> -ClientCertPass <p12-password>
Step 0 (optional) Remove Master Keypairs from Teams
When Teams is enabled, a GPG master key can be restricted to a team. Actions performed on a team-restricted master key are subject to the team’s configured multi-person approval policy. Depending on the team configuration, approval may be required from one or more team members before an action can proceed.
During migration, this approval requirement can add complexity to an already multi-step workflow. To simplify the process, the migration temporarily changes the master key only from team-restricted to open. Other keys associated with the team and the team configuration itself are not affected.
After the master key is opened:
The team’s multi-person approval policy no longer applies to the master key.
The migration uses the simpler single-approver, cross-account approval process.
Any one eligible account administrator can approve the export request.
No additional team approval is required for the master key during the remaining migration steps.
Importante
Opening the master key is not temporary. The migration process does not automatically restore the key’s team restriction or add the key back to its team after migration. If your organization requires the master key to remain team-restricted, you must reapply the appropriate team restriction through the UI or API after the migration is complete.
Master keypair access details
Item
Details
Who performs this step
An account administrator in the source environment.
When to perform this step
Only when the master keypair is assigned to a team. If your keys are already open, skip this step.
What this step does
Remove team restrictions from a keypair:
Retrieve the keypair details (
GET /gpg-keypairs/{id}?account_id=)Remove the team restriction (
PUT /gpg-keypairs/{id}/access-management)Use the keypair's current team.id as the
team_id{"team_id": "<current team id>;","limited": false}
Nota
The
team_idin the request must match the keypair's current team ID.The server removes the keypair from its team only when:
-
team_idis included in the request body, and- either the team is being changed or
limitedis set tofalse.If the key is not mapped to any team, it is recorded as already open.
.\0_remove_from_teams.ps1 `
-InputCsv input.csv `
-BaseUrl "https://clientauth.dcone.cluster.local" `
-AccountId "16d0b4f4-d1cc-4dbc-add8-8fcffc8c4889" `
-ApiKey "<admin-api-key>" `
-ClientCert "C:\path\to\admin_cert.p12" `
-ClientCertPass "<p12-password>" Output CSV: output_teams.csv (master_keypair_id, team_status). When resumed, the process skips rows with an OPEN status and retries rows with a FAILEDstatus.
Step 1: Request Export
Item | Details |
|---|---|
Who performs this step | Requester |
What this step does | For each master keypair ID:
|
.\1_request_export.ps1 `
-InputCsv input.csv `
-BaseUrl "https://clientauth.dcone.cluster.local" `
-AccountId "16d0b4f4-d1cc-4dbc-add8-8fcffc8c4889" `
-ApiKey "<requester-api-key>" `
-ClientCert "C:\path\to\requester_cert.p12" `
-ClientCertPass "<p12-password>"Expected output:
===============================================================
Step 1: Requesting GPG Secret Keyring Export
Account: 16d0b4f4-d1cc-4dbc-add8-8fcffc8c4889
Input: input.csv
===============================================================
[2] aafc011e-f7ff-433b-94ae-8673996fe121
Alias resolved: master_only (DISK, ONLINE)
[OK] export_request_id: ab147fea-bcdd-4c64-8229-93389d3a39e6
===============================================================
Done! Requested: 1 | Already done: 0 | Failed/Refused: 0
Output written to: output_export_requests.csv
Share this file with the APPROVER for step 2.
Approval emails have been sent to all eligible administrators.
=============================================================== Output CSV: output_export_requests.csv (master_keypair_id, master_alias, export_request_id). Share the file with the approver. On resume, rows with a valid export_request_id are skipped, while FAILED and REFUSEDrows are retried.
Step 2: Approve export
Item | Details |
|---|---|
Who performs this step | Approver. A different administrator on the source account (unless it is the account's only eligible administrator). |
What this step does | |
.\2_approve_export.ps1 `
-InputCsv output_export_requests.csv `
-BaseUrl "https://clientauth.dcone.cluster.local" `
-AccountId "16d0b4f4-d1cc-4dbc-add8-8fcffc8c4889" `
-ApiKey "<approver-api-key>" `
-ClientCert "C:\path\to\approver_cert.p12" `
-ClientCertPass "<p12-password>"Expected output:
===============================================================
Step 2: Deciding GPG Secret Keyring Export Requests
Decision: APPROVED
Account: 16d0b4f4-d1cc-4dbc-add8-8fcffc8c4889
Input: output_export_requests.csv
===============================================================
[2] master_only (request ab147fea-bcdd-4c64-8229-93389d3a39e6)
Master keypair : master_only
Requested by : lead01 In
Requested on : 09/11/2026 08:55:12
[OK] APPROVED
===============================================================
Done! APPROVED: 1 | Already done: 0 | Skipped/Failed: 0
Output written to: output_approved.csv
Return this file to the REQUESTER for step 3 (download).
=============================================================== Output CSV: output_approved.csv (master_keypair_id,master_alias,export_request_id,approval_status) → return to the Requester.
Pass -Reject to deny the request instead of approving it.
Nota
An export request can only be decided once. Terminal states APPROVED/REJECTED are skipped on resume; FAILED rows are retried. If a decision genuinely fails partway through a batch, continue to step 3 with the succeeded rows, or restart from step 1 for the full list.
Step 3: Download secret keyring
Item | Details |
|---|---|
Who performs this step | Requester. The original requester only (enforced by API). |
What this step does | The server marks the export request |
.\3_download_secring.ps1 `
-InputCsv output_approved.csv `
-BaseUrl "https://clientauth.dcone.cluster.local" `
-AccountId "16d0b4f4-d1cc-4dbc-add8-8fcffc8c4889" `
-ApiKey "<requester-api-key>" `
-ClientCert "C:\path\to\requester_cert.p12" `
-ClientCertPass "<p12-password>"Expected output:
===============================================================
Step 3: Downloading Approved GPG Secret Keyrings
Account: 16d0b4f4-d1cc-4dbc-add8-8fcffc8c4889
Input: output_approved.csv
===============================================================
WARNING: each download is ONE-SHOT and cannot be repeated.
WARNING: output_download.csv will contain SECRET KEY MATERIAL and passphrases.
[2] Downloading master_only (request ab147fea-bcdd-4c64-8229-93389d3a39e6)
[OK] keyring captured to output_download.csv
===============================================================
Done! Downloaded: 1 | Already done: 0 | Skipped/Failed: 0
Output written to: output_download.csv
*** output_download.csv CONTAINS SECRET KEY MATERIAL AND PASSPHRASES ***
Transfer it to the IMPORTER over an encrypted channel only, and
destroy every copy once step 4 has completed successfully.
=============================================================== Output CSV: output_download.csv (master_keypair_id,master_alias,export_request_id,secring_base64,passphrase,download_status) → transfer securely to the Importer.
Resume skips rows recorded as DOWNLOADED and FAILED by default (a failure may mean the server already consumed the one-shot request); pass --retry-failed to force a retry of FAILED rows.
This file contains the secret keyring and its passphrase together.
Encrypt it in transit and delete every copy once step 4 has completed.
Step 4: Import secret keyring
Item | Details |
|---|---|
Who performs this step | Importer. The user on the target environment. Requires |
What this step does |
|
Alias derivation |
|
Dry run
Pass --dry-run to inspect the keyring, print the full alias plan (master + every subkey), and run the best-effort alias availability check — without writing the ledger or any import:
.\4_import_secring.ps1 `
-InputCsv output_download.csv `
-BaseUrl "https://clientauth.one.stage.az.digicert.net" `
-AccountId "492569b0-9b1b-4d6e-ba2b-d30fe725feb2" `
-ApiKey "<importer-api-key>" `
-ClientCert "C:\path\to\importer_cert.p12" `
-ClientCertPass "<p12-password>" `
-DryRunReal import
Drop --dry-run to perform the import:
.\4_import_secring.ps1 `
-InputCsv output_download.csv `
-BaseUrl "https://clientauth.one.stage.az.digicert.net" `
-AccountId "492569b0-9b1b-4d6e-ba2b-d30fe725feb2" `
-ApiKey "<importer-api-key>" `
-ClientCert "C:\path\to\importer_cert.p12" `
-ClientCertPass "<p12-password>"Expected output (master + 3 subkeys):
===============================================================
Step 4: Importing GPG Secret Keyrings
Target account: 492569b0-9b1b-4d6e-ba2b-d30fe725feb2
Target URL: https://clientauth.one.stage.az.digicert.net
Input: output_download.csv
===============================================================
[2] master_01
Inspecting keyring content...
-> Master key
Fingerprint : 6A5046352D0F7C456B0F58D618FADCBF05502F0E
Algorithm : RSA
Will import as alias : 'master_01_6A504635' (from 'master_01' + fingerprint suffix)
Validity : VALID (usable for import)
-> Subkeys found: 3
Subkey #1
Fingerprint : 8A8ABA2A6D07ED10AF076465B287034EEA11B5DE
Algorithm : RSA
Will import as alias : 'master_01_sub_8A8ABA2A'
Validity : VALID (usable for import)
...
Checking whether alias 'master_01_6A504635' is free in the target account...
ALIAS CHECK: 'master_01_6A504635' not found in the TARGET account (looks available).
[OK] keyring imported: 1 master + 3 subkey(s) = 4 keypair(s) total
[OK] target master keypair id (in target account): ce818f10-fc1d-481a-b1ad-be2937239129
===============================================================
Done! Keyrings imported: 1 (= 4 individual keypair(s) counting master+subkeys)
Already done (skipped): 0 | Refused: 0 | Failed: 0
Output written to: output_import.csv
Migration complete. Securely destroy output_download.csv and any temp files.
=============================================================== Output CSV: output_import.csv (master_keypair_id,master_alias,master_fingerprint,imported_master_alias,import_status,imported_count,target_master_id,sub_keys,detail)
The summary line distinguishes keyrings imported (one row = one master + all its subkeys) from individual keypairs (master + every subkey counted separately) to avoid ambiguity — e.g. "Keyrings imported: 1 (= 4 individual keypair(s)...)" means one master-keypair row succeeded, representing 4 distinct GPG keypairs now present in the target account.
Resume skips rows recorded as IMPORTEDI or REFUSED; FAILED rows are retried.
Nota
An import rejected with gpg.alias.duplicate — the server rolls the entire keyring back (all-or-nothing). Edit the master_alias cell of that row in the input CSV (output_download.csv) and re-run; only the master_alias cell of a non-terminal row should ever be hand-edited.
Error / symptom | Cause | Solution |
|---|---|---|
| The GET lookup endpoints ( | Always use |
| A subkey UUID was supplied as | Look up the subkey's |
| The master key is | TEST-type keys are not eligible for export/migration. |
| The master key's | HSM-backed keys cannot leave the HSM; not migratable via this tool. |
| Master key belongs to a team | Run |
Step 2 fails with | The request was already approved (e.g. on a prior run) | Treat the row as approved and continue to step 3. |
Step 3 fails, reason mentions | This export request was already downloaded once. | Recovery requires a brand-new export request (step 1) and a new approval (step 2). |
Step 3 fails, reason mentions | The export request expired before download | New export request with new approval. |
Inspect (step 4) rejects the file at ~100 KB | Keyring exceeds the 102,400-byte inspection ceiling | Not fixable client-side; keyring is too large for this API. |
| The derived master alias already exists somewhere on the server (aliases are global) | Edit the |
Alias-availability check reports "skipped" | Importer lacks | Informational only — the import itself still succeeds or fails on the server's own uniqueness check |
| Custom certificate-validation scriptblocks fail because | Not an operator-facing issue in the shipped scripts — used |
URLs built with "$var?account_id=..." silently drop the variable | PowerShell string interpolation misparses $var? — the ? breaks variable name resolution | Not an operator-facing issue in the shipped scripts — used ${var}?account_id=... brace syntax; if you customize a URL, always brace-delimit variables immediately followed by ? |
| Transient server-side blip, or GPG feature genuinely not enabled on the account/package | Retry; if persistent, confirm the account package includes GPG keypair support |
Script execution disabled | PowerShell execution policy | Run |
Two-person authorization: Export requires a requester and a separate approver (except single-admin accounts). No single person can export a secret keyring alone.
mTLS: All API calls require mutual TLS using client certificates.
One-shot download: The secret keyring can be retrieved exactly once per approved export request; the server marks the request consumed the instant it responds.
Passphrase-protected: The exported keyring is encrypted with a one-time passphrase generated by the server; both are required for import.
Sensitive artifact protection:
output_download.csvis the most sensitive artifact in this workflow. It holds the base64 keyring and its passphrase in the same row. Transfer it only over an encrypted channel and destroy every copy immediately after step 4 succeeds.Audit trail: Every export/approve/download/import operation is logged in Signing Manager's audit log;
output_import.csvadditionally records the resulting target keypair id for reconciliation.
If you encounter issues not covered above, contact DigiCert support with:
The full script output (or the relevant
[FAIL]block)The HTTP status code and
Reason/ResponselinesYour account ID (and not API key)
The environment/host you are using
These bash scripts are intended specifically for GPG keypairs and support migrating GPG master keypairs and their secret keyring.
The migration follows a strict five-step workflow across three personas.
Step | Script | Persona | Environment | Purpose |
|---|---|---|---|---|
0 (Optional | | Requester/Admin | Source | Open the key to skip the multi-person team approval flow (falls back to single-approver) |
1 | | Requester | Source | Resolve alias, verify eligibility, request export |
2 | | Approver (different user) | Source | Approve (or reject) the export request |
3 | | Requester (same as step 1) | Source | One-shot download of the encrypted secret keyring |
4 | | Importer | Source | Inspect, derive aliases, import master with all subkeys |
You supply only the master keypair's UUID — the scripts resolve the alias, discover every subkey, and derive deterministic import aliases automatically. No manual subkey bookkeeping is required.
curl, jq, opensslon the machine running the scripts (all standard on macOS/Linux; install using your package manager if missing, e.g.brew install jqorapt-get install jq)).Client certificate (
.p12/.pfx) and API key for each persona (requester, approver, importer — these can be the same person only where noted below).Permissions per persona:
Requester:
VIEW_SM_KEYPAIR(alias lookup) andREQUEST_SM_KEYPAIR_EXPORT.Approver:
APPROVE_SM_KEYPAIR_EXPORT. Must be a different user from the requester, unless the account has exactly one eligible administrator.Importer:
IMPORT_SM_KEYPAIR. VIEW_SM_KEYPAIRis optional — when present it enables the alias-availability pre-check and lets the ledger record the target keypair id; without it those checks degrade gracefully.
Create a CSV with a single column, master_keypair_id (header (optional) is auto-detected and skipped):
master_keypair_id aafc011e-f7ff-433b-94ae-8673996fe121 8733dd09-a5e6-421c-ac24-48bedb4be8c9
Only master keypair ids are accepted. If you supply a subkey id, step 1 refuses it locally with a message identifying the parent master key.
How to find your master keypair id
Use the Signing Manager UI under GPG Keypairs, or use the API:
curl -s -k --cert /tmp/requester.pem \ -X GET "https://<clientauth-host>/signingmanager/api/v1/gpg-keypairs?account_id=<account-id>" \ -H "x-api-key: <your-api-key>" | jq .
Every script accepts:
--client-cert <path-to-cert.p12-or-.pem> --client-cert-pass <p12-password>
.p12/.pfxfiles are converted on the fly to a temporary PEM usingopenssl pkcs12and shredded (via trap ... EXIT) when the script exits..pemfiles are used directly (no password needed).Pass
--insecureto skip TLS certificate verification (test/staging environments with self-signed certs only — never in production).
Step 0 (optional) Remove Master Keypairs from Teams
When Teams is enabled, a GPG master key can be restricted to a team. Actions performed on a team-restricted master key are subject to the team’s configured multi-person approval policy. Depending on the team configuration, approval may be required from one or more team members before an action can proceed.
During migration, this approval requirement can add complexity to an already multi-step workflow. To simplify the process, the migration temporarily changes the master key only from team-restricted to open. Other keys associated with the team and the team configuration itself are not affected.
After the master key is opened:
he team’s multi-person approval policy no longer applies to the master key.
The migration uses the simpler single-approver, cross-account approval process.
Any one eligible account administrator can approve the export request.
No additional team approval is required for the master key during the remaining migration steps.
Importante
Opening the master key is not temporary. The migration process does not automatically restore the key’s team restriction or add the key back to its team after migration. If your organization requires the master key to remain team-restricted, you must reapply the appropriate team restriction through the UI or API after the migration is complete.
Master keypair access details
Item
Details
Who performs this step
An account administrator in the source environment.
When to perform this step
Only when the master keypair is assigned to a team.
What this step does
Remove team restrictions from a keypair:
Retrieve the keypair details (
GET /gpg-keypairs/{id}?account_id=)Remove the team restriction (
PUT /gpg-keypairs/{id}/access-management)Use the keypair's current team.id as the
team_id{"team_id": "<current team id>;","limited": false}
Nota
The
team_idin the request must match the keypair's current team ID.The server removes the keypair from its team only when:
-
team_idis included in the request body, and- either the team is being changed or
limitedis set tofalse.If the keypair is already open
No update is required.
./0_remove_from_teams.sh \
--input input.csv \
--base-url "https://clientauth.dcone.cluster.local" \
--account-id "16d0b4f4-d1cc-4dbc-add8-8fcffc8c4889" \
--api-key "<admin-api-key>" \
--client-cert "/path/to/admin_cert.p12" \
--client-cert-pass "<p12-password>" Output CSV: output_teams.csv (master_keypair_id, team_status). When resumed, the process skips rows with an OPEN status and retries rows with a FAILED status.
Step 1: Request Export
Item | Details |
|---|---|
Who performs this step | Requester |
What this step does | For each master keypair ID:
|
./1_request_export.sh \
--input input.csv \
--base-url "https://clientauth.dcone.cluster.local" \
--account-id "16d0b4f4-d1cc-4dbc-add8-8fcffc8c4889" \
--api-key "<requester-api-key>" \
--client-cert "/path/to/requester_cert.p12" \
--client-cert-pass "<p12-password>"Expected output:
===============================================================
Step 1: Requesting GPG Secret Keyring Export
Account: 16d0b4f4-d1cc-4dbc-add8-8fcffc8c4889
Input: input.csv
===============================================================
[2] aafc011e-f7ff-433b-94ae-8673996fe121
Alias resolved: master_only (DISK, ONLINE)
[OK] export_request_id: ab147fea-bcdd-4c64-8229-93389d3a39e6
===============================================================
Done! Requested: 1 | Already done: 0 | Failed/Refused: 0
Output written to: output_export_requests.csv
Share this file with the APPROVER for step 2.
Approval emails have been sent to all eligible administrators.
=============================================================== Output CSV: output_export_requests.csv (master_keypair_id, master_alias, export_request_id). Share the file with the approver. On resume, rows with a valid export_request_id are skipped, while FAILED and REFUSEDrows are retried.
Step 2: Approve export
Item | Details |
|---|---|
Who performs this step | Approver. A different administrator on the source account (unless it is the account's only eligible administrator). |
What this step does | |
./2_approve_export.sh \
--input output_export_requests.csv \
--base-url "https://clientauth.dcone.cluster.local" \
--account-id "16d0b4f4-d1cc-4dbc-add8-8fcffc8c4889" \
--api-key "<approver-api-key>" \
--client-cert "/path/to/approver_cert.p12" \
--client-cert-pass "<p12-password>"Expected output:
===============================================================
Step 2: Deciding GPG Secret Keyring Export Requests
Decision: APPROVED
Account: 16d0b4f4-d1cc-4dbc-add8-8fcffc8c4889
Input: output_export_requests.csv
===============================================================
[2] master_only (request ab147fea-bcdd-4c64-8229-93389d3a39e6)
Master keypair : master_only
Requested by : lead01 In
Requested on : 09/11/2026 08:55:12
[OK] APPROVED
===============================================================
Done! APPROVED: 1 | Already done: 0 | Skipped/Failed: 0
Output written to: output_approved.csv
Return this file to the REQUESTER for step 3 (download).
=============================================================== Output CSV: output_approved.csv (master_keypair_id,master_alias,export_request_id,approval_status) → return to the Requester.
Nota
An export request can only be decided once. Terminal states APPROVED/REJECTED are skipped on resume; FAILED rows are retried. If a decision genuinely fails partway through a batch, continue to step 3 with the succeeded rows, or restart from step 1 for the full list.
Step 3: Download secret keyring
Item | Details |
|---|---|
Who performs this step | Requester. The original requester only — the API enforces this. |
What this step does | The server marks the export request |
./3_download_secring.sh \
--input output_approved.csv \
--base-url "https://clientauth.dcone.cluster.local" \
--account-id "16d0b4f4-d1cc-4dbc-add8-8fcffc8c4889" \
--api-key "<requester-api-key>" \
--client-cert "/path/to/requester_cert.p12" \
--client-cert-pass "<p12-password>"Expected output:
===============================================================
Step 3: Downloading Approved GPG Secret Keyrings
Account: 16d0b4f4-d1cc-4dbc-add8-8fcffc8c4889
Input: output_approved.csv
===============================================================
WARNING: each download is ONE-SHOT and cannot be repeated.
WARNING: output_download.csv will contain SECRET KEY MATERIAL and passphrases.
[2] Downloading master_only (request ab147fea-bcdd-4c64-8229-93389d3a39e6)
[OK] keyring captured to output_download.csv
===============================================================
Done! Downloaded: 1 | Already done: 0 | Skipped/Failed: 0
Output written to: output_download.csv
*** output_download.csv CONTAINS SECRET KEY MATERIAL AND PASSPHRASES ***
Transfer it to the IMPORTER over an encrypted channel only, and
destroy every copy once step 4 has completed successfully.
=============================================================== Output CSV: output_download.csv (master_keypair_id,master_alias,export_request_id,secring_base64,passphrase,download_status) → transfer securely to the Importer.
Resume skips rows recorded as DOWNLOADED and FAILED by default (a failure may mean the server already consumed the one-shot request); pass --retry-failed to force a retry of FAILED rows.
This file contains the secret keyring and its passphrase together. Encrypt it in transit and delete every copy once step 4 has completed.
Step 4: Import secret keyring
Item | Details |
|---|---|
Who performs this step | Importer. The user on the target environment. Requires |
What this step does |
|
Alias derivation |
|
Dry run
Pass --dry-run to inspect the keyring, print the full alias plan (master + every subkey), and run the best-effort alias availability check — without writing the ledger or importing anything:
./4_import_secring.sh \
--input output_download.csv \
--base-url "https://clientauth.one.stage.az.digicert.net" \
--account-id "492569b0-9b1b-4d6e-ba2b-d30fe725feb2" \
--api-key "<importer-api-key>" \
--client-cert "/path/to/importer_cert.p12" \
--client-cert-pass "<p12-password>" \
--dry-runReal import
Drop --dry-run to perform the import:
./4_import_secring.sh \
--input output_download.csv \
--base-url "https://clientauth.one.stage.az.digicert.net" \
--account-id "492569b0-9b1b-4d6e-ba2b-d30fe725feb2" \
--api-key "<importer-api-key>" \
--client-cert "/path/to/importer_cert.p12" \
--client-cert-pass "<p12-password>"Expected output (master + 3 subkeys):
==============================================================
Step 4: Importing GPG Secret Keyrings
Target account: 492569b0-9b1b-4d6e-ba2b-d30fe725feb2
Target URL: https://clientauth.one.stage.az.digicert.net
Input: output_download.csv
===============================================================
[2] master_01
Inspecting keyring content...
-> Master key
Fingerprint : 6A5046352D0F7C456B0F58D618FADCBF05502F0E
Algorithm : RSA
Will import as alias : 'master_01_6A504635' (from 'master_01' + fingerprint suffix)
Validity : VALID (usable for import)
-> Subkeys found: 3
Subkey #1
Fingerprint : 8A8ABA2A6D07ED10AF076465B287034EEA11B5DE
Algorithm : RSA
Will import as alias : 'master_01_sub_8A8ABA2A'
Validity : VALID (usable for import)
...
Checking whether alias 'master_01_6A504635' is free in the target account...
ALIAS CHECK: 'master_01_6A504635' not found in the TARGET account (looks available).
[OK] keyring imported: 1 master + 3 subkey(s) = 4 keypair(s) total
[OK] target master keypair id (in target account): ce818f10-fc1d-481a-b1ad-be2937239129
===============================================================
Done! Keyrings imported: 1 (= 4 individual keypair(s) counting master+subkeys)
Already done (skipped): 0 | Refused: 0 | Failed: 0
Output written to: output_import.csv
Migration complete. Securely destroy output_download.csv and any temp files.
=============================================================== Output CSV: output_import.csv (master_keypair_id,master_alias,master_fingerprint,imported_master_alias,import_status,imported_count,target_master_id,sub_keys,detail
The summary line distinguishes keyrings imported (one row = one master + all its subkeys) from individual keypairs (master + every subkey counted separately) to avoid ambiguity — e.g. "Keyrings imported: 1 (= 4 individual keypair(s)...)" means one master-keypair row succeeded, representing 4 distinct GPG keypairs now present in the target account.
Resume skips rows recorded as IMPORTEDI or REFUSED; FAILED rows are retried.
Nota
An import rejected with gpg.alias.duplicate — the server rolls the entire keyring back (all-or-nothing). Edit the master_alias cell of that row in the input CSV (output_download.csv) and re-run; only the master_alias cell of a non-terminal row should ever be hand-edited.
Error / symptom | Cause | Solution |
|---|---|---|
| The GET lookup endpoints ( | Always use |
| A subkey UUID was supplied as | Look up the subkey's |
| The master key is | TEST-type keys are not eligible for export/migration |
| The master key's | HSM-backed keys cannot leave the HSM; not migratable via this tool |
| Master key belongs to a team | Run |
Step 2 fails with | The request was already approved (e.g. on a prior run) | Treat the row as approved and continue to step 3 |
Step 3 fails, reason mentions | This export request was already downloaded once (one-shot) | Recovery requires a brand-new export request (step 1) and a new approval (step 2) |
Step 3 fails, reason mentions | The export request expired before download | New export request and new approval required. |
Inspect (step 4) rejects the file at ~100 KB | Keyring exceeds the 102,400-byte inspection ceiling | Not fixable client-side; keyring is too large for this API |
| The derived master alias already exists somewhere on the server (aliases are global) | Edit the |
Alias-availability check reports "skipped" | Importer lacks | Informational only — the import itself still succeeds or fails on the server's own uniqueness check |
| Transient server-side blip, or GPG feature genuinely not enabled on the account/package | Retry; if persistent, confirm the account package includes GPG keypair support |
Two-person authorization: Export requires a requester and a separate approver (except single-admin accounts). No single person can export a secret keyring alone.
mTLS: All API calls require mutual TLS using client certificates.
One-shot download: The secret keyring can be retrieved exactly once per approved export request; the server marks the request consumed the instant it responds.
Passphrase-protected: The exported keyring is encrypted with a one-time passphrase generated by the server; both are required for import.
Sensitive artifact protection:
output_download.csvis the most sensitive artifact in this workflow. It holds the base64 keyring and its passphrase in the same row. Transfer it only over an encrypted channel and destroy every copy immediately after step 4 succeeds.Audit trail: Every export/approve/download/import operation is logged in Signing Manager's audit log;
output_import.csvadditionally records the resulting target keypair id for reconciliation.
If you encounter issues not covered above, contact DigiCert support with:
The full script output (or the relevant
[FAIL]block)The HTTP status code and
Reason/ResponselinesYour account ID (and not API key)
The environment/host you are using