Using pkiaas from an AI Agent
pkiaas manages PKIaaS certificate authorities and makes keys, certificate signing requests (CSRs) and PKCS#12 files on the user’s computer. It is built to be run by AI agents as well as people. This guide is for agents.
Rules
- Add
--jsonto every command. Standard output then holds exactly one JSON value: the result, or{"error": {"code", "message", "hint"}}. Messages for people (progress, notices, update hints) go to standard error; don’t parse them. Use the exit code and the errorcode, not the message text. - Look commands up rather than guess.
pkiaas help --jsondescribes every command: its flags, examples, result fields, side effects, and whether it calls the server, needs a login or needs the user, with the exit codes and error codes.pkiaas help --json key create(orpkiaas key create --help --json) describes one command. - pkiaas never prompts without a terminal. When something is missing, such as a passphrase, it fails with the
usagecode and names the flag to give. Don’t pipe answers to prompts. Onlypkiaas loginwaits, for the user to approve the login. - Files are never overwritten unless
--forceis given (errorfile_exists). Only add--forcewhen the user wants the file replaced. If you ran the command before and lost its output, the file it wrote is the result: use it rather than making another key. - Private keys stay on this computer. Pass key files by path. Don’t read, print or copy their contents, and don’t send them anywhere.
Secrets
Your commands and their output may be logged, so keep secrets out of both.
- Passphrases are never command-line arguments. Give them with
--passphrase-env NAME(an environment variable the user has set) or--passphrase-file PATH(the first line of a file). Commands that read a key and write another file take--key-passphrase-envand--key-passphrase-filefor the key’s passphrase, andca updatetakes--cep-password-envand--cep-password-filefor a CA’s CEP password. - Ask the user to set the variable or write the file themselves. Don’t put a passphrase in a command you run, for example
echo secret | pkiaas ...orexport KEY_PASSPHRASE=secret. - If you have to make a passphrase up, generate it into a file without printing it, and tell the user where it is, so they can move it to a password manager:
(umask 077; openssl rand -base64 32 > server.key.pass), or without OpenSSL(umask 077; head -c 32 /dev/urandom | base64 > server.key.pass). In PowerShell:[Convert]::ToBase64String([Security.Cryptography.RandomNumberGenerator]::GetBytes(32)) | Set-Content server.key.pass. - Keys are encrypted by default. Only use
--no-passphrasewhen the user asks for an unencrypted key, e.g. for a service that loads its key at startup without a passphrase. - Keys, PKCS#12 files and CSRs from
cert export --csr(a SCEP CSR holds the challenge password) are secrets:pkiaas help --jsonnames them in a command’ssecretOutput. Ask the user before you make one, and say where it will go. Write it with--out FILE(readable by the user only), tell the user where the file is, and never read the file yourself. Suggest that the user add a deny rule for the folder to your settings (e.g. Claude Code’spermissions.deny), so that the file stays out of your reach. - pkiaas prints a secret only with
--out -or to a terminal, and never puts one in a result: without--outin a pipe or captured output, or with--json, the command fails withsecret_destination. It never prints passphrases or tokens. Don’t printPKIAAS_TOKEN, and don’t read the CLI’shosts.json.
Logging in
Commands that call the server need a login. Run pkiaas whoami --json to check one: exit code 3 with not_logged_in or invalid_token means there is none.
Logging in needs the user, who approves it in their browser.
- Ask the user to run
pkiaas loginthemselves. In Claude Code, they can type! pkiaas login. - Where no browser can open on this computer (SSH, containers), they run
pkiaas login --device. It prints an address and a code to enter in a browser on any device. - If the user can’t run commands, you can run
pkiaas login --device --jsonyourself. Start it in the background (it waits up to 10 minutes for the user’s approval), read the address and code from its standard error as soon as they appear, and pass them to the user. Keep it running until it exits; its standard output is then the result. Never enter a code in a browser yourself, and never approve a login you didn’t start for the user. - In CI, set
PKIAAS_TOKENfrom the CI system’s secret store instead of logging in.
The login is kept for 30 days of inactivity, and for at most 90 days. pkiaas logout revokes it.
Certificate authorities
pkiaas ca list --json lists the user’s CAs: their own and those they were invited to. Each has an id and a name, and signed (false while the CA waits for its certificate).
Commands take a CA by its name, in any case (e.g. --ca "Example Issuing CA"), or by its id. Use names with people: say the CA’s name to the user, and accept the name they give. Use IDs in scripts and in commands you keep: an ID never changes, while a CA can be renamed and two CAs can share a name. A name that more than one of the user’s CAs has fails with ca_ambiguous, whose message lists their IDs: ask the user which one they mean.
One CA is active: commands that work in a CA use it unless told otherwise. pkiaas ca show --json says which one it is and why. Login makes it the CA the user last worked in on the website; pkiaas ca set NAME --json (or ID) changes it, and keeps the ID, so renaming the CA doesn’t change it. The active CA is kept on this computer for that server; setting it doesn’t change the CA the user works in on the website. Before working in a CA, check that the active one is the CA the user means; when they have more than one and haven’t said which, ask them rather than choosing.
To work in another CA without changing the active one, give --ca NAME (or ID) to the command, or set PKIAAS_CA to its name or ID in its environment. --ca comes first, then PKIAAS_CA, then the active CA; source in pkiaas ca show --json says which chose it (flag, environment, or set, website, first for the active CA). A name or ID the account doesn’t have fails with not_found.
pkiaas ca show --json also gives the CA’s details: signed, its key (keyType, keySize, hsm), its certificate (serial, thumbprint, validFrom, validTo), activeCertificates, and urls with its public services: certificate, chain, CRL, OCSP, time stamping, the CPS page and Windows enrollment (CEP/CES).
pkiaas ca export --out FILE --json saves the CA’s certificate; with --chain, the CA’s certificate followed by those that issued it. The chain is what pkiaas pkcs12 create --chain-file and servers (e.g. nginx after the server’s certificate) need; a root CA’s certificate is what clients add to their trust store. A CA that isn’t signed yet fails with ca_not_signed. (ca cert, its name in 0.1.0, still works but is deprecated.)
pkiaas ca create --name NAME --json creates a CA owned by the user: the platform makes and keeps its key, self-signs its certificate, and gives it an OCSP certificate and a “Web Server” template, so it can issue certificates at once. The result is the new CA as ca show describes it, with its id. Create a CA only when the user asks for one, or for a test the user wants; it doesn’t become the active CA unless you add --set. --subject, --key-type, --days, --path-length and the key usages set what its certificate holds (see pkiaas help --json ca create). With --csr-only, the CA waits for another CA to sign it: pkiaas ca export --csr --ca ID --out ca.csr --json exports its CSR, and the user imports the signed certificate on the website. A user can create 20 CAs an hour; beyond that it fails with http_429 and says how long to wait. When a step fails on the server, it fails with ca_creation_failed and nothing is kept. --signature-algorithm sha1 makes a CA for testing only (OpenSSL 3 and Windows reject SHA-1 chains) and needs confirmation: pass --yes only when the person asked for SHA-1. As with requests, pass --idempotency-key KEY and keep the key (see “Requesting certificates”).
pkiaas ca update --json changes a CA’s settings, as the website’s Edit CA page does; only the settings whose flags are given change, and it needs the modify privilege in the CA (forbidden without it). settings in pkiaas ca show --json shows them all. To edit the CA’s CPS (the text of its public page), export it, change the file, and send it back:
pkiaas ca export --cps > cpspkiaas ca update --cps-file cps --jsonThe CPS you send is Markdown; an HTML CPS written in the website’s old editor is replaced by it, so tell the user that converting it on the website keeps its formatting. --policy-oid sets the certificate policy OID, and --service-key-type (with --service-signature-algorithm for RSA and EC keys) the key of the OCSP and time-stamping certificates, which they get at their next renewal. To turn Windows enrollment (CEP/CES) on, the user puts the password in an environment variable or a file: pkiaas ca update --cep on --cep-username enroll --cep-password-env CEP_PASSWORD --json. Add --dry-run to see what would change (changes, old and new) without sending anything; show it to the user before changes they haven’t spelled out. A CA that already has the settings is left as it is, so the command is safe to run again. If someone changed the CA between reading and saving, it fails with ca_changed and nothing is saved: run it again.
pkiaas ca delete NAME --json deletes a CA, with every certificate it issued, its pending requests, templates, ACME policies and log lines. OCSP, the CRL, SCEP, ACME and CEP stop answering for it, its ACME accounts stop working, and the users it is shared with lose it; an HSM keeps the key of a CA whose key is on it. It can’t be undone, and only the CA’s owner can do it (forbidden otherwise). The CA is always named (its name or id); it is never the active CA by default. Delete a CA only when the user asks you to:
- Preview it:
pkiaas ca delete NAME --dry-run --jsonchanges nothing;impactsays how many certificates (activeCertificatesstill valid), pending requests, templates, ACME accounts and other users (delegates) the delete takes with it, andhsm. - Show that to the user, naming the CA (name and
id), and ask whether to go ahead. - Only if they agree, run
pkiaas ca delete ID --yes --json. Without--yesand without a terminal it fails withusage; on a terminal it asks for the CA’s name to be typed instead.
If the CA changed between the preview and the delete, it fails with ca_changed and deletes nothing: preview it again and ask again. A retry of a delete that already went through reports deleted as true. If the deleted CA was the active one, the active CA is cleared on this computer.
Exporting
ca export and cert export work the same way, as openssl x509 does:
- Without
--out, the output goes to standard output, ready to pipe into another command; there is no result then, so--jsonneeds--out FILE. With--out FILE --json, the file is written and the result describes it. A CSR fromcert export --csris a secret (see “Secrets”): write it with--out FILE. --format pem(default) or--format der, as OpenSSL’s-outform. PEM is what servers, OpenSSL andpkcs12 createread; DER is the binary form (.cer,.der) Windows and Java also take. DER holds one certificate, so it can’t be combined with--chain. Redirect or pipe DER: it is binary.--chainadds the certificates that issued it, up to the root.--forcereplaces an existing--outfile.
Prefer --out FILE --json: you get the file and a result to check (content, certificates, format). Use standard output only to pipe the output straight into another command.
Standard input and output
The local commands work the same way: key create, csr create and pkcs12 create write to standard output without --out (then --json needs --out FILE; keys and PKCS#12 files only to a terminal, see below), and key create and csr create take --format pem|der (pkcs12 create always writes DER). Their input files, --key, --cert and --chain-file, may be - for standard input; PEM or DER is recognized from the content. Only one input or passphrase per command can come from standard input, and with data on standard input passphrases can’t be prompted for, so give them with --*passphrase-env or --*passphrase-file FILE.
Keys, PKCS#12 files and CSRs from cert export --csr are secrets: always write them with --out FILE (owner-only), since your transcript is kept. Without --out, they go to standard output only when it is a terminal; in a pipe the command fails with secret_destination. --out - sends them to standard output anyway: use it only to pipe one straight into another command, never to read it. Pipe certificates, and CSRs you made with csr create or a CA’s CSR from ca export --csr, e.g. pkiaas cert export SERIAL --chain | pkiaas pkcs12 create --cert - --key server.key ... --out server.pfx.
In Windows PowerShell 5.1, > and | re-encode output, which breaks keys, certificates and PKCS#12 files: always use --out FILE there, and give file names rather than -. PowerShell 7.4 and later keep the bytes. A file re-encoded this way fails with a message saying so.
Certificates
pkiaas cert list --json lists the certificates the CA issued, newest first: also expired and revoked ones, and the CAs it signed. Each has a serial, which the other cert commands take to name it in its CA, a status (valid, expired or revoked) and revocation (reason and date, or null). It returns the first --limit (default 50, at most 1000); total says how many match, so when it is larger, narrow the list rather than reading everything: --search TEXT keeps certificates whose common name contains the text, and --sort FIELD (name, revocationReason, template, validFrom, validTo, keyType or keySize) with --order asc|desc brings the ones you need first. Like every command that works in a CA, they take --ca NAME (or ID), and their results name the CA in issuer (id and name).
pkiaas cert show SERIAL --jsongives a certificate’s details; with--text,textholds every field and extension asopenssl x509 -textprints them (e.g. its subject alternative names). Serials are hex, with or without colons, in any case. A serial the CA didn’t issue fails withnot_found.pkiaas cert export SERIAL --out FILE --jsonsaves the certificate (see “Exporting” above); with--chain, followed by the CA’s certificate and its issuers, which is what a server sends (e.g. nginx’sssl_certificate).pkiaas cert export SERIAL --csr --out FILE --jsonsaves the CSR it was issued from, whenhasCsris true (otherwisecsr_not_stored). A CSR sent by SCEP holds the enrollment’s challenge password: the file is owner-only; don’t print it or put it in your output.
To find the certificate for a name, e.g. before renewing it: pkiaas cert list --search www.example.com --json, and take the newest one whose status is valid.
Revoking
Revoking stops a certificate from being trusted: the CA’s next CRL and OCSP responses list it. Clients that check revocation stop accepting it, so ask the user before revoking, naming the certificate (name and serial) and the reason, and only then run the command with --yes. Without --yes and without a terminal, it fails with usage.
pkiaas cert revoke SERIAL --reason REASON --yes --json. The reasons are RFC 5280’s:unspecified,keyCompromise(its private key leaked or may have),cACompromise,affiliationChanged,superseded(replaced by a new certificate),cessationOfOperation(no longer used) andcertificateHold(suspended for now).- Only
certificateHoldcan be undone:pkiaas cert unrevoke SERIAL --jsontakes the certificate off hold. A certificate on hold can also be revoked for good with another reason. Every other reason is final; changing or undoing it fails withrevocation_final. - Both are safe to run again: revoking with the same reason, or unrevoking a certificate that isn’t revoked, changes nothing and succeeds.
- Both need a subscription, the user’s or the CA owner’s; without one they fail with
subscription_required. Tell the user rather than retrying.
Requests that are safe to repeat (reading, revoking, unrevoking, changing a CA’s settings, deleting a CA, and requesting a certificate or creating a CA with its Idempotency-Key) are tried up to 3 times in all when the connection fails or the server answers with a 5xx or 429; a notice goes to standard error. Only run a command again yourself after it has failed. When the server asks to wait longer than 10 seconds, the command fails at once and its message says how long to wait before running it again.
Requesting certificates
pkiaas request create --csr FILE --template NAME --json sends a CSR (PEM or DER, - for standard input) to the CA. The request waits for a member of the CA to approve it, which issues the certificate. No email is sent. Add --approve to approve it in the same command when the user wants the certificate issued now: the result is then issued, with the certificate’s serial, and --out FILE (or --out -) writes the certificate too. Otherwise tell the user the request’s id and that it waits for approval.
--templateis the name of a template frompkiaas template list --jsonwhoseenabledis true, in any case (e.g.--template "Web Server"), or itsid. A template says what the certificate holds (validity, key usages and so on); if more than one fits, ask the user which to use. A wrong or disabled one fails withtemplate_not_found; a name that two enabled templates share fails withtemplate_ambiguous: use theid.- The server checks the CSR’s signature; an unreadable or altered CSR fails with
invalid_csr. Only the CSR is sent, never anything else in the file.
Keep the idempotency key. Each run is a new request. To make a create safe to repeat, make a key for it (e.g. a UUID), pass it with --idempotency-key KEY, and keep it with your notes. If you can’t tell whether the command worked (it timed out, or a later session picks up the work), run it again with the same CSR, template, CA and key: within 24 hours that returns the first result rather than a second request. Without the flag, the CLI makes a key and reports it as idempotencyKey. A key used for a different request fails with idempotency_key_reused, and one whose first request hasn’t finished with idempotency_key_in_use (wait, then retry with the same key). After 24 hours the key is forgotten and the command makes a new request. With --approve, the same command and key approves the same request, which is safe: an issued request stays as it is. If the approval fails, the request stays (waiting for approval) and the error says its id.
Pending requests
pkiaas request list --json lists the CA’s requests that wait for something, as the website’s Pending Requests page does; pkiaas request show ID --json shows one with what its CSR asks for (subject, subjectAltNames, keyType). status says what each waits for:
pendingApproval: a member of the CA approves or declines it. WithhasCsrtrue,pkiaas request approve IDissues it; one without a CSR needs an approved voucher, which only the website sends.pendingEmailVerification: the requester has yet to confirm their email address.preApproved: it is issued when the requester picks it up with its voucher or SCEP challenge.processing: it is being signed, which takes seconds. One processing for more than 10 minutes (processingSince) is stuck: it can be declined, and the requester makes a new request.
Approving and declining are the user’s decisions: approve or decline only the requests the user asked you to, and check each with pkiaas request show first. Approving issues a certificate for whatever the request’s template allows; declining is final.
pkiaas request approve ID --jsonends once the certificate is issued and gives itsserial; with--out FILE(and--chain) it writes the certificate too. It is safe to run again: an issued request stays as it is. It fails withrequest_not_approvable(no CSR, email not confirmed, pre-approved, or changes to a request that isn’treadyToBeSigned),request_declined,request_processing(wait a few seconds and check it withrequest show), orsigning_failedwhen the CA couldn’t sign (e.g. its IoT HSM didn’t answer): tell the user, whose CA log on the website says why. Approvals are never retried by themselves.- Changing what is issued. By default the certificate holds what the CSR asks for, as the template allows. When the user asks for something else,
request approve(andrequest create --approve) take--subject DN(in place of the CSR’s subject; the template’s subject attributes still win),--san NAME(repeatable; all of the certificate’s SANs, in place of the CSR’s) and--not-after TIMEwith an optional--not-before TIME(RFC 3339, e.g.2027-01-31T00:00:00Z; from now without--not-before), as the website’s override boxes do. Only a request whosestatusDetailisreadyToBeSignedcan be changed (otherwiserequest_not_approvable). Without a subscription, whilevalidityLimitDaysis set inrequest show, the validity can’t be changed (subscription_required); values OpenSSL won’t take fail withinvalid_overrides, and nothing is signed. An issued request is never signed again: running the command again with other changes succeeds but applies none. pkiaas request decline ID --yes --jsondeclines it for good. Declining a declined request succeeds; an issued one fails withrequest_issued(revoke its certificate instead, if the user wants that).
Troubleshooting with the logs
When something failed on the platform rather than in the CLI, e.g. a device’s SCEP enrollment, a CEP/CES or ACME request, or signing_failed, the CA’s log says why. pkiaas log list --json lists the latest log lines of all the user’s CAs in time order, the newest last (.logs[-1]): each has its ca (id and name), level, time (UTC), the client’s ip and the message. It doesn’t use the active CA or PKIAAS_CA; --ca NAME (or ID, repeatable) keeps the lines of those CAs. --level warning keeps warnings and the more severe lines (error, critical, alert, emergency). --since and --until keep the lines from a time and before a time: RFC 3339, a date (midnight in the computer’s time zone, so prefer RFC 3339 with an offset) or how long ago (90m, 24h, 7d); the result’s since and until say which times they stood for. --search TEXT keeps the lines with that text in the message or the client’s IP address, in any case. To find why a request failed, e.g.:
pkiaas log list --ca "Example Issuing CA" --level warning --since 24h --jsonpkiaas log list --search 203.0.113.7 --since 2026-10-24T08:00:00Z --until 2026-10-24T09:00:00Z --jsonand look for the lines near the time it failed, from the client’s IP address. Lines are kept for a while (by default 30 days).
Recipes
Choose a key type with pkiaas key types --json. The default, rsa-2048, works everywhere. Use ec-p256 for smaller, faster keys. Use ml-dsa-* or slh-dsa-* (post-quantum) only when the user asks for them, because few clients accept them yet.
Create a key and a CSR for a TLS server (the user has set KEY_PASSPHRASE):
pkiaas key create --type ec-p256 --out server.key --passphrase-env KEY_PASSPHRASE --jsonpkiaas csr create --key server.key --key-passphrase-env KEY_PASSPHRASE --cn www.example.com \ --san www.example.com --san example.com --out server.csr --jsonList the common name among the SANs too: with --san, it isn’t added for you, and most clients only check SANs.
Then request the certificate from the user’s CA, with a key you keep (see “Requesting certificates”):
pkiaas template list --jsonpkiaas request create --csr server.csr --template "Web Server" --idempotency-key KEY --jsonIf the user wants it issued now, add --approve and --out: the command issues the certificate and writes it, so no serial has to be copied between commands:
pkiaas request create --csr server.csr --template "Web Server" --approve --chain --out server.pem \ --idempotency-key KEY --json--chain adds the CA’s certificates (what a server sends); --out - writes the certificate to standard output instead, for piping, with no result. Without --approve, the user approves it (pkiaas request approve ID --out server.pem, or the website’s Pending Requests page); pkiaas request show ID --json gives the certificate’s serial for pkiaas cert export later.
Combine the key, the signed certificate and the CA chain into a PKCS#12 file for Windows, Java or a load balancer (the user has set PFX_PASSPHRASE too):
pkiaas ca export --chain --out ca.pem --jsonpkiaas pkcs12 create --key server.key --key-passphrase-env KEY_PASSPHRASE --cert server.pem --chain-file ca.pem \ --out server.pfx --passphrase-env PFX_PASSPHRASE --jsonOr, with the certificate’s serial, without saving the certificate and chain first:
pkiaas cert export SERIAL --chain | pkiaas pkcs12 create --key server.key --key-passphrase-env KEY_PASSPHRASE \ --cert - --out server.pfx --passphrase-env PFX_PASSPHRASE --jsonAdd --legacy only for systems older than Windows 10 1709, Java 12 or OpenSSL 1.1.1.
Create a disposable test CA, e.g. to try out commands without touching the user’s CAs (with the user’s agreement: it counts toward their 20 CAs an hour). Make a key for the run (e.g. a UUID) and keep it with your notes, so that running the command again returns the same CA instead of a second one:
pkiaas ca create --name "Test CA $RUN" --key-type ec-p256 --days 7 --idempotency-key "$KEY" --jsonKeep the result’s id and give it to every command with --ca ID (e.g. pkiaas template list --ca ID --json, pkiaas request create --ca ID ...), rather than making the test CA the active one. When the tests are done, delete it by its id; the user agreed to the whole run, so --yes is fine here, for the CA you created only:
pkiaas ca delete "$ID" --dry-run --jsonpkiaas ca delete "$ID" --yes --jsonVersions
pkiaas version --json shows the installed version. When the server has a newer one, pkiaas prints an update command on standard error. If a command fails with cli_outdated, run the install command in the message, then run the command again.
Exit codes
| Exit | Name | Meaning |
|---|---|---|
| 0 | ok | the command succeeded |
| 1 | error | the command failed; the error code says why |
| 2 | usage | the command line is wrong: an unknown command or flag, or missing or conflicting options |
| 3 | auth | not logged in, the login expired, or not allowed |
| 4 | not_found | the CA, certificate or other object doesn’t exist |
| 5 | conflict | the operation would overwrite or clash with something that exists, e.g. an output file |
Error codes
With --json, an error is {"error": {"code", "message", "hint"}}. The hint is what to do; when an error has none of its own, it is the one below.
| Code | Exit | Meaning | What to do |
|---|---|---|---|
error | 1 | an error without a more specific code; the message says what failed | read the message: fix the cause if it is clear (e.g. a wrong file path), otherwise tell the user |
usage | 2 | the command line is wrong, or a needed option (such as a passphrase without a terminal to prompt on) is missing | fix the command line; run the command with --help (or pkiaas help --json <command>) for its flags |
file_exists | 5 | an output file exists, and files are never replaced without --force | if an earlier run of yours wrote the file, it is the result: use it; otherwise choose another output file, or add --force if the user wants the file replaced |
secret_destination | 2 | the output is a secret (a key, a PKCS#12 file or a stored CSR), so it isn’t sent into a pipe, captured output or a --json result without --out | save it with --out FILE, tell the user where the file is, and don’t read it yourself; use --out - only to pipe it straight into another command, since your output may be logged |
wrong_passphrase | 1 | the key’s passphrase is wrong, or the key file is damaged | ask the user for the right passphrase, given the same way (environment variable or file) |
not_logged_in | 3 | there is no login for the server, and PKIAAS_TOKEN isn’t set | ask the user to run pkiaas login (or pkiaas login --device where no browser can open); see pkiaas help agents |
invalid_token | 3 | the server refused the token: the login expired, was revoked, or the account was removed | ask the user to run pkiaas login (or pkiaas login --device where no browser can open); see pkiaas help agents |
forbidden | 3 | the account isn’t allowed to do this | ask the user to check their access, or the CA owner to delegate it |
not_found | 4 | the server has no such object, or the account can’t see it | check the name or ID |
conflict | 5 | the server refused a change that clashes with something that exists | read the message; check what exists before changing it, and ask the user before replacing anything |
ca_not_signed | 5 | the CA has no certificate yet: it waits for its signed certificate to be imported | ask the user to import the CA’s signed certificate on the website (the CA’s page), or use another CA from pkiaas ca list --json (signed is true) |
csr_not_stored | 4 | no CSR is stored for the certificate (e.g. one issued by ACME) | the certificate itself is still available with pkiaas cert export SERIAL; check hasCsr in pkiaas cert show --json before asking for a CSR |
subscription_required | 3 | the feature needs a subscription, the user’s or the CA owner’s (revoking and unrevoking certificates; changing the validity when approving a request) | tell the user; they can subscribe, or link a subscription they already have, on the website’s profile page |
revocation_final | 5 | the certificate is revoked with a reason other than certificateHold, which can’t be undone or changed | nothing to do: the certificate stays revoked; pkiaas cert show SERIAL --json shows its reason |
invalid_csr | 1 | the server can’t read the CSR, or its signature doesn’t match its key | check that the file is the CSR (PEM or DER) and wasn’t changed after it was signed; make a new one with pkiaas csr create |
template_not_found | 4 | the CA has no template with this name or ID; to request a certificate, no enabled one | run pkiaas template list --json (with the same --ca) and use the name or id of a template whose enabled is true |
template_ambiguous | 2 | more than one template of the CA has this name; to request a certificate, more than one enabled one | give --template the id of the one to use; if it isn’t clear which, pkiaas template list --json shows them, and ask the user |
ca_ambiguous | 2 | more than one of the account’s CAs has this name (--ca, PKIAAS_CA or pkiaas ca set) | give the id of the one to use instead; if it isn’t clear which, pkiaas ca list --json shows them, and ask the user |
idempotency_key_reused | 5 | the --idempotency-key was used for a different request in the last 24 hours | make a new key for a new request; reuse a key only to repeat exactly the same command |
idempotency_key_in_use | 5 | the first request with this --idempotency-key hasn’t finished yet | wait a minute and run the same command with the same key again; if it lasts, check on the website whether the request exists before making a new one |
request_not_approvable | 5 | the request can’t be approved: it has no CSR, waits for the requester to confirm their email address, or is pre-approved; or it can’t be approved with changes (--subject, --san, --not-before, --not-after), since it isn’t readyToBeSigned | read the message; pkiaas request show ID --json shows its status and hasCsr. A request without a CSR needs an approved voucher, which the user sends on the website’s Pending Requests page |
invalid_overrides | 1 | OpenSSL won’t take the --subject or --san an approval gives, e.g. a common name longer than 64 characters; nothing was signed | fix the value the message names and approve again; the request still waits for approval |
request_declined | 5 | the request was declined, which is final | nothing to approve: make a new request with pkiaas request create if the certificate is still needed |
request_issued | 5 | the request is issued, so it can’t be declined | pkiaas request show ID --json gives the certificate’s serial; revoke it with pkiaas cert revoke SERIAL if it mustn’t be used |
request_processing | 5 | the request is being signed right now | wait a few seconds, then check it with pkiaas request show ID --json; one processing for more than 10 minutes (processingSince) is stuck: decline it and make a new request |
signing_failed | 1 | the CA couldn’t sign the request, e.g. its IoT HSM didn’t answer or the template doesn’t fit the CSR; the CA’s log says why | tell the user, who can read the CA’s log on the website; the request waits for approval again (or stays processing if the certificate was signed), so approve it again once the cause is fixed |
ca_creation_failed | 1 | creating the CA failed on the server at the step the message names; nothing was kept, unless the message says the half-made CA couldn’t be removed | run the same command again once (with the same --idempotency-key); if it fails again, tell the user and quote the request ID from the message. Each try counts toward the limit of 20 CAs an hour |
ca_changed | 5 | someone changed the CA since the command read it (pkiaas ca update) or previewed its delete (pkiaas ca delete), so nothing was saved or deleted | someone changed the CA since it was read; run the command again (it reads the CA again and applies only its own flags); pkiaas ca show --json shows the CA’s settings now |
cli_outdated | 1 | the server needs a newer pkiaas | update pkiaas with the install command in the message, then run the command again |
connection_failed | 1 | the server couldn’t be reached | check the server address (--server or PKIAAS_SERVER) and the network, then try again |
http_<status> | 1 | the server answered with an unexpected HTTP status, e.g. http_500; the message has the request ID to quote | try again later; if it persists, report the request ID |
no_browser | 1 | pkiaas login couldn’t open a browser, and there is no terminal to wait on | ask the user to run pkiaas login --device, or run it and pass its address and code to the user |
timeout | 1 | nobody finished the login in the browser in time | ask the user to run pkiaas login again and approve it in the browser |
access_denied | 3 | the user denied the login | ask the user whether to log in again |
expired_token | 3 | the device login code expired before the user approved it | ask the user to run pkiaas login --device again, and to enter the code promptly |
invalid_state | 3 | the browser came back from a different login | ask the user to run pkiaas login again |
invalid_issuer | 3 | the login came back from a different server | ask the user to run pkiaas login again, with the intended --server |
invalid_request | 3 | the server or the browser rejected the login request | ask the user to run pkiaas login again; if it persists, update pkiaas |
invalid_grant | 3 | the login code was used, expired or doesn’t match | ask the user to run pkiaas login again |
invalid_client | 3 | the server doesn’t know this CLI as a client | check the server address; update pkiaas |
unsupported_grant_type | 3 | the server doesn’t support this login flow | update pkiaas, or log in with the other flow (--device or without it) |
temporarily_unavailable | 3 | the server has too many pending logins | wait a minute, then ask the user to run pkiaas login --device again |
slow_down | 3 | the server is limiting login requests from this address | wait a minute, then ask the user to run pkiaas login again |