├── tests
├── inventory
└── test.yml
├── .gitignore
├── handlers
└── main.yml
├── molecule
├── default
│ ├── INSTALL.rst
│ ├── prepare.yml
│ ├── converge.yml
│ ├── molecule.yml
│ └── verify.yml
└── second-change
│ ├── molecule.yml
│ ├── converge.yml
│ └── verify.yml
├── meta
└── main.yml
├── .yamllint
├── LICENSE
├── .travis.yml
├── defaults
└── main.yml
├── .gitlab-ci.yml
├── README.md
└── tasks
└── main.yml
/tests/inventory:
--------------------------------------------------------------------------------
1 | localhost
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vaultpass
2 | .retry
3 | secret
4 | *.secret
5 | .venv
6 | .vscode
7 | *.tmp
8 |
--------------------------------------------------------------------------------
/tests/test.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - hosts: localhost
3 | remote_user: root
4 | roles:
5 | - ryandaniels.firewalld
6 |
--------------------------------------------------------------------------------
/handlers/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Reload firewalld
3 | #command: firewall-cmd --reload
4 | systemd:
5 | name: firewalld
6 | state: reloaded
7 | when: firewalld_managed|bool and stat_service_firewalld_status.rc == 0
8 |
--------------------------------------------------------------------------------
/molecule/default/INSTALL.rst:
--------------------------------------------------------------------------------
1 | *******
2 | Docker driver installation guide
3 | *******
4 |
5 | Requirements
6 | ============
7 |
8 | * Docker Engine
9 |
10 | Install
11 | =======
12 |
13 | Please refer to the `Virtual environment`_ documentation for installation best
14 | practices. If not using a virtual environment, please consider passing the
15 | widely recommended `'--user' flag`_ when invoking ``pip``.
16 |
17 | .. _Virtual environment: https://virtualenv.pypa.io/en/latest/
18 | .. _'--user' flag: https://packaging.python.org/tutorials/installing-packages/#installing-to-the-user-site
19 |
20 | .. code-block:: bash
21 |
22 | $ pip install 'molecule[docker]'
23 |
--------------------------------------------------------------------------------
/meta/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | galaxy_info:
3 | role_name: firewalld
4 | author: Ryan Daniels
5 | description: Role to manage firewalld configuration using simple variables. All changes made in "offline" mode to prevent blocking existing services.
6 | license: MIT
7 | min_ansible_version: 2.3
8 | platforms:
9 | - name: EL
10 | versions:
11 | - 7
12 | - 8
13 | - name: Fedora
14 | versions:
15 | - 30
16 | - 31
17 | - name: ArchLinux
18 | versions:
19 | - all
20 | galaxy_tags:
21 | - firewalld
22 | - firewall
23 | - system
24 | - security
25 | - networking
26 | - tcp
27 | - port
28 |
29 | dependencies: []
30 |
--------------------------------------------------------------------------------
/.yamllint:
--------------------------------------------------------------------------------
1 | ---
2 | # Based on ansible-lint config
3 | extends: default
4 |
5 | rules:
6 | braces:
7 | max-spaces-inside: 1
8 | level: error
9 | brackets:
10 | max-spaces-inside: 1
11 | level: error
12 | colons:
13 | max-spaces-after: -1
14 | level: error
15 | commas:
16 | max-spaces-after: -1
17 | level: error
18 | comments: disable
19 | comments-indentation: disable
20 | document-start: disable
21 | empty-lines:
22 | max: 3
23 | level: error
24 | hyphens:
25 | level: error
26 | indentation: disable
27 | key-duplicates: enable
28 | line-length: disable
29 | new-line-at-end-of-file: disable
30 | new-lines:
31 | type: unix
32 | trailing-spaces: disable
33 | truthy: disable
34 |
--------------------------------------------------------------------------------
/molecule/second-change/molecule.yml:
--------------------------------------------------------------------------------
1 | ---
2 | dependency:
3 | name: galaxy
4 | driver:
5 | name: docker
6 | # lint: |
7 | # set -e
8 | # yamllint .
9 | # ansible-lint
10 | # lint: ansible-lint
11 | # platforms:
12 | # - name: instance
13 | # image: docker.io/pycontribs/centos:7
14 | # pre_build_image: true
15 | platforms:
16 | - name: instance
17 | privileged: true
18 | # image: centos:7
19 | image: ${MOLECULE_DISTRO:-centos:7}
20 | command: ${MOLECULE_DOCKER_COMMAND:-"/sbin/init"}
21 | # command: /sbin/init
22 | tmpfs:
23 | - /run
24 | - /tmp
25 | volumes:
26 | - /sys/fs/cgroup:/sys/fs/cgroup:ro
27 | provisioner:
28 | name: ansible
29 | # playbooks:
30 | # converge: ${MOLECULE_PLAYBOOK:-converge.yml}
31 | verifier:
32 | name: ansible
33 | # directory: ../tests/
34 | scenario:
35 | test_sequence:
36 | # - create
37 | # - prepare
38 | - converge
39 | - verify
40 | - cleanup
41 | - destroy
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Ryan Daniels
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | ---
2 | language: python
3 | # python: "2.7"
4 | services: docker
5 |
6 | # Use the new container infrastructure
7 | sudo: false
8 |
9 | # Install ansible
10 | addons:
11 | apt:
12 | packages:
13 | - python-pip
14 |
15 | env:
16 | global:
17 | - ROLE_NAME: firewalld
18 | matrix:
19 | - MOLECULE_DISTRO: centos:7
20 | - MOLECULE_DISTRO: centos:8
21 | # Fedora 29 has problem with ip6tables kernel module
22 | # - MOLECULE_DISTRO: fedora:29
23 | # - MOLECULE_DISTRO: fedora:30
24 | - MOLECULE_DISTRO: fedora:31
25 | # - MOLECULE_DISTRO: archlinux
26 |
27 | install:
28 | # Install ansible
29 | - pip install ansible ansible-lint 'molecule[docker]'
30 |
31 | # Check ansible version
32 | - ansible --version
33 |
34 | # Create ansible.cfg with correct roles_path
35 | - printf '[defaults]\nroles_path=../' >ansible.cfg
36 |
37 | before_script:
38 | # Use actual Ansible Galaxy role name for the project directory.
39 | - cd ../
40 | - mv ansible-role-$ROLE_NAME ryandaniels.$ROLE_NAME
41 | - cd ryandaniels.$ROLE_NAME
42 |
43 | script:
44 | # Basic role syntax check
45 | - ansible-playbook tests/test.yml -i tests/inventory --syntax-check
46 | # - molecule test
47 | - molecule test --destroy=never && molecule test --scenario-name second-change
48 | # - molecule destroy
49 |
50 | notifications:
51 | webhooks: https://galaxy.ansible.com/api/v1/notifications/
52 |
--------------------------------------------------------------------------------
/defaults/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | debug_enabled_default: false
3 | proxy_env: []
4 | #Do not change firewalld_reload_hint_result
5 | firewalld_reload_hint_result: false
6 |
7 | firewalld_managed: false
8 | firewalld_show_config: true
9 | firewalld_check_problem_service_managed: true
10 | firewalld_check_problem_service:
11 | - docker.service
12 | firewalld_start: false
13 | firewalld_managed_pkg: true
14 | firewalld_packages:
15 | - firewalld
16 |
17 | firewalld_public_remove_default: []
18 | # firewalld_public_remove_default:
19 | # - mdns
20 | # - samba-client
21 |
22 | firewalld_internal_remove_default: []
23 | # firewalld_internal_remove_default:
24 | # - mdns
25 | # - samba-client
26 |
27 | firewalld_zone_source: []
28 | # firewalld_zone_source:
29 | # - zone: internal
30 | # state: enabled
31 | # # state: disabled
32 | # source:
33 | # - "192.168.22.64/26"
34 | # - "192.168.23.64/26"
35 | # - zone: internal
36 | # # state: enabled
37 | # state: disabled
38 | # source:
39 | # - "192.168.32.64/26"
40 | # - "192.168.33.64/26"
41 | # - zone: public
42 | # # state: enabled
43 | # state: disabled
44 | # source:
45 | # - "192.168.48.192/26"
46 | # - "192.168.49.192/26"
47 |
48 | firewalld_custom_service: []
49 | # firewalld_custom_service:
50 | # - name: app123-public
51 | # zone: public
52 | # # state: disabled
53 | # state: enabled
54 | # description: app123 firewall rules for public zone
55 | # port_protocol:
56 | # - 5000/tcp
57 | # - name: app123-internal
58 | # zone: internal
59 | # # state: disabled
60 | # state: enabled
61 | # description: app123 firewall rules for internal zone
62 | # port_protocol:
63 | # - 8080/tcp
64 | # - 9000/tcp
65 | # - name: zabbix-agent
66 | # zone: public
67 | # state: enabled
68 | # port_protocol:
69 | # # - 10050/tcp
70 | # - 3333/tcp
71 | # - name: openvpn
72 | # zone: public
73 | # state: enabled
74 |
--------------------------------------------------------------------------------
/molecule/default/prepare.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Prepare
3 | hosts: all
4 | vars:
5 | proxy_env: []
6 |
7 | tasks:
8 |
9 | #Fix for CentOS 7 on OpenVZ virtualization / custom kernel missing modules needed by firewalld
10 | #source: https://www.getpagespeed.com/server-setup/fix-firewalld-in-centos-7
11 | # MODULES_DIR=/lib/modules/$(uname -r)
12 | # mkdir -p ${MODULES_DIR}
13 | # # touch ${MODULES_DIR}/modules.{builtin,order}
14 | # /bin/truncate --size=0 ${MODULES_DIR}/modules.builtin
15 | # /bin/truncate --size=0 ${MODULES_DIR}/modules.order
16 | # for i in /sys/module/*; do echo kernel/${i##**/}.ko; done >> ${MODULES_DIR}/modules.builtin
17 | # depmod -a
18 |
19 | - name: firewalld | Install packages dependencies for OpenVZ / custom kernel workaround
20 | package:
21 | name: kmod
22 | update_cache: yes
23 | state: installed
24 | environment: "{{ proxy_env }}"
25 | when:
26 | - ansible_virtualization_type|lower == "docker"
27 | - ansible_os_family|lower == "redhat"
28 |
29 | - name: firewalld | fix OpenVZ virtualization or custom kernel missing kernel modules
30 | shell: MODULES_DIR=/lib/modules/$(uname -r) && \
31 | mkdir -p ${MODULES_DIR} && \
32 | /bin/truncate --size=0 ${MODULES_DIR}/modules.builtin && \
33 | /bin/truncate --size=0 ${MODULES_DIR}/modules.order && \
34 | for i in /sys/module/*; do echo kernel/${i##**/}.ko; done >> ${MODULES_DIR}/modules.builtin && \
35 | depmod -a
36 | register: cmd
37 | # failed_when: false
38 | ignore_errors: true
39 | # changed_when: false
40 | # no_log: True
41 | when:
42 | - ansible_virtualization_type|lower == "docker"
43 | - ansible_os_family|lower == "redhat"
44 |
45 | # - name: debug fix OpenVZ output
46 | # debug: var=cmd
47 | # when:
48 | # # - ansible_os_family == "RedHat"
49 | # # - ansible_distribution_major_version == '7'
50 | # # - firewalld_managed|bool
51 | # - ansible_virtualization_type|lower == "docker"
52 | # - ansible_os_family|lower == "redhat"
53 | # # - debug_enabled_default|bool
54 |
--------------------------------------------------------------------------------
/molecule/second-change/converge.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Converge
3 | hosts: all
4 | become: true
5 |
6 | vars:
7 | debug_enabled_default: false
8 | firewalld_managed: true
9 | firewalld_start: true
10 | firewalld_managed_pkg: true
11 | firewalld_packages:
12 | - firewalld
13 |
14 | # firewalld_public_remove_default: []
15 | firewalld_public_remove_default:
16 | - mdns
17 | - samba-client
18 |
19 | # firewalld_internal_remove_default: []
20 | firewalld_internal_remove_default:
21 | - mdns
22 | - samba-client
23 |
24 | # firewalld_zone_source: []
25 | firewalld_zone_source:
26 | - zone: internal
27 | # state: enabled
28 | state: disabled
29 | source:
30 | - "192.168.22.64/26"
31 | - "192.168.23.64/26"
32 | - zone: internal
33 | state: enabled
34 | # state: disabled
35 | source:
36 | - "192.168.32.64/26"
37 | - "192.168.33.64/26"
38 | - zone: public
39 | # state: enabled
40 | state: disabled
41 | source:
42 | - "192.168.48.192/26"
43 | - "192.168.49.192/26"
44 |
45 | # firewalld_custom_service: []
46 | firewalld_custom_service:
47 | - name: app123-public
48 | zone: public
49 | state: disabled
50 | # state: enabled
51 | description: app123 firewall rules for public zone
52 | port_protocol:
53 | - 5000/tcp
54 | - name: app123-internal
55 | zone: internal
56 | # state: disabled
57 | state: enabled
58 | description: app123 firewall rules for internal zone
59 | port_protocol:
60 | - 8089/tcp
61 | - 8501/udp
62 | - 9000/tcp
63 | - name: zabbix-agent
64 | zone: public
65 | state: enabled
66 | port_protocol:
67 | # - 10050/tcp
68 | - 3333/tcp
69 | - name: openvpn
70 | zone: public
71 | state: enabled
72 |
73 | tasks:
74 | - name: "Include firewalld"
75 | include_role:
76 | name: "ryandaniels.firewalld"
77 |
--------------------------------------------------------------------------------
/molecule/default/converge.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Converge
3 | hosts: all
4 | become: true
5 |
6 | vars:
7 | debug_enabled_default: false
8 | firewalld_managed: true
9 | firewalld_show_config: false
10 | firewalld_check_problem_service_managed: true
11 | firewalld_start: true
12 | firewalld_managed_pkg: true
13 | firewalld_packages:
14 | - firewalld
15 |
16 | # firewalld_public_remove_default: []
17 | firewalld_public_remove_default:
18 | - mdns
19 | - samba-client
20 |
21 | # firewalld_internal_remove_default: []
22 | firewalld_internal_remove_default:
23 | - mdns
24 | - samba-client
25 |
26 | # firewalld_zone_source: []
27 | firewalld_zone_source:
28 | - zone: internal
29 | state: enabled
30 | # state: disabled
31 | source:
32 | - "192.168.22.64/26"
33 | - "192.168.23.64/26"
34 | - zone: internal
35 | # state: enabled
36 | state: disabled
37 | source:
38 | - "192.168.32.64/26"
39 | - "192.168.33.64/26"
40 | - zone: public
41 | # state: enabled
42 | state: disabled
43 | source:
44 | - "192.168.48.192/26"
45 | - "192.168.49.192/26"
46 |
47 | # firewalld_custom_service: []
48 | firewalld_custom_service:
49 | - name: app123-public
50 | zone: public
51 | # state: disabled
52 | state: enabled
53 | description: app123 firewall rules for public zone
54 | port_protocol:
55 | - 5000/tcp
56 | - name: app123-internal
57 | zone: internal
58 | # state: disabled
59 | state: enabled
60 | description: app123 firewall rules for internal zone
61 | port_protocol:
62 | - 8080/tcp
63 | - 8500/udp
64 | - 9000/tcp
65 | - name: zabbix-agent
66 | zone: public
67 | state: enabled
68 | port_protocol:
69 | # - 10050/tcp
70 | - 3333/tcp
71 | - name: openvpn
72 | zone: public
73 | state: enabled
74 |
75 | tasks:
76 | - name: "Include firewalld"
77 | include_role:
78 | name: "ryandaniels.firewalld"
79 |
--------------------------------------------------------------------------------
/molecule/default/molecule.yml:
--------------------------------------------------------------------------------
1 | ---
2 | dependency:
3 | name: galaxy
4 | driver:
5 | name: docker
6 | # lint: |
7 | # set -e
8 | # yamllint .
9 | # ansible-lint
10 | lint: ansible-lint
11 | # platforms:
12 | # - name: instance
13 | # image: docker.io/pycontribs/centos:7
14 | # pre_build_image: true
15 | platforms:
16 | - name: instance
17 | privileged: true
18 | # image: centos:7.6.1810
19 | # image: centos:7.7.1908
20 | # image: centos:7
21 | image: ${MOLECULE_DISTRO:-centos:7}
22 | # command: /sbin/init
23 | # image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos7}-ansible:latest"
24 | command: ${MOLECULE_DOCKER_COMMAND:-"/sbin/init"}
25 | # pre_build_image: true
26 | # Only enable this if variable exists
27 | buildargs:
28 | http_proxy: ${http_proxy-""}
29 | https_proxy: ${https_proxy-""}
30 | tmpfs:
31 | - /run
32 | - /tmp
33 | volumes:
34 | - /sys/fs/cgroup:/sys/fs/cgroup:ro
35 | provisioner:
36 | name: ansible
37 | log: false
38 | # playbooks:
39 | # converge: ${MOLECULE_PLAYBOOK:-converge.yml}
40 | verifier:
41 | name: ansible
42 | # directory: ../tests/
43 | scenario:
44 | test_sequence:
45 | - dependency
46 | - lint
47 | - cleanup
48 | - destroy
49 | - syntax
50 | - create
51 | - prepare
52 | - converge
53 | - idempotence
54 | - side_effect
55 | - verify
56 | - cleanup
57 | - destroy
58 | # scenario:
59 | # create_sequence:
60 | # - dependency
61 | # - create
62 | # - prepare
63 | # check_sequence:
64 | # - dependency
65 | # - cleanup
66 | # - destroy
67 | # - create
68 | # - prepare
69 | # - converge
70 | # - check
71 | # - destroy
72 | # converge_sequence:
73 | # - dependency
74 | # - create
75 | # - prepare
76 | # - converge
77 | # destroy_sequence:
78 | # - dependency
79 | # - cleanup
80 | # - destroy
81 | # test_sequence:
82 | # - dependency
83 | # - lint
84 | # - cleanup
85 | # - destroy
86 | # - syntax
87 | # - create
88 | # - prepare
89 | # - converge
90 | # - idempotence
91 | # - side_effect
92 | # - verify
93 | # - cleanup
94 | # - destroy
95 |
--------------------------------------------------------------------------------
/molecule/second-change/verify.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Verify
3 | hosts: all
4 | tasks:
5 |
6 | - name: Check firewalld running
7 | command: systemctl status firewalld warn=false
8 | # register: stat_service_firewalld_status
9 | # ignore_errors: true
10 | changed_when: false
11 | # no_log: True
12 | # failed_when: not stat_service_firewalld_status.rc == 0
13 |
14 | # - debug: var=stat_service_firewalld_status
15 |
16 | - name: Check source ip removed from internal zone
17 | command: firewall-cmd --permanent --zone=internal --query-source=192.168.22.64/26
18 | register: cmd
19 | # ignore_errors: true
20 | changed_when: false
21 | failed_when: not cmd.rc == 1
22 |
23 | - name: Check source ip added to internal zone
24 | command: firewall-cmd --permanent --zone=internal --query-source=192.168.32.64/26
25 | register: cmd
26 | # ignore_errors: true
27 | changed_when: false
28 | # failed_when: not cmd.rc == 1
29 |
30 | - name: Check service removed
31 | command: firewall-cmd --permanent --zone=public --query-service=app123-public
32 | register: cmd
33 | # ignore_errors: true
34 | changed_when: false
35 | failed_when: not cmd.rc == 1
36 |
37 | #Can't query port since service is gone.
38 | # - name: Check port not added to custom service when disabled
39 | # command: firewall-cmd --permanent --service=app123-public --query-port=5000/tcp
40 | # register: cmd
41 | # ignore_errors: true
42 | # changed_when: false
43 | # failed_when: not cmd.rc == 1
44 |
45 | - name: Check tcp port added to custom service
46 | command: firewall-cmd --permanent --service=app123-internal --query-port=8089/tcp
47 | register: cmd
48 | # ignore_errors: true
49 | changed_when: false
50 | # failed_when: not cmd.rc == 0
51 |
52 | - name: Check port not added to custom service when removed from config
53 | command: firewall-cmd --permanent --service=app123-internal --query-port=8080/tcp
54 | register: cmd
55 | # ignore_errors: true
56 | changed_when: false
57 | failed_when: not cmd.rc == 1
58 |
59 | - name: Check udp port added to custom service
60 | command: firewall-cmd --permanent --service=app123-internal --query-port=8501/udp
61 | register: cmd
62 | # ignore_errors: true
63 | changed_when: false
64 | # failed_when: not cmd.rc == 0
65 |
--------------------------------------------------------------------------------
/.gitlab-ci.yml:
--------------------------------------------------------------------------------
1 | ---
2 | image: quay.io/ansible/molecule:3.0.2
3 | services:
4 | - name: docker:dind
5 | entrypoint: ["dockerd-entrypoint.sh"]
6 |
7 | stages:
8 | - tests
9 |
10 | variables:
11 | GIT_STRATEGY: clone
12 | # DOCKER_HOST: "tcp://localhost:2375"
13 | DOCKER_TLS_CERTDIR: ""
14 |
15 | .molecule_test:
16 | variables:
17 | DOCKER_HOST: "tcp://docker:2375"
18 | PY_COLORS: 1
19 | tags:
20 | - docker
21 | before_script:
22 | - export ROLE_NAME=firewalld
23 | # - apk update && apk add --no-cache py3-pip
24 | - python3 -m pip install ansible-lint==4.2.0
25 | - docker -v
26 | - python3 --version
27 | - ansible --version
28 | - molecule --version
29 | - ansible-lint --version
30 | # Use actual Ansible Galaxy role name for the project directory.
31 | - cd ../
32 | # - mv ansible-role-$ROLE_NAME ryandaniels.$ROLE_NAME
33 | # - cd ryandaniels.$ROLE_NAME
34 | - ln -s ansible-role-$ROLE_NAME ryandaniels.$ROLE_NAME
35 | - cd ryandaniels.$ROLE_NAME
36 | script:
37 | - molecule test --destroy=never && molecule test --scenario-name second-change
38 | # - molecule destroy
39 | # - sleep 3600
40 | # only:
41 | # refs:
42 | # - branches
43 | # - tags
44 | # - merge_requests
45 | # except:
46 | # changes:
47 | # - "**/*.{md,rst,gitignore}"
48 | # - "meta/*"
49 |
50 | molecule-centos7:
51 | stage: tests
52 | extends: .molecule_test
53 | variables:
54 | MOLECULE_DISTRO: "centos:7"
55 |
56 | molecule-centos8:
57 | stage: tests
58 | extends: .molecule_test
59 | variables:
60 | MOLECULE_DISTRO: "centos:8"
61 |
62 | molecule-fedora31:
63 | stage: tests
64 | extends: .molecule_test
65 | variables:
66 | MOLECULE_DISTRO: "fedora:31"
67 |
68 | #much slower but works
69 | # image: docker:git
70 | # services:
71 | # - docker:dind
72 |
73 | # stages:
74 | # - tests
75 |
76 | # before_script:
77 | # - export ROLE_NAME=firewalld
78 | # - apk update && apk add --no-cache docker
79 | # python3-dev py3-pip docker gcc git curl build-base
80 | # autoconf automake py3-cryptography linux-headers
81 | # musl-dev libffi-dev openssl-dev openssh
82 | # - python3 -m pip install ansible molecule docker ansible-lint
83 | # - docker -v
84 | # - python3 --version
85 | # - ansible --version
86 | # - molecule --version
87 | # - ansible-lint --version
88 | # # Use actual Ansible Galaxy role name for the project directory.
89 | # - cd ../
90 | # # - mv ansible-role-$ROLE_NAME ryandaniels.$ROLE_NAME
91 | # # - cd ryandaniels.$ROLE_NAME
92 | # - ln -s ansible-role-$ROLE_NAME ryandaniels.$ROLE_NAME
93 | # - cd ryandaniels.$ROLE_NAME
94 |
95 | # molecule-centos7:
96 | # stage: tests
97 | # script:
98 | # - export MOLECULE_DISTRO="centos:7"
99 | # - molecule test --destroy=never && molecule test --scenario-name second-change
100 | # - molecule destroy
101 |
102 | # molecule-fedora31:
103 | # stage: tests
104 | # script:
105 | # - export MOLECULE_DISTRO="fedora:31"
106 | # - molecule test --destroy=never && molecule test --scenario-name second-change
107 | # - molecule destroy
108 |
--------------------------------------------------------------------------------
/molecule/default/verify.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Verify
3 | hosts: all
4 | tasks:
5 |
6 | # - name: show setup
7 | # setup:
8 | # gather_subset:
9 | # - 'all'
10 | # register: stat_setup
11 |
12 | # - name: debug stat_setup
13 | # debug: var=stat_setup
14 |
15 | - name: Check firewalld running
16 | command: systemctl status firewalld warn=false
17 | # register: stat_service_firewalld_status
18 | # ignore_errors: true
19 | changed_when: false
20 | # no_log: True
21 | # failed_when: not stat_service_firewalld_status.rc == 0
22 |
23 | # - name: debug stat_service_firewalld_status
24 | # debug: var=stat_service_firewalld_status
25 |
26 | - name: Check firewalld can reload
27 | command: firewall-cmd --reload
28 | register: stat_service_firewalld_reload
29 | # ignore_errors: true
30 | changed_when: false
31 | # no_log: True
32 | # failed_when: not stat_service_firewalld_reload.rc == 0
33 |
34 | - name: Check source ip added to internal zone
35 | command: firewall-cmd --permanent --zone=internal --query-source=192.168.22.64/26
36 | register: cmd
37 | # ignore_errors: true
38 | changed_when: false
39 | # failed_when: not cmd.rc == 0
40 |
41 | - name: Check source ip not added to internal zone
42 | command: firewall-cmd --permanent --zone=internal --query-source=192.168.32.64/26
43 | register: cmd
44 | # ignore_errors: true
45 | changed_when: false
46 | failed_when: not cmd.rc == 1
47 |
48 | - name: Check service created and in public zone
49 | command: firewall-cmd --permanent --zone=public --query-service=app123-public
50 | register: cmd
51 | # ignore_errors: true
52 | changed_when: false
53 | # failed_when: not cmd.rc == 0
54 |
55 | - name: Check service created and not in internal zone
56 | command: firewall-cmd --permanent --zone=internal --query-service=app123-public
57 | register: cmd
58 | # ignore_errors: true
59 | changed_when: false
60 | failed_when: not cmd.rc == 1
61 |
62 | - name: Check tcp port added to custom service
63 | command: firewall-cmd --permanent --service=app123-public --query-port=5000/tcp
64 | register: cmd
65 | # ignore_errors: true
66 | changed_when: false
67 | # failed_when: not cmd.rc == 0
68 |
69 | # - name: debug Check port added to custom service cmd
70 | # debug: var=cmd
71 |
72 | - name: Check udp port added to custom service
73 | command: firewall-cmd --permanent --service=app123-internal --query-port=8500/udp
74 | register: cmd
75 | # ignore_errors: true
76 | changed_when: false
77 | # failed_when: not cmd.rc == 0
78 |
79 | - name: Check custom port added to built-in service
80 | command: firewall-cmd --permanent --service=zabbix-agent --query-port=3333/tcp
81 | register: cmd
82 | # ignore_errors: true
83 | changed_when: false
84 | # failed_when: not cmd.rc == 0
85 |
86 | - name: Check default port not added to built-in service
87 | command: firewall-cmd --permanent --service=zabbix-agent --query-port=10050/tcp
88 | register: cmd
89 | # ignore_errors: true
90 | changed_when: false
91 | failed_when: not cmd.rc == 1
92 |
93 | # # Check firewalld running
94 | # - systemctl status firewalld
95 | # # Check source ip in internal zone
96 | # - sudo firewall-cmd --permanent --zone=internal --query-source=192.168.22.64/26
97 | # # Check source ip not in internal zone
98 | # - sudo firewall-cmd --permanent --zone=internal --query-source=192.168.32.64/26 || echo "success, not found"
99 | # # Check service created and in public zone
100 | # - sudo firewall-cmd --permanent --zone=public --query-service=app123-public
101 | # # Check service created and not in internal zone
102 | # - sudo firewall-cmd --permanent --zone=internal --query-service=app123-public || echo "success, not found"
103 |
104 | # # Check port added to custom service
105 | # - sudo firewall-cmd --permanent --service=app123-public --query-port=5000/tcp
106 |
107 | # # Check custom port added to built-in service
108 | # - sudo firewall-cmd --permanent --service=zabbix-agent --query-port=3333/tcp
109 | # # Check default port not added to built-in service
110 | # - sudo firewall-cmd --permanent --service=zabbix-agent --query-port=10050/tcp || echo "success, not found"
111 |
112 | # # Run the role/playbook again but make change
113 | # - "ansible-playbook -i tests/inventory tests/test-change.yml --connection=local --become"
114 |
115 | # # Check port not added to custom service when disabled
116 | # - sudo firewall-cmd --permanent --service=app123-public --query-port=5000/tcp || echo "success, not found"
117 |
118 | # # Check port added to custom service
119 | # - sudo firewall-cmd --permanent --service=app123-internal --query-port=8089/tcp
120 | # # Check port not added to custom service when removed from config
121 | # - sudo firewall-cmd --permanent --service=app123-internal --query-port=8080/tcp || echo "success, not found"
122 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ansible Role: firewalld
2 |
3 | Add local firewall rules on server via firewalld.
4 | Why another Ansible role to manage firewalld? The role does everything in "offline" mode. Even creating a new service works offline.
5 | So there should be no issues when firewalld starts, and blocks EVERYTHING by default! (Make sure you test in non-production first, I cannot make any guarantees)
6 | This supports adding custom firewalld "services" into zones with custom ports. Also can add or remove ports for built-in services provided by firewalld.
7 | Removes unwanted default services from public/internal zone.
8 |
9 | Zones: Add IP ranges to Zones. To remove, change state to `disabled`. If only one IP range needs to be disabled, create a new zone entry for just that IP range.
10 | Services: `disable` a service will remove it from that zone as specified in the variables. Don't just delete the config to remove it!
11 | Ports: To remove a port, delete it from the config (under port_protocol).
12 |
13 | Since VMs could have different interfaces (eth0/eth1 etc.), interfaces aren't managed.
14 |
15 | Be careful, this will remove and add firewalld rules on the OS. Use with caution.
16 |
17 | firewalld manual:
18 |
19 | **Note**: Docker and firewalld do not get along. This role has a check enabled to fail this role if the docker service is running or enabled.
20 | For more information about firewalld and Docker:
21 |
22 |
23 |
24 |
25 | ## Testing
26 |
27 | Molecule is used for testing, and all features are tested. Changes are then made a second time and re-tested to be sure everything works.
28 |
29 | ## Distros tested
30 |
31 | * CentOS: 7.6, 7.7, 8.1
32 | * Fedora 30, 31
33 | * Arch Linux (firewalld version 0.8.1) - But who would run a bunch of Arch servers..
34 |
35 | ## Dependencies
36 |
37 | * firewalld
38 |
39 | Tested with version 0.6.3 (Latest available in CentOS 7)
40 | Tested with version 0.6.6 (Latest available in Fedora 30)
41 | Tested with version 0.7.0 (Latest available in CentOS 8)
42 | Tested with version 0.7.3 (Latest available in Fedora 31)
43 | Tested with version 0.8.1 (Latest available in Arch Linux)
44 |
45 | ## Default Settings
46 |
47 | * Enable debug
48 |
49 | ```yaml
50 | debug_enabled_default: false
51 | ```
52 |
53 | * Proxy (Needed when installing required packages if behind a proxy)
54 |
55 | ```yaml
56 | proxy_env: []
57 | ```
58 |
59 | * Role disabled by default. Change to true in group_vars or playbook etc
60 |
61 | ```yaml
62 | firewalld_managed: false
63 | ```
64 |
65 | * Check if (Docker) service is running or enabled, and fail the role
66 |
67 | ```yaml
68 | firewalld_check_problem_service_managed: true
69 | ```
70 |
71 | * Services to check, and fail the role
72 |
73 | ```yaml
74 | firewalld_check_problem_service:
75 | - docker.service
76 | ```
77 |
78 | * Show configuration from variables
79 |
80 | ```yaml
81 | firewalld_show_config: false
82 | ```
83 |
84 | * Start firewalld service
85 |
86 | ```yaml
87 | firewalld_start: false
88 | ```
89 |
90 | * Install firewalld package
91 |
92 | ```yaml
93 | firewalld_managed_pkg: true
94 | ```
95 |
96 | ## User Settings
97 |
98 | * Remove unwanted default services from public zone
99 |
100 | ```yaml
101 | firewalld_public_remove_default:
102 | - mdns
103 | - samba-client
104 | ```
105 |
106 | * Remove unwanted default services from internal zone
107 |
108 | ```yaml
109 | firewalld_internal_remove_default:
110 | - mdns
111 | - samba-client
112 | ```
113 |
114 | * Zone Config
115 |
116 | Full list of firewalld predefined zones:
117 |
118 | ```yaml
119 | firewalld_zone_source:
120 | - zone: name of predefined zone (ex. internal|public) (Required)
121 | state: enabled|disabled (Required)
122 | source:
123 | - "IP/Subnet" (Required)
124 | ```
125 |
126 | * Service and Port Config
127 |
128 | ```yaml
129 | firewalld_custom_service:
130 | - name: service name (Required)
131 | zone: public|internal etc (See zone list above) (Required)
132 | state: enabled (Required)
133 | description: Description of service (Optional)
134 | port_protocol: (Required, unless a built-in service except when changing a default port for built-in service)
135 | - port/protocol (Required, unless a built-in service)
136 | ```
137 |
138 | See example for more details.
139 | Get list of build-in services:
140 |
141 | ```bash
142 | firewall-offline-cmd --get-services
143 | ```
144 |
145 | ## Example config file (inventories/dev-env/group_vars/all.yml)
146 |
147 | From the example below:
148 | IP ranges will be added/removed from a zone:
149 |
150 | * `192.168.22.64/26` and `192.168.23.64/26` will be added to the zone `internal`
151 | * `192.168.32.64/26` and `192.168.33.64/26` will be removed from the zone `internal`
152 |
153 | Custom services will be created with port(s) specified, and added to a zone:
154 |
155 | * `app123-public` service is created with port/protocol `5000/tcp`, and added to zone `public`.
156 | * `app123-internal` service is created with ports/protocol `8080/tcp`, `9000/tcp`, and added to zone `internal`.
157 | * `zabbix-agent` service (which is a built-in service in firewalld) is not using the default port (10050) since it's not in the config, `10050/tcp` is removed. Instead using port/protocol `3333/tcp`, and added to zone `public`. (Note: The port doesn't need to be commented out).
158 | * `openvpn` service (which is a built-in service in firewalld) is using the default port/protocol, and added to zone `public`. Since this service is built-in, you don't need to specify the port. But to be safe, you should still specify it.
159 |
160 | ```yaml
161 | ---
162 | firewalld_zone_source:
163 | - zone: internal
164 | state: enabled
165 | source:
166 | - "192.168.22.64/26"
167 | - "192.168.23.64/26"
168 | - zone: internal
169 | state: disabled
170 | source:
171 | - "192.168.32.64/26"
172 | - "192.168.33.64/26"
173 |
174 | firewalld_custom_service:
175 | - name: app123-public
176 | zone: public
177 | # state: disabled
178 | state: enabled
179 | description: app123 firewall rules for public zone
180 | port_protocol:
181 | - 5000/tcp
182 | - name: app123-internal
183 | zone: internal
184 | # state: disabled
185 | state: enabled
186 | description: app123 firewall rules for internal zone
187 | port_protocol:
188 | - 8080/tcp
189 | - 9000/tcp
190 | - name: zabbix-agent
191 | zone: public
192 | # state: disabled
193 | state: enabled
194 | port_protocol:
195 | # - 10050/tcp
196 | - 3333/tcp
197 | - name: openvpn
198 | zone: public
199 | state: enabled
200 | ```
201 |
202 | ## Example Playbook firewalld.yml
203 |
204 | ```yaml
205 | ---
206 | - hosts: '{{ inventory }}'
207 | become: yes
208 | vars:
209 | # Use this role #RTFM
210 | # firewalld_managed: true
211 | roles:
212 | - firewalld
213 | ```
214 |
215 | ## Usage
216 |
217 | By default no tasks will run unless you set `firewalld_managed=true`. This is by design to prevent accidents by people who don't RTFM.
218 |
219 | ```bash
220 | ansible-playbook firewalld.yml --extra-vars "inventory=centos7 firewalld_managed=true" -i hosts-dev
221 | ```
222 |
223 | Skip installing packages (if known already there - speeds up task)
224 |
225 | ```bash
226 | ansible-playbook firewalld.yml --extra-vars "inventory=centos7 firewalld_managed=true" -i hosts --skip-tags=firewalld_pkg_install
227 | ```
228 |
229 | Show more verbose output (debug info)
230 |
231 | ```bash
232 | ansible-playbook firewalld.yml --extra-vars "inventory=centos7 firewalld_managed=true debug_enabled_default=true" -i hosts-dev
233 | ```
234 |
235 | Start firewalld service at end of role
236 |
237 | ```bash
238 | ansible-playbook firewalld.yml --extra-vars "inventory=centos7 firewalld_managed=true firewalld_start=true" -i hosts-dev
239 | ```
240 |
241 | Only show configuration (from variables)
242 |
243 | ```bash
244 | ansible-playbook firewalld.yml --extra-vars "inventory=centos7 firewalld_managed=true firewalld_show_config=true" -i hosts --tags "firewalld_show_config"
245 | ```
246 |
247 | ## firewalld Command Reference
248 |
249 | More commands can be found in firewalld documentation:
250 |
251 | Add IPs to a Zone:
252 |
253 | ```bash
254 | firewall-offline-cmd --zone=public --list-all
255 |
256 | firewall-offline-cmd --zone=internal --add-source=192.168.22.64/26
257 | firewall-offline-cmd --zone=internal --add-source=192.168.23.64/26
258 | ```
259 |
260 | Add custom service to public zone:
261 |
262 | ```bash
263 | firewall-offline-cmd --new-service=app123-public
264 | firewall-offline-cmd --service=app123-public --set-short=app123-public
265 | firewall-offline-cmd --service=app123-public --set-description='app123 fw rules for public zone'
266 | firewall-offline-cmd --service=app123-public --add-port=5000/tcp
267 | firewall-offline-cmd --zone=public --add-service=app123-public
268 | ```
269 |
270 | Add custom service to internal zone:
271 |
272 | ```bash
273 | firewall-offline-cmd --new-service=app123-internal
274 | firewall-offline-cmd --service=app123-internal --set-short=app123-internal
275 | firewall-offline-cmd --service=app123-internal --set-description='app123 fw rules for internal zone'
276 | firewall-offline-cmd --service=app123-internal --add-port=8080/tcp
277 | firewall-offline-cmd --service=app123-internal --add-port=9000/tcp
278 | firewall-offline-cmd --zone=internal --add-service=app123-internal
279 |
280 | firewall-offline-cmd --zone=internal --list-all
281 | ```
282 |
283 | Get list of build-in services:
284 |
285 | ```bash
286 | firewall-offline-cmd --get-services
287 | ```
288 |
289 | Misc useful commands:
290 |
291 | ```bash
292 | firewall-cmd --state
293 | firewall-cmd --get-active-zones
294 |
295 | firewall-offline-cmd --zone=public --list-all
296 | firewall-offline-cmd --zone=internal --list-all
297 |
298 | firewall-offline-cmd --zone=public --list-services
299 | firewall-offline-cmd --zone=internal --list-services
300 |
301 | firewall-offline-cmd --info-service=app123-public
302 | firewall-offline-cmd --info-service=app123-internal
303 |
304 | firewall-cmd --reload
305 | ```
306 |
307 | ## iptables Command Reference
308 |
309 | List iptables that are active:
310 |
311 | ```bash
312 | iptables -nL
313 | ```
314 |
315 | ## nftables Command Reference
316 |
317 | List nftables that are active:
318 |
319 | ```bash
320 | nft list tables
321 | nft list ruleset
322 | nft list table inet firewalld
323 | nft list chain inet firewalld filter_IN_public_allow
324 | ```
325 |
326 | ## TODO
327 |
328 | * [x] Get working with firewalld started or stopped
329 | * [x] Confirm reload everywhere needed: "notify: Reload firewalld"
330 | * [ ] Add more tags to tasks
331 | * [x] Test this actually works if firewalld service is running and doesn't block traffic to running app
332 | * [x] Build travis tests for many scenarios
333 | * [ ] Improve/shorten changing/removing a port
334 | * [ ] --diff doesn't show much since using many commands. Show what's going to happen and add pause when is debug enabled?
335 |
336 | ## Author
337 |
338 | Ryan Daniels
339 |
--------------------------------------------------------------------------------
/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # - name: show setup
3 | # setup:
4 | # gather_subset:
5 | # - 'all'
6 | # register: stat_setup
7 |
8 | # - name: debug stat_setup
9 | # debug: var=stat_setup
10 | # when:
11 | # # - ansible_os_family == "RedHat"
12 | # # - ansible_distribution_major_version == '7'
13 | # - firewalld_managed|bool
14 | # # - debug_enabled_default|bool
15 | # tags:
16 | # - firewalld
17 |
18 | - block:
19 | # - name: debug groups
20 | # debug: var=groups
21 | - name: firewalld | Show firewalld_zone_source
22 | debug: var=firewalld_zone_source
23 | - name: firewalld | Show firewalld_custom_service
24 | debug: var=firewalld_custom_service
25 | - name: pause
26 | pause:
27 | seconds: 5
28 | when:
29 | # - ansible_os_family == "RedHat"
30 | # - ansible_distribution_major_version == '7'
31 | - firewalld_managed|bool
32 | # - debug_enabled_default|bool
33 | - firewalld_show_config|bool
34 | tags:
35 | - firewalld
36 | - firewalld_show_config
37 |
38 | - name: firewalld | Check for problem services
39 | command: systemctl show -p UnitFileState -p SubState {{ item }} warn=false
40 | register: stat_service_bad
41 | # failed_when: ("SubState=running" in stat_service_bad.stdout) or ("UnitFileState=enabled" in stat_service_bad.stdout)
42 | # ignore_errors: true
43 | changed_when: false
44 | # no_log: true
45 | # - debug: var=stat_service_bad.stdout_lines
46 | with_items:
47 | - "{{ firewalld_check_problem_service }}"
48 | when:
49 | - firewalld_managed|bool
50 | - firewalld_check_problem_service_managed|bool
51 | tags:
52 | - firewalld
53 | - firewalld_check_service
54 |
55 | # - debug: var=stat_service_bad.results
56 | # when:
57 | # - firewalld_managed|bool
58 | # - firewalld_check_problem_service_managed|bool
59 | # tags:
60 | # - firewalld
61 | # - firewalld_check_service
62 |
63 | - name: firewalld | Fail if specified problem service is running
64 | fail:
65 | msg: "{{ item.item }} service is running or enabled, and firewalld can cause a problem with that service"
66 | with_items: "{{ stat_service_bad.results }}"
67 | when:
68 | - firewalld_managed|bool
69 | - firewalld_check_problem_service_managed|bool
70 | - ("SubState=running" in item.stdout_lines) or ("UnitFileState=enabled" in item.stdout_lines)
71 | # loop_control:
72 | # label: "Service {{ item }} is running or enabled. It can have a problem with firewalld"
73 | tags:
74 | - firewalld
75 | - firewalld_check_service
76 |
77 | - name: Ensure required packages are installed
78 | package:
79 | name: "{{ firewalld_packages|default([]) }}"
80 | update_cache: yes
81 | state: present
82 | environment: "{{ proxy_env }}"
83 | when:
84 | # - ansible_os_family == "RedHat"
85 | # - ansible_distribution_major_version == '7'
86 | - firewalld_managed|bool
87 | - firewalld_managed_pkg|bool
88 | tags:
89 | - firewalld
90 | - firewalld_pkg_install
91 |
92 | - name: firewalld | check version
93 | command: firewall-offline-cmd -V warn=false
94 | register: stat_service_firewalld_version
95 | failed_when: false
96 | ignore_errors: true
97 | changed_when: false
98 | # no_log: True
99 | when:
100 | # - ansible_os_family == "RedHat"
101 | # - ansible_distribution_major_version == '7'
102 | - firewalld_managed|bool
103 | # - debug_enabled_default|bool
104 | tags:
105 | - firewalld
106 |
107 | - name: debug stat_service_firewalld_version
108 | debug: var=stat_service_firewalld_version.stdout_lines
109 | when:
110 | # - ansible_os_family == "RedHat"
111 | # - ansible_distribution_major_version == '7'
112 | - firewalld_managed|bool
113 | # - debug_enabled_default|bool
114 | tags:
115 | - firewalld
116 |
117 | - name: firewalld | check if running
118 | command: systemctl status firewalld warn=false
119 | register: stat_service_firewalld_status
120 | failed_when: false
121 | ignore_errors: true
122 | changed_when: false
123 | no_log: True
124 | when:
125 | # - ansible_os_family == "RedHat"
126 | # - ansible_distribution_major_version == '7'
127 | - firewalld_managed|bool
128 | tags:
129 | - firewalld
130 |
131 | - name: debug stat_service_firewalld_status
132 | debug: var=stat_service_firewalld_status.stdout_lines
133 | when:
134 | # - ansible_os_family == "RedHat"
135 | # - ansible_distribution_major_version == '7'
136 | - firewalld_managed|bool
137 | - debug_enabled_default|bool
138 | tags:
139 | - firewalld
140 |
141 | - name: firewalld | Config zone source IP
142 | firewalld:
143 | zone: "{{ item.0.zone }}"
144 | source: "{{ item.1 }}"
145 | state: "{{ item.0.state|default('enabled') }}"
146 | permanent: yes
147 | offline: yes
148 | notify: Reload firewalld
149 | with_subelements:
150 | - "{{ firewalld_zone_source|default({}) }}"
151 | - source
152 | when:
153 | # - ansible_os_family == "RedHat"
154 | # - ansible_distribution_major_version == '7'
155 | - firewalld_managed|bool
156 | # loop_control:
157 | # label: "Zone: {{ item.0.zone }} Source: {{ item.1 }}"
158 | tags:
159 | - firewalld
160 |
161 | #get active services
162 | #when item not in service list, firewalld reload is needed to see item in service list so can add to zone
163 | - name: firewalld | Get active services to determine if reload needed
164 | command: firewall-offline-cmd --get-services warn=false
165 | register: stat_service_firewalld_services
166 | failed_when: false
167 | ignore_errors: true
168 | changed_when: false
169 | no_log: true
170 | when:
171 | # - ansible_os_family == "RedHat"
172 | # - ansible_distribution_major_version == '7'
173 | - firewalld_managed|bool
174 | tags:
175 | - firewalld
176 |
177 | - name: debug stat_service_firewalld_services.stdout.split()
178 | debug: var=stat_service_firewalld_services.stdout.split()
179 | when:
180 | # - ansible_os_family == "RedHat"
181 | # - ansible_distribution_major_version == '7'
182 | - firewalld_managed|bool
183 | - debug_enabled_default|bool
184 | - stat_service_firewalld_status.rc == 0
185 | tags:
186 | - firewalld
187 |
188 | #Built-in services will fail to be removed fully. But they are removed from the zone below (Add/Remove service in zone)
189 | #Use this instead? firewall-offline-cmd --zone=public --remove-service-from-zone=zabbix-agent
190 | #But then custom services aren't fully deleted..
191 | - name: firewalld | Remove custom service - failure expected if firewalld built-in service
192 | command: "firewall-offline-cmd --delete-service={{ item.name }}"
193 | ignore_errors: true
194 | notify: Reload firewalld
195 | with_items:
196 | - "{{ firewalld_custom_service|default({}) }}"
197 | when:
198 | # - ansible_os_family == "RedHat"
199 | # - ansible_distribution_major_version == '7'
200 | - firewalld_managed|bool
201 | - item.state == 'disabled'
202 | - 'item.name in stat_service_firewalld_services.stdout.split()'
203 | loop_control:
204 | label: "Removed service name: {{ item.name }}"
205 | tags:
206 | - firewalld
207 | - firewalld_remove_service
208 |
209 | #If only block can use loops..
210 | # - block:
211 | - name: firewalld | Create custom service name
212 | command: "firewall-offline-cmd --new-service={{ item.name }}"
213 | # firewall-offline-cmd --service={{ item.name }} --set-short={{ item.name }} && \
214 | # firewall-offline-cmd --service={{ item.name }} --set-description='{{ item.description }}' && \
215 | # firewall-offline-cmd --service={{ item.name }} --add-port={{ item.port_protocol }} && \
216 | # firewall-offline-cmd --zone={{ item.zone }} --add-service={{ item.name }}"
217 | with_items:
218 | - "{{ firewalld_custom_service|default({}) }}"
219 | when:
220 | # - ansible_os_family == "RedHat"
221 | # - ansible_distribution_major_version == '7'
222 | - firewalld_managed|bool
223 | - item.state == 'enabled'
224 | - 'item.name not in stat_service_firewalld_services.stdout.split()'
225 | loop_control:
226 | label: "Created service name: {{ item.name }}"
227 | tags:
228 | - firewalld
229 | - firewalld_create_service
230 |
231 | - name: firewalld | Get custom service set-short
232 | command: "firewall-offline-cmd --service={{ item.name }} --get-short"
233 | register: stat_firewalld_service_get_short
234 | failed_when: false
235 | ignore_errors: true
236 | changed_when: false
237 | # no_log: true
238 | with_items: "{{ firewalld_custom_service|default({}) }}"
239 | when:
240 | # - ansible_os_family == "RedHat"
241 | # - ansible_distribution_major_version == '7'
242 | - firewalld_managed|bool
243 | # - stat_service_firewalld_status.rc == 0
244 | loop_control:
245 | label: "{{ item.name }} - found short name: {{ stat_firewalld_service_get_short.stdout|d() }}"
246 | tags:
247 | - firewalld
248 |
249 | # - name: debug stat_firewalld_service_get_short
250 | # debug: var=stat_firewalld_service_get_short
251 | # # with_items: "{{ stat_firewalld_service_get_short.results }}"
252 | # when:
253 | # - debug_enabled_default|bool
254 | # - firewalld_managed|bool
255 | # # - stat_service_firewalld_status.rc == 0
256 | # tags:
257 | # - firewalld
258 |
259 | - name: firewalld | Set custom service set-short
260 | command: "firewall-offline-cmd --service={{ item.item.name }} --set-short={{ item.item.name }}"
261 | with_items:
262 | # - "{{ firewalld_custom_service|default({}) }}"
263 | - "{{ stat_firewalld_service_get_short.results }}"
264 | when:
265 | # - ansible_os_family == "RedHat"
266 | # - ansible_distribution_major_version == '7'
267 | - firewalld_managed|bool
268 | - item.item.state == 'enabled'
269 | - 'item.stdout != item.item.name'
270 | loop_control:
271 | label: "{{ item.item.name }} - set short name: {{ item.item.name }}"
272 | tags:
273 | - firewalld
274 | - firewalld_create_service
275 |
276 | - name: firewalld | Get custom service description
277 | command: "firewall-offline-cmd --service={{ item.name }} --get-description"
278 | register: stat_firewalld_service_get_description
279 | failed_when: false
280 | ignore_errors: true
281 | changed_when: false
282 | with_items: "{{ firewalld_custom_service|default({}) }}"
283 | when:
284 | # - ansible_os_family == "RedHat"
285 | # - ansible_distribution_major_version == '7'
286 | - firewalld_managed|bool
287 | loop_control:
288 | label: "{{ item.name }} - found description: {{ stat_firewalld_service_get_description.stdout|d() }}"
289 | tags:
290 | - firewalld
291 |
292 | # - name: debug stat_firewalld_service_get_description
293 | # debug: var=stat_firewalld_service_get_description
294 | # # with_items: "{{ stat_firewalld_service_get_description.results }}"
295 | # when:
296 | # - debug_enabled_default|bool
297 | # - firewalld_managed|bool
298 | # # - stat_service_firewalld_status.rc == 0
299 | # tags:
300 | # - firewalld
301 |
302 | - name: firewalld | Set custom service description
303 | command: "firewall-offline-cmd --service={{ item.item.name }} --set-description='{{ item.item.description }}'"
304 | with_items:
305 | - "{{ stat_firewalld_service_get_description.results }}"
306 | when:
307 | # - ansible_os_family == "RedHat"
308 | # - ansible_distribution_major_version == '7'
309 | - firewalld_managed|bool
310 | - item.item.state == 'enabled'
311 | - item.item.description is defined
312 | - item.stdout != item.item.description
313 | loop_control:
314 | label: "{{ item.item.name }} - set description: {{ item.item.description|default({}) }}"
315 | tags:
316 | - firewalld
317 | - firewalld_create_service
318 |
319 | #DONE: how to 'change' a port that's defined?? Can only 'disable' entire service.
320 | # Can add new ports. But not remove existing.
321 | #firewall-offline-cmd --service=zabbix-agent --get-ports
322 | #Remove ports in output of above command that aren't in variable provided.
323 | #Can't because built-in services I don't have ports for! Means all ports need to be defined!
324 | #DONE: add strict mode so this can be disabled (by default?). Not needed. Just dont remove ports if port_protocol is undefined.
325 | #TODO: Seems like round-about way to do this. Shorten somehow?
326 |
327 | #Remove if port is not defined in vars
328 | - name: firewalld | Get custom service ports in firewalld
329 | command: "firewall-offline-cmd --service={{ item.name }} --get-ports"
330 | register: stat_firewalld_service_get_service_port_list
331 | failed_when: false
332 | # ignore_errors: true
333 | changed_when: false
334 | with_items:
335 | - "{{ firewalld_custom_service|default({}) }}"
336 | when:
337 | # - ansible_os_family == "RedHat"
338 | # - ansible_distribution_major_version == '7'
339 | - firewalld_managed|bool
340 | # - item.state == 'enabled'
341 | loop_control:
342 | label: "{{ item.name }} - found ports: {{ stat_firewalld_service_get_service_port_list.stdout|d() }}"
343 | tags:
344 | - firewalld
345 |
346 | # - name: debug stat_firewalld_service_get_service_port_list
347 | # debug: var=stat_firewalld_service_get_service_port_list
348 | # when:
349 | # - debug_enabled_default|bool
350 | # - firewalld_managed|bool
351 | # tags:
352 | # - firewalld
353 |
354 | # - name: firewalld | debug stat_firewalld_service_get_service_port_list.results
355 | # debug: msg="{{ item.item.name }}, {{ item.stdout }}" #, item.rc={{ item.rc }}, item.item_debug={{ item.item|type_debug }}"
356 | # with_items: "{{ stat_firewalld_service_get_service_port_list.results }}"
357 | # when:
358 | # - ansible_os_family == "RedHat"
359 | # - ansible_distribution_major_version == '7'
360 | # - firewalld_managed|bool
361 | # - debug_enabled_default|bool
362 | # loop_control:
363 | # label: ""
364 | # tags:
365 | # - firewalld
366 |
367 | - name: firewalld | Set variable firewalld_service_port_list
368 | set_fact:
369 | firewalld_service_port_list: "{{ firewalld_service_port_list|default([]) + [{'name': item.item.name , 'port_protocol': item.item.port_protocol , 'port_stdout': item.stdout.split(' ')} ] }}" # noqa 204
370 | when:
371 | # - ansible_os_family == "RedHat"
372 | # - ansible_distribution_major_version == '7'
373 | - firewalld_managed|bool
374 | - item.item.port_protocol is defined #prevents removing ports of built-in firewalld services (if port_protocol is empty)
375 | # - item.rc != 0
376 | loop: "{{ stat_firewalld_service_get_service_port_list.results|flatten(levels=1) }}"
377 | loop_control:
378 | label: ""
379 | tags:
380 | - firewalld
381 |
382 | # - name: firewalld | show variable firewalld_service_port_list
383 | # debug: var=firewalld_service_port_list
384 | # when: debug_enabled_default|bool and firewalld_service_port_list is defined
385 |
386 | - name: firewalld | debug firewalld_service_port_list
387 | debug: msg="{{ item.name }}, {{ item.port_protocol }}, {{ item.port_stdout }}" #, item.rc={{ item.rc }}, item.item_debug={{ item.item|type_debug }}"
388 | with_items: "{{ firewalld_service_port_list }}"
389 | when:
390 | # - ansible_os_family == "RedHat"
391 | # - ansible_distribution_major_version == '7'
392 | - firewalld_managed|bool
393 | - debug_enabled_default|bool
394 | loop_control:
395 | label: ""
396 | tags:
397 | - firewalld
398 |
399 | - name: firewalld | Remove custom service ports not specified
400 | command: "firewall-offline-cmd --service={{ item.0.name }} --remove-port='{{ item.1 }}'"
401 | notify: Reload firewalld
402 | with_subelements:
403 | - "{{ firewalld_service_port_list }}"
404 | - port_stdout
405 | when:
406 | # - ansible_os_family == "RedHat"
407 | # - ansible_distribution_major_version == '7'
408 | - firewalld_managed|bool
409 | # - item.item.state == 'enabled'
410 | - item.1 is defined
411 | - item.1|length > 0
412 | - item.1 not in item.0.port_protocol
413 | loop_control:
414 | label: "{{ item.0.name }} - removed port: {{ item.1|default({}) }}"
415 | tags:
416 | - firewalld
417 | - firewalld_create_service
418 |
419 | # - name: pause
420 | # pause:
421 | # seconds: 30
422 | # when: debug_enabled_default|bool and firewalld_managed|bool
423 | # tags:
424 | # - firewalld
425 |
426 | #firewall-offline-cmd --service=app123-internal --query-port=2181/tcp
427 | - name: firewalld | Get custom service ports to add
428 | command: "firewall-offline-cmd --service={{ item.0.name }} --query-port={{ item.1 }}"
429 | register: stat_firewalld_service_get_service_port_add
430 | failed_when: false
431 | # ignore_errors: true
432 | changed_when: false
433 | with_subelements:
434 | - "{{ firewalld_custom_service|default({}) }}"
435 | - port_protocol
436 | - skip_missing: True
437 | when:
438 | # - ansible_os_family == "RedHat"
439 | # - ansible_distribution_major_version == '7'
440 | - firewalld_managed|bool
441 | - item.0.state == 'enabled'
442 | - item is defined
443 | - item.1 is defined
444 | loop_control:
445 | label: "{{ item.0.name }} - found: {{ 'True' if not stat_firewalld_service_get_service_port_add.rc|d(false)|bool else 'False' }}"
446 | tags:
447 | - firewalld
448 |
449 | # - name: firewalld | debug stat_firewalld_service_get_service_port_add
450 | # debug: var=stat_firewalld_service_get_service_port_add
451 | # when:
452 | # # - ansible_os_family == "RedHat"
453 | # # - ansible_distribution_major_version == '7'
454 | # - firewalld_managed|bool
455 | # - debug_enabled_default|bool
456 | # tags:
457 | # - firewalld
458 |
459 | - name: firewalld | debug stat_firewalld_service_get_service_port_add_add.results|last
460 | debug: msg="{{ item.item | last }}" #, item.rc={{ item.rc }}, item.item_debug={{ item.item|type_debug }}"
461 | with_items: "{{ stat_firewalld_service_get_service_port_add.results }}"
462 | when:
463 | # - ansible_os_family == "RedHat"
464 | # - ansible_distribution_major_version == '7'
465 | - firewalld_managed|bool
466 | - debug_enabled_default|bool
467 | loop_control:
468 | label: ""
469 | tags:
470 | - firewalld
471 |
472 | # - name: firewalld | debug stat_firewalld_service_get_service_port_add type_debug
473 | # debug: msg="item.item={{ item.item | last | type_debug }}"
474 | # when: debug_enabled_default|bool
475 | # loop: "{{ stat_firewalld_service_get_service_port_add.results|flatten(levels=1) }}"
476 | # loop_control:
477 | # label: ""
478 |
479 | #Don't need to use set_fact to create new var? just use stat_firewalld_service_get_service_port_add.results with the magic of map etc
480 | # - name: firewalld | Set variable firewalld_add_name_port
481 | # set_fact:
482 | # # test123: "{{ test123|default([]) }} name: {{ item.item|map(attribute='name')|list|select('defined')|list }} + {{ item.item|last }}"
483 | # # test123: "{{ test123|default([]) + [{'name': item.item|map(attribute='name')|list|select('defined')|list|join(', ') }] }}"
484 | # firewalld_add_name_port: "{{ firewalld_add_name_port|default([]) + [{'name': item.item|map(attribute='name')|list|select('defined')|list|join(', ') , 'port': item.item|last} ] }}"
485 | # when:
486 | # - ansible_os_family == "RedHat"
487 | # - ansible_distribution_major_version == '7'
488 | # - firewalld_managed|bool
489 | # - item.rc != 0
490 | # loop: "{{ stat_firewalld_service_get_service_port_add.results|flatten(levels=1) }}"
491 | # loop_control:
492 | # label: ""
493 | # tags:
494 | # - firewalld
495 |
496 | # - name: firewalld | show variable firewalld_add_name_port
497 | # debug: var=firewalld_add_name_port
498 | # when: debug_enabled_default|bool and firewalld_add_name_port is defined
499 |
500 | # - name: firewalld | show variable firewalld_add_name_port items
501 | # debug: msg="name={{ item.name }}, port={{ item.port }}"
502 | # when: debug_enabled_default|bool and item is defined
503 | # loop: "{{ firewalld_add_name_port|flatten(levels=1) }}"
504 | # loop_control:
505 | # label: ""
506 |
507 | # - name: firewalld | Set port for service
508 | # command: "firewall-offline-cmd --service={{ item.name }} --add-port={{ item.port }}"
509 | # # with_subelements:
510 | # # - "{{ firewalld_custom_service|default({}) }}"
511 | # # - port_protocol
512 | # with_items:
513 | # # - "{{ firewalld_custom_service|default({}) }}"
514 | # - "{{ firewalld_add_name_port }}"
515 | # when:
516 | # - ansible_os_family == "RedHat"
517 | # - ansible_distribution_major_version == '7'
518 | # - firewalld_managed|bool
519 | # - item is defined
520 | # # - item.state == 'enabled'
521 | # # - item.rc != 0
522 | # # - '" " ~ item.1 ~ " " not in stat_service_firewalld_services.stdout'
523 | # loop_control:
524 | # label: "{{ item.name }} - added port: {{ item.port }}"
525 | # tags:
526 | # - firewalld
527 | # - firewalld_create_service
528 |
529 | #Don't need to use set_fact to create new var. just use stat_firewalld_service_get_service_port_add.results with the magic of map etc
530 | - name: firewalld | Add port for custom service
531 | command: "firewall-offline-cmd --service={{ item.item|map(attribute='name')|list|select('defined')|list|join(', ') }} --add-port={{ item.item|last }}"
532 | notify: Reload firewalld
533 | with_items:
534 | - "{{ stat_firewalld_service_get_service_port_add.results }}"
535 | when:
536 | # - ansible_os_family == "RedHat"
537 | # - ansible_distribution_major_version == '7'
538 | - firewalld_managed|bool
539 | - item.rc is defined
540 | # - item is not skipped
541 | - item.rc != 0
542 | loop_control:
543 | label: "{{ item.item|map(attribute='name')|list|select('defined')|list|join(', ') }} - added port: {{ item.item|last }}"
544 | tags:
545 | - firewalld
546 | - firewalld_create_service
547 |
548 | # - name: debug stat_service_firewalld_services
549 | # debug: var=stat_service_firewalld_services.stdout
550 | # when:
551 | # # - ansible_os_family == "RedHat"
552 | # # - ansible_distribution_major_version == '7'
553 | # - firewalld_managed|bool
554 | # - debug_enabled_default|bool
555 | # - stat_service_firewalld_status.rc == 0
556 | # tags:
557 | # - firewalld
558 |
559 | - name: set fact firewalld reload needed
560 | set_fact:
561 | firewalld_reload_hint_result: true
562 | with_items: "{{ firewalld_custom_service }}"
563 | when:
564 | # - ansible_os_family == "RedHat"
565 | # - ansible_distribution_major_version == '7'
566 | - firewalld_managed|bool
567 | - stat_service_firewalld_status.rc == 0
568 | # - stat_service_firewalld_services is failed
569 | - item.state == 'enabled'
570 | - 'item.name not in stat_service_firewalld_services.stdout.split()'
571 | loop_control:
572 | label: "{{ item.name }} not in firewalld service list"
573 | tags:
574 | - firewalld
575 |
576 | - name: debug firewalld_reload_hint_result
577 | debug: var=firewalld_reload_hint_result
578 | when:
579 | # - ansible_os_family == "RedHat"
580 | # - ansible_distribution_major_version == '7'
581 | - firewalld_managed|bool
582 | - debug_enabled_default|bool
583 | - stat_service_firewalld_status.rc == 0
584 | tags:
585 | - firewalld
586 |
587 | #Reload firewall now (if running) so service is visible for next task
588 | #Don't reload if doing remove/re-add right away. not needed since service is visible
589 | #reload here causes outage if firewalld running and app123 is in service! Don't reload yet if exists..
590 | - name: firewalld | reload firewalld
591 | #command: firewall-cmd --reload
592 | systemd:
593 | name: firewalld
594 | state: reloaded
595 | when:
596 | # - ansible_os_family == "RedHat"
597 | # - ansible_distribution_major_version == '7'
598 | - firewalld_managed|bool
599 | - stat_service_firewalld_status.rc == 0
600 | - firewalld_reload_hint_result|bool
601 | tags:
602 | - firewalld
603 | - skip_ansible_lint
604 |
605 | - name: firewalld | Add/Remove service in zone
606 | # command: 'firewall-offline-cmd --zone=internal --add-service=app123-internal'
607 | firewalld:
608 | service: "{{ item.name }}"
609 | zone: "{{ item.zone }}"
610 | state: "{{ item.state }}"
611 | offline: yes
612 | permanent: yes
613 | notify: Reload firewalld
614 | with_items: "{{ firewalld_custom_service|default({}) }}"
615 | when:
616 | # - ansible_os_family == "RedHat"
617 | # - ansible_distribution_major_version == '7'
618 | - firewalld_managed|bool
619 | loop_control:
620 | # label: "{{ item.name }} - found=0, not found=1: {{ stat_firewalld_service_get_service_zone.rc }}"
621 | label: "{{ item.name }} - {{ item.state }} in zone {{ item.zone }}"
622 | tags:
623 | - firewalld
624 | #End - add service to zone
625 |
626 | #Remove default firewalld services that are not needed from public zone
627 | - name: firewalld | Remove default firewalld services from public zone
628 | firewalld:
629 | service: "{{ item }}"
630 | zone: public
631 | state: disabled
632 | offline: yes
633 | permanent: yes
634 | notify: Reload firewalld
635 | with_items: "{{ firewalld_public_remove_default }}"
636 | when:
637 | # - ansible_os_family == "RedHat"
638 | # - ansible_distribution_major_version == '7'
639 | - firewalld_managed|bool
640 | - firewalld_public_remove_default is defined
641 | tags:
642 | - firewalld
643 | - firewalld_remove_default
644 |
645 | #Remove default firewalld services that are not needed from internal zone
646 | - name: firewalld | Remove default firewalld services from internal zone
647 | firewalld:
648 | service: "{{ item }}"
649 | zone: internal
650 | state: disabled
651 | offline: yes
652 | permanent: yes
653 | notify: Reload firewalld
654 | with_items: "{{ firewalld_internal_remove_default }}"
655 | when:
656 | # - ansible_os_family == "RedHat"
657 | # - ansible_distribution_major_version == '7'
658 | - firewalld_managed|bool
659 | - firewalld_internal_remove_default is defined
660 | tags:
661 | - firewalld
662 | - firewalld_remove_default
663 |
664 | - name: firewalld | Start the firewalld service
665 | systemd:
666 | name: firewalld
667 | state: started
668 | enabled: yes
669 | register: stat_service_firewalld_start
670 | when:
671 | # - ansible_os_family == "RedHat"
672 | # - ansible_distribution_major_version == '7'
673 | - firewalld_managed|bool
674 | - firewalld_start|bool
675 | tags:
676 | - firewalld
677 | - firewalld_start
678 |
679 | - name: pause to wait in case firewalld service fails to start
680 | pause:
681 | seconds: 10
682 | when:
683 | - firewalld_managed|bool
684 | - firewalld_start|bool
685 | - stat_service_firewalld_start.changed
686 | tags:
687 | - firewalld
688 | - firewalld_start
689 |
690 | - name: firewalld | check if running
691 | command: systemctl status firewalld warn=false
692 | register: stat_service_firewalld_status_end
693 | failed_when: not stat_service_firewalld_status_end.rc == 0
694 | # ignore_errors: true
695 | changed_when: false
696 | # no_log: True
697 | when:
698 | # - ansible_os_family == "RedHat"
699 | # - ansible_distribution_major_version == '7'
700 | - firewalld_managed|bool
701 | - firewalld_start|bool
702 | - stat_service_firewalld_start.changed
703 | tags:
704 | - firewalld
705 | - firewalld_start
706 |
707 | - name: debug stat_service_firewalld_status_end
708 | debug: var=stat_service_firewalld_status_end.stdout_lines
709 | when:
710 | # - ansible_os_family == "RedHat"
711 | # - ansible_distribution_major_version == '7'
712 | - firewalld_managed|bool
713 | - firewalld_start|bool
714 | - stat_service_firewalld_start.changed
715 | - debug_enabled_default|bool
716 | tags:
717 | - firewalld
718 | - firewalld_start
719 |
720 | #Fedora <30 claims firewalld is running but ip6tables is not working.
721 | #Force a reload check to be safe.
722 | - name: firewalld | Check firewalld can reload
723 | command: firewall-cmd --reload
724 | changed_when: false
725 | when:
726 | # - ansible_os_family == "RedHat"
727 | # - ansible_distribution_major_version == '7'
728 | - firewalld_managed|bool
729 | - (firewalld_start|bool or stat_service_firewalld_status.rc == 0)
730 |
--------------------------------------------------------------------------------