Commands
Not built yet. This is the command set decided in ADR 0004; the code is issue #10 and issue #30. The commands of M1, with their arguments and files, are in The first version’s commands.
Commands
Section titled “Commands”| Command | Does | Needs a person |
|---|---|---|
ritueel init |
Creates the directory, the roots (--roots N, default 2, both cards present) with their attestations and revocation signatures, and the first trust products. |
Yes |
ritueel yearly |
The yearly ceremony: renews every registered intermediate by re-signing, with the root of the year, extends that root, and publishes the next trust sequence. | Yes |
ritueel intermediate add NAME --request STEM |
Registers an intermediate and certifies its first request. | Yes |
ritueel intermediate replace NAME |
The event path: certifies a new key for a registered intermediate. --revoke also revokes the old one, with a reason. |
Yes |
ritueel intermediate revoke NAME |
Revokes the certificate and subkey binding of an intermediate, or withdraws its SSH CA key, with a reason (--reason compromise, superseded or cessation), without a replacement. It lists the intermediate’s unexpired certificates on the CRL of each root that issued them, so it needs those roots’ cards. |
Yes |
ritueel root add |
Creates a new root in a store and has an existing root vouch for it. This starts an overlap. | Yes |
ritueel root retire ROOT |
Ends an overlap: removes the root from the next trust products. | Yes |
ritueel root revoke ROOT |
Revokes a lost, stolen or compromised root, and builds the trust products without it. | Yes |
ritueel status |
Lists roots, intermediates, the root list and unresolved attempts, with what expires when. | No |
ritueel handoff check STEM |
Runs every check of the hand-off contract on the request STEM, and signs nothing. |
No |
ritueel bundle build, ritueel keyring build |
Build the CA bundle and the keyring package from the directory. Same directory, same bytes. | No |
ritueel root-list verify, ssh-ca-keys verify, crl verify, keyring verify |
The host’s and the relying party’s side of each trust product: run its checks on a file, signing and writing nothing. | No |
ritueel ssh-ca break-glass ROOT |
Makes the break-glass SSH CA of a root that was made before ritueel made one at init and root add, and lists it. |
Yes |
ritueel records list, records verify, records close |
Read the ceremony records, check their hash chain, and close an unresolved attempt. | close only |
ritueel wizard |
A guided front end to the commands above, in the terminal or in a browser on localhost. | Yes |
The verbs of a transition map onto the commands: create and vouch are root add, overlap is a state and not a command, supersede is root retire, and revoke is root revoke.
Flags every ceremony shares
Section titled “Flags every ceremony shares”| Flag | Meaning |
|---|---|
--dir DIR |
The directory. The default is the current directory when it holds ritueel.yaml. |
--plan-only |
Write the plan and stop. |
--plan FILE |
Run from a plan made earlier, after checking it still matches the directory. |
--confirm DIGEST |
Confirm a plan from a script; the digest must be the plan’s. |
--root ROOT |
Sign with this root instead of the root of the year; the reason is recorded. |
--allow-missing NAME |
yearly only: go on without a request for this intermediate, and record it. |
--passphrase-fd N |
Software roots: read the passphrase from this file descriptor. |
--key-dir DIR |
Software roots: the directory of the key files. Refused when it is inside --dir. |
--test-root |
Software roots: no passphrase, marked TEST ONLY everywhere. Products refuse to mix test and real roots. |
--output json |
Every command, ceremony or not: print one JSON object on standard output (below). The default is --output text. |
A PIN is never a flag or an environment variable; the holder types it at the terminal.
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
| 0 | Success; for status, nothing due. |
| 1 | Failure. |
| 2 | Usage error. |
| 3 | Refused by a check or by the policy. |
| 4 | Refused by the card or its PIN state. |
| 5 | Not confirmed. |
| 10, 11, 12 | status only: notice, alert and critical. Intermediates warn at 60, 30 and 14 days, the root list, the SSH CA key list and each CRL at 60, 30 and 14 days, roots at 6 months, 3 months and 30 days. An unresolved attempt is critical, because it may mean a signature that was made and never recorded. The highest finding wins. |
The first version’s commands
Section titled “The first version’s commands”M1 builds these, with the software store only (issue #8, issue #9, issue #10). The paths are those of the directory. A ceremony writes its plan, attempt, record and transcript, and the trust products of its new trust sequence under products/<sequence>/.
| Command | Reads | Writes | Exit codes |
|---|---|---|---|
ritueel version |
Nothing. | The version and the commit it was built from. | 0 |
ritueel init --store software [--roots N] [--test-root] --key-dir DIR |
ritueel.yaml, which the operator writes first. |
roots/<label>/ for each root (A, then B), the key files in DIR, and the first trust products (products/1/). |
0, 1, 2, 3, 5 |
ritueel intermediate add NAME --request STEM |
The entry NAME of ritueel.yaml, and the request requests/STEM.*. |
The answer answers/STEM.*, and the trust products. |
0, 1, 2, 3, 5 |
ritueel handoff check STEM [--intermediate NAME] |
The request requests/STEM.*, ritueel.yaml. |
Nothing. | 0, 1, 2, 3 |
ritueel status |
The directory. | Nothing. | 0, 1, 2, 10, 11, 12 |
ritueel records list |
records/. |
Nothing. | 0, 1, 2 |
ritueel records verify |
The directory. | Nothing. | 0, 1, 2, 3 |
ritueel records close CEREMONY --reason TEXT |
attempts/CEREMONY.json. |
A closing record and its transcript. | 0, 1, 2, 3, 5 |
ritueel bundle build [--out FILE] |
The roots and the newest root list. | The CA bundle, to FILE or standard output. |
0, 1, 2, 3 |
ritueel root-list verify FILE (--held FILE | --pin SHA256...) [--bundle FILE] |
A root list, the list the host holds or its initial pins, and a CA bundle. | Nothing. | 0, 1, 2, 3 |
initmakes--roots Nroots, 2 by default, 1 allowed for a software root. It refuses a directory that already has a root, and a key directory that already has key files. The passphrase is asked once for each root, or read from--passphrase-fd;--test-rootasks none. It prints the accepted limit, and the record says so.intermediate addrefuses aNAMEthatritueel.yamldoes not declare, or that an earlier record registered, and a request whose type is not the entry’stypeor whose stem already has an answer. It runs the contract’s checks 1 to 9, then the six steps; the person’s confirmation is check 10, and a person may decline the request instead (--decline REASONwith--plan FILEfrom a script), which writes the answer with the codedeclinedand a record (exit code 3). A plan that no longer matches the directory is refused withplan-stale(exit code 3). A request refused by a check getsanswers/STEM.result.jsonwithoutcomerefusedand its code, and nothing else is written: no plan, no attempt, no record (exit code 3).handoff checkruns checks 1 to 9 of the hand-off contract and signs nothing. Without--intermediate, the rules that belong to one intermediate (name constraints, KMS read roles) are reported as not run, never as passed. It exits 0 when every check that ran passed, and 3 with the code when one refused.statusexits with the highest finding (Exit codes). An unresolved attempt is critical (12).records verifychecks the hash chain; a break is exit code 3.records closeshows the attempt and asks the person to type the first eight characters of its plan digest, or takes--confirm DIGEST. Its record says that signatures may exist from that plan.bundle buildgives the bytes ofproducts/<sequence>/ca-bundle.pemfor the newest sequence, and refuses to mix test and real roots.root-list verifyis the host’s side: it runs the host’s checks onFILE(aroot-list.json, with its.jwsbeside it) against--held FILE, the list the host holds, or--pin, its initial pins.--bundle FILEalso checks a CA bundle against the list. It exits 0 when the list is accepted and 3 with the code when it is refused; a held list that has expired is a warning in the output. It needs no directory.
yearly, intermediate replace and revoke, the root commands, keyring build and wizard come with M2 to M4; the commands of the trust products that come after M1 are below.
Commands for the trust products after M1
Section titled “Commands for the trust products after M1”These are the arguments of the commands that build and check the CRLs (M2, issue #30), the SSH CA key list (M3, issue #55) and the keyring package (M3, issue #15). The formats are on the CRL page, the SSH CA key list page and the keyring package page.
| Command | Reads | Writes | Exit codes |
|---|---|---|---|
ritueel crl verify FILE --bundle FILE [--held FILE] [--cert FILE] |
A CRL, the CA bundle of the roots the party trusts, the CRL it holds and a certificate. | Nothing. | 0, 1, 2, 3 |
ritueel ssh-ca-keys verify FILE (--held FILE | --root-list FILE) [--user-keys FILE] |
An SSH CA key list, the list the host holds or the root list it holds (with its .jws), and the file for sshd. |
Nothing. | 0, 1, 2, 3 |
ritueel keyring build --name NAME [--out DIR] |
The roots and the bindings in the directory, and the newest root list. | The packages and plain files, to products/<sequence>/keyring/ or DIR. |
0, 1, 2, 3 |
ritueel keyring verify FILE... --root-list FILE [--dir DIR] |
Packages or plain files, the root list, and the directory. | Nothing. | 0, 1, 2, 3 |
ritueel ssh-ca break-glass ROOT |
The root’s entry in the directory. | A break-glass SSH CA in the root’s store, its public key roots/<label>/ssh-break-glass.pub, and the next trust products. |
0, 1, 2, 3, 4, 5 |
crl verifyexits 0 when the CRL is accepted and 3 with the code when it is refused; a held CRL that has expired is a warning in the output. With--cert, a certificate the CRL lists exits 3 with the coderevoked. It needs no directory.ssh-ca-keys verifyexits 0 when the list is accepted and 3 with the code, includinguser-keys-mismatchfor the file for sshd; it needs no directory.keyring buildrefuses to mix test and real roots, asbundle builddoes, and verifies its output before it writes it. A ceremony writes the keyring with its other trust products once the builder exists.keyring verifyexits 0 when every check passes and 3 with the code. Without--dirit cannot check what a revocation dropped.ssh-ca break-glassis a ceremony: it has the plan, the confirmation and the record of every other, and needs the card ofROOT.
The codes of the new objects are in the output as reasons, like the others; trust_sequence and artifacts are written by the commands that write trust products.
A script’s ceremony
Section titled “A script’s ceremony”A test harness drives a ceremony in two runs, so that it confirms only a plan it has read. With a test root there is no passphrase; a software root with one adds --passphrase-fd N to the second run.
ritueel --dir ca intermediate add example-ca --request req-1 --key-dir keys \ --plan-only --output json > plan.jsonritueel --dir ca intermediate add example-ca --request req-1 --key-dir keys \ --plan "$(jq -r .plan.path plan.json)" --confirm "$(jq -r .plan.sha256 plan.json)" --output jsonMachine-readable output
Section titled “Machine-readable output”With --output json, a command prints one JSON object on standard output when it ends, followed by a newline, whatever its outcome. Everything a person reads (the plan in words, prompts, progress, warnings) goes to standard error, and the transcript holds it. Only arguments so broken that --output json cannot be read print no object; the exit code is then 2.
Every object has these members:
| Member | Meaning |
|---|---|
output |
The version of this format, 1. |
command |
The command, as in the plan: intermediate add. |
exit_code |
The exit code the command returns. |
outcome |
done, refused, not-confirmed, usage or failed, matching the exit code. |
reasons |
When refused: the codes, as in the hand-off contract or the root list where they apply, and plan-stale for a plan that no longer matches the directory. |
error |
When failed or a usage error: a message for a person. Its wording is not part of the format. |
And these where they apply:
| Member | Commands | Meaning |
|---|---|---|
version, commit |
version |
The release version and the commit. |
ceremony |
ceremonies | The ceremony’s name. |
plan |
ceremonies | { "path", "sha256", "prefix" }: the plan file, its digest, and the eight characters a person types. With --plan-only, this is the result. |
record |
ceremonies, records close |
{ "path", "sha256" }. |
artifacts |
ceremonies, bundle build |
A list of { "path", "sha256" }, as in the record. |
trust_sequence |
ceremonies | The trust sequence of the trust products written. |
roots |
init, status |
A list of { "label", "store", "test", "x509_spki_sha256", "openpgp_fingerprint", "not_after" }. |
answer |
intermediate add |
{ "stem", "outcome", "reasons", "artifacts" }, as in result.json. |
checks |
handoff check |
A list of { "n", "result" } for checks 1 to 9, where result is passed, failed or not-run. |
findings |
status |
A list of { "level", "kind", "name", "expires_at", "days_left" }: level is notice, alert or critical, kind is intermediate, root, root-list, ssh-ca-keys, crl or attempt. |
records |
records list |
A list of { "ceremony", "command", "outcome", "sha256" }, in chain order. |
The members are named with lower-case words and underscores, times and digests are written as in the hand-off contract, and the object is not in canonical form. A new member is not a new version, so a reader ignores a member it does not know; a member renamed, removed or changed in meaning is version 2.