From 6cc9946aec8e881cbd01c1b7bbda41309dcf9ad6 Mon Sep 17 00:00:00 2001 From: Albert Stefanov Date: Wed, 1 May 2024 16:15:32 +0300 Subject: [PATCH] Start writing the Ansible playbook If we want to automate everything :-) #8 --- automation/ansible/.ansible-lint | 1 + automation/ansible/.gitignore | 1 + automation/ansible/README.md | 32 +++++++++++++ .../ansible/group_vars/all/packages.yml | 8 ++++ .../group_vars/all/ssh_users.yml.example | 2 + .../host_vars/server1/common.yml.example | 2 + .../host_vars/server1/firewall.yml.example | 1 + automation/ansible/hosts.ini | 4 ++ automation/ansible/lint.sh | 1 + automation/ansible/main.yml | 12 +++++ .../ansible/roles/common/tasks/main.yml | 14 ++++++ .../ansible/roles/common/tasks/packages.yml | 10 ++++ .../roles/common/tasks/root_sshkeys.yml | 11 +++++ .../roles/firewall/files/nftables.service | 20 ++++++++ .../roles/firewall/handlers/firewall.yml | 6 +++ .../ansible/roles/firewall/tasks/main.yml | 47 +++++++++++++++++++ .../roles/firewall/templates/nftables.conf.j2 | 38 +++++++++++++++ .../ansible/roles/router/tasks/main.yml | 3 ++ .../ansible/roles/router/tasks/sysctl.yml | 22 +++++++++ automation/ansible/run.sh | 1 + 20 files changed, 236 insertions(+) create mode 100644 automation/ansible/.ansible-lint create mode 100644 automation/ansible/.gitignore create mode 100644 automation/ansible/README.md create mode 100644 automation/ansible/group_vars/all/packages.yml create mode 100644 automation/ansible/group_vars/all/ssh_users.yml.example create mode 100644 automation/ansible/host_vars/server1/common.yml.example create mode 100644 automation/ansible/host_vars/server1/firewall.yml.example create mode 100644 automation/ansible/hosts.ini create mode 100755 automation/ansible/lint.sh create mode 100644 automation/ansible/main.yml create mode 100644 automation/ansible/roles/common/tasks/main.yml create mode 100644 automation/ansible/roles/common/tasks/packages.yml create mode 100644 automation/ansible/roles/common/tasks/root_sshkeys.yml create mode 100644 automation/ansible/roles/firewall/files/nftables.service create mode 100644 automation/ansible/roles/firewall/handlers/firewall.yml create mode 100644 automation/ansible/roles/firewall/tasks/main.yml create mode 100644 automation/ansible/roles/firewall/templates/nftables.conf.j2 create mode 100644 automation/ansible/roles/router/tasks/main.yml create mode 100644 automation/ansible/roles/router/tasks/sysctl.yml create mode 100755 automation/ansible/run.sh diff --git a/automation/ansible/.ansible-lint b/automation/ansible/.ansible-lint new file mode 100644 index 0000000..b89a374 --- /dev/null +++ b/automation/ansible/.ansible-lint @@ -0,0 +1 @@ +profile: production diff --git a/automation/ansible/.gitignore b/automation/ansible/.gitignore new file mode 100644 index 0000000..8180076 --- /dev/null +++ b/automation/ansible/.gitignore @@ -0,0 +1 @@ +*.secret.yml diff --git a/automation/ansible/README.md b/automation/ansible/README.md new file mode 100644 index 0000000..4337f86 --- /dev/null +++ b/automation/ansible/README.md @@ -0,0 +1,32 @@ +# OpenFest Infra -- Ansible Playbooks + +## General Variables + +### Global/Group + +| Name | Description | +|-----------------|-------------------------------------------------| +| global_ssh_keys | Keys of people authorized to access _all_ hosts | + +### Host + +| Name | Description | +|--------------------|---------------------------------------------------------------| +| ssh_keys['root'] | Users authorized to run commands as root | +| ssh_keys[username] | Authorized keys for a specific user | +| ssh_keys['*'] | Authorized keys for all non-root users provisioned by ansible | + +## Secret and not-so-secret Variables (grouped by service) + +### Keycloak + +| Name | Description | +|---------------------------|----------------------------------------------------------------------| +| keycloak_hostname | Passed as the [Public URL](https://www.keycloak.org/server/hostname) | +| keycloak_db_password | PostgreSQL DB Password | +| keycloak_db_ansible_host | PostgreSQL DB Host (in inventory), for provisioning the database | +| keycloak_podman_user_name | Owner of the keycloak container | +| keycloak_podman_user_home | `{{ keycloak_podman_user_name }}`'s home directory | +| keycloak_data_dir | Used for the volumes / bind mounts | +| keycloak_listen_address | Where to bind on the host (for using a reverse proxy) | + diff --git a/automation/ansible/group_vars/all/packages.yml b/automation/ansible/group_vars/all/packages.yml new file mode 100644 index 0000000..81f9c13 --- /dev/null +++ b/automation/ansible/group_vars/all/packages.yml @@ -0,0 +1,8 @@ +--- + +global_packages: + Debian: + - vim + - mtr-tiny + - traceroute + - tcpdump diff --git a/automation/ansible/group_vars/all/ssh_users.yml.example b/automation/ansible/group_vars/all/ssh_users.yml.example new file mode 100644 index 0000000..04c9f25 --- /dev/null +++ b/automation/ansible/group_vars/all/ssh_users.yml.example @@ -0,0 +1,2 @@ +global_root_ssh_key_urls: + - https://pesho.ludost.net/files/openfest_keys diff --git a/automation/ansible/host_vars/server1/common.yml.example b/automation/ansible/host_vars/server1/common.yml.example new file mode 100644 index 0000000..c305df0 --- /dev/null +++ b/automation/ansible/host_vars/server1/common.yml.example @@ -0,0 +1,2 @@ +--- +hostname: server1.openfest.org diff --git a/automation/ansible/host_vars/server1/firewall.yml.example b/automation/ansible/host_vars/server1/firewall.yml.example new file mode 100644 index 0000000..d371b70 --- /dev/null +++ b/automation/ansible/host_vars/server1/firewall.yml.example @@ -0,0 +1 @@ +firewall: diff --git a/automation/ansible/hosts.ini b/automation/ansible/hosts.ini new file mode 100644 index 0000000..ca685df --- /dev/null +++ b/automation/ansible/hosts.ini @@ -0,0 +1,4 @@ +server1 ansible_host=192.168.122.87 ansible_user=root + +[routers] +server1 diff --git a/automation/ansible/lint.sh b/automation/ansible/lint.sh new file mode 100755 index 0000000..db329b7 --- /dev/null +++ b/automation/ansible/lint.sh @@ -0,0 +1 @@ +ansible-lint roles/*/tasks/main.yml diff --git a/automation/ansible/main.yml b/automation/ansible/main.yml new file mode 100644 index 0000000..aa69762 --- /dev/null +++ b/automation/ansible/main.yml @@ -0,0 +1,12 @@ +--- + +- name: Run common tasks + hosts: all + roles: + - common + +- name: Router + hosts: routers + roles: + - firewall + - router diff --git a/automation/ansible/roles/common/tasks/main.yml b/automation/ansible/roles/common/tasks/main.yml new file mode 100644 index 0000000..f481242 --- /dev/null +++ b/automation/ansible/roles/common/tasks/main.yml @@ -0,0 +1,14 @@ +--- + +- name: Add ssh keys for root + ansible.builtin.include_tasks: root_sshkeys.yml + +- name: Set hostname + ansible.builtin.hostname: + name: "{{ hostname }}" + when: hostname is defined + +- name: Install sudo as it's needed for 'become' + ansible.builtin.package: + name: sudo + state: present diff --git a/automation/ansible/roles/common/tasks/packages.yml b/automation/ansible/roles/common/tasks/packages.yml new file mode 100644 index 0000000..9b945ef --- /dev/null +++ b/automation/ansible/roles/common/tasks/packages.yml @@ -0,0 +1,10 @@ +--- + +- name: Install standard packages + ansible.builtin.package: + name: "{{ item }}" + state: present + with_items: "{{ + (global_packages[ansible_os_family] | default([])) + + (local_packages | default([])) + }}" diff --git a/automation/ansible/roles/common/tasks/root_sshkeys.yml b/automation/ansible/roles/common/tasks/root_sshkeys.yml new file mode 100644 index 0000000..621702c --- /dev/null +++ b/automation/ansible/roles/common/tasks/root_sshkeys.yml @@ -0,0 +1,11 @@ +--- + +- name: Add public keys for root + ansible.posix.authorized_key: + user: root + key: "{{ lookup('ansible.builtin.url', item) }}" + state: present # Note: we don't remove other/existing keys + with_items: "{{ + (global_root_ssh_key_urls | default([])) + + (root_ssh_keys | default([])) + }}" diff --git a/automation/ansible/roles/firewall/files/nftables.service b/automation/ansible/roles/firewall/files/nftables.service new file mode 100644 index 0000000..769c9fc --- /dev/null +++ b/automation/ansible/roles/firewall/files/nftables.service @@ -0,0 +1,20 @@ +[Unit] +Description=nftables +Documentation=man:nft(8) http://wiki.nftables.org +Wants=network-pre.target +Before=network-pre.target shutdown.target +Conflicts=shutdown.target +DefaultDependencies=no + +[Service] +Type=oneshot +RemainAfterExit=yes +StandardInput=null +ProtectSystem=full +ProtectHome=true +ExecStart=/usr/sbin/nft -f /etc/nftables.conf +ExecReload=/usr/sbin/nft -f /etc/nftables.conf +ExecStop=/usr/sbin/nft flush ruleset + +[Install] +WantedBy=sysinit.target diff --git a/automation/ansible/roles/firewall/handlers/firewall.yml b/automation/ansible/roles/firewall/handlers/firewall.yml new file mode 100644 index 0000000..005041f --- /dev/null +++ b/automation/ansible/roles/firewall/handlers/firewall.yml @@ -0,0 +1,6 @@ +--- + +- name: Restart nftables + ansible.builtin.service: + name: nftables.service + state: restarted diff --git a/automation/ansible/roles/firewall/tasks/main.yml b/automation/ansible/roles/firewall/tasks/main.yml new file mode 100644 index 0000000..b198ba7 --- /dev/null +++ b/automation/ansible/roles/firewall/tasks/main.yml @@ -0,0 +1,47 @@ +--- + +- name: Install nftables + ansible.builtin.package: + name: nftables + state: present + +- name: Get available services + ansible.builtin.service_facts: + +- name: Create service file if it doesn't exist already + ansible.builtin.copy: + src: nftables.service + dest: /etc/systemd/system/nftables.service + state: present + mode: "644" + when: ansible_facts.services['nftables.service'] is not defined + +- name: Add config file + ansible.builtin.template: + src: nftables.conf.j2 + dest: "{{ nftables_main_file[ansible_os_family] | + default('/etc/nftables.conf') }}" + mode: "644" + vars: + nftables_main_file: + Debian: /etc/nftables.conf + RedHat: /etc/nftables/main.nft + +- name: Create subdirs + ansible.builtin.file: + name: "{{ item }}" + state: directory + mode: "755" + with_items: + - /etc/nftables/input.d + - /etc/nftables/forward.d + - /etc/nftables/output.d + - /etc/nftables/filter.d + - /etc/nftables/global.d + +- name: Enable and start nftables + ansible.builtin.systemd_service: + name: nftables.service + enabled: true + state: started + daemon_reload: true diff --git a/automation/ansible/roles/firewall/templates/nftables.conf.j2 b/automation/ansible/roles/firewall/templates/nftables.conf.j2 new file mode 100644 index 0000000..dab350f --- /dev/null +++ b/automation/ansible/roles/firewall/templates/nftables.conf.j2 @@ -0,0 +1,38 @@ +#!/usr/sbin/nft -f + +flush ruleset + +include "/etc/nftables/global.d/*.nft"; + +table inet filter { + include "/etc/nftables/filter.d/*.nft"; + + chain input { + type filter hook input priority filter; policy {{ firewall.input_policy | default('drop') }}; + + iif lo accept + + # Anti-klonootryazvane + tcp dport ssh accept + ct state established,related accept + + # Don't block ICMP + ip protocol icmp accept + ip6 nexthdr icmpv6 accept + + include "/etc/nftables/input.d/*.nft"; + + # Should we reject or drop? + ip protocol tcp reject with tcp reset + ip6 nexthdr tcp reject with tcp reset + reject + } + + chain forward { + type filter hook forward priority filter; policy {{ firewall.forward_policy | default('drop') }}; + } + + chain output { + type filter hook output priority filter; policy {{ firewall.output_policy | default('accept') }}; + } +} diff --git a/automation/ansible/roles/router/tasks/main.yml b/automation/ansible/roles/router/tasks/main.yml new file mode 100644 index 0000000..8facb13 --- /dev/null +++ b/automation/ansible/roles/router/tasks/main.yml @@ -0,0 +1,3 @@ +--- +- name: Configure sysctl + ansible.builtin.include_tasks: sysctl.yml diff --git a/automation/ansible/roles/router/tasks/sysctl.yml b/automation/ansible/roles/router/tasks/sysctl.yml new file mode 100644 index 0000000..1388ead --- /dev/null +++ b/automation/ansible/roles/router/tasks/sysctl.yml @@ -0,0 +1,22 @@ +--- + +- name: Create sysctl.d + ansible.builtin.file: + name: /etc/sysctl.d + state: directory + mode: "755" +- name: Enable IPv4 routing + ansible.posix.sysctl: + name: net.ipv4.ip_forward + value: '1' + sysctl_file: /etc/sysctl.d/router.conf + state: present + reload: true + +- name: Enable IPv6 routing + ansible.posix.sysctl: + name: net.ipv6.conf.all.forwarding + value: '1' + sysctl_file: /etc/sysctl.d/router.conf + state: present + reload: true diff --git a/automation/ansible/run.sh b/automation/ansible/run.sh new file mode 100755 index 0000000..457398e --- /dev/null +++ b/automation/ansible/run.sh @@ -0,0 +1 @@ +ansible-playbook -i hosts.ini main.yml