Troubleshooting tessera
A single diagnostics reference. Sections:
- §1 Cert/auth errors
- §2 USB and tokens
- §3 monitord and daemon
- §4 PAM stack and lockout
- §5 Mandatory integrity control (МКЦ)
- §6 fly-dm and greeter
- §7 Clone-image / golden image
- §8 Security incidents
- §9 Backup / recovery
- §10 Installation /
gost-engine
For each case: symptom → diagnosis → fix. The logging commands are universal:
sudo journalctl -u tessera --since '5 min ago'sudo journalctl -t pam_tessera | tail -50sudo tail -f /var/log/auth.log1. Cert/auth errors
Section titled “1. Cert/auth errors”host_binding mismatch
Section titled “host_binding mismatch”Symptom: PAM denies with HostNotAllowed or
HostExtensionMissing. On the banner (TTY/sshd/sudo):
Сертификат выпущен для другого устройства.host_id этой машины: <8-hex-префикс> (source=DmiBoardSerial)Передайте администратору для перевыпуска.(English: “This certificate was issued for a different device. host_id of this machine: <8-hex-prefix> (source=DmiBoardSerial). Hand it to your administrator for re-issuance.”)
(The full host_id_hash is in syslog; the screen shows the 8-character
prefix.)
Diagnosis:
# What each configured host_identity source returnedsudo journalctl -t pam_tessera | grep 'host_identity: probe' | tail -20# probe ok source=MachineId raw=abc... host_id_hash_prefix=a1b2c3d4 host_id_hash=<full sha256 hex># probe error source=DmiBoardSerial error="ENOENT"# probe selected source=MachineId (first successful) host_id_hash_prefix=a1b2c3d4
# What is baked into the certificateopenssl x509 -in /etc/tessera/<host>.pem -noout -text \ | grep -A1 '2\.25\.183976554325829274683049824615098'Fix: re-issue the cert with the CA tool using the correct
host_id_hash. Do NOT compute the hash by hand with
sha256sum /etc/machine-id — the source of truth is determined by the
deployed [host_identity].sources. See
architecture.md.
A role outside allowed_roles
Section titled “A role outside allowed_roles”Symptom: the cert chain is valid, but a login into a specific role account is rejected: the requested role (which is also the login account name) is not covered by the credential.
Diagnosis:
openssl x509 -in /tmp/ca/serv.pem -noout -text \ | grep -A1 '2\.25\.185305973969816596290730578528098241367'Fix: re-issue the credential with the required role in
pam_cert_allowed_roles. There is no separate list of permitted
accounts: the login account name IS the role, so this list decides
admission as well.
Authentication failed (PAM_AUTH_ERR) immediately
Section titled “Authentication failed (PAM_AUTH_ERR) immediately”Symptom: pamtester denies immediately, with no delay.
Diagnosis:
sudo tail -f /var/log/auth.log &pamtester sudo alice authenticateIn the log (ident pam_tessera) look for the line tessera.auth: authentication failed — the denial category is in the error=… field.
Role denials go separately, under the role.audit target: a role_deny
event with a reason=… field (not_found / not_covered /
backend_unavailable / mask_exceeds_ceiling / syntax /
system_account). The list of
reasons is in architecture.md.
Certificate not accepted on the terminal (general checklist)
Section titled “Certificate not accepted on the terminal (general checklist)”PAM prints a PAM_TEXT_INFO on screen with diagnostics for a
host_binding mismatch and a wrong PIN. Check the screen and syslog:
# The real host_id_hash of this machinesudo journalctl -t pam_tessera | grep 'host_id resolved' | tail -1
# Step-by-step trace (mount → discovery → envelope → chain → result)sudo journalctl -t pam_tessera --since '5 min ago' \ | grep -E 'tessera\.(flow|host_identity)'Cross-check against the issuance registry (host-registry.tsv on the
admin machine):
host_id_hashin the log ≠ the value in the cert → the cert was issued for a different workstation. Re-issue it.- No
host_id resolvedin the log → the resolver did not run. Check[host_identity].sourcesinconfig.toml. PAM_TEXT_INFO«Пароль .p12 неверный. Этот сертификат выпущен для host_id_hash=…, пользователь=…» (English: “The .p12 password is wrong. This certificate was issued for host_id_hash=…, user=…”) → the engineer inserted another engineer’s USB stick. If the cert is encoded in the legacy format, the message is the shorter «Пароль .p12 неверный»; read it on the admin machine:
openssl pkcs12 -in service.p12 -nokeys -nomacver -passin pass: \ | openssl x509 -noout -text[trust.revocation] mode = "ocsp" — config won’t load
Section titled “[trust.revocation] mode = "ocsp" — config won’t load”Symptom: the daemon/module fails to load its config with
mode = "ocsp" / mode = "crl_then_ocsp".
Cause: OCSP modes require ocsp_responder_url — without it, config
validation rejects the section (fail-closed). Also check the
ocsp_timeout_seconds / ocsp_cache_ttl_seconds ranges.
Fix: set ocsp_responder_url; for zero-egress environments
(terminals with no network path to the responder) OCSP is not suitable —
use mode = "crl" with a regularly refreshed local CRL and freshness
control via crl_max_age_hours, or mode = "none" with a short-TTL
discipline. See
configuration.md.
2. USB and tokens
Section titled “2. USB and tokens”usb medium not found after waiting
Section titled “usb medium not found after waiting”Symptom: pamtester waits ~10 s, then usb medium not found.
Fix: check with lsblk that the USB is mounted and visible. For a
larger window, increase usb_wait_seconds in config.toml (see
configuration.md).
The PKCS#11 token is not visible (pcscd not running)
Section titled “The PKCS#11 token is not visible (pcscd not running)”Symptom: the PKCS#11 token (Rutoken) is not visible in
pkcs11-tool -L.
sudo systemctl enable --now pcscdsudo systemctl status pcscdpcsc_scan # should show the inserted tokenToken PIN locked
Section titled “Token PIN locked”Symptom: pkcs11-tool returns CKR_PIN_LOCKED.
Fix: unlock with the SO-PIN, re-initialize the user PIN via
pkcs11-tool --init-pin.
Silence in the logs while probing partitions on a multi-partition USB
Section titled “Silence in the logs while probing partitions on a multi-partition USB”Symptom: on a Ventoy / multi-partition USB, 10–30 s pass between
trying USB candidate and the module finishing. Duration = number of
partitions × the mount timeout.
Diagnosis: on 0.4.0 each candidate is logged step by step (INFO
tessera.flow):
INFO tessera.flow: trying USB candidate devnode="/dev/sdb1" ...INFO tessera.flow: candidate mounted devnode="/dev/sdb1" mountpoint=...INFO tessera.flow: no .p12 on this partition, trying next mountpoint=... missing=...INFO tessera.flow: trying USB candidate devnode="/dev/sdb2" ...If there are no per-candidate lines in the logs at all — the build is older than 0.3.6 (which added the step-by-step logging); upgrade.
USB token blocked by USBGuard or the closed software environment (ЗПС)
Section titled “USB token blocked by USBGuard or the closed software environment (ЗПС)”Symptom: auth fails with AUTHINFO_UNAVAIL right after insertion:
tessera: WARN tessera.flow: usb device found ...tessera: WARN tessera.auth: authentication failed error=mount: mount(2) failed: Operation not permittedDiagnosis:
# USBGuardsudo usbguard list-devices # "block" column → the token is blockedsudo usbguard list-rulesjournalctl -u usbguard.service -n 30 --no-pager
# ЗПСsudo astra-digsig-control status # "ВКЛЮЧЕНО"/"НЕАКТИВНО" (ENABLED / INACTIVE)sudo dmesg | grep -i digsig | tailFix — USBGuard:
sudo usbguard append-rule \ 'allow id 0aca:1234 name "Rutoken ECP" hash "ABC..."'# or add the rule to /etc/usbguard/rules.conf:sudo systemctl restart usbguardTo keep the daemon from starting before USBGuard:
sudo mkdir -p /etc/systemd/system/tessera.service.dsudo tee /etc/systemd/system/tessera.service.d/usbguard.conf <<EOF[Unit]After=usbguard.serviceWants=usbguard.serviceEOFsudo systemctl daemon-reloadFix — ЗПС: see §10 below.
USB token lost / blocked — the user can’t log in
Section titled “USB token lost / blocked — the user can’t log in”By design. tessera is a hard second factor: without a valid token
carrying the right extensions, the user will not pass the PAM stack
the module is integrated into. There is no alternative auth path.
BEFORE the first rollout, the admin must:
- Keep a local root shell with
tesseradisabled, or a sudoers rule for the admin that skips the second factor — otherwise losing the single token takes the machine out of service. - Prepare backup certificates: two physical USB sticks per
privileged user, both signed by the CA, both with the same
pam_cert_allowed_roles. - Document the SLA for re-issuing a lost cert.
What happens if the token is lost:
- Every auth attempt →
PAM_AUTHINFO_UNAVAILafterusb_wait_seconds. monitordruns but registers no active sessions —on_usb_removedwon’t fire.
When blocked by USBGuard / ЗПС: the same, plus error lines in
auth.log. Keep an admin channel (SSH key-only auth without the
tessera chain) until the deployment is validated.
3. monitord and daemon
Section titled “3. monitord and daemon”monitord not reachable or won’t start
Section titled “monitord not reachable or won’t start”Symptoms (one case, two facets):
- PAM denies with
monitord unavailableor hangs — the daemon is formally alive, but the IPC socket is unreachable; systemctl status tesserashowsfailed— the daemon doesn’t come up at all.
Diagnosis:
sudo systemctl status tesserasudo journalctl -xeu tessera -n 200sudo ls -la /run/tessera/lsof /run/tessera/monitord.sock # is the socket in useopenssl engine gost -t # is gost-engine availableTypical causes:
- the
/run/tessera/monitord.socksocket wasn’t created or is in use → checkRuntimeDirectory=tesserain the unit andlsofon the socket; - permissions on
/run/tessera/are wrong → should bedrwxr-x--- tessera tessera(0750). The directory, its owner (User=tessera/Group=tessera), and the mode (RuntimeDirectoryMode=0750) are created by the unit itself at startup — fix it withsudo systemctl restart tessera, not a manualchown/chmod; config.tomlis corrupted → run validation without starting the daemon:sudo /usr/bin/tessera check(or run the daemon in the foregroundsudo /usr/bin/tessera daemon --config /etc/tessera/config.tomland read the diagnostic output);gost-engineis missing →openssl engine gost -twithout the[ available ]marker.
4. PAM stack and lockout
Section titled “4. PAM stack and lockout”Lockout after a failed PAM edit
Section titled “Lockout after a failed PAM edit”Symptom: no user can log in, not even the root shell.
Recovery:
- Reboot into single-user mode: on GRUB, append
systemd.unit=rescue.target init=/bin/bashto the kernel line. - Remount
/read-write:mount -o remount,rw /. - Roll back
/etc/pam.d/*from the*.bak.<TS>backups:Terminal window ls /etc/pam.d/*.bak.* | tailcp /etc/pam.d/sudo.bak.20260501T103000Z /etc/pam.d/sudo systemctl reboot.
tessera in /etc/pam.d/login is not found
Section titled “tessera in /etc/pam.d/login is not found”Symptom: after editing, login denies with Module is unknown or
won’t start.
ls -la /lib/security/pam_tessera.sotest -f /lib/security/pam_tessera.so && echo "module installed"sudo ldd /lib/security/pam_tessera.so | grep -i 'not found'not found→ a missing dependency (libparsec-mic.so.3on older builds). Upgrade to 0.3.7+ — it hascargo:rustc-link-lib=parsec-micinbuild.rs.- File missing →
dpkg -l tessera. Possibly an interrupted install →sudo dpkg --configure -a.
Logout requested but session has no logind id
Section titled “Logout requested but session has no logind id”Symptom (0.3.10+): USB removal is detected correctly in journald
(grace window expired, dispatching action), but logout doesn’t
happen:
ERROR tessera.monitord: ALERT: USB-removal Logout has no logind id; failing closed with reboot ...Cause: at pam_sm_open_session time, XDG_SESSION_ID was not in the
PAM environment — the monitord entry was left with a placeholder target
(Tty / Display / Unknown) captured during the auth phase. The
action-runner can’t call terminate_session without a logind id.
Action-runner fail-closed (0.4.0):
| Configuration | Without a logind id |
|---|---|
action = "lock" | Fail-closed: reboot the device (ALERT in the log) |
action = "logout" | Fail-closed: reboot the device (ALERT in the log) |
action = "shutdown" | Fires — power_off doesn’t need logind |
action = "hook" | Fires — the hook receives the SESSION_ID env |
A session with no logind id can’t be terminated by address, so instead of silently dropping it, the action degrades to a reboot — the media is removed, and an open session is unacceptable.
Cause 1 (typical): the session ... pam_tessera.so line is above
@include common-session (which has pam_systemd.so), so
sm_open_session fires before pam_systemd and XDG_SESSION_ID isn’t
created yet. integrate-pam.sh places the session line AFTER
@include common-session; the daemon fails to start with
ERROR pam_stack_session_misorder if the order is wrong.
Check:
sudo tessera check 2>&1 | grep pam_stack_session# OR:sudo grep -nE 'session.*(pam_systemd|tessera)|@include[[:space:]]+(common-session|tessera)' \ /etc/pam.d/login /etc/pam.d/fly-dmFix — re-integrate with the 0.3.12+ script:
sudo /usr/share/tessera/integrate-pam.sh --unintegrate /etc/pam.d/loginsudo /usr/share/tessera/integrate-pam.sh --mode=<your-mode> /etc/pam.d/loginsudo systemctl restart tesseraCause 2: pam_systemd.so is missing from the service’s session
phase. The startup check emits INFO pam_stack_session_no_systemd. Fix —
restore the stock template with dpkg-reconfigure libpam-runtime, then
run integrate-pam.sh.
Cause 3: a console session without systemd (sysvinit, OpenRC).
pam_systemd isn’t loaded, and XDG_SESSION_ID is physically never
created. Until a TTY-based logout fallback is implemented:
[on_usb_removed].action = "shutdown"(blunt, but works);- or
"hook"with a script —pkill -KILL -u <pam_user>/chvt 1; - or enable systemd on the host.
Verify the fix:
sudo journalctl -u tessera -f# 1. Log in. The daemon should update the session target from the# placeholder (Tty/Display/Unknown) to LogindSession:# INFO tessera.monitord: session target updated session_id=… new_target=LogindSession { id: "…" }# 2. Confirm the session is visible to logind:# loginctl list-sessions# 3. Remove the USB and wait for action dispatch WITHOUT a reboot:# INFO tessera.monitord: grace window expired, dispatching action serial=…# An ALERT line "failing closed with reboot" means the logind id is# still not captured — the PAM stack order isn't fixed.5. Mandatory integrity control (МКЦ, Astra strict-mode)
Section titled “5. Mandatory integrity control (МКЦ, Astra strict-mode)”Mandatory integrity control (МКЦ) is a Biba-family integrity control on Astra; below it is referred to as МКЦ.
pam_parsec_mac(login:account): Can't obtain required data
Section titled “pam_parsec_mac(login:account): Can't obtain required data”Symptom: tessera ran successfully, but a few seconds later
pam_parsec_mac fails login in the account phase:
pam_parsec_mac(login:account): Can't obtain required data.Did you forget add pam_parsec_mac to "auth" stack?pam_parsec_mac.so stores PAM data across phases: the auth instance
writes, account/session read. This appears when the auth instance did
not run, even though it is formally present in the file.
Cause 1 (most common, integrate-pam.sh < 0.3.8): our
@include tessera-only ended up BEFORE auth required pam_parsec_mac.so. tessera-only uses
auth [success=done default=die] pam_tessera.so — success=done
short-circuits the auth stack on success, so pam_parsec_mac never gets
to store its data in auth.
Check:
sudo grep -n -E 'tessera|parsec_mac' /etc/pam.d/login /etc/pam.d/fly-dmIf the line number of @include tessera* is lower than that of
auth ... pam_parsec_mac.so, that’s it.
Fix:
# integrate-pam.sh >= 0.3.8 orders it correctly on its ownsudo /usr/share/tessera/integrate-pam.sh --unintegrate /etc/pam.d/loginsudo /usr/share/tessera/integrate-pam.sh --mode=cert-only /etc/pam.d/login# repeat for fly-dmCause 2: the МКЦ kernel is off (parsec.mac=0 in GRUB), but
pam_parsec_mac.so is in /etc/pam.d/login. The module has no MAC data —
account fails. See the next case.
Cause 3: the МКЦ kernel is on, but service has no MAC level.
sudo /sbin/pdpl-user servicesudo ls /etc/parsec/macdb/$(id -u service)If pdpl-user shows only 0:0:0x0:0x0 with no entry under
/etc/parsec/macdb/<uid>:
sudo /sbin/pdpl-user --ilevel 63 servicesudo systemctl restart fly-dmCause 4: separate pamtester (or any other PAM client) calls for
auth and for session instead of a single transaction. The order of
lines in /etc/pam.d/* is entirely correct in this case —
pam_parsec_mac.so stores data via pam_set_data() in the auth
instance and reads it via pam_get_data() in the account/session
instance, but that API is tied to a specific pamh: two separate
pamtester invocations are two separate processes and two independent
pam_start()/pam_end() calls, so the second physically cannot see
what the first one stored. The symptom reads identically to Cause 1
(the same Can't obtain required data), but the fix is a command, not
a file edit:
# wrong — three separate PAM transactions:pamtester login serv authenticatepamtester login serv acct_mgmt
# right — one transaction for the whole cycle:pamtester login serv authenticate acct_mgmt open_session close_sessionIf the grep from Cause 1 showed the correct line order and the error
is still there, check whether the run was split across several
separate pamtester invocations before suspecting the МКЦ kernel
(Causes 2–3). Details — pam-integration.md
§9.
parsec.mac=0 + pam_parsec_mac in the stack
Section titled “parsec.mac=0 + pam_parsec_mac in the stack”Symptom: the МКЦ kernel is disabled via GRUB (parsec.mac=0), but
/etc/pam.d/login contains pam_parsec_mac.so in auth/account/session.
The module waits for MAC data that doesn’t exist — login denied.
cat /proc/cmdline | tr ' ' '\n' | grep parseccat /sys/module/parsec/parameters/strict_mode # N = offsudo astra-strictmode-control status # НЕАКТИВНО(A) You need МКЦ — enable the kernel:
GRUB_CMDLINE_LINUX_DEFAULT="... parsec.mac=1 parsec.max_ilev=63 ..."sudo update-grubsudo rebootsudo /sbin/pdpl-user --ilevel 63 service(B) You don’t need МКЦ — remove pam_parsec_mac.so, set
runtime = "disabled":
[mac]runtime = "disabled"cert_integrity = "ignore"for f in /etc/pam.d/login /etc/pam.d/fly-dm; do sudo sed -i.bak 's|^\(\s*\(auth\|account\|session\).*pam_parsec_mac\.so\)|# disabled МКЦ off: \1|' "$f"donesudo systemctl restart tessera fly-dmSee install.md §8.5 — the matrix of PAM stacks with/without МКЦ.
unknown field 'enabled', expected one of ... 'runtime'
Section titled “unknown field 'enabled', expected one of ... 'runtime'”Symptom: the daemon won’t start, TOML parse error:
failed to load monitord config from /etc/tessera/config.toml:unknown field `enabled`, expected one of `cert_integrity`,`fallback_max_integrity`, `warn_on_homedir_label_mismatch`, `runtime`Cause: the legacy [mac].enabled = true field from 0.3.0–0.3.6.
Removed in 0.3.7, replaced by [mac].runtime.
# was[mac]enabled = truecert_integrity = "optional"
# now (for the МКЦ kernel ON)[mac]runtime = "required" # or "auto"cert_integrity = "optional"
# or (for the МКЦ kernel OFF)[mac]runtime = "disabled"cert_integrity = "ignore"WARN mac_caps_missing / pdp_set_fd rc=-1
Section titled “WARN mac_caps_missing / pdp_set_fd rc=-1”Symptom: at daemon startup:
WARN mac.audit: F_event="mac_caps_missing" F_detail="PARSEC_CAP_CHMAC not present in effective set"WARN mac.audit: F_event="mac_sessions_file_label_warning" F_error="parsec error: op=pdp_set_fd rc=-1"Non-blocking. The daemon starts and runs. It means the МКЦ label
could not be set on sessions.json. It doesn’t affect the auth flow.
To clear it (optional):
sudo /sbin/usercaps -m "+3" tesserasudo cp /usr/share/tessera/systemd/mac-integrity.conf.example \ /etc/systemd/system/tessera.service.d/mac-integrity.confsudo systemctl daemon-reloadsudo systemctl restart tesseradmi_board_serial = 0 (VM), hash changes when the VM is rebuilt
Section titled “dmi_board_serial = 0 (VM), hash changes when the VM is rebuilt”Symptom: on VirtualBox/QEMU, /sys/class/dmi/id/board_serial is
empty or 0. The resolver falls back to machine_id, but when the VM is
rebuilt the machine-id can change too → the cert with its embedded hash
stops validating.
cat /sys/class/dmi/id/board_serial # 0 or empty = unusablesudo journalctl -t pam_tessera | grep 'host_identity:' | tail -10For dev/test:
[host_identity]sources = ["override"]fallback = "deny"override = "test-vm-stable-id"In production on physical workstations, dmi_board_serial is usually
valid.
6. fly-dm and greeter
Section titled “6. fly-dm and greeter”fly-dm doesn’t show host_id on the login screen
Section titled “fly-dm doesn’t show host_id on the login screen”Symptom: at login, fly-dm shows no host_id — neither via
PAM_TEXT_INFO nor via the stock «Добро пожаловать в %n» (English:
“Welcome to %n”).
Cause: on Astra with МКЦ-3, the fly-modern theme
(libfly-dm_greet_modern.so) hardcodes «Усиленный уровень
защищенности» (“Hardened security level”) into the headline.
GreetString and PAM messages are ignored.
Fix — wallpaper banner:
[fly_dm_greeter]update_wallpaper = trueIf heavy dimming / blur on the host hides the text:
[background]color_overlay=0,0,0,30
[background][blur]enable=falsesudo systemctl restart tessera # redraws the bannersudo systemctl restart fly-dm # picks up the new JPGFull set of options, baseline, and implementation — fly-dm-greeter.md.
What won’t work (don’t waste your time):
greeter-show-messages = truein/etc/X11/fly-dm/fly-dmrc— a legacy KDM/LightDM key that fly-qdm 2.15+ doesn’t parse./etc/X11/fly-dm/override/GreetString.desktop— on МКЦ-3, fly-modern ignores GreetString, the headline is taken by the МКЦ status.
Wallpaper isn’t updating
Section titled “Wallpaper isn’t updating”- The daemon lacks permission on
wallpaper_target:ls -lthe source. The daemon runs as root, so 0644 is enough. - Any error (including a missing font): WARN
fly-dm wallpaper update failed (continuing)with anerrorfield (targettessera.fly_dm_greeter). For the font, installfonts-dejavu-core. - Text not visible:
color_overlayis too dense, blur is on — see the fix above.
7. Clone-image / golden image
Section titled “7. Clone-image / golden image”dump-host-id: all sources empty
Section titled “dump-host-id: all sources empty”Symptom: the TSV contains only status=err, exit ≠ 0.
Causes:
dmi_board_serial = 0— typical for VMs (KVM/VMware without a SMBIOS override). Fix: SMBIOS strings in the hypervisor, or--sources machine_id.machine_idempty — cleared before cloning, and systemd didn’t generate one on first boot. Fix:systemd-machine-id-setup && systemctl restart tessera.custom_commandexit ≠ 0 — the script’s path/permissions, seereasonin the TSV.
USB doesn’t show up during --usb
Section titled “USB doesn’t show up during --usb”finish-bootstrap.sh / dump-host-id --usb retries for up to 60 s
(polling every 5 s). If the stick isn’t detected:
- run
lsblkin parallel; - an FS from the allowlist (
vfat/exfat/ext4/ntfs); - use the fallback under
/var/lib/tessera/.
active_under_current_config=no for every row
Section titled “active_under_current_config=no for every row”Happens when --sources names non-existent sources (a typo).
tessera check usually catches it, but if it slipped through, check
[host_identity].sources in config.toml.
Bootstrap cert rejected on the clone
Section titled “Bootstrap cert rejected on the clone”- The trust anchor didn’t make it into the image:
tessera checkwill showtrust_anchor_missing. host_bindingin the cert doesn’t equal theoverridestring — rebuild the bootstrap cert with--mode bootstrap.[host_identity].override≠host_bindingin the cert — usuallyinstallationon both sides, sync them.
Repeated flip after a motherboard swap
Section titled “Repeated flip after a motherboard swap”dmi_board_serial changed → host_id_hash is different → the per-host
cert is no longer valid.
- Restore the bootstrap state:
config.toml→sources = ["override"],override = "installation". - Put the bootstrap cert on the USB.
- Run
finish-bootstrap.shagain — a new TSV dump with the newhost_id_hash. - Issue a new per-host cert (see clone-image.md §6).
finish-bootstrap.sh does not do steps 1–2 automatically —
deliberately (it requires an operator decision + a physical stick).
8. Security incidents
Section titled “8. Security incidents”Compromise of a user certificate
Section titled “Compromise of a user certificate”Symptom: a report from the user / SOC.
- Add the serial to the CA’s CRL.
- Re-issue and publish the CRL.
- Update the CRL on the endpoints (see
operations.md §2.2). The
tessera-crl-update.serviceunit is not shipped with the package — the operator creates it per operations.md §2.2; where it is set up, the refresh can be expedited with a one-offsystemctl start tessera-crl-update.service. - Check the log:
Terminal window sudo journalctl -t pam_tessera -g 'certificate revoked' -n 100 - Notify the user; arrange issuance of a new certificate.
Lost token
Section titled “Lost token”- Revoke the serial (see above).
- Wait for CRL propagation.
- Issue a replacement token with a new certificate, setting
pam_cert_host_bindingandpam_cert_allowed_rolescorrectly (see cert-issuance.md).
Loss of the CA private key (worst case)
Section titled “Loss of the CA private key (worst case)”- Immediately stop all new issuance.
- Declare a Critical incident; engage the security team.
- Disaster recovery — a separate sub-runbook
docs/operations-disaster-recovery.md(created by the organization; 10–20 pages). - Prepare a new CA from a cold-storage backup, or re-issue from scratch.
- A coordinated update of all endpoints.
- Publish the incident via
security@...and in theSecuritysection of changelog.md (Russian).
DIGSIG enforce with no signature on pam_tessera.so
Section titled “DIGSIG enforce with no signature on pam_tessera.so”Symptom: PAM unable to dlopen(pam_tessera.so) or
DIGSIG: blocked unsigned ELF in dmesg. On a production Astra with
astra-digsig-control on in enforce mode.
sudo astra-digsig-control status # ВКЛЮЧЕНО = enforcesudo dmesg | grep -i digsig | grep tesseraTwo options:
- Sign the
.debthrough the Astra partner CI/CD (bsignwith a key from/etc/digsig/keys/). The standard pipeline for production. - Temporarily switch to logging-only:
Not for production — syslog will fill up with
Terminal window sudo astra-digsig-control loggingDIGSIG: NOT_ELF_SIGNED.
See threat-model.md §3.7.
9. Backup / recovery
Section titled “9. Backup / recovery”See operations.md §4 — what to back up, what not to back up, and the commands.
10. Installation / gost-engine
Section titled “10. Installation / gost-engine”gost-engine not loaded
Section titled “gost-engine not loaded”Symptom: openssl engine gost -t prints engine "gost" not found,
or dynamic without [ available ].
sudo apt install --reinstall gost-enginesudo systemctl restart pcscdopenssl engine gost -t