diff --git a/roles/base/molecule/default/converge.yml b/roles/base/molecule/default/converge.yml index b7a8c1d..980a153 100644 --- a/roles/base/molecule/default/converge.yml +++ b/roles/base/molecule/default/converge.yml @@ -1,7 +1,22 @@ --- - name: Converge hosts: all + become: 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: - role: base diff --git a/roles/base/molecule/default/molecule.yml b/roles/base/molecule/default/molecule.yml index b23d8da..342f83a 100644 --- a/roles/base/molecule/default/molecule.yml +++ b/roles/base/molecule/default/molecule.yml @@ -26,6 +26,7 @@ provisioner: host_vars: instance: ansible_user: root + ansible_host: 10.20.0.50 verifier: name: ansible diff --git a/roles/base/tasks/firewall.yml b/roles/base/tasks/firewall.yml new file mode 100644 index 0000000..58885cc --- /dev/null +++ b/roles/base/tasks/firewall.yml @@ -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] diff --git a/roles/base/tasks/main.yml b/roles/base/tasks/main.yml index ed97d53..1d77af9 100644 --- a/roles/base/tasks/main.yml +++ b/roles/base/tasks/main.yml @@ -1 +1,4 @@ --- +- name: Configure host firewall (nftables) + ansible.builtin.include_tasks: firewall.yml + tags: [firewall] diff --git a/roles/base/templates/nftables.conf.j2 b/roles/base/templates/nftables.conf.j2 new file mode 100644 index 0000000..f887ae5 --- /dev/null +++ b/roles/base/templates/nftables.conf.j2 @@ -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"