CLI reference¶
The exhaustive command reference for the Etminan binaries. Every subcommand
and sub-subcommand that etminan-verifier, etminan-verifierd, and
etminan-agent dispatch is documented here with its one-line purpose, full
synopsis (every flag, with type and default where the source reveals it), and at
least one worked example.
This page is grounded in the same facts as the in-terminal --help
(verifier/src/help.rs, verifier/src/daemon_client.rs) and the actual argument
parsing in verifier/src/cli.rs / agent/src/main.rs. It is the authoritative
operator reference; man etminan-verifier / man etminan-verifierd /
man etminan-agent remain the deeper source for the complete ETMINAN_*
environment variable, FILES, and EXIT STATUS lists.
The operator interface is the daemon — there are no operator key files
Every trust-changing action goes through etminan-verifier op <cmd>,
which talks to the local etminan-verifierd daemon over a Unix socket.
The daemon authenticates the caller by kernel peer-UID (SO_PEERCRED) —
there is no operator key file to pass, and the daemon (not the operator) holds
the only Ed25519 signing key and signs on the operator's behalf as
operator:<label>. Roles are admin / operator / viewer, the model is
default-deny / fail-closed, and every decision — allow and deny — is
written to the audit log. This is Standard
(free) behaviour, not Enterprise. See op below.
There is no --key back door and no root break-glass path: op is the
sole way to enrol, approve, reject, exclude, assign a profile, or rotate a key.
The read/attest commands (check, run, baseline review,
baseline verify-signatures, plugins …, notify-…) stay open and take no
key either.
Conventions used throughout this page
- No operator key files exist. Authorization is the caller's kernel UID,
mapped by the daemon to a role and scope. Whatever the invoking Unix user's
UID is allowed to do is exactly what
opcan do; nothing more. - Several
opverbs require a non-empty--reason <text>(enrol, exclude create/revoke, key rotation, dual-control policy). The reason is signed into the payload by the daemon and appended to the audit log. A--reason(or any other required flag) that is missing, empty, or whitespace-only is rejected (--<name> is required and cannot be empty) — a blank justification can never be signed. - The host is a positional argument on the
opverbs that take one (op enroll <host>,op approve <host>,op check <host>, …) — it isrest[0], read strictly as the first token and never scanned past a flag. - Flag parsing is a minimal
--flag valuescanner. A flag whose next token is itself---prefixed is treated as present-but-empty (the next token is reparsed as its own flag), so--addr --reason xsetsaddr=""and still registers--reason. --help/-his honoured anywhere in a subcommand's own argument list (e.g.baseline review --host web-01 --helpworks), and is checked before the command runs — no partial/invalid invocation ever executes first.version/--version/-Vprints the binary version (0.10.2) and exits 0, recognised before subcommand dispatch on both binaries.- Commands marked Enterprise are compiled only into the
enterprisebuild; a Standard binary has no such capability and its help never mentions it. See Editions. - An unknown subcommand exits 2 (usage error), reserving 1 for a runtime failure inside a recognised command.
Table of contents¶
etminan-verifier
- The operator interface —
op—whoami,login,logout,enroll,enroll-totp,review,check,verify-signatures,approve,reject,exclude,assign-profile,rotate-tls,rotate-ak,identity,bootstrap,totp-policy,dual-control-policy,ping - Setup keys —
keygen-tls,keygen-catalog - Hosts —
check,run - Baseline & drift review —
baseline review | verify-signatures - Plugins —
plugins verify | list | install | update - Notifications —
notify-preview,notify-test - Diagnostics —
version
etminan-verifierd
- The trust daemon — the socket, env vars, and systemd unit
etminan-agent
- Agent commands — daemon,
write-ima-policy,keygen-tls,version
etminan-verifier¶
The verifier makes every trust decision. Its top-level dispatch is a
match subcommand over a small set of families. The primary operator
interface is the op command group, which forwards each
trust-changing action to the etminan-verifierd daemon —
the daemon authenticates the caller by kernel UID and signs the canonical payload
with the one daemon-held key before appending it to the hash-chained audit log.
The remaining top-level subcommands are read/attest and setup only:
check, run, keygen-tls, keygen-catalog, baseline, plugins,
notify-preview, notify-test. An unknown subcommand exits 2.
etminan-verifier op¶
The only interface for every trust-changing action.
etminan-verifier op <cmd> is a thin client: it opens the local
etminan-verifierd socket (ETMINAN_VERIFIERD_SOCKET, default
/run/etminan-verifierd/etminan-verifierd.sock), sends one request, prints the
response, and exits. The daemon reads the caller's kernel-supplied peer
credentials (SO_PEERCRED), maps the UID to a registered identity, and applies
that identity's role and scope. No key file is passed and none is held by the
operator — the daemon owns the single Ed25519 signing key and signs on the
operator's behalf as operator:<label>. The model is default-deny /
fail-closed: an unmapped UID, an out-of-scope host, or an unreachable daemon is
a refusal, and both the allow and the deny are written to the
audit log.
Standard (free) — not Enterprise
The daemon, the op interface, the admin/operator/viewer roles, and the
optional per-role TOTP second factor are all part of the Standard, free
edition and are the default access-control model. Only SIEM output (CEF/LEEF)
and dual-control / four-eyes approval remain Enterprise. See
Editions and RBAC.
| Command | Purpose |
|---|---|
op whoami |
Show the identity and role the daemon maps your UID to. |
op login |
Open an authenticated session (supply --code when TOTP is required for your role). |
op logout |
End the current session immediately. |
op enroll <host> |
Enrol a host through the daemon (daemon-signed; --reason required). |
op enroll-totp |
Enrol your own TOTP second factor. |
op review [<host>] |
List pending measurements (all hosts, or one). |
op check <host> |
Run one attestation check of a host. |
op verify-signatures |
Verify every signature, the audit chain, and the registry. |
op approve <host> |
Approve a host's pending baseline (optionally one --matching/--hash). |
op reject <host> |
Reject a specific pending measurement as a confirmed incident. |
op exclude |
create / revoke / list exclusion rules. |
op assign-profile <host> |
Push a watched-path profile selection to a host. |
op rotate-tls <host> |
Re-pin a host's TLS certificate after its agent regenerates its keypair. |
op rotate-ak <host> |
Re-bind a host's AK within the same TPM, without re-enrolling. |
op identity |
list / add / revoke in the UID→identity registry. |
op bootstrap |
One-time, root-only: seed the first admin identity. |
op totp-policy |
Set whether a role must present a TOTP code (admin only). |
op dual-control-policy |
show / set the signed four-eyes latch (Enterprise). |
op ping |
Liveness check against the daemon socket. |
op whoami¶
Print who the daemon believes you are — the identity your kernel UID maps to and
its role (admin / operator / viewer). Pure read; the first command to run
when a call is unexpectedly refused. An unmapped UID prints that it has no role
and can do nothing until an admin maps it.
Takes no flags.
op login¶
Open (or refresh) an authenticated session for your UID. When
totp-policy marks your role as requiring a second factor,
pass the current RFC 6238 code with --code; the session then lasts
ETMINAN_TOTP_SESSION_TTL_SECS (default 28800 = 8h). If --code is omitted,
op login prompts for it on stderr. With TOTP off for your role, login simply
confirms the mapping.
| Flag | Type | Default | Notes |
|---|---|---|---|
--code <n> |
integer | prompted | The current TOTP code. Required when your role's TOTP policy is required; if omitted, op login prompts for it. |
op logout¶
End the current authenticated session now, before its TTL expires — the next
trust-changing op call will require a fresh login.
Takes no flags.
op enroll¶
Enrol a monitored host through the daemon: the daemon takes and self-validates a
first quote (refusing a malformed/self-inconsistent quote rather than seed a bad
baseline), pins the host's AK and TLS fingerprints (trust-on-first-use), and
records every measurement from that quote as a pending baseline candidate. It
authorizes the caller by UID and signs the enrollment record with its own key
(operator:<label>). Confirm the printed AK fingerprint out of band before
trusting it.
| Argument / flag | Type | Default | Notes |
|---|---|---|---|
<host> |
string | required (positional) | Identifier this host is known by from now on. |
--addr <ip:port> |
socket addr | required | Where the agent is listening. |
--reason <why> |
string | required | Folded into the signed enrollment record and audited. |
--force |
boolean flag | off | Re-enrol an already-enrolled host, discarding its pinned AK/TLS identity. Only after re-confirming the new AK fingerprint out of band. |
--ek-roots <dir> |
path | none | Require manufacturer EK-certificate provenance: the host's EK cert must chain by signature to a self-signed root CA in <dir> (PEM or DER; RSA CAs only). Without it, enrollment relies on EK credential activation alone (a vTPM passes); with it, a host whose TPM ships no EK cert is refused. |
etminan-verifier op enroll web-01 --addr 10.0.3.11:7620 \
--reason "initial onboarding of web tier" \
--ek-roots /etc/etminan-verifier/ek-roots/
op enroll-totp¶
Enrol your own TOTP second factor with the daemon (RFC 6238), so that once your
role's totp-policy is required you can pass --code at
op login. This is your personal 2FA self-enrolment, distinct from
host enrollment (op enroll).
Takes no flags.
op review¶
List every pending (new or changed, not yet approved) measurement, optionally
filtered to one host. Each entry prints a plain-language ownership verdict, a
change-source-correlation line (if configured), a package trust line (if a
package match exists), and the raw sha256/owner/size/mtime detail. Entries older
than ETMINAN_PENDING_REVIEW_SLA_HOURS (default 24) are marked
[SLA EXCEEDED]. Pure read. Also available directly as
baseline review.
| Argument | Type | Default | Notes |
|---|---|---|---|
<host> |
string | all hosts | Optional positional; restrict to one host. |
op check¶
Run one attestation check of an enrolled host through the daemon: fresh quote,
verify signature and AK fingerprint against the enrollment record, replay the IMA
log against the signed PCR digest, and diff new measurements against the approved
baseline. The same check logic is available without the daemon as top-level
check.
| Argument / flag | Type | Default | Notes |
|---|---|---|---|
<host> |
string | required (positional) | The enrolled host to check. |
--addr <ip:port> |
socket addr | required | Where its agent is listening. |
op verify-signatures¶
Re-verify every approval batch signature, every exclusion rule's create/revoke
signature, every rejection's signature, the UID→identity registry, and the full
audit-log hash chain, in one pass through the daemon. The same check is available
directly as baseline verify-signatures.
Takes no flags.
op approve¶
Approve a host's pending baseline items. The bare form approves every pending
item for one host in a single signed batch. The --matching/--hash form
approves one specific hash for a path that has more than one pending candidate —
the two flags must be given together (supplying one without the other is a
usage error). Requires your identity to have operator (or admin) role and
the host to fall within your scope; an out-of-scope host is refused and audited.
| Argument / flag | Type | Default | Notes |
|---|---|---|---|
<host> |
string | required (positional) | The host whose pending items to approve. Must be in your scope. |
--matching <path> |
string | none | Approve one specific pending path. Must be given with --hash. |
--hash <sha256> |
hex | none | The exact hash to approve for that path. Must be given with --matching. |
# Approve every pending item for web-01:
etminan-verifier op approve web-01
# Approve one specific hash for a path that has two pending candidates:
etminan-verifier op approve web-01 --matching /usr/bin/openssl --hash 3f9a…e1
op reject¶
Reject a specific pending measurement as a confirmed incident — fires the full
alarm path immediately, the same as a run finding. Use the exact --path and
--hash from op review, not from memory.
| Argument / flag | Type | Default | Notes |
|---|---|---|---|
<host> |
string | required (positional) | The host the measurement was seen on. |
--path <p> |
path | required | Exact path from op review. |
--hash <sha256> |
hex | required | Exact hash from op review. |
op exclude¶
Manage exclusion rules: paths (or trailing-* glob prefixes) that should never
generate a pending-review entry — for paths expected to churn with no
security-relevant content. create and revoke are admin; list is a read.
etminan-verifier op exclude create --path <p> --reason <r> [--host <h>] [--confirm yes]
etminan-verifier op exclude revoke --id <n> --reason <r>
etminan-verifier op exclude list
| Sub-action | Flag | Type | Default | Notes |
|---|---|---|---|---|
create |
--path <p> |
string | required | Exact path, or trailing-* prefix (a plain string prefix — /etc* also matches /etcxyz; write /etc/*). |
create |
--reason <r> |
string | required | Signed, audited. |
create |
--host <h> |
string | all hosts | Scope the rule to one host; omit for a global (every-host) rule. |
create |
--confirm yes |
literal | required when --path ends in * |
Confirms after a preview of how many approved measurements the glob would affect. |
revoke |
--id <n> |
integer | required | Rule id from exclude list. |
revoke |
--reason <r> |
string | required | Revoking re-exposes what the rule hid — as consequential as creating it. |
list |
(none) | Show every rule with its scope. |
etminan-verifier op exclude create --path '/var/log/*' --confirm yes \
--host web-01 --reason "rotating logs, no security content"
etminan-verifier op exclude list
etminan-verifier op exclude revoke --id 7 --reason "log dir now security-relevant"
op assign-profile¶
Push a watched-path profile selection (never the profile's contents, which
stay local to the agent) to an enrolled host over its existing mTLS channel. Only
recorded locally if the agent acknowledges it took effect. The named profile must
already exist in that host's profiles.conf.
| Argument / flag | Type | Default | Notes |
|---|---|---|---|
<host> |
string | required (positional) | The enrolled host to reassign. |
--profile <name> |
string | required | Must already exist in that host's profiles.conf. |
op rotate-tls¶
Re-pin a host's TLS certificate fingerprint after its agent-side keypair is
regenerated (etminan-agent keygen-tls), without a full re-enrollment. Requires
the host's AK fingerprint to still match and continues the PCR 10 replay from the
stored cumulative value. AK trust and the approved baseline are untouched.
| Argument / flag | Type | Default | Notes |
|---|---|---|---|
<host> |
string | required (positional) | The host whose agent TLS keypair changed. |
--reason <why> |
string | required | Signed, audited action. |
Rotating the verifier's own certificate
That is a manual procedure, not this subcommand: run keygen-tls
again, update ETMINAN_VERIFIER_CERT_FINGERPRINT in every agent's agent.env,
then restart each agent — in that order.
op rotate-ak¶
Re-bind a host's attestation key (AK) to a new one within the same TPM, without a full re-enrollment (baseline, TLS pin, PCR replay state preserved). A fresh EK credential-activation ceremony proves the new AK resides in the same TPM as the EK on record; a different EK means a different TPM and is refused (that's a deliberate re-enroll). Use after a TPM owner-clear/firmware change or a precautionary rotation.
| Argument / flag | Type | Default | Notes |
|---|---|---|---|
<host> |
string | required (positional) | The host whose AK changed. |
--reason <why> |
string | required | Signed, audited action. |
--ek-roots <dir> |
path | none | Also re-verify the manufacturer EK-cert chain, same as op enroll --ek-roots. |
op identity¶
Manage the UID→identity registry the daemon enforces. list is readable by any
mapped identity; add and revoke are admin-only. This registry lives in
baseline.db and is the model that replaces per-operator key files.
etminan-verifier op identity list
etminan-verifier op identity add --uid <n> --role <admin|operator|viewer> --scope <host-globs> --label <name>
etminan-verifier op identity revoke --uid <n>
| Sub-action | Flag | Type | Default | Notes |
|---|---|---|---|---|
list |
(none) | Every mapping: UID, role, scope, label. | ||
add |
--uid <n> |
integer | required | The kernel UID to map. |
add |
--role <r> |
string | required | admin, operator, or viewer. |
add |
--scope <host-globs> |
string | required | Restrict the identity to a host group (comma-separated globs, e.g. region-a-*). Must be explicit — an omitted scope is refused, never silently fleet-wide. Use --scope '*' to deliberately grant every host. |
add |
--label <name> |
string | required | Human label; appears in audit rows as operator:<label>. |
revoke |
--uid <n> |
integer | required | The UID mapping to remove. |
etminan-verifier op identity list
etminan-verifier op identity add --uid 1007 --role operator \
--scope 'region-a-*' --label bob
etminan-verifier op identity revoke --uid 1007
--scope is mandatory
identity add refuses an omitted or empty --scope — the one field that
bounds a scoped operator's blast radius must never fail open to the widest
value. Pass a real host-group scope, or --scope '*' to knowingly grant every
host.
op bootstrap¶
One-time genesis: seed the first admin identity so the registry has an
owner. Must be run as root on the verifier host, and only when no admin
identity exists yet; the action is recorded in the audit log. After this, further
identities are added with op identity add.
| Flag | Type | Default | Notes |
|---|---|---|---|
--uid <n> |
integer | required | The UID to install as the first admin. |
--label <name> |
string | required | Human label for that admin identity. |
Development-only insecure bootstrap
ETMINAN_VERIFIERD_ALLOW_INSECURE_BOOTSTRAP relaxes the bootstrap
preconditions for DEV/TEST only and must never be set in production. See
Verifier configuration.
op totp-policy¶
Set, per role, whether an authenticated session requires a TOTP second factor.
Optional (RFC 6238), off by default, and admin only. When a role is set
--required true, its members must present --code at op login
(after enrolling their factor with op enroll-totp).
| Flag | Type | Default | Notes |
|---|---|---|---|
--role <r> |
string | required | The role whose policy to set. |
--required <bool> |
boolean | required | true/yes/on/1 to require TOTP for that role, false/no/off/0 to relax it. |
op dual-control-policy¶
Enterprise edition
Optional four-eyes / separation-of-duties approval, off by default and
present only in the Enterprise build. When enabled for the
baseline-approve action, an op approve records a PENDING
request over the exact payload, and a second, distinct authorized operator
must co-sign the same payload before it applies. The policy itself is a signed,
latched value stored in the daemon; changing it is itself four-eyes — a
second admin must co-sign the change before it takes effect.
show prints the effective policy (which actions require four-eyes, and the
threshold). set is admin-only and changes the latch.
etminan-verifier op dual-control-policy show
etminan-verifier op dual-control-policy set --actions baseline-approve [--threshold <n>] --reason <r>
| Sub-action | Flag | Type | Default | Notes |
|---|---|---|---|---|
show |
(none) | Print the current latched policy, or that none is set. | ||
set |
--actions <a> |
string | required | The action token(s) to require four-eyes on. baseline-approve is the only supported token in this release; off/none/empty disables. |
set |
--threshold <n> |
integer | 2 |
Distinct approvers required (M-of-N); clamped up to a floor of 2. |
set |
--reason <r> |
string | required | Signed, audited. |
etminan-verifier op dual-control-policy show
etminan-verifier op dual-control-policy set --actions baseline-approve --threshold 2 \
--reason "enforce four-eyes on baseline approvals"
op ping¶
Liveness probe: confirm the daemon socket is present and answering. Prints pong
and exits 0 on success; a non-zero exit means the daemon is down or the socket is
unreachable (and, because the model is fail-closed, that every trust-changing op
call would currently be refused).
Takes no flags.
Setup keys¶
Run these once when standing up a verifier device. The two keys are
deliberately separate — the mTLS transport identity (keygen-tls) and the
off-host plugin-catalog signing key (keygen-catalog) — so rotating one never
rotates the other. (The operator signing key is held by the daemon, not generated
here; there is no operator-key CLI.)
| Command | Purpose |
|---|---|
keygen-tls |
Create this verifier's own mTLS identity and print its SHA-256 fingerprint. |
keygen-catalog |
Off-host, run-once: the dedicated plugin-catalog signing keypair. |
keygen-tls¶
Generate this verifier's own self-signed mTLS keypair under $ETMINAN_TLS_DIR
(default /var/lib/etminan-verifier/tls) and print its SHA-256 fingerprint. Copy
that fingerprint into ETMINAN_VERIFIER_CERT_FINGERPRINT in every agent's
agent.env. Run once per verifier device, before its first op enroll or run.
Takes no flags.
Generated verifier TLS keypair at /var/lib/etminan-verifier/tls
Fingerprint (sha256): 4d1e…c0ffee
Copy this fingerprint into ETMINAN_VERIFIER_CERT_FINGERPRINT in every agent.env …
keygen-catalog¶
Generate the dedicated single-purpose Ed25519 keypair a real plugin-catalog release would be signed with — deliberately not the same key that signs operator actions and not the GPG release key. Run once, offline, wherever catalog releases are built — never on a verifier host.
| Flag | Type | Default | Notes |
|---|---|---|---|
--out <path> |
path | required | Private key (mode 0600). Replace CATALOG_VERIFYING_KEY_HEX in verifier/src/plugin_catalog.rs with the printed public key, then rebuild. |
Hosts¶
The read/attest side of host monitoring. Enrolling, rotating keys, and assigning
profiles are trust-changing and live under op
(op enroll, op rotate-tls, op rotate-ak, op assign-profile). The two
commands here take no key and make no trust change.
| Command | Purpose |
|---|---|
check |
Check one enrolled host now, interactively. |
run |
Check every host + plugins + audit chain and fire alarms (the scheduled job). |
check¶
Check one enrolled host interactively: fresh quote, verify signature and AK
fingerprint against the enrollment record, replay the IMA log against the signed
PCR digest, and diff new measurements against the approved baseline. Prints
FINDING (<kind>): … and exits 1 if anything failed — an unreachable host is
itself a finding, not a soft skip. (Also available as op check.)
| Flag | Type | Default | Notes |
|---|---|---|---|
--host <id> |
string | required | The enrolled host to check. |
--addr <ip:port> |
socket addr | required | Where its agent is listening. |
run¶
The scheduled entry point (what etminan-verifier.timer calls hourly). Runs
check against every enrolled host in one pass, fires the full alarm path (local
structured log, audit log, email, notify-plugin channels) for anything that
failed, and exits non-zero if any host produced a finding or a plugin failed
verification. Also verifies every configured change-source/notify plugin (same as
plugins verify) and the audit-log hash chain (same as
baseline verify-signatures) every cycle.
Takes no flags.
Baseline & drift review¶
The read side of baseline handling. Drift is always proposed, never
auto-accepted. Approving, rejecting, and excluding are trust-changing and live
under op (op approve, op reject, op exclude); the
two commands here are read-only and take no key.
| Action | Purpose |
|---|---|
baseline review |
List pending (new/changed, unapproved) measurements. |
baseline verify-signatures |
Re-verify every signed row + the audit chain in one pass. |
baseline review¶
List every pending measurement, optionally filtered to one host. Each entry
prints a plain-language ownership verdict, a change-source-correlation line (if
configured), a package trust line (if a package match exists), and the raw
sha256/owner/size/mtime detail. Entries older than
ETMINAN_PENDING_REVIEW_SLA_HOURS (default 24) are marked [SLA EXCEEDED].
(Also available as op review.)
| Flag | Type | Default | Notes |
|---|---|---|---|
--host <id> |
string | all hosts | Restrict to one host. |
baseline verify-signatures¶
Re-check every approval batch's signature, every exclusion rule's create/revoke
signature, every rejection's signature, and the full audit-log hash chain, in one
pass. A row written before signing existed for its action is reported as
"unsigned, predates this feature", not a failure. Exits non-zero if anything
fails. (Also available as op verify-signatures, which
additionally checks the identity registry.)
Takes no flags.
Plugins¶
The certified change-source / notify plugin catalog. Installed plugins are held to the same verify-then-exec bar (root-owned, not group/world-writable, content hash matches) whether hand-installed or catalog-installed.
Run etminan-verifier plugins <action> --help for one action's detail.
| Action | Purpose |
|---|---|
plugins verify |
Check every configured change-source/notify plugin (allowlisted + verifies), without executing it. |
plugins list |
Fetch + verify the certified catalog; show each entry's install status. |
plugins install <name> |
Download, re-verify, and allowlist a catalog plugin. |
plugins update <name> |
Re-pin an installed plugin to the catalog's current version. |
plugins verify¶
Check every plugin referenced by ETMINAN_CHANGE_SOURCES or
ETMINAN_NOTIFY_CHANNELS is allowlisted and passes verification, without running
it. Exits non-zero and prints exactly what's wrong on any failure. (This same
check runs automatically, silently on success, at the start of every run.)
Takes no flags.
plugins list¶
Fetch and verify the certified catalog (signature checked against the compiled-in trust anchor first), then print every entry with its install status: not installed / installed and up to date / installed with an update available. Never modifies anything.
Takes no flags.
plugins install¶
Download a certified catalog entry, re-verify its content hash against the
catalog's pinned value, write it under /etc/etminan-verifier/<type>-plugins/,
and append the matching allowlist entry. Must run as root. Does not add the
plugin to ETMINAN_NOTIFY_CHANNELS/ETMINAN_CHANGE_SOURCES — it prints the exact
line to add and a reminder to restart the service.
| Argument | Type | Default | Notes |
|---|---|---|---|
<name> |
string | required | Must appear in plugins list. Refuses if already installed (use plugins update). |
plugins update¶
Re-fetch and re-verify the catalog; if the pinned hash for <name> changed,
download the new content, re-hash it, and re-pin the allowlist entry. Never
automatic — runs only when you run it.
| Argument | Type | Default | Notes |
|---|---|---|---|
<name> |
string | required | Must already be installed (use plugins install first). |
Notifications¶
Preview and test the notification path without waiting for a real finding.
| Command | Purpose |
|---|---|
notify-preview |
Render current templates against sample findings (sends nothing). |
notify-test |
Send one synthetic finding through a channel's real plugin. |
notify-preview¶
Render four representative fake findings through whatever
_TEMPLATE/_FORMAT/_SEVERITIES is configured, and print the result: the full
email (subject + body) and, per channel, the raw JSON payload the channel's
plugin would receive on stdin. Never executes a plugin, never calls sendmail —
safe any time, even against a channel not yet allowlisted.
| Flag | Type | Default | Notes |
|---|---|---|---|
--channel <name> |
string | every channel in ETMINAN_NOTIFY_CHANNELS |
Preview just one channel. |
notify-test¶
Send one synthetic test finding through <name>'s real plugin invocation —
the same verify-then-exec path a live run uses — and report the plugin's actual
exit status and any stderr. Deliberately ignores that channel's configured
_SEVERITIES filter.
| Flag | Type | Default | Notes |
|---|---|---|---|
--channel <name> |
string | required | Must already be allowlisted. |
Diagnostics¶
| Command | Purpose |
|---|---|
version |
Print the version and exit (also --version, -V). |
version¶
Takes no flags. Prints etminan-verifier <version> and exits 0.
etminan-verifierd¶
The trust daemon. It is the sole owner of the verifier's trust-changing
actions and of the one Ed25519 signing key; the op
commands are thin clients that connect to its Unix socket. It runs on the verifier
host as a long-lived service (etminan-verifierd.service) and is configured
entirely through ETMINAN_* environment variables — it takes no subcommands.
Takes no flags. Started by systemd; sources the same
/etc/etminan-verifier/verifier.env (or a daemon drop-in) as the rest of the
tool.
On start it opens the baseline DB, loads (or, on first run, expects) its signing
key, and binds the peer-credentialed socket. It then authenticates each op
client by SO_PEERCRED UID, maps the UID to a registered identity, enforces
default-deny/fail-closed authorization, signs authorized actions as
operator:<label>, and records every decision — allow and deny — on the
hash-chained audit log.
| Variable | Default | Purpose |
|---|---|---|
ETMINAN_VERIFIERD_SOCKET |
/run/etminan-verifierd/etminan-verifierd.sock |
The Unix socket op clients connect to; peer-UID is read from it. |
ETMINAN_VERIFIERD_DB |
/var/lib/etminan-verifier/baseline.db |
The baseline DB, which also holds the UID→identity registry and audit log. |
ETMINAN_VERIFIERD_KEY |
/var/lib/etminan-verifier/daemon-signing.key |
The only Ed25519 signing key; the daemon signs operator actions with it (mode 0600). |
ETMINAN_TOTP_SESSION_TTL_SECS |
28800 (8h) |
How long an op login TOTP session stays valid. |
ETMINAN_VERIFIERD_ALLOW_INSECURE_BOOTSTRAP |
(unset) | DEV/TEST ONLY — relaxes op bootstrap preconditions. Never set in production. |
[Service]
Type=notify
User=etminan-verifier
Group=etminan-verifier
WorkingDirectory=/var/lib/etminan-verifier
EnvironmentFile=-/etc/etminan-verifier/verifier.env
ExecStart=/usr/bin/etminan-verifierd
RuntimeDirectory=etminan-verifierd
NoNewPrivileges=true
See Verifier configuration for standing the daemon up and bootstrapping the first admin.
etminan-agent¶
The agent is a relay: with no subcommand it starts the long-running
attestation daemon. It never decides what is trustworthy — it only produces
signed, verifiable evidence; every judgment is made by etminan-verifier on a
separate device. The handful of subcommands are one-shot setup. The agent
requires a real TPM and is Linux-only.
| Invocation | Purpose |
|---|---|
etminan-agent |
Start the long-running daemon. |
etminan-agent write-ima-policy |
Write this host's IMA measurement policy, then exit. |
etminan-agent keygen-tls |
Create the agent's mTLS identity and print its fingerprint. |
etminan-agent version |
Print the version and exit (also --version, -V). |
etminan-agent (daemon — no subcommand)¶
Start the long-running daemon: listen for mutual-TLS connections from
etminan-verifier and, on request, take a TPM quote over PCR 10, read the IMA
measurement-log delta from the last consumed offset, and return both together so
the verifier can prove they describe the same boot state.
Takes no flags — configured entirely through ETMINAN_* environment variables
(see Configuration / man etminan-agent). Key variables:
ETMINAN_AGENT_LISTEN (default 0.0.0.0:7620), ETMINAN_VERIFIER_CERT_FINGERPRINT
(the pinned verifier fingerprint — required unless
ETMINAN_ALLOW_PERMISSIVE_TLS=1 is set for the one-time enrollment bootstrap),
ETMINAN_TLS_DIR, ETMINAN_IMA_LOG_PATH, ETMINAN_WATCHED_PATHS / ETMINAN_PROFILE.
Fail-closed transport
The daemon refuses to start if ETMINAN_VERIFIER_CERT_FINGERPRINT is
unset and ETMINAN_ALLOW_PERMISSIVE_TLS is not enabled. Permissive mode
(accept any client cert) is an explicit opt-in for enrollment only; in it the
agent serves only the enrollment quote (without advancing the IMA-log cursor)
and refuses SetProfile/PackageLookup.
# Normal operation (systemd sources agent.env):
etminan-agent
# One-time enrollment bootstrap:
ETMINAN_ALLOW_PERMISSIVE_TLS=1 etminan-agent
etminan-agent write-ima-policy¶
Write this host's IMA measurement policy to /sys/kernel/security/ima/policy (or
ETMINAN_IMA_POLICY_PATH if set) and exit. Meant to run once, early at boot,
before the daemon starts — see etminan-agent-ima-policy.service. Idempotent:
a policy already active this boot is treated as success — either the write node's
open fails outright (it can disappear from securityfs once loaded) or the write
itself is rejected — as long as measurements are already flowing.
Takes no flags.
etminan-agent keygen-tls¶
Generate the agent's own self-signed mTLS keypair under $ETMINAN_TLS_DIR
(default /var/lib/etminan-agent/tls) and print its SHA-256 fingerprint. Give
that fingerprint to the verifier operator to confirm during op enroll, where
it's pinned alongside the AK fingerprint. Run once per host, before its first
connection from a verifier.
Takes no flags.
Generated agent TLS keypair at /var/lib/etminan-agent/tls
Fingerprint (sha256): a1b2…f9
Give this fingerprint to the verifier operator to confirm during `etminan-verifier enroll` …
etminan-agent version¶
Takes no flags. Prints etminan-agent <version> and exits 0.
See also¶
- Configuration reference — every
ETMINAN_*environment variable. - Verifier configuration — standing up
etminan-verifierdand bootstrapping the first admin. - RBAC — the daemon's
admin/operator/viewerroles, scope, and TOTP. - Editions — the daemon/RBAC are Standard; what Enterprise adds.
- Audit log — where every signed action (and every deny) lands.
- Troubleshooting — diagnosing a refused
opcall or a failedrun. man etminan-verifier,man etminan-verifierd,man etminan-agent— the deepest per-variable references.