diff --git a/inventory/host_vars/ch01.balsillie.house/ansible_become.yml b/inventory/group_vars/archlinux_servers/ansible_become.yml similarity index 58% rename from inventory/host_vars/ch01.balsillie.house/ansible_become.yml rename to inventory/group_vars/archlinux_servers/ansible_become.yml index 75fbfde..8185196 100644 --- a/inventory/host_vars/ch01.balsillie.house/ansible_become.yml +++ b/inventory/group_vars/archlinux_servers/ansible_become.yml @@ -1,3 +1,3 @@ ansible_become_method: ansible.builtin.sudo -ansible_sudo_user: root -ansible_sudo_pass: "{{ lookup('community.general.passwordstore', 'ansible/become-password') }}" +ansible_sudo_pass: "{{ lookup('community.general.passwordstore', ('ansible/become-passwords/' + ansible_ssh_host)) }}" +ansible_sudo_user: root \ No newline at end of file diff --git a/inventory/group_vars/archlinux_servers/ansible_connection.yml b/inventory/group_vars/archlinux_servers/ansible_connection.yml new file mode 100644 index 0000000..3329320 --- /dev/null +++ b/inventory/group_vars/archlinux_servers/ansible_connection.yml @@ -0,0 +1,3 @@ +ansible_connection: ansible.builtin.ssh +ansible_ssh_port: 22 +ansible_ssh_user: ladmin diff --git a/inventory/host_vars/ch01.balsillie.house/ansible_connection.yml b/inventory/host_vars/ch01.balsillie.house/ansible_connection.yml index be7fea2..059d209 100644 --- a/inventory/host_vars/ch01.balsillie.house/ansible_connection.yml +++ b/inventory/host_vars/ch01.balsillie.house/ansible_connection.yml @@ -1,4 +1 @@ -ansible_connection: ansible.builtin.ssh ansible_ssh_host: ch01.balsillie.house -ansible_ssh_port: 22 -ansible_ssh_user: ladmin diff --git a/inventory/host_vars/ch02.balsillie.house/ansible_connection.yml b/inventory/host_vars/ch02.balsillie.house/ansible_connection.yml new file mode 100644 index 0000000..5633ce5 --- /dev/null +++ b/inventory/host_vars/ch02.balsillie.house/ansible_connection.yml @@ -0,0 +1 @@ +ansible_ssh_host: ch02.balsillie.house diff --git a/inventory/host_vars/dl01.balsillie.house/ansible_connection.yml b/inventory/host_vars/dl01.balsillie.house/ansible_connection.yml new file mode 100644 index 0000000..e738123 --- /dev/null +++ b/inventory/host_vars/dl01.balsillie.house/ansible_connection.yml @@ -0,0 +1 @@ +ansible_ssh_host: dl01.balsillie.house diff --git a/inventory/inventory.yml b/inventory/inventory.yml index 16814b7..9916b3c 100644 --- a/inventory/inventory.yml +++ b/inventory/inventory.yml @@ -1,8 +1,16 @@ all: children: + archlinux_servers: + children: + container_hosts: + download_clients: container_hosts: hosts: ch01.balsillie.house: + ch02.balsillie.house: + download_clients: + hosts: + dl01.balsillie.house: firewalls: hosts: firewall.balsillie.house: diff --git a/playbooks/archlinux-servers.yml b/playbooks/archlinux-servers.yml new file mode 100644 index 0000000..2ba4575 --- /dev/null +++ b/playbooks/archlinux-servers.yml @@ -0,0 +1,25 @@ +--- + +- name: Configure ssh and firewall + hosts: + - archlinux_servers + gather_facts: false + become: true + pre_tasks: + + - name: Set IP facts + become: false + ansible.builtin.set_fact: + ipv4_address: "{{ query('community.dns.lookup', inventory_hostname, type='A', nxdomain_handling = 'fail') | first }}" + ipv6_address: "{{ query('community.dns.lookup', inventory_hostname, type='AAAA', nxdomain_handling = 'fail') | first }}" + + - name: Install basic utilities + community.general.pacman: + name: + - nano + - curl + state: present + update_cache: true + + roles: + - sshd diff --git a/playbooks/container-host.yml b/playbooks/container-host.yml deleted file mode 100644 index 9549d07..0000000 --- a/playbooks/container-host.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- - -- name: Configure container hosts - hosts: - - ch01.balsillie.house - gather_facts: false - tasks: - - - name: Ping - become: true - ansible.builtin.ping: - data: "pong" diff --git a/roles/sshd/files/sshd_override.conf b/roles/sshd/files/sshd_override.conf new file mode 100644 index 0000000..6a4aaef --- /dev/null +++ b/roles/sshd/files/sshd_override.conf @@ -0,0 +1,3 @@ +[Unit] +Wants=network-online.target +After=network-online.target \ No newline at end of file diff --git a/roles/sshd/handlers/main.yml b/roles/sshd/handlers/main.yml new file mode 100644 index 0000000..6477757 --- /dev/null +++ b/roles/sshd/handlers/main.yml @@ -0,0 +1,14 @@ +#code: language=ansible + +- name: Restart sshd + ansible.builtin.systemd_service: + daemon_reload: true + name: sshd.service + scope: system + state: restarted + +- name: Restart systemd-networkd + ansible.builtin.systemd_service: + name: systemd-networkd.service + scope: system + state: restarted \ No newline at end of file diff --git a/roles/sshd/tasks/main.yml b/roles/sshd/tasks/main.yml new file mode 100644 index 0000000..cecf069 --- /dev/null +++ b/roles/sshd/tasks/main.yml @@ -0,0 +1,135 @@ +#code: language=ansible + +- name: Disable link local addressing + ansible.builtin.lineinfile: + backrefs: false + backup: true + create: false + encoding: "utf-8" + firstmatch: true + group: root + insertafter: '^\[Network\]\s*$' + line: "LinkLocalAddressing=no" + mode: "0664" + owner: root + path: "/etc/systemd/network/10-cloud-init-eth0.network" + regexp: '^LinkLocalAddressing\s*=.*$' + state: present + notify: + - Restart systemd-networkd + +- name: Set link wait-online requirements + ansible.builtin.blockinfile: + append_newline: true + backup: true + block: | + [Link] + ActivationPolicy=always-up + RequiredForOnline=yes + RequiredFamilyForOnline=both + create: false + group: root + insertbefore: '^\[Network\]\s*$' + mode: "0664" + owner: root + path: "/etc/systemd/network/10-cloud-init-eth0.network" + prepend_newline: true + state: present + +- name: Disable global systemd-networkd-wait-online + ansible.builtin.systemd_service: + enabled: false + name: systemd-networkd-wait-online.service + scope: system + state: stopped + +- name: Enable instantiated systemd-networkd-wait-online + ansible.builtin.systemd_service: + enabled: true + name: systemd-networkd-wait-online@eth0.service + scope: system + state: started + +- name: Create sshd.service override directory + ansible.builtin.file: + group: root + mode: "0775" + owner: root + path: /etc/systemd/system/sshd.service.d + state: directory + +- name: Create sshd.service override config + ansible.builtin.copy: + dest: /etc/systemd/system/sshd.service.d/sshd_override.conf + group: root + mode: "0664" + owner: root + remote_src: false + src: "{{ role_path }}/files/sshd_override.conf" + notify: + - Restart sshd + +- name: Configure sshd_config + ansible.builtin.lineinfile: + backrefs: false + create: true + encoding: "utf-8" + firstmatch: false + group: root + line: "{{ item.line }}" + mode: "0664" + owner: root + path: "/etc/ssh/sshd_config" + regexp: "{{ item.pattern }}" + state: present + loop: "{{ sshd_config_lines }}" + loop_control: + label: "{{ item.label }}" + notify: + - Restart sshd + +- name: Install UFW + community.general.pacman: + name: + - ufw + state: present + update_cache: true + +- name: Configure UFW IPv4 rules + community.general.ufw: + comment: "{{ item.comment }}" + direction: "in" + from_ip: "{{ item.source }}" + log: true + proto: tcp + rule: "allow" + to_ip: "{{ ipv4_address }}" + to_port: "22" + loop: "{{ sshd_ufw_ipv4_rules }}" + loop_control: + label: "{{ item.comment }}" + +- name: Configure UFW IPv6 rules + community.general.ufw: + comment: "{{ item.comment }}" + direction: "in" + from_ip: "{{ item.source }}" + log: true + proto: tcp + rule: "allow" + to_ip: "{{ ipv6_address }}" + to_port: "22" + loop: "{{ sshd_ufw_ipv6_rules }}" + loop_control: + label: "{{ item.comment }}" + +- name: Enable UFW + community.general.ufw: + state: enabled + +- name: Enable and start UFW service + ansible.builtin.systemd_service: + enabled: true + name: ufw.service + scope: system + state: started diff --git a/roles/sshd/vars/main.yml b/roles/sshd/vars/main.yml new file mode 100644 index 0000000..5501a37 --- /dev/null +++ b/roles/sshd/vars/main.yml @@ -0,0 +1,58 @@ +#code: language=ansible + +sshd_port: 22 + +sshd_config_lines: + - label: PubkeyAuthentication + pattern: '^\s*#*\s*PubkeyAuthentication\s*(yes|no)$' + line: 'PubkeyAuthentication yes' + - label: HostbasedAuthentication + pattern: '^\s*#*\s*HostbasedAuthentication\s*(yes|no)$' + line: 'HostbasedAuthentication no' + - label: IgnoreUserKnownHosts + pattern: '^\s*#*\s*IgnoreUserKnownHosts\s*(yes|no)$' + line: 'IgnoreUserKnownHosts no' + - label: PasswordAuthentication + pattern: '^\s*#*\s*PasswordAuthentication\s*(yes|no)$' + line: 'PasswordAuthentication no' + - label: KbdInteractiveAuthentication + pattern: '^\s*#*\s*KbdInteractiveAuthentication\s*(yes|no)$' + line: 'KbdInteractiveAuthentication no' + - label: KerberosAuthentication + pattern: '^\s*#*\s*KerberosAuthentication\s*(yes|no)$' + line: 'KerberosAuthentication no' + - label: GSSAPIAuthentication + pattern: '^\s*#*\s*GSSAPIAuthentication\s*(yes|no)$' + line: 'GSSAPIAuthentication no' + - label: UsePAM + pattern: '^\s*#*\s*UsePAM\s*(yes|no)$' + line: 'UsePAM yes' + - label: PermitRootLogin + pattern: '^\s*#*\s*PermitRootLogin\s*(yes|no|prohibit-password)$' + line: 'PermitRootLogin prohibit-password' + - label: AddressFamily + pattern: '^\s*#*\s*AddressFamily\s*(inet|inet6|any)$' + line: 'AddressFamily any' + - label: ListenAddress (IPv4) + pattern: "^\\s*#*\\s*ListenAddress\\s*(0\\.0\\.0\\.0|{{ ipv4_address | replace('.', '\\.') }})$" + line: "ListenAddress {{ ipv4_address }}" + - label: ListenAddress (IPv6) + pattern: "^\\s*#*\\s*ListenAddress\\s*(::|{{ ipv6_address}})$" + line: "ListenAddress {{ ipv6_address }}" + - label: Port + pattern: '^\s*#*\s*Port\s*[0-9]{1,5}$' + line: "Port {{ sshd_port }}" + +sshd_ufw_ipv4_rules: + - comment: SSH Clients v4 + source: 10.96.30.0/24 + - comment: SSH Servers v4 + source: 10.96.10.0/24 + - comment: SSH VPN v4 + source: 192.168.200.0/24 + +sshd_ufw_ipv6_rules: + - comment: "SSH Clients v6" + source: "2600:4040:593d:8b30::/64" + - comment: "SSH Servers v6" + source: "2600:4040:593d:8b10::/64" \ No newline at end of file