Supports nftables instead of iptables
This patch introduces a new role (tripleo_nftables) as well as a new tripleo_firewall_engine parameter, allowing to switch from iptables to nftables. All of tripleo rules are pushed in the "inet" family, in a dedicated chains therein. It allows to avoid rule duplication between IPv6 and IPv4, while ensuring we don't break the compatibility layer for iptables-nft - that tool is checking only the "ip" family, while ip6tables-nft is checking the "ip6" one. This means some changes are needed in the doc, when it comes to listing the existing rules. Also, please note some tools such as neutron are still heavily using the iptables family, as well as some part of podman apparently. Change-Id: Ia43b58f304d8ef41b80820c3c98696650eb362e1
This commit is contained in:
parent
feb150954f
commit
656c1aba3d
|
@ -0,0 +1,6 @@
|
|||
=======================
|
||||
Role - tripleo_nftables
|
||||
=======================
|
||||
|
||||
.. ansibleautoplugin::
|
||||
:role: tripleo_ansible/roles/tripleo_nftables
|
|
@ -29,6 +29,8 @@
|
|||
# dport: 22
|
||||
# extras:
|
||||
# ensure: 'absent'
|
||||
tripleo_firewall_engine: 'iptables'
|
||||
|
||||
tripleo_firewall_rules: {}
|
||||
|
||||
tripleo_firewall_frontend_enabled: false
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
# Copyright 2019 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
- name: Converge
|
||||
hosts: all
|
||||
roles:
|
||||
- role: "tripleo_firewall"
|
||||
tripleo_firewall_engine: 'nftables'
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
provisioner:
|
||||
name: ansible
|
||||
config_options:
|
||||
defaults:
|
||||
fact_caching: jsonfile
|
||||
fact_caching_connection: /tmp/molecule/facts
|
||||
inventory:
|
||||
hosts:
|
||||
all:
|
||||
hosts:
|
||||
instance:
|
||||
ansible_host: localhost
|
||||
log: true
|
||||
env:
|
||||
ANSIBLE_STDOUT_CALLBACK: yaml
|
||||
ANSIBLE_ROLES_PATH: "${ANSIBLE_ROLES_PATH}:${HOME}/zuul-jobs/roles"
|
||||
|
||||
scenario:
|
||||
name: nftables
|
||||
test_sequence:
|
||||
- prepare
|
||||
- converge
|
||||
- check
|
||||
|
||||
verifier:
|
||||
name: testinfra
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
# Copyright 2019 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
- name: Prepare
|
||||
hosts: all
|
||||
roles:
|
||||
- role: test_deps
|
|
@ -0,0 +1,98 @@
|
|||
---
|
||||
# Copyright 2019 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
# "tripleo_firewall" will search for and load any operating system variable file
|
||||
- name: Firewall add block
|
||||
become: true
|
||||
block:
|
||||
- name: Ensure firewall is installed
|
||||
package:
|
||||
name: "{{ tripleo_firewall_packages }}"
|
||||
state: present
|
||||
|
||||
- name: Create empty ruleset in /etc/sysconfig/iptables and /etc/sysconfig/ip6tables
|
||||
become: true
|
||||
ignore_errors: "{{ (((ansible_facts['os_family'] | lower) ~ '-' ~ ansible_facts['distribution_major_version']) == 'redhat-7') | bool }}"
|
||||
copy:
|
||||
dest: "{{ item }}"
|
||||
content: "# empty ruleset created by deployed-server bootstrap"
|
||||
loop:
|
||||
- /etc/sysconfig/iptables
|
||||
- /etc/sysconfig/ip6tables
|
||||
|
||||
- name: Ensure firewall is enabled/started
|
||||
systemd:
|
||||
name: iptables
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
- name: Manage firewall rules
|
||||
tripleo_iptables:
|
||||
tripleo_rules: "{{ firewall_rules_sorted }}"
|
||||
|
||||
- name: Firewall save block
|
||||
become: true
|
||||
block:
|
||||
- name: Save firewall rules ipv4
|
||||
command: /usr/libexec/iptables/iptables.init save
|
||||
|
||||
- name: Save firewall rules ipv6
|
||||
command: /usr/libexec/iptables/ip6tables.init save
|
||||
|
||||
- name: Enable iptables service (and do a daemon-reload systemd)
|
||||
systemd:
|
||||
daemon_reload: true
|
||||
enabled: true
|
||||
name: "{{ item }}"
|
||||
state: started
|
||||
loop:
|
||||
- iptables.service
|
||||
- ip6tables.service
|
||||
|
||||
- name: Enable tripleo-iptables service (and do a daemon-reload systemd)
|
||||
systemd:
|
||||
daemon_reload: true
|
||||
enabled: true
|
||||
name: "{{ item }}"
|
||||
state: started
|
||||
loop:
|
||||
- tripleo-iptables.service
|
||||
- tripleo-ip6tables.service
|
||||
failed_when: false
|
||||
|
||||
- name: Stop and disable firewalld
|
||||
systemd:
|
||||
enabled: false
|
||||
name: "firewalld.service"
|
||||
state: stopped
|
||||
failed_when: false
|
||||
|
||||
- name: Find non-persistent rules
|
||||
command: egrep -l 'comment.*(neutron-|ironic-inspector)' /etc/sysconfig/iptables* /etc/sysconfig/ip6tables*
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
register: neutron_rules
|
||||
|
||||
- name: Remove non-persistent line(s)
|
||||
lineinfile:
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
regexp: '^((?!.*comment)(?=.*(ironic-inspector|neutron-)))'
|
||||
when:
|
||||
- not ansible_check_mode|bool
|
||||
- item.find('v=' ~ '^/') == -1
|
||||
loop: "{{ neutron_rules.stdout_lines }}"
|
|
@ -87,83 +87,15 @@
|
|||
list
|
||||
}}"
|
||||
|
||||
- name: Firewall add block
|
||||
become: true
|
||||
block:
|
||||
- name: Ensure firewall is installed
|
||||
package:
|
||||
name: "{{ tripleo_firewall_packages }}"
|
||||
state: present
|
||||
- name: Manage rules via iptables
|
||||
when:
|
||||
- tripleo_firewall_engine == 'iptables'
|
||||
include_tasks: iptables.yaml
|
||||
|
||||
- name: Create empty ruleset in /etc/sysconfig/iptables and /etc/sysconfig/ip6tables
|
||||
become: true
|
||||
ignore_errors: "{{ (((ansible_facts['os_family'] | lower) ~ '-' ~ ansible_facts['distribution_major_version']) == 'redhat-7') | bool }}"
|
||||
copy:
|
||||
dest: "{{ item }}"
|
||||
content: "# empty ruleset created by deployed-server bootstrap"
|
||||
loop:
|
||||
- /etc/sysconfig/iptables
|
||||
- /etc/sysconfig/ip6tables
|
||||
|
||||
- name: Ensure firewall is enabled/started
|
||||
systemd:
|
||||
name: iptables
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
- name: Manage firewall rules
|
||||
tripleo_iptables:
|
||||
tripleo_rules: "{{ firewall_rules_sorted }}"
|
||||
|
||||
- name: Firewall save block
|
||||
become: true
|
||||
block:
|
||||
- name: Save firewall rules ipv4
|
||||
command: /usr/libexec/iptables/iptables.init save
|
||||
|
||||
- name: Save firewall rules ipv6
|
||||
command: /usr/libexec/iptables/ip6tables.init save
|
||||
|
||||
- name: Enable iptables service (and do a daemon-reload systemd)
|
||||
systemd:
|
||||
daemon_reload: true
|
||||
enabled: true
|
||||
name: "{{ item }}"
|
||||
state: started
|
||||
loop:
|
||||
- iptables.service
|
||||
- ip6tables.service
|
||||
|
||||
- name: Enable tripleo-iptables service (and do a daemon-reload systemd)
|
||||
systemd:
|
||||
daemon_reload: true
|
||||
enabled: true
|
||||
name: "{{ item }}"
|
||||
state: started
|
||||
loop:
|
||||
- tripleo-iptables.service
|
||||
- tripleo-ip6tables.service
|
||||
failed_when: false
|
||||
|
||||
- name: Stop and disable firewalld
|
||||
systemd:
|
||||
enabled: false
|
||||
name: "firewalld.service"
|
||||
state: stopped
|
||||
failed_when: false
|
||||
|
||||
- name: Find non-persistent rules
|
||||
command: egrep -l 'comment.*(neutron-|ironic-inspector)' /etc/sysconfig/iptables* /etc/sysconfig/ip6tables*
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
register: neutron_rules
|
||||
|
||||
- name: Remove non-persistent line(s)
|
||||
lineinfile:
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
regexp: '^((?!.*comment)(?=.*(ironic-inspector|neutron-)))'
|
||||
when:
|
||||
- not ansible_check_mode|bool
|
||||
- item.find('v=' ~ '^/') == -1
|
||||
loop: "{{ neutron_rules.stdout_lines }}"
|
||||
- name: Manage rules via nftables
|
||||
when:
|
||||
- tripleo_firewall_engine == 'nftables'
|
||||
vars:
|
||||
tripleo_nftables_rules: "{{ firewall_rules_sorted | sort(attribute='rule_name') |list }}"
|
||||
include_role:
|
||||
name: tripleo_nftables
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
# Copyright 2022 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
# All variables intended for modification should be placed in this file.
|
||||
|
||||
# All variables within this role should have a prefix of "tripleo_nftables_"
|
||||
|
||||
# Example rule definition
|
||||
tripleo_nftables_rules:
|
||||
- rule:
|
||||
proto: all
|
||||
state:
|
||||
- RELATED
|
||||
- ESTABLISHED
|
||||
rule_name: 000 accept related established rules
|
||||
- rule:
|
||||
ipversion: ipv4
|
||||
proto: icmp
|
||||
rule_name: 001 accept all icmp
|
||||
- rule:
|
||||
ipversion: ipv6
|
||||
proto: ipv6-icmp
|
||||
rule_name: 001 accept all ipv6-icmp
|
||||
- rule:
|
||||
interface: lo
|
||||
proto: all
|
||||
rule_name: 002 accept all to lo interface
|
||||
- rule:
|
||||
destination: fe80::/64
|
||||
dport: 546
|
||||
ipversion: ipv6
|
||||
proto: udp
|
||||
state:
|
||||
- NEW
|
||||
rule_name: 004 accept ipv6 dhcpv6
|
||||
- rule:
|
||||
jump: LOG
|
||||
limit: 20/min
|
||||
limit_burst: 15
|
||||
proto: all
|
||||
rule_name: 998 log all
|
||||
- rule:
|
||||
action: drop
|
||||
proto: all
|
||||
rule_name: 999 drop all
|
|
@ -0,0 +1,83 @@
|
|||
#!/usr/sbin/nft -f
|
||||
#
|
||||
# Managed by tripleo-ansible/tripleo_nftables
|
||||
#
|
||||
# Ensure we get the iptables layout to make the whole thing 100% compatible,
|
||||
# even if some other tools are still relying on iptables-nft compatibility
|
||||
# wrapper
|
||||
|
||||
# We will push our tripleo rules in the inet table - it avoids rule duplication
|
||||
# and allows to keep good compatibility with the iptables-nft layer
|
||||
table inet filter {
|
||||
chain INPUT {
|
||||
type filter hook input priority filter; policy accept;
|
||||
}
|
||||
chain FORWARD {
|
||||
type filter hook forward priority filter; policy accept;
|
||||
}
|
||||
chain OUTPUT {
|
||||
type filter hook output priority filter; policy accept;
|
||||
}
|
||||
}
|
||||
table inet raw {
|
||||
chain PREROUTING {
|
||||
type filter hook prerouting priority raw; policy accept;
|
||||
}
|
||||
chain OUTPUT {
|
||||
type filter hook output priority raw; policy accept;
|
||||
}
|
||||
}
|
||||
# Compatibility tables and chains for iptables-nft
|
||||
table ip filter {
|
||||
chain INPUT {
|
||||
type filter hook input priority filter; policy accept;
|
||||
}
|
||||
chain FORWARD {
|
||||
type filter hook forward priority filter; policy accept;
|
||||
}
|
||||
chain OUTPUT {
|
||||
type filter hook output priority filter; policy accept;
|
||||
}
|
||||
}
|
||||
table ip raw {
|
||||
chain PREROUTING {
|
||||
type filter hook prerouting priority raw; policy accept;
|
||||
}
|
||||
chain OUTPUT {
|
||||
type filter hook output priority raw; policy accept;
|
||||
}
|
||||
}
|
||||
table ip nat {
|
||||
chain PREROUTING {
|
||||
type nat hook prerouting priority dstnat; policy accept;
|
||||
}
|
||||
chain INPUT {
|
||||
type nat hook input priority 100; policy accept;
|
||||
}
|
||||
chain OUTPUT {
|
||||
type nat hook output priority -100; policy accept;
|
||||
}
|
||||
chain POSTROUTING {
|
||||
type nat hook postrouting priority srcnat; policy accept;
|
||||
}
|
||||
}
|
||||
|
||||
table ip6 raw {
|
||||
chain PREROUTING {
|
||||
type filter hook prerouting priority raw; policy accept;
|
||||
}
|
||||
chain OUTPUT {
|
||||
type filter hook output priority raw; policy accept;
|
||||
}
|
||||
}
|
||||
table ip6 filter {
|
||||
chain INPUT {
|
||||
type filter hook input priority filter; policy accept;
|
||||
}
|
||||
chain FORWARD {
|
||||
type filter hook forward priority filter; policy accept;
|
||||
}
|
||||
chain OUTPUT {
|
||||
type filter hook output priority filter; policy accept;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
# Copyright 2020 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
galaxy_info:
|
||||
author: OpenStack
|
||||
description: TripleO OpenStack Role -- tripleo_nftables
|
||||
company: Red Hat
|
||||
license: Apache-2.0
|
||||
min_ansible_version: 2.7
|
||||
namespace: openstack
|
||||
#
|
||||
# Provide a list of supported platforms, and for each platform a list of versions.
|
||||
# If you don't wish to enumerate all versions for a particular platform, use 'all'.
|
||||
# To view available platforms and versions (or releases), visit:
|
||||
# https://galaxy.ansible.com/api/v1/platforms/
|
||||
#
|
||||
platforms:
|
||||
- name: CentOS
|
||||
versions:
|
||||
- 8
|
||||
- 9
|
||||
|
||||
galaxy_tags:
|
||||
- tripleo
|
||||
|
||||
|
||||
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
|
||||
# if you add dependencies to this list.
|
||||
dependencies: []
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
# Copyright 2020 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
- name: Converge
|
||||
hosts: all
|
||||
roles:
|
||||
- role: "tripleo_nftables"
|
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
log: true
|
||||
|
||||
provisioner:
|
||||
name: ansible
|
||||
config_options:
|
||||
defaults:
|
||||
fact_caching: jsonfile
|
||||
fact_caching_connection: /tmp/molecule/facts
|
||||
inventory:
|
||||
hosts:
|
||||
all:
|
||||
hosts:
|
||||
instance:
|
||||
ansible_host: localhost
|
||||
log: true
|
||||
env:
|
||||
ANSIBLE_STDOUT_CALLBACK: yaml
|
||||
ANSIBLE_ROLES_PATH: "${ANSIBLE_ROLES_PATH}:${HOME}/zuul-jobs/roles"
|
||||
|
||||
scenario:
|
||||
test_sequence:
|
||||
- prepare
|
||||
- converge
|
||||
- check
|
||||
|
||||
verifier:
|
||||
name: testinfra
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
# Copyright 2020 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
- name: Prepare
|
||||
hosts: all
|
||||
tasks:
|
||||
- name: test_deps
|
||||
include_role:
|
||||
name: test_deps
|
||||
- name: Install nftables
|
||||
become: true
|
||||
package:
|
||||
name: nftables
|
|
@ -0,0 +1,137 @@
|
|||
---
|
||||
# Copyright 2022 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
# systemctl will return 0 if enabled, 3 if disabled
|
||||
- name: Get nftables service state
|
||||
ansible.builtin.command: systemctl status nftables
|
||||
register: nftables_status
|
||||
failed_when: nftables_status.rc not in [0, 3]
|
||||
|
||||
- name: Swith firewall management to nftables if needed
|
||||
when:
|
||||
- nftables_status.rc == 3
|
||||
include_tasks: service.yaml
|
||||
|
||||
- name: IPtables compatibility layout
|
||||
become: true
|
||||
block:
|
||||
- name: Push initial, empty ruleset
|
||||
register: init_nftables
|
||||
copy:
|
||||
dest: /etc/nftables/iptables.nft
|
||||
src: iptables.nft
|
||||
|
||||
- name: Load empty ruleset if needed
|
||||
when:
|
||||
- init_nftables is changed
|
||||
ansible.builtin.command: nft -f /etc/nftables/iptables.nft
|
||||
|
||||
# Get current nft rules in JSON format, with our iptables compat content.
|
||||
- name: Get current nftables content
|
||||
become: true
|
||||
ansible.builtin.command: nft -j list ruleset
|
||||
register: nft_current_rules
|
||||
|
||||
- name: nftables files generation
|
||||
become: true
|
||||
block:
|
||||
# Create a dedicated file for jumps - makes easier to manage afterward.
|
||||
# That one will be loaded upon boot only.
|
||||
- name: Generate chain jumps
|
||||
ignore_errors: "{{ ansible_check_mode|bool }}"
|
||||
vars:
|
||||
current_nft: "{{ nft_current_rules }}"
|
||||
nft_is_update: false
|
||||
template:
|
||||
dest: /etc/nftables/tripleo-jumps.nft
|
||||
src: jump-chain.j2
|
||||
|
||||
# Create a special "update chain jumps" file, adding just the MISSING
|
||||
# jumps in the main, default chains. This will avoid useless duplication
|
||||
# upon update/day-2 operation, since we cannot really flush INPUT and other
|
||||
# default chains.
|
||||
- name: Generate chain jumps
|
||||
ignore_errors: "{{ ansible_check_mode|bool }}"
|
||||
vars:
|
||||
current_nft: "{{ nft_current_rules }}"
|
||||
nft_is_update: true
|
||||
template:
|
||||
dest: /etc/nftables/tripleo-update-jumps.nft
|
||||
src: jump-chain.j2
|
||||
|
||||
# Note: we do NOT include this one for boot, since chains are
|
||||
# already empty!
|
||||
- name: Generate nft flushes
|
||||
register: nft_flushes
|
||||
template:
|
||||
dest: /etc/nftables/tripleo-flushes.nft
|
||||
src: flush-chain.j2
|
||||
|
||||
- name: Generate nft tripleo chains
|
||||
register: nft_chains
|
||||
template:
|
||||
dest: /etc/nftables/tripleo-chains.nft
|
||||
src: chains.j2
|
||||
|
||||
- name: Generate nft ruleset in static file
|
||||
register: nft_ruleset
|
||||
template:
|
||||
dest: /etc/nftables/tripleo-rules.nft
|
||||
src: ruleset.j2
|
||||
|
||||
# We cannot use the "validate" parameter from the "template" module, since
|
||||
# we don't load the chains before. So let's validate now, with all the things.
|
||||
# Remember, the "iptables" compat layout is already loaded at this point.
|
||||
- name: Validate all of the generated content before loading
|
||||
ansible.builtin.shell: >-
|
||||
cat /etc/nftables/tripleo-chains.nft
|
||||
/etc/nftables/tripleo-flushes.nft
|
||||
/etc/nftables/tripleo-rules.nft
|
||||
/etc/nftables/tripleo-update-jumps.nft
|
||||
/etc/nftables/tripleo-jumps.nft | nft -c -f -
|
||||
|
||||
# Order is important here.
|
||||
# Please keep that in mind in case you want to add some new ruleset in their
|
||||
# dedicated file!
|
||||
- name: Ensure we load our different nft rulesets on boot
|
||||
become: true
|
||||
ansible.builtin.blockinfile:
|
||||
path: /etc/sysconfig/nftables.conf
|
||||
backup: false
|
||||
validate: nft -c -f %s
|
||||
block: |
|
||||
include "/etc/nftables/iptables.nft"
|
||||
include "/etc/nftables/tripleo-chains.nft"
|
||||
include "/etc/nftables/tripleo-rules.nft"
|
||||
include "/etc/nftables/tripleo-jumps.nft"
|
||||
|
||||
- name: Create our custom chains
|
||||
become: true
|
||||
ansible.builtin.command: nft -f /etc/nftables/tripleo-chains.nft
|
||||
|
||||
# Here, we make different call in order to avoid jumps duplication.
|
||||
# In both cases, we flush the custom chains. Doing things like that ensures
|
||||
# we run all, from the flush to the rule creation, in a single transaction.
|
||||
# This prevents accidental lock-outs.
|
||||
- name: Reload custom nftables ruleset WITH jumps
|
||||
become: true
|
||||
ansible.builtin.shell: >-
|
||||
cat /etc/nftables/tripleo-flushes.nft
|
||||
/etc/nftables/tripleo-rules.nft
|
||||
/etc/nftables/tripleo-update-jumps.nft | nft -f -
|
||||
when:
|
||||
- nft_ruleset is changed
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
# Copyright 2022 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# systemctl will return 0 if success, 1 if unit not found
|
||||
- name: Ensure legacy iptables services are off
|
||||
become: true
|
||||
ansible.builtin.command: "systemctl disable --now {{ item }}"
|
||||
register: ipt_service
|
||||
failed_when:
|
||||
- ipt_service.rc not in [0, 1]
|
||||
loop:
|
||||
- iptables.service
|
||||
- ip6tables.service
|
||||
|
||||
- name: Ensure nftables service is enabled and running
|
||||
become: true
|
||||
ansible.builtin.systemd:
|
||||
name: nftables
|
||||
state: started
|
||||
enabled: true
|
|
@ -0,0 +1,8 @@
|
|||
# Create chain if needed
|
||||
{%- for ruleset in tripleo_nftables_rules %}
|
||||
{% set rule=ruleset['rule'] %}
|
||||
{%- if 'extras' not in rule or rule['extras'].get('ensure', 'present') in ['enabled', 'present'] %}
|
||||
# Create chain TRIPLEO_{{ rule.get('chain', 'INPUT') }} in {{rule.get('table', 'filter') }} table
|
||||
add chain inet {{ rule.get('table', 'filter') }} TRIPLEO_{{ rule.get('chain', 'INPUT') }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
|
@ -0,0 +1,6 @@
|
|||
{%- if 'destination' in rule %}
|
||||
{%- if 'ipversion' in rule and rule['ipversion'] == 'ipv6' %}
|
||||
ip6
|
||||
{%- endif %}
|
||||
daddr {{ rule['destination'] }}
|
||||
{%- endif %}
|
|
@ -0,0 +1,15 @@
|
|||
{%- if 'dport' in rule %}
|
||||
{%- if rule['dport'] is iterable %}
|
||||
{{ rule.get('proto', false)|ternary('', 'tcp ') }}dport { {{ rule['dport'] |join(',') }} }
|
||||
{%- else %}
|
||||
{{ rule.get('proto', false)|ternary('', 'tcp ') }}dport {{ rule['dport'] }}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{#- This is for legacy things - Really, use dport... #}
|
||||
{%- if 'port' in rule %}
|
||||
{%- if rule['port'] is iterable %}
|
||||
{{ rule.get('proto', false)|ternary('', 'tcp ') }}dport { {{ rule['port'] |join(',') }} }
|
||||
{%- else %}
|
||||
{{ rule.get('proto', false)|ternary('', 'tcp ') }}dport {{ rule['port'] }}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
|
@ -0,0 +1,7 @@
|
|||
# Managed by tripleo-ansible/tripleo_nftables
|
||||
{%- for ruleset in tripleo_nftables_rules %}
|
||||
{% set rule=ruleset['rule'] %}
|
||||
{% if 'extras' not in rule or rule['extras'].get('ensure', 'present') in ['enabled', 'present'] %}
|
||||
flush chain inet {{ rule.get('table', 'filter') }} TRIPLEO_{{ rule.get('chain', 'INPUT') }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
|
@ -0,0 +1,3 @@
|
|||
{%- if 'interface' in rule %}
|
||||
iifname {{ rule['interface'] }}
|
||||
{%- endif %}
|
|
@ -0,0 +1,4 @@
|
|||
{# We force everything into the "inet" family so that we cover both
|
||||
ip and ip6. This also ensures proper compat with iptables-nft.
|
||||
#}
|
||||
inet
|
|
@ -0,0 +1,31 @@
|
|||
# Managed by tripleo-ansible/tripleo_nftables
|
||||
{% set chains = namespace(chains=[]) %}
|
||||
{% if nft_is_update|default(false)|bool %}
|
||||
|
||||
{# Add missing jumps only (usually during day-2 operations) #}
|
||||
{% set existing = (current_nft['stdout']|from_json)['nftables']|map(attribute='rule', default={})|list %}
|
||||
{% for ruleset in tripleo_nftables_rules %}
|
||||
{% set rule=ruleset['rule'] %}
|
||||
{% set query="[? table==`"~rule.get('table', 'filter')~"` && family==`inet` && chain==`"~rule.get('chain', 'INPUT')~"`].expr[*].jump.target" %}
|
||||
{% set chain_key = rule.get('chain', 'INPUT') ~ rule.get('table', 'filter') %}
|
||||
{% if chain_key not in chains.chains %}
|
||||
{% if 'TRIPLEO_'~rule.get('chain', 'INPUT') not in (existing|json_query(query)|flatten) %}
|
||||
insert rule inet {{ rule.get('table', 'filter') }} {{ rule.get('chain', 'INPUT') }} position 0 jump TRIPLEO_{{ rule.get('chain', 'INPUT') }}
|
||||
{% endif %}
|
||||
{% set _ = chains.chains.append(chain_key) %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
|
||||
{# Insert all jumps to custom chains (usually during boot) #}
|
||||
{% for ruleset in tripleo_nftables_rules %}
|
||||
{% set rule=ruleset['rule'] %}
|
||||
{% if 'extras' not in rule or rule['extras'].get('ensure', 'present') in ['enabled', 'present'] %}
|
||||
{% set chain_key = rule.get('chain', 'INPUT') ~ rule.get('table', 'filter') %}
|
||||
{% if chain_key not in chains.chains %}
|
||||
insert rule inet {{ rule.get('table', 'filter') }} {{ rule.get('chain', 'INPUT') }} position 0 jump TRIPLEO_{{ rule.get('chain', 'INPUT') }}
|
||||
{% set _ = chains.chains.append(chain_key) %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
|
@ -0,0 +1,9 @@
|
|||
{%- if 'jump' in rule %}
|
||||
{% if (rule['jump']|lower) not in ['accept', 'drop', 'log', 'masquerade', 'notrack', 'return'] %}
|
||||
jump {{ rule['jump'] }}
|
||||
{%- else %}
|
||||
{{ rule['jump']|lower }}
|
||||
{%- endif %}
|
||||
{%- else %}
|
||||
accept
|
||||
{%- endif %}
|
|
@ -0,0 +1,3 @@
|
|||
{%- if 'limit' in rule %}
|
||||
limit rate {{ rule['limit']|regex_replace('([0-9]+)/min', '\\1/minute') }}
|
||||
{%- endif %}
|
|
@ -0,0 +1,3 @@
|
|||
{%- if 'limit_burst' in rule %}
|
||||
burst {{ rule['limit_burst'] }} packets
|
||||
{%- endif %}
|
|
@ -0,0 +1,6 @@
|
|||
{%- if 'proto' in rule and (rule['proto']|lower) != 'all' %}
|
||||
{%- if (rule['proto']|lower) not in ['tcp', 'udp'] %}
|
||||
meta l4proto
|
||||
{%- endif %}
|
||||
{{ rule['proto']|lower }}
|
||||
{%- endif %}
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/sbin/nft -f
|
||||
# Managed by tripleo-ansible/tripleo_nftables
|
||||
# Valid starting nft-0.9.8
|
||||
|
||||
{%- for ruleset in tripleo_nftables_rules %}
|
||||
{% set rule=ruleset['rule'] %}
|
||||
{% set name=ruleset['rule_name'] %}
|
||||
{%- if 'extras' not in rule or rule['extras'].get('ensure', 'present') in ['enabled', 'present'] %}
|
||||
# {{ rule.get('rule_name', name) }} {{ rule }}
|
||||
add rule
|
||||
{%- include 'templates/ipversion.j2' %}
|
||||
{{ rule.get('table', 'filter') }} TRIPLEO_{{ rule.get('chain', 'INPUT') }}
|
||||
{%- include 'templates/interface.j2' %}
|
||||
{%- include 'templates/source.j2' %}
|
||||
{%- include 'templates/sport.j2' %}
|
||||
{%- include 'templates/destination.j2' %}
|
||||
{%- include 'templates/protocol.j2' %}
|
||||
{%- include 'templates/dport.j2' %}
|
||||
{%- include 'templates/state.j2' %}
|
||||
{%- include 'templates/limit.j2' %}
|
||||
{%- include 'templates/limit_burst.j2' %}
|
||||
counter
|
||||
{%- include 'templates/jump.j2' %}
|
||||
comment "{{rule.get('rule_name', name) }}"
|
||||
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
# Lock down INPUT chains
|
||||
add chain inet filter INPUT { policy drop; }
|
|
@ -0,0 +1,6 @@
|
|||
{%- if 'source' in rule %}
|
||||
{%- if 'ipversion' not in rule %}
|
||||
ip
|
||||
{%- endif %}
|
||||
saddr {{ rule['source'] }}
|
||||
{%- endif %}
|
|
@ -0,0 +1,3 @@
|
|||
{%- if 'sport' in rule %}
|
||||
{{ rule.get('proto', false)|ternary('', 'tcp ') }}sport {{ rule['sport'] }}
|
||||
{%- endif %}
|
|
@ -0,0 +1,7 @@
|
|||
{%- if 'state' in rule %}
|
||||
{%- if rule['state']|length > 0 %}
|
||||
ct state {{ rule['state'] |join(',')|lower }}
|
||||
{%- endif %}
|
||||
{%- else %}
|
||||
ct state new
|
||||
{%- endif %}
|
|
@ -44,6 +44,7 @@
|
|||
- tripleo-ansible-centos-stream-molecule-tripleo_multipathd
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_mysql_client
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_network_config
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_nftables
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_nodes_validation
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_nova_image_cache
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_nvdimm
|
||||
|
@ -111,6 +112,7 @@
|
|||
- tripleo-ansible-centos-stream-molecule-tripleo_multipathd
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_mysql_client
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_network_config
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_nftables
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_nodes_validation
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_nova_image_cache
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_nvdimm
|
||||
|
@ -176,6 +178,7 @@
|
|||
- tripleo-ansible-centos-stream-molecule-tripleo_multipathd
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_mysql_client
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_network_config
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_nftables
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_nodes_validation
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_nova_image_cache
|
||||
- tripleo-ansible-centos-stream-molecule-tripleo_nvdimm
|
||||
|
@ -507,6 +510,13 @@
|
|||
parent: tripleo-ansible-centos-stream-base
|
||||
vars:
|
||||
tripleo_role_name: tripleo_network_config
|
||||
- job:
|
||||
files:
|
||||
- ^tripleo_ansible/roles/tripleo_nftables/(?!meta).*
|
||||
name: tripleo-ansible-centos-stream-molecule-tripleo_nftables
|
||||
parent: tripleo-ansible-centos-stream-base
|
||||
vars:
|
||||
tripleo_role_name: tripleo_nftables
|
||||
- job:
|
||||
files:
|
||||
- ^tripleo_ansible/roles/tripleo_nodes_validation/(?!meta).*
|
||||
|
|
Loading…
Reference in New Issue