Change to a non-root account with ssh key
This commit is contained in:
@@ -15,6 +15,8 @@
|
||||
# Required Gitea repo secrets:
|
||||
# REGISTRY_USERNAME - registry user for `oci_image` (oci_push=true)
|
||||
# REGISTRY_TOKEN - registry password/token
|
||||
# SSH_AUTHORIZED_KEY - public key for the sudo admin user; empty => no admin
|
||||
# user + root left unlocked (lab). Set it to lock root.
|
||||
# # SB_KEY, SB_CERT - (future) Secure Boot signing key + cert for signed UKIs
|
||||
#
|
||||
# Runner: needs KVM (qemu accelerator=kvm) and the build-host tooling installed
|
||||
@@ -153,4 +155,5 @@ jobs:
|
||||
-var oci_push=true \
|
||||
-var disable_dot1x=${{ env.DISABLE_DOT1X }} \
|
||||
-var nvmet_traddr="${{ env.NVMET_TRADDR }}" \
|
||||
-var ssh_authorized_key="${{ secrets.SSH_AUTHORIZED_KEY }}" \
|
||||
.
|
||||
|
||||
@@ -100,6 +100,18 @@ variable "nvmet_traddr" {
|
||||
default = "nvme.fleet.lab"
|
||||
}
|
||||
|
||||
variable "ssh_authorized_key" {
|
||||
type = string
|
||||
description = "Single SSH public key authorized for the sudo-enabled admin user. Fleet-generic (same on every host — not per-host state). Baked into the immutable rootfs, so rotating it needs a rebuild. EMPTY = no admin user is created and root is left UNLOCKED (lab convenience, avoids a no-way-in image)."
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "admin_user" {
|
||||
type = string
|
||||
description = "Username of the sudo-enabled, key-only admin account baked into the image (wheel group, NOPASSWD sudo since the account has no password). Created only when ssh_authorized_key is set."
|
||||
default = "fleetadmin"
|
||||
}
|
||||
|
||||
variable "sb_key" {
|
||||
type = string
|
||||
description = "Secure Boot signing key (PEM) for the UKI. Empty = unsigned lab build. Production: CI/HSM-held; never enters the build VM."
|
||||
@@ -232,6 +244,46 @@ build {
|
||||
]
|
||||
}
|
||||
|
||||
# --- 2c. Admin access: sudo-enabled key user + locked root --------------
|
||||
# Fleet-generic (same user + key on every host => NOT per-host state). The
|
||||
# key comes from var.ssh_authorized_key (CI secret). If no key is supplied we
|
||||
# skip the whole thing AND leave root unlocked, so a lab build can't end up
|
||||
# with no way in. Runs LAST: locking root is safe because Packer drives
|
||||
# shutdown over the already-authenticated SSH session (no re-auth as root).
|
||||
provisioner "shell" {
|
||||
environment_vars = [
|
||||
"SSH_AUTHORIZED_KEY=${var.ssh_authorized_key}",
|
||||
"ADMIN_USER=${var.admin_user}",
|
||||
]
|
||||
inline = [
|
||||
"set -e",
|
||||
"if [ -z \"$SSH_AUTHORIZED_KEY\" ]; then echo 'WARNING: ssh_authorized_key empty -> not creating admin user, leaving root UNLOCKED (lab build).'; exit 0; fi",
|
||||
"id \"$ADMIN_USER\" >/dev/null 2>&1 || useradd -m -G wheel \"$ADMIN_USER\"",
|
||||
"install -d -m0700 -o \"$ADMIN_USER\" -g \"$ADMIN_USER\" \"/home/$ADMIN_USER/.ssh\"",
|
||||
"printf '%s\\n' \"$SSH_AUTHORIZED_KEY\" > \"/home/$ADMIN_USER/.ssh/authorized_keys\"",
|
||||
"chmod 0600 \"/home/$ADMIN_USER/.ssh/authorized_keys\"",
|
||||
"chown \"$ADMIN_USER:$ADMIN_USER\" \"/home/$ADMIN_USER/.ssh/authorized_keys\"",
|
||||
"restorecon -R \"/home/$ADMIN_USER/.ssh\"",
|
||||
# Key-only account (useradd leaves no password), so sudo must not prompt
|
||||
# for one. NOPASSWD is a STIG finding (tracked in TODO #2) — acceptable for
|
||||
# a key-only admin; reconcile when hardening lands.
|
||||
"printf '%s ALL=(ALL) NOPASSWD:ALL\\n' \"$ADMIN_USER\" > \"/etc/sudoers.d/$ADMIN_USER\"",
|
||||
"chmod 0440 \"/etc/sudoers.d/$ADMIN_USER\"",
|
||||
"visudo -cf \"/etc/sudoers.d/$ADMIN_USER\"",
|
||||
"restorecon \"/etc/sudoers.d/$ADMIN_USER\"",
|
||||
# Image sshd: no root login, key-only. A drop-in (read via Include before
|
||||
# the main config) overrides the ks's PermitRootLogin yes. Takes effect on
|
||||
# the next boot only (sshd isn't restarted), so the live build session is
|
||||
# unaffected.
|
||||
"printf 'PermitRootLogin no\\nPasswordAuthentication no\\nKbdInteractiveAuthentication no\\n' > /etc/ssh/sshd_config.d/50-fleet-hardening.conf",
|
||||
"chmod 0644 /etc/ssh/sshd_config.d/50-fleet-hardening.conf",
|
||||
"restorecon /etc/ssh/sshd_config.d/50-fleet-hardening.conf",
|
||||
# Lock root in the image. Done last; admin access is via the key user.
|
||||
"passwd -l root",
|
||||
"echo \"root locked; admin user $ADMIN_USER created (wheel + NOPASSWD sudo, key-only).\"",
|
||||
]
|
||||
}
|
||||
|
||||
# --- 3. Extract kernel, initramfs, rootfs from the built disk ------------
|
||||
# --- 4. Assemble + sign the UKI; build the OCI release-artifact image ----
|
||||
post-processor "shell-local" {
|
||||
|
||||
@@ -56,6 +56,14 @@ and cleanup.
|
||||
report-only.
|
||||
- Note: orthogonal to the `rd.dot1x=0` test toggle, but a full STIG production
|
||||
posture wants 802.1X re-enabled.
|
||||
- **Credentials (partly done):** root is now **locked** and access is via a
|
||||
baked sudo-enabled key-only admin user (`var.ssh_authorized_key` /
|
||||
`var.admin_user`, `wheel` + NOPASSWD sudo), with sshd drop-in
|
||||
`PermitRootLogin no` / `PasswordAuthentication no`. Two items for STIG to
|
||||
reconcile: **NOPASSWD sudo** is a finding (acceptable for a key-only account,
|
||||
but document/deviate), and the admin key/user are **fleet-wide baked** — for
|
||||
per-host/rotatable access without rebuilds, layer the signed HTTP/SMBIOS
|
||||
config-agent or an SSH CA (`TrustedUserCAKeys`) discussed in session.
|
||||
|
||||
## [ ] 3. Roll the errata into design doc v3
|
||||
|
||||
|
||||
Reference in New Issue
Block a user