--- - name: Verify hosts: all become: true gather_facts: false tasks: - name: Read the rendered ruleset ansible.builtin.slurp: src: /etc/nftables.conf register: ruleset - name: Decode it ansible.builtin.set_fact: nft: "{{ ruleset.content | b64decode }}" - name: Assert default-deny input policy and management plane ansible.builtin.assert: that: - "'type filter hook input priority 0; policy drop;' in nft" - "'ct state established,related accept' in nft" - "'iifname \"wt0\" tcp dport 22 accept' in nft" - "'ip saddr 10.10.0.99 tcp dport 22 accept' in nft" fail_msg: >- input chain is missing default-deny, the wt0 SSH allow, or the ssh-from-control management-plane rule - name: Assert the lan->reverse_proxy:443 ingress rule (zone source) ansible.builtin.assert: that: - "'10.30.0.0/24' in nft" - "'tcp dport 443 accept' in nft" fail_msg: "missing lan->443 rule for reverse_proxy" - name: Assert the srv->photoprism:2342 ingress rule (zone source) ansible.builtin.assert: that: - "'10.20.0.0/24' in nft" - "'tcp dport 2342 accept' in nft" fail_msg: "missing srv->2342 rule for photoprism" - name: Assert the public->stun:3478/udp ingress rule (0.0.0.0/0 source) ansible.builtin.assert: that: - "'0.0.0.0/0' in nft" - "'udp dport 3478 accept' in nft" fail_msg: "missing public->3478/udp rule for netbird_stun" - name: Assert the docker_host extension hook is present ansible.builtin.assert: that: - "'include \"/etc/nftables.d/*.nft\"' in nft" fail_msg: "missing drop-in include hook" - name: Assert the forward chain defaults to policy drop (input_only off) ansible.builtin.assert: that: - "'hook forward priority 0; policy drop;' in nft" fail_msg: >- forward chain must default to policy drop when base__firewall_input_only is false (container isolation stays the norm on real service hosts) - name: Assert the admin-addr SSH allow rule (operator workstation on the LAN) ansible.builtin.assert: that: - "'ip saddr 10.30.0.77 tcp dport 22 accept' in nft" fail_msg: "missing admin-addr SSH allow rule from base__firewall_admin_addrs" - name: Syntax-check the rendered ruleset (no apply) ansible.builtin.command: nft -c -f /etc/nftables.conf changed_when: false - name: Sshd drop-in present and config valid ansible.builtin.command: sshd -t changed_when: false - name: PasswordAuthentication is disabled ansible.builtin.command: grep -q '^PasswordAuthentication no' /etc/ssh/sshd_config.d/10-boma.conf changed_when: false - name: Fail2ban sshd jail configured ansible.builtin.command: grep -q '^\[sshd\]' /etc/fail2ban/jail.d/sshd.local changed_when: false - name: ListenAddress bound to the fixture mesh IP (mesh-only mode) ansible.builtin.command: grep -q '^ListenAddress 100.99.0.1$' /etc/ssh/sshd_config.d/10-boma.conf changed_when: false - name: Sysctl drop-in for ip_nonlocal_bind is present ansible.builtin.command: grep -q '^net.ipv4.ip_nonlocal_bind=1' /etc/sysctl.d/60-boma-nonlocal-bind.conf changed_when: false - name: Kernel ip_nonlocal_bind is live in this netns ansible.builtin.command: sysctl -n net.ipv4.ip_nonlocal_bind register: _nonlocal changed_when: false failed_when: _nonlocal.stdout | trim != '1' # mesh concern: enabled but manage=false must be a clean no-op (no install/enrol) - name: Check whether netbird got installed ansible.builtin.command: which netbird register: _nb changed_when: false failed_when: false - name: Assert mesh manage=false installed nothing ansible.builtin.assert: that: - _nb.rc != 0 fail_msg: "netbird must not be installed when base__mesh_manage is false" success_msg: "mesh concern is a clean no-op under manage=false" - name: Read /etc/hosts (coordinator pin) ansible.builtin.slurp: src: /etc/hosts register: _etchosts - name: Assert the coordinator FQDN is pinned to the fixture IP (DNS-resilience / R8) ansible.builtin.assert: that: - "'203.0.113.9 netbird.askari.wingu.me' in (_etchosts.content | b64decode)" # slurp content is always base64 fail_msg: "base__mesh_coordinator_pin did not render the /etc/hosts coordinator pin" success_msg: "coordinator FQDN pinned in /etc/hosts"