Fix: Complete SSH bootstrap hardening
This commit is contained in:
+42
-18
@@ -33,8 +33,11 @@ real firewall, install a real package, start a service, or apply changes to a se
|
||||
- Safe target SSH state means a non-root account, an absolute home, a real `.ssh`
|
||||
directory owned by the target UID with mode `0700`, and a nonempty regular
|
||||
`authorized_keys` file owned by the target UID with mode `0600`. Symlinks are
|
||||
refused. Panama may create and normalize files it copied from root, but it does
|
||||
not take ownership of an unsafe pre-existing target path.
|
||||
refused. Every nonblank, non-comment key line must parse with OpenSSH tooling.
|
||||
Panama may create and normalize files it copied from root, but final destination
|
||||
creation and writing run as the target UID. It does not take ownership of an
|
||||
unsafe pre-existing target path or assume that the user's primary group has the
|
||||
same name as the user.
|
||||
- Failed SSH reload rollback includes restored-config validation and a reload of the
|
||||
restored configuration, because a command can apply state and still return
|
||||
nonzero.
|
||||
@@ -92,16 +95,21 @@ Before offering hardening, Panama verifies:
|
||||
absolute and nonempty;
|
||||
- neither the home-relative `.ssh` path nor `authorized_keys` is a symlink;
|
||||
- `.ssh` and `authorized_keys` have the exact ownership and modes in Decisions;
|
||||
- `authorized_keys` contains at least one nonblank, non-comment line;
|
||||
- exactly one installed SSH unit is detected, preferring `sshd.service` and falling
|
||||
back to `ssh.service` only when the first unit is absent.
|
||||
- `authorized_keys` contains at least one nonblank, non-comment line, and OpenSSH
|
||||
parses every such line as a public key;
|
||||
- an installed SSH unit is detected, preferring `sshd.service` and falling back to
|
||||
`ssh.service` only when the first unit is absent.
|
||||
|
||||
If the target has no key and root has a safe regular key file, Panama copies only that
|
||||
file, creates `.ssh`, applies `0700/0600`, and changes ownership only on those two
|
||||
paths. It does not recursively take ownership of an existing directory tree.
|
||||
file. The target UID creates or normalizes `.ssh` at `0700` and writes
|
||||
`authorized_keys` at `0600` through an already-open root-key input. Panama then
|
||||
revalidates exact UID ownership, modes, and OpenSSH key parsing. It does not chown a
|
||||
target-controlled path or assume a same-named primary group.
|
||||
|
||||
If the preconditions fail, Panama prints why hardening is unavailable, keeps
|
||||
root/password authentication unchanged, and continues the clone/install handoff.
|
||||
If the key preconditions fail, no SSH unit is installed, or the Panama drop-in path
|
||||
already names a symlink or non-regular object, Panama prints why hardening is
|
||||
unavailable, keeps root/password authentication unchanged, and continues the
|
||||
clone/install handoff. Declining the prompt has the same unchanged-state outcome.
|
||||
|
||||
### Transaction
|
||||
|
||||
@@ -110,22 +118,32 @@ The desired drop-in is exactly:
|
||||
```text
|
||||
PermitRootLogin no
|
||||
PasswordAuthentication no
|
||||
KbdInteractiveAuthentication no
|
||||
```
|
||||
|
||||
Panama creates the candidate with `umask 077` and `mktemp` in
|
||||
`/etc/ssh/sshd_config.d`. Its temporary name does not end in `.conf`, so the normal
|
||||
include glob cannot activate it early. It preserves an existing
|
||||
`90-panama.conf` in the same directory, arms EXIT/INT/TERM rollback, and atomically
|
||||
renames the candidate over the final path.
|
||||
include glob cannot activate it early. It refuses a pre-existing Panama path unless
|
||||
it is a non-symlink regular file. It preserves an existing `00-panama.conf`, including
|
||||
its ownership, mode, timestamps, ACLs, and extended attributes, in the same directory.
|
||||
State-aware EXIT/INT/TERM cleanup is armed before the first candidate or backup
|
||||
artifact, and the candidate is atomically renamed over the final path.
|
||||
|
||||
It then runs `sshd -t` against the complete active configuration and reloads only the
|
||||
detected unit. Success disarms rollback and removes the backup.
|
||||
It then runs `sshd -t` against the complete active configuration. Before reload,
|
||||
`sshd -T -C` must report `permitrootlogin no`, `passwordauthentication no`, and
|
||||
`kbdinteractiveauthentication no` for the root context. The target-user context must
|
||||
report both authentication directives as `no`. This fails closed when an earlier
|
||||
main-config directive wins despite the precedence-safe filename. Panama reloads only
|
||||
the detected unit after every check passes. Success disarms rollback and removes the
|
||||
backup.
|
||||
|
||||
On validation failure, Panama restores or removes the new drop-in, validates the
|
||||
restored configuration, and returns nonzero without reloading the rejected candidate.
|
||||
On reload failure, Panama restores the previous drop-in, validates it, reloads the
|
||||
restored unit, and returns nonzero. A rollback validation/reload failure preserves the
|
||||
backup and prints its path plus exact recovery commands.
|
||||
backup and prints its path plus exact recovery commands. When no prior file existed,
|
||||
recovery instead instructs the operator to remove `00-panama.conf`, run `sshd -t`,
|
||||
and reload the detected unit.
|
||||
|
||||
Existing drop-ins go through the same desired-content, validation, and reload path;
|
||||
mere existence is not treated as proof of hardening.
|
||||
@@ -143,12 +161,18 @@ and `systemctl`, and provides temporary account and filesystem state.
|
||||
|
||||
Required cases are:
|
||||
|
||||
- missing, empty, comment-only, symlinked, wrong-owner, and wrong-mode target keys;
|
||||
- missing, empty, comment-only, malformed, mixed valid/malformed, symlinked,
|
||||
wrong-owner, and wrong-mode target keys;
|
||||
- safe root-key copy and safe existing target key;
|
||||
- target-UID copy normalization with a primary group whose name differs from the user;
|
||||
- declined hardening and no installed SSH unit;
|
||||
- pre-existing symlink, directory, and FIFO Panama drop-ins;
|
||||
- successful initial install and replacement of an existing drop-in;
|
||||
- invalid candidate rollback;
|
||||
- invalid syntax and conflicting effective-policy rollback;
|
||||
- failed reload rollback, including restored validation and reload;
|
||||
- rollback failure retaining its recovery artifact;
|
||||
- rollback failure retaining its recovery artifact or printing no-prior-file removal;
|
||||
- INT/TERM during candidate and backup preparation as well as after activation;
|
||||
- actual-root rejection of `PANAMA_BOOT_FIXTURE_ROOT` in a user namespace;
|
||||
- exact command ordering and no install handoff after a transactional failure.
|
||||
|
||||
## Verified bootstrap and installer inputs
|
||||
|
||||
Reference in New Issue
Block a user