Merge branch 'master' into change-meta
This commit is contained in:
@@ -7,3 +7,4 @@ loop_var_prefix: "^(__|{role}_)"
|
||||
|
||||
exclude_paths:
|
||||
- .github/
|
||||
- .ansible/
|
||||
|
||||
4
.github/workflows/linters.yml
vendored
4
.github/workflows/linters.yml
vendored
@@ -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}
|
||||
|
||||
4
.github/workflows/molecule.yml
vendored
4
.github/workflows/molecule.yml
vendored
@@ -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 }}
|
||||
|
||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.ansible
|
||||
.vscode
|
||||
53
roles/alertmanager/README.md
Normal file
53
roles/alertmanager/README.md
Normal file
@@ -0,0 +1,53 @@
|
||||
genlab.alertmanager
|
||||
=========
|
||||
|
||||
The [Alertmanager](https://github.com/prometheus/alertmanager) handles alerts sent by client applications such as the Prometheus server. It takes care of deduplicating, grouping, and routing them to the correct receiver integration such as email, PagerDuty, or OpsGenie. It also takes care of silencing and inhibition of alerts.
|
||||
|
||||
You'll need to manually specify the paths to your template files in the main Alertmanager configuration file (`alertmanager.yml`) on the target machine. The configuration file must have a `.yml` suffix, and template files must use a `.tmpl` suffix.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
None
|
||||
|
||||
Role Variables
|
||||
--------------
|
||||
|
||||
```
|
||||
alertmanager_version: 0.28.1 # version of Alertmanager (AM)
|
||||
alertmanager_config_dir: "/etc/alertmanager/conf" # where to place AM configs
|
||||
alertmanager_storage_dir: "/var/lib/alertmanager" # path to AM storage
|
||||
alertmanager_dir: "/etc/alertmanager" # where to install AM on target
|
||||
alertmanager_user: "alertmanager" # system user name
|
||||
alertmanager_group: "alertmanager" # system group name
|
||||
config_source_dir: "./alertmanager" # path to config files on source
|
||||
|
||||
# Optional
|
||||
template_source_dir: "./templates" # path to template files on source
|
||||
```
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
None
|
||||
|
||||
Example Playbook
|
||||
----------------
|
||||
|
||||
```yaml
|
||||
roles:
|
||||
- role: genlab.template
|
||||
config_source_dir: alertmanager
|
||||
alertmanager_version: 0.28.1
|
||||
|
||||
```
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
BSD
|
||||
|
||||
Author Information
|
||||
------------------
|
||||
|
||||
corvus-migratorius@proton.me
|
||||
7
roles/alertmanager/defaults/main.yml
Normal file
7
roles/alertmanager/defaults/main.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
alertmanager_version: 0.28.1
|
||||
alertmanager_config_dir: "/etc/alertmanager/conf"
|
||||
alertmanager_storage_dir: "/var/lib/alertmanager"
|
||||
alertmanager_dir: "/etc/alertmanager"
|
||||
alertmanager_user: alertmanager
|
||||
alertmanager_group: alertmanager
|
||||
7
roles/alertmanager/handlers/main.yml
Normal file
7
roles/alertmanager/handlers/main.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: "(Re)start and enable Alertmanager"
|
||||
ansible.builtin.systemd_service:
|
||||
name: alertmanager.service
|
||||
state: restarted
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
17
roles/alertmanager/meta/main.yml
Normal file
17
roles/alertmanager/meta/main.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
galaxy_info:
|
||||
role_name: alertmanager
|
||||
namespace: genlab
|
||||
author: "Alexander Gorelyshev"
|
||||
company: "Genlab, LLC"
|
||||
description: ""
|
||||
license: "MIT"
|
||||
min_ansible_version: "2.1"
|
||||
|
||||
platforms:
|
||||
- name: "Ubuntu"
|
||||
versions: ["focal", "jammy", "noble"]
|
||||
|
||||
galaxy_tags: []
|
||||
|
||||
dependencies: []
|
||||
@@ -0,0 +1,36 @@
|
||||
global:
|
||||
# SMTP configuration for email notifications (if needed)
|
||||
smtp_smarthost: 'mailserver.example.com:587'
|
||||
smtp_from: 'alertmanager@example.com'
|
||||
smtp_auth_username: 'alertmanager'
|
||||
smtp_auth_password: 'your_password'
|
||||
|
||||
# Other global settings like resolve_timeout, http_config, etc.
|
||||
|
||||
route:
|
||||
# Default receiver for alerts
|
||||
receiver: 'default-receiver'
|
||||
|
||||
# Labels used for grouping alerts
|
||||
group_by: ['alertname', 'instance', 'severity']
|
||||
|
||||
# Timing settings (group_wait, group_interval, repeat_interval)
|
||||
# You can have nested 'routes' for more complex routing logic
|
||||
|
||||
receivers:
|
||||
- name: 'default-receiver'
|
||||
email_configs:
|
||||
- to: 'ops-team@example.com'
|
||||
|
||||
inhibit_rules:
|
||||
# Rules to suppress alerts based on other alerts
|
||||
# Example:
|
||||
- source_match:
|
||||
severity: 'critical'
|
||||
target_match:
|
||||
severity: 'warning'
|
||||
# Suppress 'warning' alerts if a 'critical' alert is also firing
|
||||
|
||||
templates:
|
||||
# Paths to template files for customizing notifications
|
||||
- '/etc/alertmanager/templates/*.tmpl'
|
||||
6
roles/alertmanager/molecule/default/converge.yml
Normal file
6
roles/alertmanager/molecule/default/converge.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: Converge
|
||||
hosts: all
|
||||
roles:
|
||||
- role: genlab.common.alertmanager
|
||||
config_source_dir: alertmanager
|
||||
27
roles/alertmanager/molecule/default/molecule.yml
Normal file
27
roles/alertmanager/molecule/default/molecule.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
dependency:
|
||||
name: galaxy
|
||||
|
||||
driver:
|
||||
name: docker
|
||||
|
||||
platforms:
|
||||
- name: ubuntu
|
||||
image: geerlingguy/docker-${MOLECULE_DISTRO:-ubuntu2404}-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 .
|
||||
55
roles/alertmanager/molecule/default/verify.yml
Normal file
55
roles/alertmanager/molecule/default/verify.yml
Normal file
@@ -0,0 +1,55 @@
|
||||
---
|
||||
- name: Verify
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
any_errors_fatal: true
|
||||
|
||||
tasks:
|
||||
|
||||
- name: "Include default vars"
|
||||
ansible.builtin.include_vars:
|
||||
dir: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/defaults/"
|
||||
extensions: ['yml']
|
||||
|
||||
- name: "Check if Alertmanager is installed"
|
||||
changed_when: false
|
||||
ansible.builtin.command: "alertmanager --version"
|
||||
register: alertmanager_installed_version
|
||||
|
||||
- name: "Check Alertmanager version"
|
||||
ansible.builtin.assert:
|
||||
that: "alertmanager_installed_version.stdout is regex('{{ alertmanager_version }}')"
|
||||
success_msg: "Alertmanager version {{ alertmanager_version }} is installed and working"
|
||||
fail_msg: "Alertmanager version {{ alertmanager_version }} is not installed or not working correctly"
|
||||
|
||||
# kics-scan ignore-block
|
||||
- name: "Check if Alertmanager is reachable"
|
||||
ansible.builtin.uri:
|
||||
url: "http://localhost:9093/-/healthy"
|
||||
return_content: true
|
||||
status_code: 200
|
||||
method: GET
|
||||
body_format: json
|
||||
register: alertmanager_health
|
||||
|
||||
- name: "Assert Alertmanager health status"
|
||||
ansible.builtin.assert:
|
||||
that: "alertmanager_health.content == 'OK'"
|
||||
success_msg: "Alertmanager is healthy"
|
||||
fail_msg: "Alertmanager is not healthy"
|
||||
|
||||
# kics-scan ignore-block
|
||||
- name: "Check if Alertmanager is ready"
|
||||
ansible.builtin.uri:
|
||||
url: "http://localhost:9093/-/ready"
|
||||
return_content: true
|
||||
status_code: 200
|
||||
method: GET
|
||||
body_format: json
|
||||
register: alertmanager_ready
|
||||
|
||||
- name: "Assert Alertmanager readiness status"
|
||||
ansible.builtin.assert:
|
||||
that: "alertmanager_ready.content == 'OK'"
|
||||
success_msg: "Alertmanager is ready"
|
||||
fail_msg: "Alertmanager is not ready"
|
||||
24
roles/alertmanager/tasks/configuration.yml
Normal file
24
roles/alertmanager/tasks/configuration.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
|
||||
- name: "Copy config file"
|
||||
notify: "(Re)start and enable Alertmanager"
|
||||
ansible.builtin.template:
|
||||
src: "{{ item }}"
|
||||
dest: "{{ alertmanager_config_dir }}/{{ item | basename }}"
|
||||
owner: "{{ alertmanager_user }}"
|
||||
group: "{{ alertmanager_group }}"
|
||||
mode: "0660"
|
||||
with_fileglob:
|
||||
- "{{ config_source_dir }}/*.yml"
|
||||
|
||||
- name: "Copy templates if existed"
|
||||
notify: "(Re)start and enable Alertmanager"
|
||||
when: template_source_dir is defined
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item }}"
|
||||
dest: "{{ alertmanager_config_dir }}/{{ item | basename }}"
|
||||
owner: "{{ alertmanager_user }}"
|
||||
group: "{{ alertmanager_group }}"
|
||||
mode: "0660"
|
||||
with_fileglob:
|
||||
- "{{ template_source_dir }}/*.tmpl"
|
||||
85
roles/alertmanager/tasks/install.yml
Normal file
85
roles/alertmanager/tasks/install.yml
Normal file
@@ -0,0 +1,85 @@
|
||||
---
|
||||
- name: "Create Alertmanager system group"
|
||||
ansible.builtin.group:
|
||||
name: "{{ alertmanager_user }}"
|
||||
system: true
|
||||
state: present
|
||||
|
||||
- name: "Create Alertmanager system user"
|
||||
ansible.builtin.user:
|
||||
name: "{{ alertmanager_user }}"
|
||||
group: "{{ alertmanager_group }}"
|
||||
system: true
|
||||
shell: "/sbin/nologin"
|
||||
create_home: false
|
||||
state: present
|
||||
|
||||
- name: "Install Alertmanager from binary"
|
||||
block:
|
||||
- name: "Check Alertmanager version"
|
||||
changed_when: false
|
||||
ansible.builtin.command:
|
||||
cmd: "alertmanager --version"
|
||||
register: alertmanager_ver
|
||||
|
||||
- name: "Assert version correctness"
|
||||
ansible.builtin.assert:
|
||||
that: "alertmanager_ver.stdout is regex('{{ alertmanager_version }}')"
|
||||
success_msg: "alertmanager version {{ alertmanager_version }} is installed and working"
|
||||
fail_msg: "alertmanager version {{ alertmanager_version }} is not installed or not working correctly"
|
||||
|
||||
rescue:
|
||||
- name: "Create Alertmanager directories '{{ item }}'"
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
owner: "{{ alertmanager_user }}"
|
||||
group: "{{ alertmanager_group }}"
|
||||
mode: "0755"
|
||||
with_items:
|
||||
- "{{ alertmanager_config_dir }}"
|
||||
- "{{ alertmanager_dir }}"
|
||||
- "{{ alertmanager_storage_dir }}"
|
||||
|
||||
- name: "Download Alertmanager binary"
|
||||
ansible.builtin.get_url:
|
||||
url: "https://github.com/prometheus/alertmanager/releases/download/v{{ alertmanager_version }}/\
|
||||
alertmanager-{{ alertmanager_version }}.linux-amd64.tar.gz"
|
||||
dest: "/tmp/alertmanager-{{ alertmanager_version }}.linux-amd64.tar.gz"
|
||||
owner: "{{ alertmanager_user }}"
|
||||
group: "{{ alertmanager_group }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: "Unpack Alertmanager binaries"
|
||||
notify: "(Re)start and enable Alertmanager"
|
||||
ansible.builtin.unarchive:
|
||||
src: "/tmp/alertmanager-{{ alertmanager_version }}.linux-amd64.tar.gz"
|
||||
dest: "{{ alertmanager_dir }}"
|
||||
creates: "{{ alertmanager_dir }}/alertmanager-{{ alertmanager_version }}.linux-amd64"
|
||||
remote_src: true
|
||||
|
||||
- name: "Cleanup downloaded file"
|
||||
ansible.builtin.file:
|
||||
path: "/tmp/alertmanager-{{ alertmanager_version }}.linux-amd64.tar.gz"
|
||||
state: absent
|
||||
|
||||
- name: "Move official alertmanager and amtool binaries"
|
||||
ansible.builtin.copy:
|
||||
src: "{{ alertmanager_dir }}/alertmanager-{{ alertmanager_version }}.linux-amd64/{{ item }}"
|
||||
dest: "/usr/local/bin/{{ item }}"
|
||||
mode: "0755"
|
||||
owner: "{{ alertmanager_user }}"
|
||||
group: "{{ alertmanager_group }}"
|
||||
remote_src: true
|
||||
with_items:
|
||||
- alertmanager
|
||||
- amtool
|
||||
|
||||
|
||||
- name: "Create systemd service unit"
|
||||
ansible.builtin.template:
|
||||
src: alertmanager.service.j2
|
||||
dest: /etc/systemd/system/alertmanager.service
|
||||
owner: "{{ alertmanager_user }}"
|
||||
group: "{{ alertmanager_group }}"
|
||||
mode: "0660"
|
||||
9
roles/alertmanager/tasks/main.yml
Normal file
9
roles/alertmanager/tasks/main.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
- name: "Run installation tasks"
|
||||
ansible.builtin.include_tasks: install.yml
|
||||
|
||||
- name: "Run configuration tasks"
|
||||
ansible.builtin.include_tasks: configuration.yml
|
||||
|
||||
- name: "Flush handlers"
|
||||
ansible.builtin.meta: "flush_handlers"
|
||||
27
roles/alertmanager/templates/alertmanager.service.j2
Normal file
27
roles/alertmanager/templates/alertmanager.service.j2
Normal file
@@ -0,0 +1,27 @@
|
||||
[Unit]
|
||||
Description=Alertmanager Service
|
||||
After=network.target
|
||||
Documentation="https://prometheus.io/docs/alerting/latest/alertmanager/"
|
||||
|
||||
[Service]
|
||||
User={{ alertmanager_user }}
|
||||
Group={{ alertmanager_group }}
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/alertmanager \
|
||||
--config.file={{ alertmanager_config_dir }}/alertmanager.yml \
|
||||
--storage.path={{ alertmanager_storage_dir }}
|
||||
Restart=on-failure
|
||||
|
||||
# Security hardening
|
||||
ReadWritePaths={{ alertmanager_storage_dir }}
|
||||
ProtectSystem=strict
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
ProtectKernelModules=true
|
||||
ProtectControlGroups=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectClock=yes
|
||||
RestrictSUIDSGID=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
1
roles/alertmanager/vars/main.yml
Normal file
1
roles/alertmanager/vars/main.yml
Normal file
@@ -0,0 +1 @@
|
||||
---
|
||||
16
roles/dnsmasq/.ansible-lint
Normal file
16
roles/dnsmasq/.ansible-lint
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
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/
|
||||
2
roles/dnsmasq/.gitignore
vendored
Normal file
2
roles/dnsmasq/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.vscode
|
||||
.idea
|
||||
8
roles/dnsmasq/.yamllint
Normal file
8
roles/dnsmasq/.yamllint
Normal file
@@ -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
|
||||
37
roles/dnsmasq/README.md
Normal file
37
roles/dnsmasq/README.md
Normal file
@@ -0,0 +1,37 @@
|
||||
ansible-dnsmasq
|
||||
=========
|
||||
|
||||
Deploy dnsmasq on the target node. For now, supports only DNS functionality (DHCP and TFTP are not configuratble).
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
Take care to open the port you choose for dnsmasq to serve queries on. This role does not handle firewall configuration.
|
||||
|
||||
Role Variables
|
||||
--------------
|
||||
|
||||
None
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
None
|
||||
|
||||
Example Playbook
|
||||
----------------
|
||||
|
||||
```yaml
|
||||
roles:
|
||||
- role: genlab.dnsmasq
|
||||
```
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
BSD
|
||||
|
||||
Author Information
|
||||
------------------
|
||||
|
||||
corvus-migratorius@proton.me
|
||||
11
roles/dnsmasq/conda.dev.yml
Normal file
11
roles/dnsmasq/conda.dev.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
name: ansible-dnsmasq
|
||||
channels:
|
||||
- conda-forge
|
||||
dependencies:
|
||||
- python~=3.12.0
|
||||
- pip>=24.2
|
||||
- actionlint
|
||||
- pip:
|
||||
- -r requirements.txt
|
||||
- -r requirements.ci.txt
|
||||
9
roles/dnsmasq/conda.prod.yml
Normal file
9
roles/dnsmasq/conda.prod.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
name: ansible-dnsmasq
|
||||
channels:
|
||||
- conda-forge
|
||||
dependencies:
|
||||
- python~=3.12.0
|
||||
- pip>=24.2
|
||||
- pip:
|
||||
- -r requirements.txt
|
||||
3
roles/dnsmasq/defaults/main.yml
Normal file
3
roles/dnsmasq/defaults/main.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
dnsmasq_cache_size: 100
|
||||
dnsmasq_dns_port: 5300
|
||||
7
roles/dnsmasq/handlers/main.yml
Normal file
7
roles/dnsmasq/handlers/main.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: "Restart dnsmasq"
|
||||
ansible.builtin.systemd_service:
|
||||
name: dnsmasq
|
||||
state: restarted
|
||||
daemon_reload: true
|
||||
enabled: true
|
||||
17
roles/dnsmasq/meta/main.yml
Normal file
17
roles/dnsmasq/meta/main.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
galaxy_info:
|
||||
role_name: dnsmasq
|
||||
namespace: genlab
|
||||
author: "Alexander Gorelyshev"
|
||||
company: "Genlab, LLC"
|
||||
description: ""
|
||||
license: "MIT"
|
||||
min_ansible_version: "2.1"
|
||||
|
||||
platforms:
|
||||
- name: "Ubuntu"
|
||||
versions: ["focal", "jammy"]
|
||||
|
||||
galaxy_tags: []
|
||||
|
||||
dependencies: []
|
||||
21
roles/dnsmasq/molecule/default/converge.yml
Normal file
21
roles/dnsmasq/molecule/default/converge.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
- name: Converge
|
||||
hosts: all
|
||||
roles:
|
||||
- role: genlab.common.ufw
|
||||
disable_ipv6: true
|
||||
rules:
|
||||
- rule: allow
|
||||
# proto: udp
|
||||
port: 5300
|
||||
interface: lo
|
||||
direction: in
|
||||
comment: "Allow dnsmasq to serve DNS queries on the given interface"
|
||||
|
||||
- role: genlab.common.dnsmasq
|
||||
dnsmasq_iface: lo
|
||||
dnsmasq_domain: adm.local
|
||||
dnsmasq_dns_port: 5300
|
||||
dnsmasq_nodes:
|
||||
- name: hub
|
||||
ip: 127.0.0.1
|
||||
27
roles/dnsmasq/molecule/default/molecule.yml
Normal file
27
roles/dnsmasq/molecule/default/molecule.yml
Normal file
@@ -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 .
|
||||
19
roles/dnsmasq/molecule/default/verify.yml
Normal file
19
roles/dnsmasq/molecule/default/verify.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
- name: Verify
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
any_errors_fatal: true
|
||||
|
||||
pre_tasks:
|
||||
- name: "Install a package providing the `dig` tool"
|
||||
ansible.builtin.apt:
|
||||
name: dnsutils
|
||||
state: present
|
||||
|
||||
tasks:
|
||||
- name: "Test the output of the `dig` command"
|
||||
changed_when: false
|
||||
register: dnsmasq_dig
|
||||
failed_when: 'dnsmasq_dig.stdout != "127.0.0.1"'
|
||||
ansible.builtin.command:
|
||||
cmd: "dig @127.0.0.1 -p 5300 hub.adm.local +short"
|
||||
6
roles/dnsmasq/renovate.json
Normal file
6
roles/dnsmasq/renovate.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:recommended"
|
||||
]
|
||||
}
|
||||
6
roles/dnsmasq/requirements.ci.txt
Normal file
6
roles/dnsmasq/requirements.ci.txt
Normal file
@@ -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
|
||||
1
roles/dnsmasq/requirements.txt
Normal file
1
roles/dnsmasq/requirements.txt
Normal file
@@ -0,0 +1 @@
|
||||
ansible~=11.1.0
|
||||
5
roles/dnsmasq/requirements.yml
Normal file
5
roles/dnsmasq/requirements.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
# requirements file
|
||||
---
|
||||
roles:
|
||||
- name: genlab.ufw
|
||||
src: https://github.com/corvus-migratorius/ansible-ufw.git
|
||||
38
roles/dnsmasq/tasks/main.yml
Normal file
38
roles/dnsmasq/tasks/main.yml
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
- name: "Install dnsmasq"
|
||||
ansible.builtin.apt:
|
||||
name: dnsmasq
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
|
||||
- name: "Create interface-specific configuration file"
|
||||
notify: "Restart dnsmasq"
|
||||
ansible.builtin.blockinfile:
|
||||
path: /etc/dnsmasq.d/{{ dnsmasq_domain }}.conf
|
||||
create: true
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0660"
|
||||
block: |
|
||||
interface="{{ dnsmasq_iface }}"
|
||||
port="{{ dnsmasq_dns_port }}"
|
||||
cache-size="{{ dnsmasq_cache_size }}"
|
||||
log-queries
|
||||
server=1.1.1.1 # Cloudflare DNS
|
||||
server=8.8.8.8 # Google DNS
|
||||
server=8.8.4.4 # Google DNS (secondary)
|
||||
|
||||
|
||||
- name: "Add dnsmasq_nodes to the configuration file"
|
||||
notify: "Restart dnsmasq"
|
||||
loop: "{{ dnsmasq_nodes }}"
|
||||
ansible.builtin.blockinfile:
|
||||
path: /etc/dnsmasq.d/{{ dnsmasq_domain }}.conf
|
||||
marker: "# {mark} ANSIBLE MANAGED: {{ item.name }}.{{ dnsmasq_domain }}"
|
||||
block: |
|
||||
address=/{{ item.name }}.{{ dnsmasq_domain }}/{{ item.ip }}
|
||||
|
||||
|
||||
- name: "Flush handlers"
|
||||
ansible.builtin.meta: flush_handlers
|
||||
1
roles/dnsmasq/vars/main.yml
Normal file
1
roles/dnsmasq/vars/main.yml
Normal file
@@ -0,0 +1 @@
|
||||
---
|
||||
37
roles/ufw/README.md
Normal file
37
roles/ufw/README.md
Normal file
@@ -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
|
||||
4
roles/ufw/defaults/main.yml
Normal file
4
roles/ufw/defaults/main.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
ufw_rules: []
|
||||
ufw_limit_ssh: false
|
||||
ufw_openssh_port: 22
|
||||
4
roles/ufw/handlers/main.yml
Normal file
4
roles/ufw/handlers/main.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
- name: "Reload-ufw"
|
||||
community.general.ufw:
|
||||
state: reloaded
|
||||
17
roles/ufw/meta/main.yml
Normal file
17
roles/ufw/meta/main.yml
Normal file
@@ -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: []
|
||||
17
roles/ufw/molecule/default/converge.yml
Normal file
17
roles/ufw/molecule/default/converge.yml
Normal file
@@ -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.common.ufw
|
||||
disable_ipv6: true
|
||||
ufw_limit_ssh: true
|
||||
ufw_rules: "{{ custom_rules }}"
|
||||
27
roles/ufw/molecule/default/molecule.yml
Normal file
27
roles/ufw/molecule/default/molecule.yml
Normal file
@@ -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 .
|
||||
28
roles/ufw/molecule/default/verify.yml
Normal file
28
roles/ufw/molecule/default/verify.yml
Normal file
@@ -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)"
|
||||
54
roles/ufw/tasks/main.yml
Normal file
54
roles/ufw/tasks/main.yml
Normal file
@@ -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: "{{ ufw_limit_ssh | ternary('limit', 'allow') }}"
|
||||
port: "{{ ufw_openssh_port }}"
|
||||
proto: tcp
|
||||
|
||||
- name: "Set whitelist rules"
|
||||
notify: Reload-ufw
|
||||
loop: "{{ ufw_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
|
||||
1
roles/ufw/vars/main.yml
Normal file
1
roles/ufw/vars/main.yml
Normal file
@@ -0,0 +1 @@
|
||||
---
|
||||
43
roles/wg_hub/README.md
Normal file
43
roles/wg_hub/README.md
Normal file
@@ -0,0 +1,43 @@
|
||||
template
|
||||
=========
|
||||
|
||||
Template for Ansible role monorepos.
|
||||
|
||||
⚠️ Do not forget to update:
|
||||
|
||||
- `meta/main.yml`
|
||||
- Conda/Mamba manifests
|
||||
- this README =)
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
None
|
||||
|
||||
Role Variables
|
||||
--------------
|
||||
|
||||
None
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
None
|
||||
|
||||
Example Playbook
|
||||
----------------
|
||||
|
||||
```yaml
|
||||
roles:
|
||||
- role: genlab.template
|
||||
```
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
BSD
|
||||
|
||||
Author Information
|
||||
------------------
|
||||
|
||||
corvus-migratorius@proton.me
|
||||
7
roles/wg_hub/defaults/main.yml
Normal file
7
roles/wg_hub/defaults/main.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
wg_hub_iface_name: wg0
|
||||
wg_hub_host_id: hub
|
||||
wg_hub_ipv4_vpn_addr: 10.0.0.254
|
||||
wg_hub_ipv4_vpn_cidr: 24
|
||||
wg_hub_wg_port: 51820
|
||||
wg_hub_hide_secrets: true
|
||||
7
roles/wg_hub/handlers/main.yml
Normal file
7
roles/wg_hub/handlers/main.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: "Run the Wireguard service"
|
||||
ansible.builtin.systemd_service:
|
||||
name: wg-quick@{{ wg_hub_iface_name | replace("-", "_") }}
|
||||
state: restarted
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
17
roles/wg_hub/meta/main.yml
Normal file
17
roles/wg_hub/meta/main.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
galaxy_info:
|
||||
role_name: "wg_hub"
|
||||
namespace: genlab
|
||||
author: "Alexander Gorelyshev"
|
||||
company: "Genlab, LLC"
|
||||
description: ""
|
||||
license: "MIT"
|
||||
min_ansible_version: "2.1"
|
||||
|
||||
platforms:
|
||||
- name: "Ubuntu"
|
||||
versions: ["jammy", "noble"]
|
||||
|
||||
galaxy_tags: []
|
||||
|
||||
dependencies: []
|
||||
24
roles/wg_hub/molecule/default/converge.yml
Normal file
24
roles/wg_hub/molecule/default/converge.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
- name: Converge
|
||||
hosts: all
|
||||
vars:
|
||||
wg_hub_iface_name: adm
|
||||
wg_hub_ipv4_vpn_addr: 10.0.0.254
|
||||
wg_hub_ipv4_vpn_cidr: 24
|
||||
wg_hub_wg_port: 51820
|
||||
wg_hub_wg_pkey: gABk6e/n3UDgudEVlUrEVcVdn0tc0YVDeCASsI10QFA=
|
||||
wg_hub_wg_pubkey: EvcoZ21/p0AHz5y95jwjVIR9puljc2kXqh/f3U1A4nk=
|
||||
wg_hub_hide_secrets: false
|
||||
# dns_server: 127.0.0.1:5300 # doesn't work in Github Actions environment
|
||||
peers:
|
||||
- wg_hub_host_id: alpha
|
||||
wg_hub_ipv4_vpn_addr: 10.0.0.1
|
||||
wg_hub_wg_pubkey: LfEJgNiJ05nx4nWB0Pj3wS3WRyFq567fsdDh4XZqRF0=
|
||||
wg_psk: i3JCrQOfptZhgpL+BTm/65MPW/ljJexCgiuWMIqZJYo=
|
||||
- wg_hub_host_id: beta
|
||||
wg_hub_ipv4_vpn_addr: 10.0.0.2
|
||||
wg_hub_wg_pubkey: oq3Fcwwfxsi5f5UHcZKtxMwQ2aSeHOUe3r35soUUYzU=
|
||||
wg_psk: Z/z7Qo8hW97UcImYE/ZbCxpNmizfVhvl0dzygtvtYYg=
|
||||
|
||||
roles:
|
||||
- role: genlab.common.wg_hub
|
||||
27
roles/wg_hub/molecule/default/molecule.yml
Normal file
27
roles/wg_hub/molecule/default/molecule.yml
Normal file
@@ -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 .
|
||||
13
roles/wg_hub/molecule/default/verify.yml
Normal file
13
roles/wg_hub/molecule/default/verify.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
- name: Verify
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
any_errors_fatal: true
|
||||
vars:
|
||||
iface_name: adm
|
||||
|
||||
tasks:
|
||||
- name: "Check that the Wireguard service is running"
|
||||
ansible.builtin.service:
|
||||
name: wg-quick@{{ iface_name }}
|
||||
state: started
|
||||
54
roles/wg_hub/tasks/main.yml
Normal file
54
roles/wg_hub/tasks/main.yml
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
- name: "Install wireguard system-wide"
|
||||
ansible.builtin.apt:
|
||||
name: wireguard
|
||||
state: present
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
|
||||
- name: "Ensure no dashes in the interface name"
|
||||
when: "'-' in wg_hub_iface_name"
|
||||
ansible.builtin.fail:
|
||||
msg: "The interface name must not contain dashes, got: '{{ wg_hub_iface_name }}'"
|
||||
|
||||
- name: "Create the Hub configuration file"
|
||||
no_log: "{{ wg_hub_hide_secrets }}"
|
||||
notify: "Run the Wireguard service"
|
||||
ansible.builtin.blockinfile:
|
||||
path: "/etc/wireguard/{{ wg_hub_iface_name }}.conf"
|
||||
create: true
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
state: present
|
||||
block: |
|
||||
[Interface]
|
||||
Address = {{ wg_hub_ipv4_vpn_addr }}/32
|
||||
ListenPort = {{ wg_hub_wg_port }}
|
||||
PrivateKey = {{ wg_hub_wg_pkey }}
|
||||
|
||||
PreUp = sysctl -w net.ipv4.ip_forward=1
|
||||
{% if dns_server is defined %}
|
||||
PostUp = resolvectl dns %i {{ dns_server }}; resolvectl domain %i {{ wg_hub_iface_name }}.local
|
||||
{% endif %}
|
||||
PostDown = sysctl -w net.ipv4.ip_forward=0
|
||||
|
||||
- name: "Add [Peer] sections to the Hub configuration file"
|
||||
no_log: "{{ wg_hub_hide_secrets }}"
|
||||
notify: "Run the Wireguard service"
|
||||
loop: "{{ peers }}"
|
||||
vars:
|
||||
domain_name: "{{ item.wg_hub_host_id }}.{{ wg_hub_iface_name }}.local"
|
||||
ansible.builtin.blockinfile:
|
||||
path: "/etc/wireguard/{{ wg_hub_iface_name }}.conf"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
marker: "# {mark} ANSIBLE MANAGED SPOKE BLOCK: {{ domain_name }}"
|
||||
block: |
|
||||
#
|
||||
[Peer] # {{ domain_name }}
|
||||
PublicKey = {{ item.wg_hub_wg_pubkey }}
|
||||
PresharedKey = {{ item.wg_psk }}
|
||||
AllowedIPs = {{ item.wg_hub_ipv4_vpn_addr }}/32
|
||||
#
|
||||
1
roles/wg_hub/vars/main.yml
Normal file
1
roles/wg_hub/vars/main.yml
Normal file
@@ -0,0 +1 @@
|
||||
---
|
||||
Reference in New Issue
Block a user