feat(base): render nftables ruleset from catalog (+ molecule fixture)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
7dae93e4e1
commit
eeab5ed8de
5 changed files with 72 additions and 1 deletions
|
|
@ -1,7 +1,22 @@
|
||||||
---
|
---
|
||||||
- name: Converge
|
- name: Converge
|
||||||
hosts: all
|
hosts: all
|
||||||
|
become: true
|
||||||
gather_facts: true
|
gather_facts: true
|
||||||
|
vars:
|
||||||
|
base__firewall_apply: false
|
||||||
|
firewall_zones:
|
||||||
|
lan: 10.30.0.0/24
|
||||||
|
srv: 10.20.0.0/24
|
||||||
|
mgmt: 10.10.0.0/24
|
||||||
|
firewall_catalog:
|
||||||
|
reverse_proxy:
|
||||||
|
host: instance
|
||||||
|
ingress:
|
||||||
|
- { from: lan, port: 443, proto: tcp }
|
||||||
|
photoprism:
|
||||||
|
host: instance
|
||||||
|
ingress:
|
||||||
|
- { from: reverse_proxy, port: 2342, proto: tcp }
|
||||||
roles:
|
roles:
|
||||||
- role: base
|
- role: base
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ provisioner:
|
||||||
host_vars:
|
host_vars:
|
||||||
instance:
|
instance:
|
||||||
ansible_user: root
|
ansible_user: root
|
||||||
|
ansible_host: 10.20.0.50
|
||||||
|
|
||||||
verifier:
|
verifier:
|
||||||
name: ansible
|
name: ansible
|
||||||
|
|
|
||||||
30
roles/base/tasks/firewall.yml
Normal file
30
roles/base/tasks/firewall.yml
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
- name: Install nftables
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: nftables
|
||||||
|
state: present
|
||||||
|
tags: [firewall]
|
||||||
|
|
||||||
|
- name: Ensure nftables drop-in dir exists
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ base__firewall_dropin_dir }}"
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
tags: [firewall]
|
||||||
|
|
||||||
|
- name: Resolve firewall ingress rules for this host
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
base__firewall_resolved: >-
|
||||||
|
{{ firewall_catalog | default({})
|
||||||
|
| resolve_firewall_rules(firewall_zones | default({}),
|
||||||
|
inventory_hostname, hostvars, groups) }}
|
||||||
|
tags: [firewall]
|
||||||
|
|
||||||
|
- name: Render nftables ruleset (syntax-checked before install)
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: nftables.conf.j2
|
||||||
|
dest: /etc/nftables.conf
|
||||||
|
mode: "0644"
|
||||||
|
validate: "nft -c -f %s"
|
||||||
|
register: base__firewall_render
|
||||||
|
tags: [firewall]
|
||||||
|
|
@ -1 +1,4 @@
|
||||||
---
|
---
|
||||||
|
- name: Configure host firewall (nftables)
|
||||||
|
ansible.builtin.include_tasks: firewall.yml
|
||||||
|
tags: [firewall]
|
||||||
|
|
|
||||||
22
roles/base/templates/nftables.conf.j2
Normal file
22
roles/base/templates/nftables.conf.j2
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/usr/sbin/nft -f
|
||||||
|
# Ansible managed — do not edit by hand. Source: roles/base (ADR-020).
|
||||||
|
flush ruleset
|
||||||
|
|
||||||
|
table inet filter {
|
||||||
|
chain input {
|
||||||
|
type filter hook input priority 0; policy drop;
|
||||||
|
iif "lo" accept
|
||||||
|
ct state established,related accept
|
||||||
|
ct state invalid drop
|
||||||
|
iif "{{ base__firewall_mgmt_interface }}" tcp dport {{ base__firewall_ssh_port }} accept
|
||||||
|
ip protocol icmp accept
|
||||||
|
ip6 nexthdr ipv6-icmp accept
|
||||||
|
{% for r in base__firewall_resolved %}
|
||||||
|
ip saddr { {{ r.sources | join(', ') }} } {{ r.proto }} dport {{ r.port }} accept
|
||||||
|
{% endfor %}
|
||||||
|
}
|
||||||
|
chain forward { type filter hook forward priority 0; policy drop; }
|
||||||
|
chain output { type filter hook output priority 0; policy accept; }
|
||||||
|
}
|
||||||
|
|
||||||
|
include "{{ base__firewall_dropin_dir }}/*.nft"
|
||||||
Loading…
Add table
Reference in a new issue