From 0b9ba8964fd3c711fb6dc34ce564bbb2b200ecf2 Mon Sep 17 00:00:00 2001 From: Sergey Malyuk Date: Thu, 11 Dec 2025 10:28:32 +0300 Subject: [PATCH 1/5] add ufw role --- roles/ufw/.ansible-lint | 17 ++++++++ roles/ufw/.gitignore | 2 + roles/ufw/.yamllint | 8 ++++ roles/ufw/README.md | 37 +++++++++++++++++ roles/ufw/defaults/main.yml | 4 ++ roles/ufw/environment.ci.yml | 10 +++++ roles/ufw/environment.yml | 9 +++++ roles/ufw/handlers/main.yml | 4 ++ roles/ufw/meta/main.yml | 17 ++++++++ roles/ufw/molecule/default/converge.yml | 17 ++++++++ roles/ufw/molecule/default/molecule.yml | 27 +++++++++++++ roles/ufw/molecule/default/verify.yml | 28 +++++++++++++ roles/ufw/renovate.json | 6 +++ roles/ufw/requirements.ci.txt | 6 +++ roles/ufw/requirements.txt | 1 + roles/ufw/tasks/main.yml | 54 +++++++++++++++++++++++++ roles/ufw/vars/main.yml | 1 + 17 files changed, 248 insertions(+) create mode 100644 roles/ufw/.ansible-lint create mode 100644 roles/ufw/.gitignore create mode 100644 roles/ufw/.yamllint create mode 100644 roles/ufw/README.md create mode 100644 roles/ufw/defaults/main.yml create mode 100644 roles/ufw/environment.ci.yml create mode 100644 roles/ufw/environment.yml create mode 100644 roles/ufw/handlers/main.yml create mode 100644 roles/ufw/meta/main.yml create mode 100644 roles/ufw/molecule/default/converge.yml create mode 100644 roles/ufw/molecule/default/molecule.yml create mode 100644 roles/ufw/molecule/default/verify.yml create mode 100644 roles/ufw/renovate.json create mode 100644 roles/ufw/requirements.ci.txt create mode 100644 roles/ufw/requirements.txt create mode 100644 roles/ufw/tasks/main.yml create mode 100644 roles/ufw/vars/main.yml diff --git a/roles/ufw/.ansible-lint b/roles/ufw/.ansible-lint new file mode 100644 index 0000000..64a836a --- /dev/null +++ b/roles/ufw/.ansible-lint @@ -0,0 +1,17 @@ +--- +profile: production +strict: true + +# Enable checking of loop variable prefixes in roles +loop_var_prefix: "^(__|{role}_)" + +skip_list: + - var-naming[no-role-prefix] + +warn_list: + - role-name[path] + - var-naming[no-role-prefix] + +exclude_paths: + - .github/ + - ufw-rules.yml diff --git a/roles/ufw/.gitignore b/roles/ufw/.gitignore new file mode 100644 index 0000000..8cd0df3 --- /dev/null +++ b/roles/ufw/.gitignore @@ -0,0 +1,2 @@ +.vscode +.idea \ No newline at end of file diff --git a/roles/ufw/.yamllint b/roles/ufw/.yamllint new file mode 100644 index 0000000..611db54 --- /dev/null +++ b/roles/ufw/.yamllint @@ -0,0 +1,8 @@ +--- +rules: + brackets: + forbid: false + min-spaces-inside: 0 + max-spaces-inside: 2 + min-spaces-inside-empty: -1 + max-spaces-inside-empty: 2 diff --git a/roles/ufw/README.md b/roles/ufw/README.md new file mode 100644 index 0000000..7207f41 --- /dev/null +++ b/roles/ufw/README.md @@ -0,0 +1,37 @@ +template +========= + +Whitelist network ports with UFW + +Requirements +------------ + +None + +Role Variables +-------------- + +None + +Dependencies +------------ + +None + +Example Playbook +---------------- + +```yaml +roles: + - role: genlab.ufw +``` + +License +------- + +BSD + +Author Information +------------------ + +corvus-migratorius@proton.me diff --git a/roles/ufw/defaults/main.yml b/roles/ufw/defaults/main.yml new file mode 100644 index 0000000..7aa973f --- /dev/null +++ b/roles/ufw/defaults/main.yml @@ -0,0 +1,4 @@ +--- +rules: [] +limit_ssh: false +openssh_port: 22 diff --git a/roles/ufw/environment.ci.yml b/roles/ufw/environment.ci.yml new file mode 100644 index 0000000..b91f882 --- /dev/null +++ b/roles/ufw/environment.ci.yml @@ -0,0 +1,10 @@ +--- +name: ansible-ufw +channels: + - conda-forge +dependencies: + - python~=3.12.0 + - pip>=22.2 + - pip: + - -r requirements.txt + - -r requirements.ci.txt diff --git a/roles/ufw/environment.yml b/roles/ufw/environment.yml new file mode 100644 index 0000000..a5a6851 --- /dev/null +++ b/roles/ufw/environment.yml @@ -0,0 +1,9 @@ +--- +name: ansible-ufw +channels: + - conda-forge +dependencies: + - python~=3.12 + - pip>=22.2 + - pip: + - -r requirements.txt diff --git a/roles/ufw/handlers/main.yml b/roles/ufw/handlers/main.yml new file mode 100644 index 0000000..802d7ec --- /dev/null +++ b/roles/ufw/handlers/main.yml @@ -0,0 +1,4 @@ +--- +- name: "Reload-ufw" + community.general.ufw: + state: reloaded diff --git a/roles/ufw/meta/main.yml b/roles/ufw/meta/main.yml new file mode 100644 index 0000000..39c7f50 --- /dev/null +++ b/roles/ufw/meta/main.yml @@ -0,0 +1,17 @@ +--- +galaxy_info: + role_name: ufw + namespace: genlab + author: "Alexander Gorelyshev" + company: "Genlab, LLC" + description: "Whitelist network ports with UFW" + license: "MIT" + min_ansible_version: "2.1" + + platforms: + - name: "Ubuntu" + versions: [ "focal", "jammy" ] + + galaxy_tags: [ ] + +dependencies: [] diff --git a/roles/ufw/molecule/default/converge.yml b/roles/ufw/molecule/default/converge.yml new file mode 100644 index 0000000..26ef0bd --- /dev/null +++ b/roles/ufw/molecule/default/converge.yml @@ -0,0 +1,17 @@ +--- +- name: Converge + hosts: all + vars: + custom_rules: + - port: 80 + - port: 9080 + src: "10.2.1.0/24" + - interface: eth0@if288 + direction: in + comment: "Allow all incoming traffic on eth0@if288" + + roles: + - role: genlab.ufw + disable_ipv6: true + limit_ssh: true + rules: "{{ custom_rules }}" diff --git a/roles/ufw/molecule/default/molecule.yml b/roles/ufw/molecule/default/molecule.yml new file mode 100644 index 0000000..fd2f06d --- /dev/null +++ b/roles/ufw/molecule/default/molecule.yml @@ -0,0 +1,27 @@ +--- +dependency: + name: galaxy + +driver: + name: docker + +platforms: + - name: ubuntu + image: geerlingguy/docker-${MOLECULE_DISTRO:-ubuntu2204}-ansible:latest + pre_build_image: true + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + +provisioner: + name: ansible + +verifier: + name: ansible + +lint: | + set -e + yamllint . + ansible-lint . diff --git a/roles/ufw/molecule/default/verify.yml b/roles/ufw/molecule/default/verify.yml new file mode 100644 index 0000000..3130f87 --- /dev/null +++ b/roles/ufw/molecule/default/verify.yml @@ -0,0 +1,28 @@ +--- +- name: Verify + hosts: all + gather_facts: false + any_errors_fatal: true + + tasks: + - name: "Get the UFW status" + register: ufw_status + changed_when: false + ansible.builtin.command: + cmd: ufw status + + - name: "Verify expected UFW status" + vars: + expected: + - "Status: active" + - "" + - "To Action From" + - "-- ------ ----" + - "22/tcp LIMIT Anywhere " + - "80 ALLOW Anywhere " + - "9080 ALLOW 10.2.1.0/24 " + - "Anywhere on eth0@if288 ALLOW Anywhere # Allow all incoming traffic on eth0@if288" + ansible.builtin.assert: + that: ufw_status.stdout_lines == expected + success_msg: "UFW has the expected state" + fail_msg: "Unexpected UFW state (some rules may have not been applied correctly)" diff --git a/roles/ufw/renovate.json b/roles/ufw/renovate.json new file mode 100644 index 0000000..5db72dd --- /dev/null +++ b/roles/ufw/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ] +} diff --git a/roles/ufw/requirements.ci.txt b/roles/ufw/requirements.ci.txt new file mode 100644 index 0000000..2316ec9 --- /dev/null +++ b/roles/ufw/requirements.ci.txt @@ -0,0 +1,6 @@ +ansible-lint +molecule~=24.12.0 +molecule-plugins[docker] +docker==7.1.0 +requests==2.31.0 # pinned to the latest version not breaking Docker SDK +yamllint diff --git a/roles/ufw/requirements.txt b/roles/ufw/requirements.txt new file mode 100644 index 0000000..90d4055 --- /dev/null +++ b/roles/ufw/requirements.txt @@ -0,0 +1 @@ +ansible diff --git a/roles/ufw/tasks/main.yml b/roles/ufw/tasks/main.yml new file mode 100644 index 0000000..21973d5 --- /dev/null +++ b/roles/ufw/tasks/main.yml @@ -0,0 +1,54 @@ +--- +- name: "Ensure that ufw is installed" + ansible.builtin.apt: + name: ufw + update_cache: true + +- name: "Disable IPv6" + when: (disable_ipv6 is defined) and (disable_ipv6 is true) + ansible.builtin.lineinfile: + path: /etc/default/ufw + regexp: ^IPV6 + line: IPV6=no + +- name: "Deny incoming connections" + notify: Reload-ufw + community.general.ufw: + direction: incoming + proto: any + policy: deny + +- name: "Allow outgoing connections" + notify: Reload-ufw + community.general.ufw: + direction: outgoing + proto: any + policy: allow + +- name: "Allow SSH access" + notify: Reload-ufw + community.general.ufw: + rule: "{{ limit_ssh | ternary('limit', 'allow') }}" + port: "{{ openssh_port }}" + proto: tcp + +- name: "Set whitelist rules" + notify: Reload-ufw + loop: "{{ rules }}" + community.general.ufw: + rule: "{{ item.rule | default('allow') }}" + comment: "{{ item.comment | default(omit) }}" + port: "{{ item.port | default(omit) }}" + proto: "{{ item.proto | default('any') }}" + src: "{{ item.src | default('any') }}" + dest: "{{ item.dest | default(omit) }}" + interface: "{{ item.interface | default(omit) }}" + direction: "{{ item.direction | default(omit) }}" + route: "{{ item.route | default(false) }}" + +- name: "Enable the ufw service" + community.general.ufw: + state: enabled + +- name: "Flush handlers" + ansible.builtin.meta: flush_handlers diff --git a/roles/ufw/vars/main.yml b/roles/ufw/vars/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/ufw/vars/main.yml @@ -0,0 +1 @@ +--- From 20f56a3d194528b209fbb32112ebed8df731642a Mon Sep 17 00:00:00 2001 From: Sergey Malyuk Date: Thu, 11 Dec 2025 10:37:39 +0300 Subject: [PATCH 2/5] fix linter error --- roles/ufw/defaults/main.yml | 6 +++--- roles/ufw/meta/main.yml | 4 ++-- roles/ufw/molecule/default/converge.yml | 6 +++--- roles/ufw/tasks/main.yml | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/roles/ufw/defaults/main.yml b/roles/ufw/defaults/main.yml index 7aa973f..702f638 100644 --- a/roles/ufw/defaults/main.yml +++ b/roles/ufw/defaults/main.yml @@ -1,4 +1,4 @@ --- -rules: [] -limit_ssh: false -openssh_port: 22 +ufw_rules: [] +ufw_limit_ssh: false +ufw_openssh_port: 22 diff --git a/roles/ufw/meta/main.yml b/roles/ufw/meta/main.yml index 39c7f50..004334a 100644 --- a/roles/ufw/meta/main.yml +++ b/roles/ufw/meta/main.yml @@ -10,8 +10,8 @@ galaxy_info: platforms: - name: "Ubuntu" - versions: [ "focal", "jammy" ] + versions: ["focal", "jammy"] - galaxy_tags: [ ] + galaxy_tags: [] dependencies: [] diff --git a/roles/ufw/molecule/default/converge.yml b/roles/ufw/molecule/default/converge.yml index 26ef0bd..ddd580c 100644 --- a/roles/ufw/molecule/default/converge.yml +++ b/roles/ufw/molecule/default/converge.yml @@ -11,7 +11,7 @@ comment: "Allow all incoming traffic on eth0@if288" roles: - - role: genlab.ufw + - role: genlab.common.ufw disable_ipv6: true - limit_ssh: true - rules: "{{ custom_rules }}" + ufw_limit_ssh: true + ufw_rules: "{{ custom_rules }}" diff --git a/roles/ufw/tasks/main.yml b/roles/ufw/tasks/main.yml index 21973d5..30885d3 100644 --- a/roles/ufw/tasks/main.yml +++ b/roles/ufw/tasks/main.yml @@ -28,13 +28,13 @@ - name: "Allow SSH access" notify: Reload-ufw community.general.ufw: - rule: "{{ limit_ssh | ternary('limit', 'allow') }}" - port: "{{ openssh_port }}" + rule: "{{ ufw_limit_ssh | ternary('limit', 'allow') }}" + port: "{{ ufw_openssh_port }}" proto: tcp - name: "Set whitelist rules" notify: Reload-ufw - loop: "{{ rules }}" + loop: "{{ ufw_rules }}" community.general.ufw: rule: "{{ item.rule | default('allow') }}" comment: "{{ item.comment | default(omit) }}" From 233987878e509005c68794429231ddc0e2fb474d Mon Sep 17 00:00:00 2001 From: Sergey Malyuk Date: Thu, 11 Dec 2025 10:38:15 +0300 Subject: [PATCH 3/5] update galaxy version --- galaxy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galaxy.yml b/galaxy.yml index beac011..1c0944f 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,7 +1,7 @@ --- namespace: genlab name: common -version: 0.3.1 +version: 0.4.0 readme: README.md authors: - Alexander Gorelyshev (corvus-migratorius@proton.me) From 0f9fdc9e93852d73e01248451684571d5c92c833 Mon Sep 17 00:00:00 2001 From: Sergey Malyuk Date: Thu, 11 Dec 2025 10:40:10 +0300 Subject: [PATCH 4/5] remove excessive files --- roles/ufw/.ansible-lint | 17 ----------------- roles/ufw/.gitignore | 2 -- roles/ufw/.yamllint | 8 -------- roles/ufw/environment.ci.yml | 10 ---------- roles/ufw/environment.yml | 9 --------- roles/ufw/renovate.json | 6 ------ roles/ufw/requirements.ci.txt | 6 ------ roles/ufw/requirements.txt | 1 - 8 files changed, 59 deletions(-) delete mode 100644 roles/ufw/.ansible-lint delete mode 100644 roles/ufw/.gitignore delete mode 100644 roles/ufw/.yamllint delete mode 100644 roles/ufw/environment.ci.yml delete mode 100644 roles/ufw/environment.yml delete mode 100644 roles/ufw/renovate.json delete mode 100644 roles/ufw/requirements.ci.txt delete mode 100644 roles/ufw/requirements.txt diff --git a/roles/ufw/.ansible-lint b/roles/ufw/.ansible-lint deleted file mode 100644 index 64a836a..0000000 --- a/roles/ufw/.ansible-lint +++ /dev/null @@ -1,17 +0,0 @@ ---- -profile: production -strict: true - -# Enable checking of loop variable prefixes in roles -loop_var_prefix: "^(__|{role}_)" - -skip_list: - - var-naming[no-role-prefix] - -warn_list: - - role-name[path] - - var-naming[no-role-prefix] - -exclude_paths: - - .github/ - - ufw-rules.yml diff --git a/roles/ufw/.gitignore b/roles/ufw/.gitignore deleted file mode 100644 index 8cd0df3..0000000 --- a/roles/ufw/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.vscode -.idea \ No newline at end of file diff --git a/roles/ufw/.yamllint b/roles/ufw/.yamllint deleted file mode 100644 index 611db54..0000000 --- a/roles/ufw/.yamllint +++ /dev/null @@ -1,8 +0,0 @@ ---- -rules: - brackets: - forbid: false - min-spaces-inside: 0 - max-spaces-inside: 2 - min-spaces-inside-empty: -1 - max-spaces-inside-empty: 2 diff --git a/roles/ufw/environment.ci.yml b/roles/ufw/environment.ci.yml deleted file mode 100644 index b91f882..0000000 --- a/roles/ufw/environment.ci.yml +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: ansible-ufw -channels: - - conda-forge -dependencies: - - python~=3.12.0 - - pip>=22.2 - - pip: - - -r requirements.txt - - -r requirements.ci.txt diff --git a/roles/ufw/environment.yml b/roles/ufw/environment.yml deleted file mode 100644 index a5a6851..0000000 --- a/roles/ufw/environment.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: ansible-ufw -channels: - - conda-forge -dependencies: - - python~=3.12 - - pip>=22.2 - - pip: - - -r requirements.txt diff --git a/roles/ufw/renovate.json b/roles/ufw/renovate.json deleted file mode 100644 index 5db72dd..0000000 --- a/roles/ufw/renovate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "config:recommended" - ] -} diff --git a/roles/ufw/requirements.ci.txt b/roles/ufw/requirements.ci.txt deleted file mode 100644 index 2316ec9..0000000 --- a/roles/ufw/requirements.ci.txt +++ /dev/null @@ -1,6 +0,0 @@ -ansible-lint -molecule~=24.12.0 -molecule-plugins[docker] -docker==7.1.0 -requests==2.31.0 # pinned to the latest version not breaking Docker SDK -yamllint diff --git a/roles/ufw/requirements.txt b/roles/ufw/requirements.txt deleted file mode 100644 index 90d4055..0000000 --- a/roles/ufw/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -ansible From bfdb8cad552fb0e49e7e34bf655496abea44e11f Mon Sep 17 00:00:00 2001 From: Sergey Malyuk Date: Thu, 11 Dec 2025 10:49:01 +0300 Subject: [PATCH 5/5] add community.general installation in github actions --- .github/workflows/linters.yml | 4 ++++ .github/workflows/molecule.yml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index b90a6ea..0aace81 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -26,6 +26,10 @@ jobs: # run: ansible-galaxy install -r requirements.yml # shell: micromamba-shell {0} + - name: "Install community.general collection" + run: ansible-galaxy collection install community.general + shell: micromamba-shell {0} + - name: Check workflow files themselves with ActionLint run: actionlint shell: micromamba-shell {0} diff --git a/.github/workflows/molecule.yml b/.github/workflows/molecule.yml index 2fde508..97885ee 100644 --- a/.github/workflows/molecule.yml +++ b/.github/workflows/molecule.yml @@ -78,6 +78,10 @@ jobs: run: ansible-galaxy install -r requirements.yml shell: micromamba-shell {0} + - name: "Install community.general collection" + run: ansible-galaxy collection install community.general + shell: micromamba-shell {0} + - name: "Run Molecule tests" if: ${{ matrix.role != '__no_role__' }} working-directory: ${{ matrix.role }}