diff --git a/.github/workflows/molecule-firewalld.yml b/.github/workflows/molecule-firewalld.yml new file mode 100644 index 00000000..15ac044b --- /dev/null +++ b/.github/workflows/molecule-firewalld.yml @@ -0,0 +1,39 @@ +name: Test firewalld +on: + pull_request: + paths: + - "roles/firewalld/**" + +jobs: + molecule-firewalld: + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + scenario: + - centos7 + env: + MOLECULE_RUN_TAGS: firewalld + PY_COLORS: 1 + ANSIBLE_FORCE_COLOR: 1 + steps: + - name: Check out the codebase + uses: actions/checkout@v4 + with: + path: ansible_collections/mirsg/infrastructure + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.11 + + - name: Install test dependencies + run: | + sudo apt-get update && sudo apt-get -y install rsync + python3 -m pip install --upgrade pip + python3 -m pip install ansible molecule molecule-plugins[docker] docker requests + + - name: Test with molecule + run: | + cd ansible_collections/mirsg/infrastructure/tests + molecule test --scenario-name "${{ matrix.scenario }}" diff --git a/.github/workflows/molecule-provision.yml b/.github/workflows/molecule-provision.yml index bc14f598..b9447b16 100644 --- a/.github/workflows/molecule-provision.yml +++ b/.github/workflows/molecule-provision.yml @@ -5,7 +5,7 @@ on: - "roles/provision/**" jobs: - molecule: + molecule-provision: runs-on: ubuntu-latest strategy: fail-fast: true diff --git a/roles/firewalld/README.md b/roles/firewalld/README.md index 2966283e..634f48c7 100644 --- a/roles/firewalld/README.md +++ b/roles/firewalld/README.md @@ -57,28 +57,10 @@ See `defaults/main.yml` for the full list. - `rich_rules`: A list of hashes defining rich rules to apply. The zone to apply the rule to should be a key in the hash. -## Installation - -Include in a `requirements.yml` file as follows: - -```yaml -- src: https://github.com/UCL-MIRSG/ansible-role-dual-vm-firewalld.git - version: 2022.12.22.0 - name: mirsg.firewalld -``` - ## Example Playbook ```yaml - hosts: servers roles: - - { role: mirsg.firewalld } + - role: mirsg.infrastructure.firewalld ``` - -## License - -[BSD 3-Clause License](https://github.com/UCL-MIRSG/ansible-role-postgresql/blob/main/LICENSE). - -## Author Information - -This role was created by the [Medical Imaging Research Software Group](https://www.ucl.ac.uk/advanced-research-computing/expertise/research-software-development/medical-imaging-research-software-group) at [UCL](https://www.ucl.ac.uk/). diff --git a/tests/molecule/centos7/molecule.yml b/tests/molecule/centos7/molecule.yml index ba996f8c..b830ec60 100644 --- a/tests/molecule/centos7/molecule.yml +++ b/tests/molecule/centos7/molecule.yml @@ -48,6 +48,8 @@ provisioner: group_vars: ../resources/inventory/group_vars/ playbooks: converge: ../resources/converge.yml + prepare: ../resources/prepare.yml + verify: ../resources/verify.yml env: ANSIBLE_VERBOSITY: "1" diff --git a/tests/molecule/resources/converge.yml b/tests/molecule/resources/converge.yml index fe594211..8eacb225 100644 --- a/tests/molecule/resources/converge.yml +++ b/tests/molecule/resources/converge.yml @@ -8,3 +8,5 @@ tags: provision - role: mirsg.infrastructure.install_python tags: python + - role: mirsg.infrastructure.firewalld + tags: firewalld diff --git a/tests/molecule/resources/inventory/group_vars/all.yml b/tests/molecule/resources/inventory/group_vars/all.yml index 158dae9c..614f72d8 100644 --- a/tests/molecule/resources/inventory/group_vars/all.yml +++ b/tests/molecule/resources/inventory/group_vars/all.yml @@ -3,3 +3,20 @@ EXTERNAL_STORAGE_DRIVE: "/storage/molecule" # mirsg.infrastructure.provision server_locale: "en_GB.UTF-8" + +# mirsg.infrastructure.firewalld +allow_public_access: true +internal_zone_open_services: + - http + - https + - ssh +public_zone_open_services: + - http + - https +work_zone_open_services: + - http + - https +public_zone_ports: + - "8080" +internal_zone_ports: + - "5432" diff --git a/tests/molecule/resources/prepare.yml b/tests/molecule/resources/prepare.yml new file mode 100644 index 00000000..d6743a87 --- /dev/null +++ b/tests/molecule/resources/prepare.yml @@ -0,0 +1,18 @@ +--- +- name: Install firewalld + hosts: all + gather_facts: true + tasks: + - name: Install and configure firewalld + tags: firewalld + block: + - name: Install firewalld + ansible.builtin.package: + name: firewalld + state: present + + - name: Change firewalld backend to iptables + ansible.builtin.lineinfile: + path: /etc/firewalld/firewalld.conf + regexp: "^FirewallBackend=" + line: FirewallBackend=iptables diff --git a/tests/molecule/resources/verify-firewalld.yml b/tests/molecule/resources/verify-firewalld.yml new file mode 100644 index 00000000..4c52ac7a --- /dev/null +++ b/tests/molecule/resources/verify-firewalld.yml @@ -0,0 +1,88 @@ +--- +- name: Get services in internal zone + become: true + ansible.builtin.shell: | + set -o pipefail + firewall-cmd --list-services --zone=internal + register: internal_zone_services + changed_when: false + failed_when: false + +- name: Get services in public zone + become: true + ansible.builtin.shell: | + set -o pipefail + firewall-cmd --list-services --zone=public + register: public_zone_services + changed_when: false + failed_when: false + +- name: Get services in work zone + become: true + ansible.builtin.shell: | + set -o pipefail + firewall-cmd --list-services --zone=work + register: work_zone_services + changed_when: false + failed_when: false + +- name: Test that correct services are in internal zone + ansible.builtin.assert: + that: + - "'{{ item }}' in internal_zone_services.stdout" + loop: "{{ internal_zone_open_services }}" + when: internal_zone_open_services is defined + +- name: Test that correct services are in public zone + ansible.builtin.assert: + that: + - "'{{ item }}' in public_zone_services.stdout" + loop: "{{ public_zone_open_services }}" + when: public_zone_open_services is defined + +- name: Test that correct services are in work zone + ansible.builtin.assert: + that: + - "'{{ item }}' in work_zone_services.stdout" + loop: "{{ work_zone_open_services }}" + when: work_zone_open_services is defined + +- name: Test that internal zone is closed to the correct services + ansible.builtin.assert: + that: + - "'{{ item }}' not in internal_zone_services.stdout" + loop: "{{ internal_zone_closed_services }}" + when: internal_zone_closed_services is defined + +- name: Test that public zone is closed to the correct services + ansible.builtin.assert: + that: + - "'{{ item }}' not in public_zone_services.stdout" + loop: "{{ public_zone_closed_services }}" + when: public_zone_closed_services is defined + +- name: Test that work zone is closed to the correct services + ansible.builtin.assert: + that: + - "'{{ item }}' not in work_zone_services.stdout" + loop: "{{ work_zone_closed_services }}" + when: work_zone_closed_services is defined + +- name: Get firewall default zone + become: true + ansible.builtin.shell: | + set -o pipefail + firewall-cmd --get-default-zone + register: firewall_default_zone + changed_when: false + failed_when: false + +- name: Assert that public is the default zone + ansible.builtin.assert: + that: "'public' in firewall_default_zone.stdout" + when: allow_public_access + +- name: Assert that drop is the default zone + ansible.builtin.assert: + that: "'drop' in firewall_default_zone.stdout" + when: not allow_public_access diff --git a/tests/molecule/resources/verify.yml b/tests/molecule/resources/verify.yml new file mode 100644 index 00000000..31fea53b --- /dev/null +++ b/tests/molecule/resources/verify.yml @@ -0,0 +1,13 @@ +--- +- name: Verify + hosts: all + gather_facts: false + tasks: + - name: Verify firewalld + ansible.builtin.include_tasks: + file: verify-firewalld.yml + apply: + tags: + - firewalld + tags: + - firewalld