---
name: audit-server-config
description: Audit server OS configuration for security issues — SSH hardening, firewall rules, sudo permissions, fail2ban, unattended-upgrades, and per-person accounts. Supports SSH-based automated checks and a guided manual questionnaire fallback.
argument-hint: "[user@host | --guided]"
---

# Audit Server Config

Apply the security checklist at `${CLAUDE_SKILL_DIR}/references/checklist.md`
to a live server via SSH, or guide an engineer through a manual questionnaire
using `${CLAUDE_SKILL_DIR}/references/guided-checklist.md`.

**Argument**: `$ARGUMENTS`

---

## Step 1 — Determine mode

Parse `$ARGUMENTS`:

- **SSH mode**: argument matches pattern `user@host` or `user@ip.address`
  → proceed to Step 2 (SSH retrieval)
- **Guided mode**: argument is `--guided`
  → skip to Step 4 (guided questionnaire)
- **No argument**: ask the user:

  > Do you have SSH access to the server you want to audit?
  > - If **yes**, re-run with the host as argument (e.g. `/audit-server-config ubuntu@1.2.3.4`) and configs will be retrieved automatically.
  > - If **no**, re-run with `--guided` for a manual checklist instead.

  Wait for the response, then proceed to the appropriate mode.

---

## Step 2 — SSH mode: retrieve server configs

Using the Bash tool, run the following commands against `<host>`:

```bash
ssh -o ConnectTimeout=10 -o BatchMode=yes <host> "sudo cat /etc/ssh/sshd_config"
ssh -o ConnectTimeout=10 -o BatchMode=yes <host> "sudo sshd -T 2>/dev/null | grep -E 'passwordauth|permitrootlogin|allowgroups|loglevel|maxauthtries|logingracetime|x11forwarding|allowtcpforwarding|permituserenvironment|permitemptypasswords|pubkeyauth'"
ssh -o ConnectTimeout=10 -o BatchMode=yes <host> "sudo ufw status verbose"
ssh -o ConnectTimeout=10 -o BatchMode=yes <host> "sudo ufw status numbered"
ssh -o ConnectTimeout=10 -o BatchMode=yes <host> "sudo grep -rn 'NOPASSWD' /etc/sudoers /etc/sudoers.d/ 2>/dev/null || echo 'no sudoers files found'"
ssh -o ConnectTimeout=10 -o BatchMode=yes <host> "sudo cat /etc/sudoers.d/* 2>/dev/null || true"
ssh -o ConnectTimeout=10 -o BatchMode=yes <host> "getent passwd | awk -F: '\$3 >= 1000 && \$3 < 65534 {print \$1, \$7}'"
ssh -o ConnectTimeout=10 -o BatchMode=yes <host> "sudo systemctl is-active fail2ban 2>/dev/null || echo 'not installed'"
ssh -o ConnectTimeout=10 -o BatchMode=yes <host> "sudo fail2ban-client status sshd 2>/dev/null || echo 'sshd jail not found'"
ssh -o ConnectTimeout=10 -o BatchMode=yes <host> "sudo systemctl is-active unattended-upgrades 2>/dev/null || echo 'not installed'"
ssh -o ConnectTimeout=10 -o BatchMode=yes <host> "cat /etc/apt/apt.conf.d/50unattended-upgrades 2>/dev/null || echo 'config not found'"
ssh -o ConnectTimeout=10 -o BatchMode=yes <host> "sudo cat /home/deploy/.ssh/authorized_keys 2>/dev/null || sudo cat /home/ci/.ssh/authorized_keys 2>/dev/null || echo 'deploy user authorized_keys not found'"
```

If any SSH command fails (connection refused, authentication error, permission
denied), note the failure against that specific check and continue with the
remaining commands. Do not abort the entire audit on a single command failure.

After collecting all outputs, proceed to Step 3.

---

## Step 3 — SSH mode: apply the checklist

Read `${CLAUDE_SKILL_DIR}/references/checklist.md` in full. Apply each check
using the retrieved data:

**SSH password authentication** — from `sshd -T` output, check
`passwordauthentication` value. Also check `sshd_config` for explicit
directives. FAIL if `passwordauthentication yes`.

**PermitRootLogin** — from `sshd -T` output. FAIL if value is anything other
than `no` (including `prohibit-password`).

**AllowGroups** — from `sshd -T` output. FAIL if `allowgroups` line is absent
or empty.

**UFW default-deny** — from `ufw status verbose`. FAIL if status is inactive,
or if `Default:` line does not show `deny (incoming)`.

**Open ports** — from `ufw status numbered`. FAIL if port 22 appears with
`Anywhere` as source (not restricted to a CIDR or interface). Also flag any
unexpected open ports (5432, 3306, 27017, etc.).

**fail2ban** — from `systemctl is-active fail2ban`. FAIL if not active. Check
`fail2ban-client status sshd` for an active sshd jail.

**unattended-upgrades** — from `systemctl is-active unattended-upgrades`. FAIL
if not active. Check `50unattended-upgrades` config for the
`${distro_id}:${distro_codename}-security` origin.

**sudo NOPASSWD** — from `grep -rn NOPASSWD` output. FAIL if any line contains
`NOPASSWD: ALL`. Flag any service account (deploy, appuser, ci) with any sudo
access.

**Per-person accounts** — from `getent passwd` filtered output. Flag if
accounts named `ubuntu`, `admin`, `devops`, or `app` are the only non-system
accounts (suggests shared logins). Note that this is a MANUAL confirmation —
flag for the engineer to verify.

**SSH LogLevel** — from `sshd -T` output. FAIL if `loglevel` is `INFO`
(default) rather than `VERBOSE`.

**MaxAuthTries / LoginGraceTime** — from `sshd -T` output. FAIL if
`maxauthtries` > 3 or `logingracetime` > 30.

**X11Forwarding / AllowTcpForwarding** — from `sshd -T` output. FAIL if
either is `yes`.

**Deploy user ForceCommand** — from `authorized_keys` output. FAIL if the
deploy/CI key entry does not contain `command="..."` restriction. Also check
for `no-port-forwarding,no-X11-forwarding,no-agent-forwarding`.

Skip to Step 5 after applying all checks.

---

## Step 4 — Guided mode: manual questionnaire

Read `${CLAUDE_SKILL_DIR}/references/guided-checklist.md` in full.

Present each section of the guided checklist to the engineer as a questionnaire.
For each section (Network & Firewall, SSH Hardening, OS User Accounts, Sudo
Permissions, CI/CD Deploy User, Automatic Security Patches, Brute-Force
Protection):

1. Show the section header and all its checklist items.
2. Ask: "For each item, answer ✅ (confirmed), ❌ (not in place), or ❓
   (unknown)."
3. Wait for the answers.
4. After all items in the section are answered, acknowledge and move to the next
   section.

Once all sections are answered, generate a findings summary:
- Group ❌ answers as findings (use the checklist Priority for severity).
- Group ❓ answers as "unconfirmed — needs investigation".
- Group ✅ answers as passed.

Proceed to Step 5 to format output.

---

## Step 5 — Output findings

### Header

```
## Server Configuration Security Audit
Mode: [SSH — host: <host>] or [Guided — manual questionnaire]
Audit date: <today's date>
```

If SSH mode, list which commands succeeded and which failed (for scope
transparency).

If guided mode, note: "Findings are based on engineer-provided answers. All
items marked ❓ should be verified against the live server configuration."

### Findings by severity

Group findings under these headings (omit empty headings):

```
### Critical findings
### Important findings
### Recommended findings
### Nice-to-have findings
```

Each finding entry:

```
**[CHECK NAME]** — [file or config location]
<One-sentence description of what was found and the risk.>
Fix: <key remediation step from the checklist.>
```

Never include actual values from config files that could be credentials (e.g.,
key material found in authorized_keys). Reference the location and type only.

### Summary table

| Check | Status | Notes |
|---|---|---|
| SSH password auth disabled | PASS / FAIL / SKIP | |
| PermitRootLogin no | PASS / FAIL / SKIP | |
| AllowGroups configured | PASS / FAIL / SKIP | |
| UFW default-deny incoming | PASS / FAIL / SKIP | |
| Only 80/443 + restricted SSH | PASS / FAIL / SKIP | |
| fail2ban active | PASS / FAIL / SKIP | |
| unattended-upgrades active | PASS / FAIL / SKIP | |
| sudo NOPASSWD:ALL absent | PASS / FAIL / SKIP | |
| Per-person OS accounts | PASS / UNCONFIRMED / SKIP | |
| SSH LogLevel VERBOSE | PASS / FAIL / SKIP | |
| MaxAuthTries 3 / GraceTime 30 | PASS / FAIL / SKIP | |
| X11/TCP forwarding disabled | PASS / FAIL / SKIP | |

### Passed checks and skipped checks

List passed checks as a bullet list. List skipped checks with the reason (e.g.,
SSH command failed, guided mode — not applicable).

---

## Notes

- This skill is read-only. It does not modify server configuration.
- SSH mode requires that the running user has SSH access with sudo privileges.
  If sudo is unavailable, some checks will be skipped.
- In guided mode, findings accuracy depends on the engineer's knowledge of the
  server state. Treat ❓ answers as potential findings requiring follow-up.
- For guided mode, use `${CLAUDE_SKILL_DIR}/references/guided-checklist.md` as
  the question source — do not rely on memory for checklist items.
