Skip to content

Commit 37f534b

Browse files
committed
Extend Molecule smoke to staged MFA, msmtp, and Lynis install.
Cover the remaining reaudit test gap without live SMTP, TOTP enrolment, or a full lynis audit run, which stay operator-owned.
1 parent fe900cb commit 37f534b

5 files changed

Lines changed: 49 additions & 6 deletions

File tree

ansible/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ pip install 'molecule' 'molecule-plugins[docker]'
9393
molecule test
9494
```
9595

96-
Default scenario converges **bootstrap → admin → sysctl → passwords → ssh_hardening → firewall_stack** on Debian 13 Docker (privileged) and verifies UFW active + Fail2Ban jail. Still not a full `02-harden.yml` substitute (no mail/MFA/Lynis).
96+
Default scenario converges **bootstrap → admin → sysctl → passwords → sshMFA (wired/`nullok`) → firewall_stack → msmtp → Lynis install** on Debian 13 Docker (privileged). It verifies UFW, Fail2Ban, PAM TOTP staging, msmtp `0600`, and Debian Lynis without a third-party repo. It is still not a substitute for a full `02-harden.yml` run (no live SMTP, no TOTP enrolment, no `lynis audit system`).
9797

9898
## Directory map
9999

ansible/molecule/default/converge.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
- name: Converge — packages, identity, SSH, firewall
2+
- name: Converge — identity, SSH, staged MFA, firewall, mail, Lynis
33
hosts: all
44
become: true
55
gather_facts: true
@@ -16,7 +16,8 @@
1616
harden_ssh_port: 2222
1717
harden_ssh_use_dns: "no"
1818
harden_ssh_mfa_enable: false
19-
harden_enable_mfa_role: false
19+
harden_ssh_mfa_nullok: true
20+
harden_enable_mfa_role: true
2021
harden_fail2ban_require_ignoreip: false
2122
harden_fail2ban_ignoreip: "127.0.0.1"
2223
harden_strict_ops: false
@@ -26,6 +27,9 @@
2627
harden_enable_chkrootkit: false
2728
harden_enable_aide: false
2829
harden_enable_logwatch: false
30+
harden_lynis_force_run: false
31+
harden_enable_lynis_mail_report: false
32+
harden_allow_third_party_lynis_repo: false
2933
harden_mail_to: molecule@example.com
3034
harden_mail_from: molecule@example.com
3135
harden_smtp_host: localhost
@@ -36,7 +40,12 @@
3640
- ca-certificates
3741
- curl
3842
- fail2ban
43+
- libpam-google-authenticator
3944
- libpam-pwquality
45+
- lynis
46+
- mailutils
47+
- msmtp
48+
- msmtp-mta
4049
- openssh-server
4150
- psad
4251
- rsyslog
@@ -53,4 +62,7 @@
5362
- role: host_sysctl
5463
- role: password_policy
5564
- role: ssh_hardening
65+
- role: ssh_mfa
5666
- role: firewall_stack
67+
- role: outbound_mail
68+
- role: security_audit

ansible/molecule/default/molecule.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
# Minimal Molecule skeleton for Debian converge smoke tests.
2+
# Debian 13 Docker smoke: identity, SSH, staged MFA, UFW/IDS, msmtp, Lynis install.
33
# Requires: pip install molecule molecule-plugins[docker] ansible-core
44
# Run from ansible/: molecule test
55
dependency:

ansible/molecule/default/verify.yml

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@
2929
src: /etc/ssh/sshd_config.d/10-nowo-hardening.conf
3030
register: sshd_conf
3131

32-
- name: MFA must stay off in smoke converge
32+
- name: MFA wired but not enforced (nullok staging)
3333
ansible.builtin.assert:
3434
that:
3535
- "'AuthenticationMethods' not in (sshd_conf.content | b64decode)"
36+
- "'KbdInteractiveAuthentication no' in (sshd_conf.content | b64decode)"
3637

3738
- name: Assert sysctl drop-in exists
3839
ansible.builtin.stat:
@@ -92,3 +93,32 @@
9293
- name: Sysctl includes kptr_restrict
9394
ansible.builtin.command: grep -F 'kernel.kptr_restrict = 2' /etc/sysctl.d/60-nowo-hardening.conf
9495
changed_when: false
96+
97+
- name: PAM TOTP line is staged with nullok
98+
ansible.builtin.command: grep -F 'pam_google_authenticator.so nullok' /etc/pam.d/sshd
99+
changed_when: false
100+
101+
- name: msmtp config is root-only
102+
ansible.builtin.stat:
103+
path: /etc/msmtprc
104+
register: msmtprc
105+
106+
- name: Require msmtp 0600
107+
ansible.builtin.assert:
108+
that:
109+
- msmtprc.stat.exists
110+
- msmtprc.stat.mode == '0600'
111+
112+
- name: Lynis is installed from Debian (no third-party repo)
113+
ansible.builtin.command: dpkg -s lynis
114+
changed_when: false
115+
116+
- name: Cisofy third-party list must stay absent
117+
ansible.builtin.stat:
118+
path: /etc/apt/sources.list.d/cisofy-lynis.list
119+
register: cisofy_list
120+
121+
- name: Require no Cisofy source
122+
ansible.builtin.assert:
123+
that:
124+
- not cisofy_list.stat.exists

docs/CONTROL-COVERAGE.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ flowchart TB
8585
## Residual risks
8686

8787
- Focused auditd rules are not a full enterprise syscall pack.
88-
- CrowdSec and Docker firewalling need human design.
88+
- CrowdSec and Docker firewalling need human design (documented, not automated).
89+
- Molecule CI covers staging MFA, msmtp file perms, and Lynis package install — not live SMTP, TOTP enrolment, or a full Lynis audit run.
8990
- Physical/console threats remain operator-owned.
9091
- Application security is out of scope.

0 commit comments

Comments
 (0)