Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a role to configure masquerading on hypervisor #1880

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/dictionary/en-custom.txt
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ ipam
ipi
ipmi
ips
iptables
ipv
iscsi
itldwuw
Expand Down
50 changes: 50 additions & 0 deletions roles/masquerade_external/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# masquerade_external
A role to configure masquerading of traffic going out the default interface,
based on the source address.

This is handy when libvirt networks need to have routing to different libvirt
networks on the host enabled. In `nat` mode libvirt inserts firewall rules that
prevent this. Instead of using `nat` mode for libvirt networks, the `routed` or
`open` mode can be used instead, and this role can set up the masquerading
rules so that the VMs on these networks can still reach external networks.

Example rules inserted by this role:
```bash
Chain POSTROUTING (policy ACCEPT 118 packets, 13329 bytes)
pkts bytes target prot opt in out source destination
0 0 CIFMW-PRT all -- any any anywhere anywhere

Chain CIFMW-PRT (1 references)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- any eth0 172.17.0.0/24 anywhere
0 0 MASQUERADE all -- any eth0 172.16.0.0/24 anywhere
```

## Privilege escalation
Requires privileged escalation to manipulate iptables firewall.

## Parameters
* `cifmw_masquerade_external_source_ranges`: (List) List of source IP or ip networks in CIDR format. Defaults to: `[]`
* `cifmw_masquerade_external_post_routing_chain_name`: (String) Name of the iptables chain
* `cifmw_masquerade_external_out_interface`: (String) Device name for the outgoing interface. Defaults to: `{{ hostvars[inventory_hostname].ansible_default_ipv4.interface }}`

## Examples

### Add masquerading rules for sources `172.16.0.0/24` and `172.17.0.0/24`
```yaml
- name: Include the role with var
vars:
cifmw_masquerade_external_source_ranges:
- '172.16.0.0/24'
- '172.17.0.0/24'
ansible.builtin.include_role:
name: masquerade_external
```

### Cleanup masquerading rules and chain
```yaml
- name: Include the role with var
ansible.builtin.include_role:
name: masquerade_external
tasks_from: cleanup.yml
```
23 changes: 23 additions & 0 deletions roles/masquerade_external/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
# Copyright 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 "cifmw_masquerade_external"

cifmw_masquerade_external_source_ranges: []
cifmw_masquerade_external_post_routing_chain_name: CIFMW-PRT
cifmw_masquerade_external_out_interface: "{{ hostvars[inventory_hostname].ansible_default_ipv4.interface }}"
41 changes: 41 additions & 0 deletions roles/masquerade_external/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
# Copyright 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: CI Framework
description: CI Framework Role -- masquerade_external
company: Red Hat
license: Apache-2.0
min_ansible_version: 2.14
namespace: cifmw
#
# 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:
- 9

galaxy_tags:
- cifmw

# List your role dependencies here, one per line. Be sure to remove the '[]' above,
# if you add dependencies to this list.
dependencies: []
70 changes: 70 additions & 0 deletions roles/masquerade_external/molecule/default/converge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
# Copyright 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: instance
vars:
cifmw_masquerade_external_source_ranges:
- '172.16.0.0/24'
- '172.17.0.0/24'
tasks:
- name: Insert rules
ansible.builtin.include_role:
name: masquerade_external

- name: Assert rules are present
block:
- name: List POSTROUTING chain in nat table
become: true
register: _out
ansible.builtin.command: 'iptables -t nat -L POSTROUTING -v'
- name: Assert CIFMW-PRT in POSTROUTING chain
vars:
ref: '\s*CIFMW-PRT\s*all\s*--\s*any\s*any\s*anywhere\s*anywhere'
ansible.builtin.assert:
that: _out.stdout is regex(ref)
- name: List CIFMW-PRT chain in nat table
become: true
register: _out
ansible.builtin.command: 'iptables -t nat -L CIFMW-PRT -v'
- name: Assert MASQUERADE rules in CIFMW-PRT chain
ansible.builtin.assert:
that: _out.stdout is regex(item)
loop:
- '\s*MASQUERADE\s*all\s*--\s*any\s*.*\s*172.16.0.0/24\s*anywhere'
- '\s*MASQUERADE\s*all\s*--\s*any\s*.*\s*172.17.0.0/24\s*anywhere'

- name: Cleanup rules
ansible.builtin.include_role:
name: masquerade_external
tasks_from: cleanup.yml

- name: Assert rules where removed
block:
- name: List POSTROUTING chain in nat table
become: true
register: _out
ansible.builtin.command: 'iptables -t nat -L POSTROUTING'
- name: Assert CIFMW-PRT is not in POSTROUTING chain
ansible.builtin.assert:
that: '"CIFMW-PRT" not in _out.stdout'
- name: List CIFMW-PRT chain in nat table - should fail with No chain ...
become: true
register: _out
ansible.builtin.command: 'iptables -t nat -L CIFMW-PRT -v'
failed_when:
- '"No chain/target/match by that name." not in _out.stderr'
11 changes: 11 additions & 0 deletions roles/masquerade_external/molecule/default/molecule.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
# Mainly used to override the defaults set in .config/molecule/
# By default, it uses the "config_podman.yml" - in CI, it will use
# "config_local.yml".
log: true

provisioner:
name: ansible
log: true
env:
ANSIBLE_STDOUT_CALLBACK: yaml
21 changes: 21 additions & 0 deletions roles/masquerade_external/molecule/default/prepare.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
# Copyright 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
42 changes: 42 additions & 0 deletions roles/masquerade_external/tasks/cleanup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
# Copyright 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: Ensure cifmw post routing chain in POSTROUTING is removed
become: true
ansible.builtin.iptables:
state: absent
table: nat
chain: POSTROUTING
jump: "{{ cifmw_masquerade_external_post_routing_chain_name }}"

- name: Ensure cifmw post routing chain is flushed
become: true
register: _flush
ansible.builtin.iptables:
table: nat
chain: "{{ cifmw_masquerade_external_post_routing_chain_name }}"
flush: true
failed_when:
- '_flush.rc is defined and _flush.rc != 0'
- '"No chain/target/match by that name." not in _flush.stderr'

- name: Ensure cifmw post routing chain is removed
become: true
ansible.builtin.iptables:
state: absent
table: nat
chain_management: true
chain: "{{ cifmw_masquerade_external_post_routing_chain_name }}"
37 changes: 37 additions & 0 deletions roles/masquerade_external/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
# Copyright 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: Ensure masquerading rules in cifmw post routing chain
become: true
ansible.builtin.iptables:
state: present
action: insert
table: nat
chain_management: true
chain: "{{ cifmw_masquerade_external_post_routing_chain_name }}"
source: "{{ item }}"
out_interface: "{{ cifmw_masquerade_external_out_interface }}"
jump: "MASQUERADE"
loop: "{{ cifmw_masquerade_external_source_ranges }}"

- name: Ensure cifmw post routing chain in POSTROUTING
become: true
ansible.builtin.iptables:
state: present
action: insert
table: nat
chain: POSTROUTING
jump: "{{ cifmw_masquerade_external_post_routing_chain_name }}"
5 changes: 5 additions & 0 deletions roles/reproducer/tasks/cleanup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,8 @@

- name: Ensure handlers are flushed
ansible.builtin.meta: flush_handlers

- name: Clean up masquerading rules
ansible.builtin.import_role:
name: masquerade_external
tasks_from: cleanup.yml
12 changes: 12 additions & 0 deletions roles/reproducer/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,18 @@
- bootstrap_env
- bootstrap_layout

- name: Masquerade libvirt networks
when:
- cifmw_use_libvirt | default(false) | bool
- cifmw_masquerade_networks | default(false) | bool
- cifmw_masquerade_external_source_ranges is defined
- cifmw_masquerade_external_source_ranges | length > 0
tags:
- bootstrap_layout
- bootstrap_env
ansible.builtin.include_role:
name: masquerade_external

- name: Bootstrap nat64 if needed
when:
- cifmw_use_libvirt | default(false) | bool
Expand Down
11 changes: 11 additions & 0 deletions zuul.d/molecule.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,17 @@
parent: cifmw-molecule-base
vars:
TEST_RUN: manage_secrets
- job:
files:
- ^common-requirements.txt
- ^test-requirements.txt
- ^roles/masquerade_external/(?!meta|README).*
- ^ci/playbooks/molecule.*
- ^.config/molecule/.*
name: cifmw-molecule-masquerade_external
parent: cifmw-molecule-base
vars:
TEST_RUN: masquerade_external
- job:
files:
- ^common-requirements.txt
Expand Down
1 change: 1 addition & 0 deletions zuul.d/projects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
- cifmw-molecule-kustomize_deploy
- cifmw-molecule-libvirt_manager
- cifmw-molecule-manage_secrets
- cifmw-molecule-masquerade_external
- cifmw-molecule-mirror_registry
- cifmw-molecule-nat64_appliance
- cifmw-molecule-networking_mapper
Expand Down