From 347f864abb8c502152e9c7ad74dc438ced206d3e Mon Sep 17 00:00:00 2001 From: Jack Ivanov <17044561+jackivanov@users.noreply.github.com> Date: Sat, 30 Jul 2022 15:01:24 +0300 Subject: [PATCH] Ansible upgrade 6.1 (#14500) * linting * update ansible * linters --- .ansible-lint | 4 + .github/workflows/main.yml | 2 +- cloud.yml | 14 +- deploy_client.yml | 2 +- input.yml | 207 ++++---- main.yml | 15 +- playbooks/cloud-post.yml | 7 +- playbooks/cloud-pre.yml | 86 ++-- playbooks/tmpfs/linux.yml | 2 +- playbooks/tmpfs/macos.yml | 4 +- playbooks/tmpfs/main.yml | 2 +- playbooks/tmpfs/umount.yml | 32 +- requirements.txt | 3 +- roles/client/tasks/main.yml | 22 +- roles/client/tasks/systems/main.yml | 1 - roles/cloud-azure/defaults/main.yml | 1 - roles/cloud-azure/tasks/prompts.yml | 30 +- roles/cloud-azure/tasks/venv.yml | 2 +- roles/cloud-cloudstack/tasks/main.yml | 2 +- roles/cloud-cloudstack/tasks/prompts.yml | 108 ++-- roles/cloud-digitalocean/tasks/main.yml | 22 +- roles/cloud-digitalocean/tasks/prompts.yml | 4 +- roles/cloud-ec2/tasks/cloudformation.yml | 2 +- roles/cloud-ec2/tasks/main.yml | 2 +- roles/cloud-ec2/tasks/prompts.yml | 90 ++-- roles/cloud-gce/tasks/main.yml | 36 +- roles/cloud-gce/tasks/prompts.yml | 67 +-- roles/cloud-hetzner/tasks/main.yml | 2 +- .../cloud-lightsail/tasks/cloudformation.yml | 2 +- roles/cloud-lightsail/tasks/prompts.yml | 60 +-- roles/cloud-linode/tasks/main.yml | 6 +- roles/cloud-openstack/tasks/main.yml | 2 +- roles/cloud-scaleway/tasks/main.yml | 123 ++--- roles/cloud-vultr/tasks/main.yml | 88 ++-- roles/common/handlers/main.yml | 1 + roles/common/tasks/freebsd.yml | 5 +- roles/common/tasks/iptables.yml | 1 - roles/common/tasks/ubuntu.yml | 9 +- roles/dns/tasks/freebsd.yml | 2 +- roles/dns/tasks/ubuntu.yml | 56 +-- roles/local/tasks/prompts.yml | 28 +- roles/ssh_tunneling/defaults/main.yml | 2 +- roles/ssh_tunneling/handlers/main.yml | 1 + roles/ssh_tunneling/tasks/main.yml | 156 +++--- roles/strongswan/defaults/main.yml | 6 +- roles/strongswan/handlers/main.yml | 1 + roles/strongswan/tasks/client_configs.yml | 2 +- roles/strongswan/tasks/distribute_keys.yml | 13 +- .../strongswan/tasks/ipsec_configuration.yml | 13 +- roles/strongswan/tasks/main.yml | 2 +- roles/strongswan/tasks/openssl.yml | 466 +++++++++--------- roles/strongswan/tasks/ubuntu.yml | 37 +- roles/wireguard/defaults/main.yml | 5 +- roles/wireguard/tasks/keys.yml | 68 +-- roles/wireguard/tasks/main.yml | 100 ++-- roles/wireguard/tasks/mobileconfig.yml | 2 +- roles/wireguard/tasks/ubuntu.yml | 2 +- server.yml | 201 ++++---- users.yml | 82 +-- 59 files changed, 1157 insertions(+), 1156 deletions(-) diff --git a/.ansible-lint b/.ansible-lint index f119d61..21d582b 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -1,6 +1,10 @@ skip_list: + - yaml - '204' verbosity: 1 warn_list: - no-changed-when + - no-handler + - fqcn-builtins + - var-spacing diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8bed89c..6676ef7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,7 +18,7 @@ jobs: python -m pip install --upgrade pip pip install -r requirements.txt sudo snap install shellcheck - pip install ansible-lint + pip install ansible-lint==6.3.0 - name: Checks and linters run: | diff --git a/cloud.yml b/cloud.yml index 310bf23..91d65fa 100644 --- a/cloud.yml +++ b/cloud.yml @@ -8,14 +8,14 @@ tasks: - block: - - name: Local pre-tasks - import_tasks: playbooks/cloud-pre.yml + - name: Local pre-tasks + import_tasks: playbooks/cloud-pre.yml - - name: Include a provisioning role - include_role: - name: "{{ 'local' if algo_provider == 'local' else 'cloud-' + algo_provider }}" + - name: Include a provisioning role + include_role: + name: "{{ 'local' if algo_provider == 'local' else 'cloud-' + algo_provider }}" - - name: Local post-tasks - import_tasks: playbooks/cloud-post.yml + - name: Local post-tasks + import_tasks: playbooks/cloud-post.yml rescue: - include_tasks: playbooks/rescue.yml diff --git a/deploy_client.yml b/deploy_client.yml index 8ee8767..ca89c40 100644 --- a/deploy_client.yml +++ b/deploy_client.yml @@ -13,7 +13,7 @@ ansible_ssh_user: "{{ 'root' if client_ip == 'localhost' else ssh_user }}" vpn_user: "{{ vpn_user }}" IP_subject_alt_name: "{{ server_ip }}" - ansible_python_interpreter: "/usr/bin/python3" + ansible_python_interpreter: /usr/bin/python3 - name: Configure the client and install required software hosts: client-host diff --git a/input.yml b/input.yml index 6415acc..043a129 100644 --- a/input.yml +++ b/input.yml @@ -18,127 +18,126 @@ - { name: Google Compute Engine, alias: gce } - { name: Hetzner Cloud, alias: hetzner } - { name: Vultr, alias: vultr } - - { name: Scaleway, alias: scaleway} + - { name: Scaleway, alias: scaleway } - { name: OpenStack (DreamCompute optimised), alias: openstack } - { name: CloudStack (Exoscale optimised), alias: cloudstack } - { name: Linode, alias: linode } - - { name: "Install to existing Ubuntu 18.04 or 20.04 server (for more advanced users)", alias: local } + - { name: Install to existing Ubuntu 18.04 or 20.04 server (for more advanced users), alias: local } vars_files: - config.cfg tasks: - block: - - name: Cloud prompt - pause: - prompt: | - What provider would you like to use? - {% for p in providers_map %} - {{ loop.index }}. {{ p['name'] }} - {% endfor %} + - name: Cloud prompt + pause: + prompt: | + What provider would you like to use? + {% for p in providers_map %} + {{ loop.index }}. {{ p['name'] }} + {% endfor %} - Enter the number of your desired provider - register: _algo_provider - when: provider is undefined + Enter the number of your desired provider + register: _algo_provider + when: provider is undefined - - name: Set facts based on the input - set_fact: - algo_provider: "{{ provider | default(providers_map[_algo_provider.user_input|default(omit)|int - 1]['alias']) }}" + - name: Set facts based on the input + set_fact: + algo_provider: "{{ provider | default(providers_map[_algo_provider.user_input|default(omit)|int - 1]['alias']) }}" - - name: VPN server name prompt - pause: - prompt: | - Name the vpn server - [algo] - register: _algo_server_name - when: - - server_name is undefined - - algo_provider != "local" + - name: VPN server name prompt + pause: + prompt: | + Name the vpn server + [algo] + register: _algo_server_name + when: + - server_name is undefined + - algo_provider != "local" - - name: Cellular On Demand prompt - pause: - prompt: | - Do you want macOS/iOS clients to enable "Connect On Demand" when connected to cellular networks? - [y/N] - register: _ondemand_cellular - when: ondemand_cellular is undefined + - name: Cellular On Demand prompt + pause: + prompt: | + Do you want macOS/iOS clients to enable "Connect On Demand" when connected to cellular networks? + [y/N] + register: _ondemand_cellular + when: ondemand_cellular is undefined - - name: Wi-Fi On Demand prompt - pause: - prompt: | - Do you want macOS/iOS clients to enable "Connect On Demand" when connected to Wi-Fi? - [y/N] - register: _ondemand_wifi - when: ondemand_wifi is undefined + - name: Wi-Fi On Demand prompt + pause: + prompt: | + Do you want macOS/iOS clients to enable "Connect On Demand" when connected to Wi-Fi? + [y/N] + register: _ondemand_wifi + when: ondemand_wifi is undefined - - name: Trusted Wi-Fi networks prompt - pause: - prompt: | - List the names of any trusted Wi-Fi networks where macOS/iOS clients should not use "Connect On Demand" - (e.g., your home network. Comma-separated value, e.g., HomeNet,OfficeWifi,AlgoWiFi) - register: _ondemand_wifi_exclude - when: - - ondemand_wifi_exclude is undefined - - (ondemand_wifi|default(false)|bool) or - (booleans_map[_ondemand_wifi.user_input|default(omit)]|default(false)) + - name: Trusted Wi-Fi networks prompt + pause: + prompt: | + List the names of any trusted Wi-Fi networks where macOS/iOS clients should not use "Connect On Demand" + (e.g., your home network. Comma-separated value, e.g., HomeNet,OfficeWifi,AlgoWiFi) + register: _ondemand_wifi_exclude + when: + - ondemand_wifi_exclude is undefined + - (ondemand_wifi|default(false)|bool) or (booleans_map[_ondemand_wifi.user_input|default(omit)]|default(false)) - - name: Retain the PKI prompt - pause: - prompt: | - Do you want to retain the keys (PKI)? (required to add users in the future, but less secure) - [y/N] - register: _store_pki - when: - - store_pki is undefined - - ipsec_enabled + - name: Retain the PKI prompt + pause: + prompt: | + Do you want to retain the keys (PKI)? (required to add users in the future, but less secure) + [y/N] + register: _store_pki + when: + - store_pki is undefined + - ipsec_enabled - - name: DNS adblocking prompt - pause: - prompt: | - Do you want to enable DNS ad blocking on this VPN server? - [y/N] - register: _dns_adblocking - when: dns_adblocking is undefined + - name: DNS adblocking prompt + pause: + prompt: | + Do you want to enable DNS ad blocking on this VPN server? + [y/N] + register: _dns_adblocking + when: dns_adblocking is undefined - - name: SSH tunneling prompt - pause: - prompt: | - Do you want each user to have their own account for SSH tunneling? - [y/N] - register: _ssh_tunneling - when: ssh_tunneling is undefined + - name: SSH tunneling prompt + pause: + prompt: | + Do you want each user to have their own account for SSH tunneling? + [y/N] + register: _ssh_tunneling + when: ssh_tunneling is undefined - - name: Set facts based on the input - set_fact: - algo_server_name: >- - {% if server_name is defined %}{% set _server = server_name %} - {%- elif _algo_server_name.user_input is defined and _algo_server_name.user_input|length > 0 -%} - {%- set _server = _algo_server_name.user_input -%} - {%- else %}{% set _server = defaults['server_name'] %}{% endif -%} - {{ _server | regex_replace('(?!\.)(\W|_)', '-') }} - algo_ondemand_cellular: >- - {% if ondemand_cellular is defined %}{{ ondemand_cellular | bool }} - {%- elif _ondemand_cellular.user_input is defined %}{{ booleans_map[_ondemand_cellular.user_input] | default(defaults['ondemand_cellular']) }} - {%- else %}false{% endif %} - algo_ondemand_wifi: >- - {% if ondemand_wifi is defined %}{{ ondemand_wifi | bool }} - {%- elif _ondemand_wifi.user_input is defined %}{{ booleans_map[_ondemand_wifi.user_input] | default(defaults['ondemand_wifi']) }} - {%- else %}false{% endif %} - algo_ondemand_wifi_exclude: >- - {% if ondemand_wifi_exclude is defined %}{{ ondemand_wifi_exclude | b64encode }} - {%- elif _ondemand_wifi_exclude.user_input is defined and _ondemand_wifi_exclude.user_input|length > 0 -%} - {{ _ondemand_wifi_exclude.user_input | b64encode }} - {%- else %}{{ '_null' | b64encode }}{% endif %} - algo_dns_adblocking: >- - {% if dns_adblocking is defined %}{{ dns_adblocking | bool }} - {%- elif _dns_adblocking.user_input is defined %}{{ booleans_map[_dns_adblocking.user_input] | default(defaults['dns_adblocking']) }} - {%- else %}false{% endif %} - algo_ssh_tunneling: >- - {% if ssh_tunneling is defined %}{{ ssh_tunneling | bool }} - {%- elif _ssh_tunneling.user_input is defined %}{{ booleans_map[_ssh_tunneling.user_input] | default(defaults['ssh_tunneling']) }} - {%- else %}false{% endif %} - algo_store_pki: >- - {% if ipsec_enabled %}{%- if store_pki is defined %}{{ store_pki | bool }} - {%- elif _store_pki.user_input is defined %}{{ booleans_map[_store_pki.user_input] | default(defaults['store_pki']) }} - {%- else %}false{% endif %}{% endif %} + - name: Set facts based on the input + set_fact: + algo_server_name: >- + {% if server_name is defined %}{% set _server = server_name %} + {%- elif _algo_server_name.user_input is defined and _algo_server_name.user_input|length > 0 -%} + {%- set _server = _algo_server_name.user_input -%} + {%- else %}{% set _server = defaults['server_name'] %}{% endif -%} + {{ _server | regex_replace('(?!\.)(\W|_)', '-') }} + algo_ondemand_cellular: >- + {% if ondemand_cellular is defined %}{{ ondemand_cellular | bool }} + {%- elif _ondemand_cellular.user_input is defined %}{{ booleans_map[_ondemand_cellular.user_input] | default(defaults['ondemand_cellular']) }} + {%- else %}false{% endif %} + algo_ondemand_wifi: >- + {% if ondemand_wifi is defined %}{{ ondemand_wifi | bool }} + {%- elif _ondemand_wifi.user_input is defined %}{{ booleans_map[_ondemand_wifi.user_input] | default(defaults['ondemand_wifi']) }} + {%- else %}false{% endif %} + algo_ondemand_wifi_exclude: >- + {% if ondemand_wifi_exclude is defined %}{{ ondemand_wifi_exclude | b64encode }} + {%- elif _ondemand_wifi_exclude.user_input is defined and _ondemand_wifi_exclude.user_input|length > 0 -%} + {{ _ondemand_wifi_exclude.user_input | b64encode }} + {%- else %}{{ '_null' | b64encode }}{% endif %} + algo_dns_adblocking: >- + {% if dns_adblocking is defined %}{{ dns_adblocking | bool }} + {%- elif _dns_adblocking.user_input is defined %}{{ booleans_map[_dns_adblocking.user_input] | default(defaults['dns_adblocking']) }} + {%- else %}false{% endif %} + algo_ssh_tunneling: >- + {% if ssh_tunneling is defined %}{{ ssh_tunneling | bool }} + {%- elif _ssh_tunneling.user_input is defined %}{{ booleans_map[_ssh_tunneling.user_input] | default(defaults['ssh_tunneling']) }} + {%- else %}false{% endif %} + algo_store_pki: >- + {% if ipsec_enabled %}{%- if store_pki is defined %}{{ store_pki | bool }} + {%- elif _store_pki.user_input is defined %}{{ booleans_map[_store_pki.user_input] | default(defaults['store_pki']) }} + {%- else %}false{% endif %}{% endif %} rescue: - include_tasks: playbooks/rescue.yml diff --git a/main.yml b/main.yml index f990776..1b68d4c 100644 --- a/main.yml +++ b/main.yml @@ -23,12 +23,15 @@ - name: Set required ansible version as a fact set_fact: - required_ansible_version: - "{{ item | regex_replace('^ansible-core[\\s+]?(?P[=,>,<]+)[\\s+]?(?P\\d.\\d+(.\\d+)?)$', - '{\"op\": \"\\g\",\"ver\": \"\\g\" }') }}" - when: '"ansible-core" in item' + required_ansible_version: "{{ item | regex_replace('^ansible[\\s+]?(?P[=,>,<]+)[\\s+]?(?P\\d.\\d+(.\\d+)?)$', '{\"op\": \"\\g\",\"ver\"\ + : \"\\g\" }') }}" + when: '"ansible" in item' with_items: "{{ lookup('file', 'requirements.txt').splitlines() }}" + - name: Just get the list from default pip + community.general.pip_package_info: + register: pip_package_info + - name: Verify Python meets Algo VPN requirements assert: that: (ansible_python.version.major|string + '.' + ansible_python.version.minor|string) is version('3.8', '>=') @@ -40,10 +43,10 @@ - name: Verify Ansible meets Algo VPN requirements assert: that: - - ansible_version.full is version(required_ansible_version.ver, required_ansible_version.op) + - pip_package_info.packages.pip.ansible.0.version is version(required_ansible_version.ver, required_ansible_version.op) - not ipaddr.failed msg: > - Ansible version is {{ ansible_version.full }}. + Ansible version is {{ pip_package_info.packages.pip.ansible.0.version }}. You must update the requirements to use this version of Algo. Try to run python3 -m pip install -U -r requirements.txt diff --git a/playbooks/cloud-post.yml b/playbooks/cloud-post.yml index 3ae2387..36b7d94 100644 --- a/playbooks/cloud-post.yml +++ b/playbooks/cloud-post.yml @@ -10,7 +10,7 @@ ansible_connection: "{% if cloud_instance_ip == 'localhost' %}local{% else %}ssh{% endif %}" ansible_ssh_user: "{{ ansible_ssh_user|default('root') }}" ansible_ssh_port: "{{ ansible_ssh_port|default(22) }}" - ansible_python_interpreter: "/usr/bin/python3" + ansible_python_interpreter: /usr/bin/python3 algo_provider: "{{ algo_provider }}" algo_server_name: "{{ algo_server_name }}" algo_ondemand_cellular: "{{ algo_ondemand_cellular }}" @@ -33,7 +33,7 @@ wait_for: port: "{{ ansible_ssh_port|default(22) }}" host: "{{ cloud_instance_ip }}" - search_regex: "OpenSSH" + search_regex: OpenSSH delay: 10 timeout: 320 state: present @@ -44,8 +44,7 @@ when: - pki_in_tmpfs - not algo_store_pki - - ansible_system == "Darwin" or - ansible_system == "Linux" + - ansible_system == "Darwin" or ansible_system == "Linux" - debug: var: IP_subject_alt_name diff --git a/playbooks/cloud-pre.yml b/playbooks/cloud-pre.yml index cb9a77f..da0019d 100644 --- a/playbooks/cloud-pre.yml +++ b/playbooks/cloud-pre.yml @@ -1,53 +1,53 @@ --- - block: - - name: Display the invocation environment - shell: > - ./algo-showenv.sh \ - 'algo_provider "{{ algo_provider }}"' \ - {% if ipsec_enabled %} - 'algo_ondemand_cellular "{{ algo_ondemand_cellular }}"' \ - 'algo_ondemand_wifi "{{ algo_ondemand_wifi }}"' \ - 'algo_ondemand_wifi_exclude "{{ algo_ondemand_wifi_exclude }}"' \ - {% endif %} - 'algo_dns_adblocking "{{ algo_dns_adblocking }}"' \ - 'algo_ssh_tunneling "{{ algo_ssh_tunneling }}"' \ - 'wireguard_enabled "{{ wireguard_enabled }}"' \ - 'dns_encryption "{{ dns_encryption }}"' \ - > /dev/tty || true - tags: debug + - name: Display the invocation environment + shell: > + ./algo-showenv.sh \ + 'algo_provider "{{ algo_provider }}"' \ + {% if ipsec_enabled %} + 'algo_ondemand_cellular "{{ algo_ondemand_cellular }}"' \ + 'algo_ondemand_wifi "{{ algo_ondemand_wifi }}"' \ + 'algo_ondemand_wifi_exclude "{{ algo_ondemand_wifi_exclude }}"' \ + {% endif %} + 'algo_dns_adblocking "{{ algo_dns_adblocking }}"' \ + 'algo_ssh_tunneling "{{ algo_ssh_tunneling }}"' \ + 'wireguard_enabled "{{ wireguard_enabled }}"' \ + 'dns_encryption "{{ dns_encryption }}"' \ + > /dev/tty || true + tags: debug - - name: Install the requirements - pip: - state: present - name: - - pyOpenSSL>=0.15 - - segno - tags: - - always - - skip_ansible_lint + - name: Install the requirements + pip: + state: present + name: + - pyOpenSSL>=0.15 + - segno + tags: + - always + - skip_ansible_lint delegate_to: localhost become: false - block: - - name: Generate the SSH private key - openssl_privatekey: - path: "{{ SSH_keys.private }}" - size: 2048 - mode: "0600" - type: RSA + - name: Generate the SSH private key + openssl_privatekey: + path: "{{ SSH_keys.private }}" + size: 2048 + mode: "0600" + type: RSA - - name: Generate the SSH public key - openssl_publickey: - path: "{{ SSH_keys.public }}" - privatekey_path: "{{ SSH_keys.private }}" - format: OpenSSH + - name: Generate the SSH public key + openssl_publickey: + path: "{{ SSH_keys.public }}" + privatekey_path: "{{ SSH_keys.private }}" + format: OpenSSH - - name: Copy the private SSH key to /tmp - copy: - src: "{{ SSH_keys.private }}" - dest: "{{ SSH_keys.private_tmp }}" - force: true - mode: '0600' - delegate_to: localhost - become: false + - name: Copy the private SSH key to /tmp + copy: + src: "{{ SSH_keys.private }}" + dest: "{{ SSH_keys.private_tmp }}" + force: true + mode: "0600" + delegate_to: localhost + become: false when: algo_provider != "local" diff --git a/playbooks/tmpfs/linux.yml b/playbooks/tmpfs/linux.yml index 64a9651..d36ef7b 100644 --- a/playbooks/tmpfs/linux.yml +++ b/playbooks/tmpfs/linux.yml @@ -1,5 +1,5 @@ --- - name: Linux | set OS specific facts set_fact: - tmpfs_volume_name: "AlgoVPN-{{ IP_subject_alt_name }}" + tmpfs_volume_name: AlgoVPN-{{ IP_subject_alt_name }} tmpfs_volume_path: /dev/shm diff --git a/playbooks/tmpfs/macos.yml b/playbooks/tmpfs/macos.yml index 72243da..2e56037 100644 --- a/playbooks/tmpfs/macos.yml +++ b/playbooks/tmpfs/macos.yml @@ -1,7 +1,7 @@ --- - name: MacOS | set OS specific facts set_fact: - tmpfs_volume_name: "AlgoVPN-{{ IP_subject_alt_name }}" + tmpfs_volume_name: AlgoVPN-{{ IP_subject_alt_name }} tmpfs_volume_path: /Volumes - name: MacOS | mount a ram disk @@ -9,4 +9,4 @@ /usr/sbin/diskutil info "/{{ tmpfs_volume_path }}/{{ tmpfs_volume_name }}/" || /usr/sbin/diskutil erasevolume HFS+ "{{ tmpfs_volume_name }}" $(hdiutil attach -nomount ram://64000) args: - creates: "/{{ tmpfs_volume_path }}/{{ tmpfs_volume_name }}" + creates: /{{ tmpfs_volume_path }}/{{ tmpfs_volume_name }} diff --git a/playbooks/tmpfs/main.yml b/playbooks/tmpfs/main.yml index 32a01b7..628130e 100644 --- a/playbooks/tmpfs/main.yml +++ b/playbooks/tmpfs/main.yml @@ -9,7 +9,7 @@ - name: Set config paths as facts set_fact: - ipsec_pki_path: "/{{ tmpfs_volume_path }}/{{ tmpfs_volume_name }}/IPsec/" + ipsec_pki_path: /{{ tmpfs_volume_path }}/{{ tmpfs_volume_name }}/IPsec/ - name: Update config paths add_host: diff --git a/playbooks/tmpfs/umount.yml b/playbooks/tmpfs/umount.yml index 681278e..6c002cc 100644 --- a/playbooks/tmpfs/umount.yml +++ b/playbooks/tmpfs/umount.yml @@ -1,26 +1,26 @@ --- - name: Linux | Delete the PKI directory file: - path: "/{{ facts.tmpfs_volume_path }}/{{ facts.tmpfs_volume_name }}/" + path: /{{ facts.tmpfs_volume_path }}/{{ facts.tmpfs_volume_name }}/ state: absent when: facts.ansible_system == "Linux" - block: - - name: MacOS | check fs the ramdisk exists - command: /usr/sbin/diskutil info "{{ facts.tmpfs_volume_name }}" - ignore_errors: true - changed_when: false - register: diskutil_info + - name: MacOS | check fs the ramdisk exists + command: /usr/sbin/diskutil info "{{ facts.tmpfs_volume_name }}" + ignore_errors: true + changed_when: false + register: diskutil_info - - name: MacOS | unmount and eject the ram disk - shell: > - /usr/sbin/diskutil umount force "/{{ facts.tmpfs_volume_path }}/{{ facts.tmpfs_volume_name }}/" && - /usr/sbin/diskutil eject "{{ facts.tmpfs_volume_name }}" - changed_when: false - when: diskutil_info.rc == 0 - register: result - until: result.rc == 0 - retries: 5 - delay: 3 + - name: MacOS | unmount and eject the ram disk + shell: > + /usr/sbin/diskutil umount force "/{{ facts.tmpfs_volume_path }}/{{ facts.tmpfs_volume_name }}/" && + /usr/sbin/diskutil eject "{{ facts.tmpfs_volume_name }}" + changed_when: false + when: diskutil_info.rc == 0 + register: result + until: result.rc == 0 + retries: 5 + delay: 3 when: - facts.ansible_system == "Darwin" diff --git a/requirements.txt b/requirements.txt index 3274540..886f8b4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ -ansible-core==2.12.3 -ansible==5.0.1 +ansible==6.1.0 jinja2~=3.0.3 netaddr diff --git a/roles/client/tasks/main.yml b/roles/client/tasks/main.yml index bc7a221..098da97 100644 --- a/roles/client/tasks/main.yml +++ b/roles/client/tasks/main.yml @@ -1,6 +1,6 @@ +--- - name: Gather Facts setup: - - name: Include system based facts and tasks import_tasks: systems/main.yml @@ -22,9 +22,9 @@ - name: Setup the ipsec config template: - src: "roles/strongswan/templates/client_ipsec.conf.j2" + src: roles/strongswan/templates/client_ipsec.conf.j2 dest: "{{ configs_prefix }}/ipsec.{{ IP_subject_alt_name }}.conf" - mode: '0644' + mode: "0644" with_items: - "{{ vpn_user }}" notify: @@ -32,9 +32,9 @@ - name: Setup the ipsec secrets template: - src: "roles/strongswan/templates/client_ipsec.secrets.j2" + src: roles/strongswan/templates/client_ipsec.secrets.j2 dest: "{{ configs_prefix }}/ipsec.{{ IP_subject_alt_name }}.secrets" - mode: '0600' + mode: "0600" with_items: - "{{ vpn_user }}" notify: @@ -44,12 +44,12 @@ lineinfile: dest: "{{ item.dest }}" line: "{{ item.line }}" - create: yes + create: true with_items: - dest: "{{ configs_prefix }}/ipsec.conf" - line: "include ipsec.{{ IP_subject_alt_name }}.conf" + line: include ipsec.{{ IP_subject_alt_name }}.conf - dest: "{{ configs_prefix }}/ipsec.secrets" - line: "include ipsec.{{ IP_subject_alt_name }}.secrets" + line: include ipsec.{{ IP_subject_alt_name }}.secrets notify: - restart strongswan @@ -66,11 +66,11 @@ src: "{{ item.src }}" dest: "{{ item.dest }}" with_items: - - src: "configs/{{ IP_subject_alt_name }}/ipsec/.pki/certs/{{ vpn_user }}.crt" + - src: configs/{{ IP_subject_alt_name }}/ipsec/.pki/certs/{{ vpn_user }}.crt dest: "{{ configs_prefix }}/ipsec.d/certs/{{ vpn_user }}.crt" - - src: "configs/{{ IP_subject_alt_name }}/ipsec/.pki/cacert.pem" + - src: configs/{{ IP_subject_alt_name }}/ipsec/.pki/cacert.pem dest: "{{ configs_prefix }}/ipsec.d/cacerts/{{ IP_subject_alt_name }}.pem" - - src: "configs/{{ IP_subject_alt_name }}/ipsec/.pki/private/{{ vpn_user }}.key" + - src: configs/{{ IP_subject_alt_name }}/ipsec/.pki/private/{{ vpn_user }}.key dest: "{{ configs_prefix }}/ipsec.d/private/{{ vpn_user }}.key" notify: - restart strongswan diff --git a/roles/client/tasks/systems/main.yml b/roles/client/tasks/systems/main.yml index ba24c93..62bf573 100644 --- a/roles/client/tasks/systems/main.yml +++ b/roles/client/tasks/systems/main.yml @@ -1,5 +1,4 @@ --- - - include_tasks: Debian.yml when: ansible_distribution == 'Debian' diff --git a/roles/cloud-azure/defaults/main.yml b/roles/cloud-azure/defaults/main.yml index e026664..bfcd8b9 100644 --- a/roles/cloud-azure/defaults/main.yml +++ b/roles/cloud-azure/defaults/main.yml @@ -208,4 +208,3 @@ azure_regions: - displayName: West US (Stage) name: westusstage regionalDisplayName: (US) West US (Stage) - diff --git a/roles/cloud-azure/tasks/prompts.yml b/roles/cloud-azure/tasks/prompts.yml index da772b5..99fd03b 100644 --- a/roles/cloud-azure/tasks/prompts.yml +++ b/roles/cloud-azure/tasks/prompts.yml @@ -6,21 +6,21 @@ subscription_id: "{{ azure_subscription_id | default(lookup('env','AZURE_SUBSCRIPTION_ID'), true) }}" - block: - - name: Set the default region - set_fact: - default_region: >- - {% for r in azure_regions %} - {%- if r['name'] == "eastus" %}{{ loop.index }}{% endif %} - {%- endfor %} - - - pause: - prompt: | - What region should the server be located in? + - name: Set the default region + set_fact: + default_region: >- {% for r in azure_regions %} - {{ loop.index }}. {{ r['regionalDisplayName'] }} - {% endfor %} + {%- if r['name'] == "eastus" %}{{ loop.index }}{% endif %} + {%- endfor %} + + - pause: + prompt: | + What region should the server be located in? + {% for r in azure_regions %} + {{ loop.index }}. {{ r['regionalDisplayName'] }} + {% endfor %} - Enter the number of your desired region - [{{ default_region }}] - register: _algo_region + Enter the number of your desired region + [{{ default_region }}] + register: _algo_region when: region is undefined diff --git a/roles/cloud-azure/tasks/venv.yml b/roles/cloud-azure/tasks/venv.yml index caac3d4..5b8d52b 100644 --- a/roles/cloud-azure/tasks/venv.yml +++ b/roles/cloud-azure/tasks/venv.yml @@ -1,6 +1,6 @@ --- - name: Install requirements pip: - requirements: https://raw.githubusercontent.com/ansible-collections/azure/v1.9.0/requirements-azure.txt + requirements: https://raw.githubusercontent.com/ansible-collections/azure/v1.13.0/requirements-azure.txt state: latest virtualenv_python: python3 diff --git a/roles/cloud-cloudstack/tasks/main.yml b/roles/cloud-cloudstack/tasks/main.yml index 82b6c25..ea05938 100644 --- a/roles/cloud-cloudstack/tasks/main.yml +++ b/roles/cloud-cloudstack/tasks/main.yml @@ -26,7 +26,7 @@ end_port: "{{ item.end_port }}" cidr: "{{ item.range }}" with_items: - - { proto: tcp, start_port: '{{ ssh_port }}', end_port: '{{ ssh_port }}', range: 0.0.0.0/0 } + - { proto: tcp, start_port: "{{ ssh_port }}", end_port: "{{ ssh_port }}", range: 0.0.0.0/0 } - { proto: udp, start_port: 4500, end_port: 4500, range: 0.0.0.0/0 } - { proto: udp, start_port: 500, end_port: 500, range: 0.0.0.0/0 } - { proto: udp, start_port: "{{ wireguard_port }}", end_port: "{{ wireguard_port }}", range: 0.0.0.0/0 } diff --git a/roles/cloud-cloudstack/tasks/prompts.yml b/roles/cloud-cloudstack/tasks/prompts.yml index 5be0ca2..df39a35 100644 --- a/roles/cloud-cloudstack/tasks/prompts.yml +++ b/roles/cloud-cloudstack/tasks/prompts.yml @@ -1,65 +1,65 @@ --- - block: - - pause: - prompt: | - Enter the API key (https://trailofbits.github.io/algo/cloud-cloudstack.html): - echo: false - register: _cs_key - when: - - cs_key is undefined - - lookup('env','CLOUDSTACK_KEY')|length <= 0 + - pause: + prompt: | + Enter the API key (https://trailofbits.github.io/algo/cloud-cloudstack.html): + echo: false + register: _cs_key + when: + - cs_key is undefined + - lookup('env','CLOUDSTACK_KEY')|length <= 0 - - pause: - prompt: | - Enter the API ssecret (https://trailofbits.github.io/algo/cloud-cloudstack.html): - echo: false - register: _cs_secret - when: - - cs_secret is undefined - - lookup('env','CLOUDSTACK_SECRET')|length <= 0 + - pause: + prompt: | + Enter the API ssecret (https://trailofbits.github.io/algo/cloud-cloudstack.html): + echo: false + register: _cs_secret + when: + - cs_secret is undefined + - lookup('env','CLOUDSTACK_SECRET')|length <= 0 - - pause: - prompt: | - Enter the API endpoint (https://trailofbits.github.io/algo/cloud-cloudstack.html) - [https://api.exoscale.com/compute] - register: _cs_url - when: - - cs_url is undefined - - lookup('env', 'CLOUDSTACK_ENDPOINT') | length <= 0 + - pause: + prompt: | + Enter the API endpoint (https://trailofbits.github.io/algo/cloud-cloudstack.html) + [https://api.exoscale.com/compute] + register: _cs_url + when: + - cs_url is undefined + - lookup('env', 'CLOUDSTACK_ENDPOINT') | length <= 0 - - set_fact: - algo_cs_key: "{{ cs_key | default(_cs_key.user_input|default(None)) | default(lookup('env', 'CLOUDSTACK_KEY'), true) }}" - algo_cs_token: "{{ cs_secret | default(_cs_secret.user_input|default(None)) | default(lookup('env', 'CLOUDSTACK_SECRET'), true) }}" - algo_cs_url: "{{ cs_url | default(_cs_url.user_input|default(None)) | default(lookup('env', 'CLOUDSTACK_ENDPOINT'), true) | default('https://api.exoscale.com/compute', true) }}" + - set_fact: + algo_cs_key: "{{ cs_key | default(_cs_key.user_input|default(None)) | default(lookup('env', 'CLOUDSTACK_KEY'), true) }}" + algo_cs_token: "{{ cs_secret | default(_cs_secret.user_input|default(None)) | default(lookup('env', 'CLOUDSTACK_SECRET'), true) }}" + algo_cs_url: "{{ cs_url | default(_cs_url.user_input|default(None)) | default(lookup('env', 'CLOUDSTACK_ENDPOINT'), true) | default('https://api.exoscale.com/compute',\ + \ true) }}" - - name: Get zones on cloud - cs_zone_info: - register: _cs_zones - environment: - CLOUDSTACK_KEY: "{{ algo_cs_key }}" - CLOUDSTACK_SECRET: "{{ algo_cs_token }}" - CLOUDSTACK_ENDPOINT: "{{ algo_cs_url }}" + - name: Get zones on cloud + cs_zone_info: + register: _cs_zones + environment: + CLOUDSTACK_KEY: "{{ algo_cs_key }}" + CLOUDSTACK_SECRET: "{{ algo_cs_token }}" + CLOUDSTACK_ENDPOINT: "{{ algo_cs_url }}" - - name: Extract zones from output - set_fact: - cs_zones: "{{ _cs_zones['zones'] | sort(attribute='name') }}" + - name: Extract zones from output + set_fact: + cs_zones: "{{ _cs_zones['zones'] | sort(attribute='name') }}" - - name: Set the default zone - set_fact: - default_zone: >- - {% for z in cs_zones %} - {%- if z['name'] == "ch-gva-2" %}{{ loop.index }}{% endif %} - {%- endfor %} - - - pause: - prompt: | - What zone should the server be located in? + - name: Set the default zone + set_fact: + default_zone: >- {% for z in cs_zones %} - {{ loop.index }}. {{ z['name'] }} - {% endfor %} + {%- if z['name'] == "ch-gva-2" %}{{ loop.index }}{% endif %} + {%- endfor %} - Enter the number of your desired zone - [{{ default_zone }}] - register: _algo_region - when: region is undefined + - pause: + prompt: | + What zone should the server be located in? + {% for z in cs_zones %} + {{ loop.index }}. {{ z['name'] }} + {% endfor %} + Enter the number of your desired zone + [{{ default_zone }}] + register: _algo_region + when: region is undefined diff --git a/roles/cloud-digitalocean/tasks/main.yml b/roles/cloud-digitalocean/tasks/main.yml index d226d25..952b4fc 100644 --- a/roles/cloud-digitalocean/tasks/main.yml +++ b/roles/cloud-digitalocean/tasks/main.yml @@ -2,14 +2,14 @@ - name: Include prompts import_tasks: prompts.yml -- name: "Upload the SSH key" +- name: Upload the SSH key digital_ocean_sshkey: oauth_token: "{{ algo_do_token }}" name: "{{ SSH_keys.comment }}" ssh_pub_key: "{{ lookup('file', '{{ SSH_keys.public }}') }}" register: do_ssh_key -- name: "Creating a droplet..." +- name: Creating a droplet... digital_ocean_droplet: state: present name: "{{ algo_server_name }}" @@ -31,16 +31,16 @@ droplet: "{{ digital_ocean_droplet.data.droplet | default(digital_ocean_droplet.data) }}" - block: - - name: "Create a Floating IP" - digital_ocean_floating_ip: - state: present - oauth_token: "{{ algo_do_token }}" - droplet_id: "{{ droplet.id }}" - register: digital_ocean_floating_ip + - name: Create a Floating IP + digital_ocean_floating_ip: + state: present + oauth_token: "{{ algo_do_token }}" + droplet_id: "{{ droplet.id }}" + register: digital_ocean_floating_ip - - name: Set the static ip as a fact - set_fact: - cloud_alternative_ingress_ip: "{{ digital_ocean_floating_ip.data.floating_ip.ip }}" + - name: Set the static ip as a fact + set_fact: + cloud_alternative_ingress_ip: "{{ digital_ocean_floating_ip.data.floating_ip.ip }}" when: alternative_ingress_ip - set_fact: diff --git a/roles/cloud-digitalocean/tasks/prompts.yml b/roles/cloud-digitalocean/tasks/prompts.yml index 5fdfe4a..7f24e3f 100644 --- a/roles/cloud-digitalocean/tasks/prompts.yml +++ b/roles/cloud-digitalocean/tasks/prompts.yml @@ -18,8 +18,8 @@ method: GET status_code: 200 headers: - Content-Type: "application/json" - Authorization: "Bearer {{ algo_do_token }}" + Content-Type: application/json + Authorization: Bearer {{ algo_do_token }} register: _do_regions - name: Set facts about the regions diff --git a/roles/cloud-ec2/tasks/cloudformation.yml b/roles/cloud-ec2/tasks/cloudformation.yml index 3eb3250..f05ab37 100644 --- a/roles/cloud-ec2/tasks/cloudformation.yml +++ b/roles/cloud-ec2/tasks/cloudformation.yml @@ -4,7 +4,7 @@ aws_access_key: "{{ access_key }}" aws_secret_key: "{{ secret_key }}" stack_name: "{{ stack_name }}" - state: "present" + state: present region: "{{ algo_region }}" template: roles/cloud-ec2/files/stack.yaml template_parameters: diff --git a/roles/cloud-ec2/tasks/main.yml b/roles/cloud-ec2/tasks/main.yml index 3b47b50..5f68c92 100644 --- a/roles/cloud-ec2/tasks/main.yml +++ b/roles/cloud-ec2/tasks/main.yml @@ -13,7 +13,7 @@ region: "{{ algo_region }}" filters: architecture: "{{ cloud_providers.ec2.image.arch }}" - name: "ubuntu/images/hvm-ssd/{{ cloud_providers.ec2.image.name }}-*64-server-*" + name: ubuntu/images/hvm-ssd/{{ cloud_providers.ec2.image.name }}-*64-server-* register: ami_search - name: Set the ami id as a fact diff --git a/roles/cloud-ec2/tasks/prompts.yml b/roles/cloud-ec2/tasks/prompts.yml index 4c9e6a5..368922f 100644 --- a/roles/cloud-ec2/tasks/prompts.yml +++ b/roles/cloud-ec2/tasks/prompts.yml @@ -6,8 +6,8 @@ echo: false register: _aws_access_key when: - - aws_access_key is undefined - - lookup('env','AWS_ACCESS_KEY_ID')|length <= 0 + - aws_access_key is undefined + - lookup('env','AWS_ACCESS_KEY_ID')|length <= 0 - pause: prompt: | @@ -23,35 +23,35 @@ secret_key: "{{ aws_secret_key | default(_aws_secret_key.user_input|default(None)) | default(lookup('env','AWS_SECRET_ACCESS_KEY'), true) }}" - block: - - name: Get regions - aws_region_info: - aws_access_key: "{{ access_key }}" - aws_secret_key: "{{ secret_key }}" - region: us-east-1 - register: _aws_regions + - name: Get regions + aws_region_info: + aws_access_key: "{{ access_key }}" + aws_secret_key: "{{ secret_key }}" + region: us-east-1 + register: _aws_regions - - name: Set facts about the regions - set_fact: - aws_regions: "{{ _aws_regions.regions | sort(attribute='region_name') }}" + - name: Set facts about the regions + set_fact: + aws_regions: "{{ _aws_regions.regions | sort(attribute='region_name') }}" - - name: Set the default region - set_fact: - default_region: >- - {% for r in aws_regions %} - {%- if r['region_name'] == "us-east-1" %}{{ loop.index }}{% endif %} - {%- endfor %} - - - pause: - prompt: | - What region should the server be located in? - (https://docs.aws.amazon.com/general/latest/gr/rande.html#ec2_region) + - name: Set the default region + set_fact: + default_region: >- {% for r in aws_regions %} - {{ loop.index }}. {{ r['region_name'] }} - {% endfor %} + {%- if r['region_name'] == "us-east-1" %}{{ loop.index }}{% endif %} + {%- endfor %} + + - pause: + prompt: | + What region should the server be located in? + (https://docs.aws.amazon.com/general/latest/gr/rande.html#ec2_region) + {% for r in aws_regions %} + {{ loop.index }}. {{ r['region_name'] }} + {% endfor %} - Enter the number of your desired region - [{{ default_region }}] - register: _algo_region + Enter the number of your desired region + [{{ default_region }}] + register: _algo_region when: region is undefined - name: Set algo_region and stack_name facts @@ -63,26 +63,26 @@ stack_name: "{{ algo_server_name | replace('.', '-') }}" - block: - - name: Get existing available Elastic IPs - ec2_eip_info: - aws_access_key: "{{ access_key }}" - aws_secret_key: "{{ secret_key }}" - region: "{{ algo_region }}" - register: raw_eip_addresses + - name: Get existing available Elastic IPs + ec2_eip_info: + aws_access_key: "{{ access_key }}" + aws_secret_key: "{{ secret_key }}" + region: "{{ algo_region }}" + register: raw_eip_addresses - - set_fact: - available_eip_addresses: "{{ raw_eip_addresses.addresses | selectattr('association_id', 'undefined') | list }}" + - set_fact: + available_eip_addresses: "{{ raw_eip_addresses.addresses | selectattr('association_id', 'undefined') | list }}" - - pause: - prompt: >- - What Elastic IP would you like to use? - {% for eip in available_eip_addresses %} - {{ loop.index }}. {{ eip['public_ip'] }} - {% endfor %} + - pause: + prompt: >- + What Elastic IP would you like to use? + {% for eip in available_eip_addresses %} + {{ loop.index }}. {{ eip['public_ip'] }} + {% endfor %} - Enter the number of your desired Elastic IP - register: _use_existing_eip + Enter the number of your desired Elastic IP + register: _use_existing_eip - - set_fact: - existing_eip: "{{ available_eip_addresses[_use_existing_eip.user_input | int -1 ]['allocation_id'] }}" + - set_fact: + existing_eip: "{{ available_eip_addresses[_use_existing_eip.user_input | int -1 ]['allocation_id'] }}" when: cloud_providers.ec2.use_existing_eip diff --git a/roles/cloud-gce/tasks/main.yml b/roles/cloud-gce/tasks/main.yml index ca68567..69aa56a 100644 --- a/roles/cloud-gce/tasks/main.yml +++ b/roles/cloud-gce/tasks/main.yml @@ -27,27 +27,27 @@ allowed: - ip_protocol: udp ports: - - '500' - - '4500' - - '{{ wireguard_port|string }}' + - "500" + - "4500" + - "{{ wireguard_port|string }}" - ip_protocol: tcp ports: - - '{{ ssh_port }}' + - "{{ ssh_port }}" - ip_protocol: icmp - block: - - name: External IP allocated - gcp_compute_address: - auth_kind: serviceaccount - service_account_file: "{{ credentials_file_path }}" - project: "{{ project_id }}" - name: "{{ algo_server_name }}" - region: "{{ algo_region }}" - register: gcp_compute_address + - name: External IP allocated + gcp_compute_address: + auth_kind: serviceaccount + service_account_file: "{{ credentials_file_path }}" + project: "{{ project_id }}" + name: "{{ algo_server_name }}" + region: "{{ algo_region }}" + register: gcp_compute_address - - name: Set External IP as a fact - set_fact: - external_ip: "{{ gcp_compute_address.address }}" + - name: Set External IP as a fact + set_fact: + external_ip: "{{ gcp_compute_address.address }}" when: cloud_providers.gce.external_static_ip - name: Instance created @@ -62,9 +62,9 @@ - auto_delete: true boot: true initialize_params: - source_image: "projects/ubuntu-os-cloud/global/images/family/{{ cloud_providers.gce.image }}" + source_image: projects/ubuntu-os-cloud/global/images/family/{{ cloud_providers.gce.image }} metadata: - ssh-keys: "algo:{{ ssh_public_key_lookup }}" + ssh-keys: algo:{{ ssh_public_key_lookup }} user-data: "{{ lookup('template', 'files/cloud-init/base.yml') }}" network_interfaces: - network: "{{ gcp_compute_network }}" @@ -74,7 +74,7 @@ type: ONE_TO_ONE_NAT tags: items: - - "environment-algo" + - environment-algo register: gcp_compute_instance - set_fact: diff --git a/roles/cloud-gce/tasks/prompts.yml b/roles/cloud-gce/tasks/prompts.yml index b8a3896..bc7eedd 100644 --- a/roles/cloud-gce/tasks/prompts.yml +++ b/roles/cloud-gce/tasks/prompts.yml @@ -9,7 +9,8 @@ - lookup('env','GCE_CREDENTIALS_FILE_PATH')|length <= 0 - set_fact: - credentials_file_path: "{{ gce_credentials_file | default(_gce_credentials_file.user_input|default(None)) | default(lookup('env','GCE_CREDENTIALS_FILE_PATH'), true) }}" + credentials_file_path: "{{ gce_credentials_file | default(_gce_credentials_file.user_input|default(None)) | default(lookup('env','GCE_CREDENTIALS_FILE_PATH'),\ + \ true) }}" ssh_public_key_lookup: "{{ lookup('file', '{{ SSH_keys.public }}') }}" - set_fact: @@ -20,40 +21,40 @@ project_id: "{{ credentials_file_lookup.project_id | default(lookup('env','GCE_PROJECT')) }}" - block: - - name: Get regions - gcp_compute_location_info: - auth_kind: serviceaccount - service_account_file: "{{ credentials_file_path }}" - project: "{{ project_id }}" - scope: regions - filters: status=UP - register: gcp_compute_regions_info + - name: Get regions + gcp_compute_location_info: + auth_kind: serviceaccount + service_account_file: "{{ credentials_file_path }}" + project: "{{ project_id }}" + scope: regions + filters: status=UP + register: gcp_compute_regions_info - - name: Set facts about the regions - set_fact: - gce_regions: >- - [{%- for region in gcp_compute_regions_info.resources | sort(attribute='name') -%} - '{{ region.name }}'{% if not loop.last %},{% endif %} - {%- endfor -%}] + - name: Set facts about the regions + set_fact: + gce_regions: >- + [{%- for region in gcp_compute_regions_info.resources | sort(attribute='name') -%} + '{{ region.name }}'{% if not loop.last %},{% endif %} + {%- endfor -%}] - - name: Set facts about the default region - set_fact: - default_region: >- - {% for region in gce_regions %} - {%- if region == "us-east1" %}{{ loop.index }}{% endif %} - {%- endfor %} + - name: Set facts about the default region + set_fact: + default_region: >- + {% for region in gce_regions %} + {%- if region == "us-east1" %}{{ loop.index }}{% endif %} + {%- endfor %} - - pause: - prompt: | - What region should the server be located in? - (https://cloud.google.com/compute/docs/regions-zones/#locations) - {% for r in gce_regions %} - {{ loop.index }}. {{ r }} - {% endfor %} + - pause: + prompt: | + What region should the server be located in? + (https://cloud.google.com/compute/docs/regions-zones/#locations) + {% for r in gce_regions %} + {{ loop.index }}. {{ r }} + {% endfor %} - Enter the number of your desired region - [{{ default_region }}] - register: _gce_region + Enter the number of your desired region + [{{ default_region }}] + register: _gce_region when: region is undefined - name: Set region as a fact @@ -70,8 +71,8 @@ project: "{{ project_id }}" scope: zones filters: - - "name={{ algo_region }}-*" - - "status=UP" + - name={{ algo_region }}-* + - status=UP register: gcp_compute_zone_info - name: Set random available zone as a fact diff --git a/roles/cloud-hetzner/tasks/main.yml b/roles/cloud-hetzner/tasks/main.yml index cbae7c6..c533164 100644 --- a/roles/cloud-hetzner/tasks/main.yml +++ b/roles/cloud-hetzner/tasks/main.yml @@ -7,7 +7,7 @@ - name: Create an ssh key hcloud_ssh_key: - name: "algo-{{ 999999 | random(seed=lookup('file', SSH_keys.public)) }}" + name: algo-{{ 999999 | random(seed=lookup('file', SSH_keys.public)) }} public_key: "{{ lookup('file', SSH_keys.public) }}" state: present api_token: "{{ algo_hcloud_token }}" diff --git a/roles/cloud-lightsail/tasks/cloudformation.yml b/roles/cloud-lightsail/tasks/cloudformation.yml index 1e3a6a0..d3798a9 100644 --- a/roles/cloud-lightsail/tasks/cloudformation.yml +++ b/roles/cloud-lightsail/tasks/cloudformation.yml @@ -4,7 +4,7 @@ aws_access_key: "{{ access_key }}" aws_secret_key: "{{ secret_key }}" stack_name: "{{ stack_name }}" - state: "present" + state: present region: "{{ algo_region }}" template: roles/cloud-lightsail/files/stack.yaml template_parameters: diff --git a/roles/cloud-lightsail/tasks/prompts.yml b/roles/cloud-lightsail/tasks/prompts.yml index 08605de..49e6bd0 100644 --- a/roles/cloud-lightsail/tasks/prompts.yml +++ b/roles/cloud-lightsail/tasks/prompts.yml @@ -6,8 +6,8 @@ echo: false register: _aws_access_key when: - - aws_access_key is undefined - - lookup('env','AWS_ACCESS_KEY_ID')|length <= 0 + - aws_access_key is undefined + - lookup('env','AWS_ACCESS_KEY_ID')|length <= 0 - pause: prompt: | @@ -23,35 +23,35 @@ secret_key: "{{ aws_secret_key | default(_aws_secret_key.user_input|default(None)) | default(lookup('env','AWS_SECRET_ACCESS_KEY'), true) }}" - block: - - name: Get regions - lightsail_region_facts: - aws_access_key: "{{ access_key }}" - aws_secret_key: "{{ secret_key }}" - region: us-east-1 - register: _lightsail_regions - - - name: Set facts about the regions - set_fact: - lightsail_regions: "{{ _lightsail_regions.data.regions | sort(attribute='name') }}" - - - name: Set the default region - set_fact: - default_region: >- - {% for r in lightsail_regions %} - {%- if r['name'] == "us-east-1" %}{{ loop.index }}{% endif %} - {%- endfor %} - - - pause: - prompt: | - What region should the server be located in? - (https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/) + - name: Get regions + lightsail_region_facts: + aws_access_key: "{{ access_key }}" + aws_secret_key: "{{ secret_key }}" + region: us-east-1 + register: _lightsail_regions + + - name: Set facts about the regions + set_fact: + lightsail_regions: "{{ _lightsail_regions.data.regions | sort(attribute='name') }}" + + - name: Set the default region + set_fact: + default_region: >- {% for r in lightsail_regions %} - {{ (loop.index|string + '.').ljust(3) }} {{ r['name'].ljust(20) }} {{ r['displayName'] }} - {% endfor %} - - Enter the number of your desired region - [{{ default_region }}] - register: _algo_region + {%- if r['name'] == "us-east-1" %}{{ loop.index }}{% endif %} + {%- endfor %} + + - pause: + prompt: | + What region should the server be located in? + (https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/) + {% for r in lightsail_regions %} + {{ (loop.index|string + '.').ljust(3) }} {{ r['name'].ljust(20) }} {{ r['displayName'] }} + {% endfor %} + + Enter the number of your desired region + [{{ default_region }}] + register: _algo_region when: region is undefined - set_fact: diff --git a/roles/cloud-linode/tasks/main.yml b/roles/cloud-linode/tasks/main.yml index a27c95f..8cdd47f 100644 --- a/roles/cloud-linode/tasks/main.yml +++ b/roles/cloud-linode/tasks/main.yml @@ -26,7 +26,7 @@ - name: Update the stackscript uri: - url: "https://api.linode.com/v4/linode/stackscripts/{{ _linode_stackscript.stackscript.id }}" + url: https://api.linode.com/v4/linode/stackscripts/{{ _linode_stackscript.stackscript.id }} method: PUT body_format: json body: @@ -34,10 +34,10 @@ {{ stackscript }} headers: Content-Type: application/json - Authorization: "Bearer {{ algo_linode_token }}" + Authorization: Bearer {{ algo_linode_token }} when: (_linode_stackscript.stackscript.script | hash('md5')) != (stackscript | hash('md5')) -- name: "Creating an instance..." +- name: Creating an instance... linode_v4: access_token: "{{ algo_linode_token }}" label: "{{ algo_server_name }}" diff --git a/roles/cloud-openstack/tasks/main.yml b/roles/cloud-openstack/tasks/main.yml index 39899af..ac6cbd3 100644 --- a/roles/cloud-openstack/tasks/main.yml +++ b/roles/cloud-openstack/tasks/main.yml @@ -22,7 +22,7 @@ port_range_max: "{{ item.port_max }}" remote_ip_prefix: "{{ item.range }}" with_items: - - { proto: tcp, port_min: '{{ ssh_port }}', port_max: '{{ ssh_port }}', range: 0.0.0.0/0 } + - { proto: tcp, port_min: "{{ ssh_port }}", port_max: "{{ ssh_port }}", range: 0.0.0.0/0 } - { proto: icmp, port_min: -1, port_max: -1, range: 0.0.0.0/0 } - { proto: udp, port_min: 4500, port_max: 4500, range: 0.0.0.0/0 } - { proto: udp, port_min: 500, port_max: 500, range: 0.0.0.0/0 } diff --git a/roles/cloud-scaleway/tasks/main.yml b/roles/cloud-scaleway/tasks/main.yml index 96a4940..05c1d53 100644 --- a/roles/cloud-scaleway/tasks/main.yml +++ b/roles/cloud-scaleway/tasks/main.yml @@ -1,73 +1,74 @@ +--- - name: Include prompts import_tasks: prompts.yml - block: - - name: Gather Scaleway organizations facts - scaleway_organization_info: - register: scaleway_org + - name: Gather Scaleway organizations facts + scaleway_organization_info: + register: scaleway_org - - name: Get images - scaleway_image_info: - region: "{{ algo_region }}" - register: scaleway_image + - name: Get images + scaleway_image_info: + region: "{{ algo_region }}" + register: scaleway_image - - name: Set cloud specific facts - set_fact: - organization_id: "{{ scaleway_org.scaleway_organization_info[0]['id'] }}" - images: >- - [{% for i in scaleway_image.scaleway_image_info -%} - {% if i.name == cloud_providers.scaleway.image and - i.arch == cloud_providers.scaleway.arch -%} - '{{ i.id }}'{% if not loop.last %},{% endif %} - {%- endif -%} - {%- endfor -%}] + - name: Set cloud specific facts + set_fact: + organization_id: "{{ scaleway_org.scaleway_organization_info[0]['id'] }}" + images: >- + [{% for i in scaleway_image.scaleway_image_info -%} + {% if i.name == cloud_providers.scaleway.image and + i.arch == cloud_providers.scaleway.arch -%} + '{{ i.id }}'{% if not loop.last %},{% endif %} + {%- endif -%} + {%- endfor -%}] - - name: Create a server - scaleway_compute: - name: "{{ algo_server_name }}" - enable_ipv6: true - public_ip: dynamic - boot_type: local - state: present - image: "{{ images[0] }}" - organization: "{{ organization_id }}" - region: "{{ algo_region }}" - commercial_type: "{{ cloud_providers.scaleway.size }}" - wait: true - tags: - - Environment:Algo - - AUTHORIZED_KEY={{ lookup('file', SSH_keys.public)|regex_replace(' ', '_') }} - register: scaleway_compute + - name: Create a server + scaleway_compute: + name: "{{ algo_server_name }}" + enable_ipv6: true + public_ip: dynamic + boot_type: local + state: present + image: "{{ images[0] }}" + organization: "{{ organization_id }}" + region: "{{ algo_region }}" + commercial_type: "{{ cloud_providers.scaleway.size }}" + wait: true + tags: + - Environment:Algo + - AUTHORIZED_KEY={{ lookup('file', SSH_keys.public)|regex_replace(' ', '_') }} + register: scaleway_compute - - name: Patch the cloud-init - uri: - url: "https://cp-{{ algo_region }}.scaleway.com/servers/{{ scaleway_compute.msg.id }}/user_data/cloud-init" - method: PATCH - body: "{{ lookup('template', 'files/cloud-init/base.yml') }}" - status_code: 204 - headers: - Content-Type: "text/plain" - X-Auth-Token: "{{ algo_scaleway_token }}" + - name: Patch the cloud-init + uri: + url: https://cp-{{ algo_region }}.scaleway.com/servers/{{ scaleway_compute.msg.id }}/user_data/cloud-init + method: PATCH + body: "{{ lookup('template', 'files/cloud-init/base.yml') }}" + status_code: 204 + headers: + Content-Type: text/plain + X-Auth-Token: "{{ algo_scaleway_token }}" - - name: Start the server - scaleway_compute: - name: "{{ algo_server_name }}" - enable_ipv6: true - public_ip: dynamic - boot_type: local - state: running - image: "{{ images[0] }}" - organization: "{{ organization_id }}" - region: "{{ algo_region }}" - commercial_type: "{{ cloud_providers.scaleway.size }}" - wait: true - tags: - - Environment:Algo - - AUTHORIZED_KEY={{ lookup('file', SSH_keys.public)|regex_replace(' ', '_') }} - register: algo_instance - until: algo_instance.msg.public_ip - retries: 3 - delay: 3 + - name: Start the server + scaleway_compute: + name: "{{ algo_server_name }}" + enable_ipv6: true + public_ip: dynamic + boot_type: local + state: running + image: "{{ images[0] }}" + organization: "{{ organization_id }}" + region: "{{ algo_region }}" + commercial_type: "{{ cloud_providers.scaleway.size }}" + wait: true + tags: + - Environment:Algo + - AUTHORIZED_KEY={{ lookup('file', SSH_keys.public)|regex_replace(' ', '_') }} + register: algo_instance + until: algo_instance.msg.public_ip + retries: 3 + delay: 3 environment: SCW_TOKEN: "{{ algo_scaleway_token }}" diff --git a/roles/cloud-vultr/tasks/main.yml b/roles/cloud-vultr/tasks/main.yml index 6ad1d7b..2aa1b8d 100644 --- a/roles/cloud-vultr/tasks/main.yml +++ b/roles/cloud-vultr/tasks/main.yml @@ -3,54 +3,54 @@ import_tasks: prompts.yml - block: - - name: Creating a firewall group - vultr_firewall_group: - name: "{{ algo_server_name }}" + - name: Creating a firewall group + vultr_firewall_group: + name: "{{ algo_server_name }}" - - name: Creating firewall rules - vultr_firewall_rule: - group: "{{ algo_server_name }}" - protocol: "{{ item.protocol }}" - port: "{{ item.port }}" - ip_version: "{{ item.ip }}" - cidr: "{{ item.cidr }}" - with_items: - - { protocol: tcp, port: "{{ ssh_port }}", ip: v4, cidr: "0.0.0.0/0" } - - { protocol: tcp, port: "{{ ssh_port }}", ip: v6, cidr: "::/0" } - - { protocol: udp, port: 500, ip: v4, cidr: "0.0.0.0/0" } - - { protocol: udp, port: 500, ip: v6, cidr: "::/0" } - - { protocol: udp, port: 4500, ip: v4, cidr: "0.0.0.0/0" } - - { protocol: udp, port: 4500, ip: v6, cidr: "::/0" } - - { protocol: udp, port: "{{ wireguard_port }}", ip: v4, cidr: "0.0.0.0/0" } - - { protocol: udp, port: "{{ wireguard_port }}", ip: v6, cidr: "::/0" } + - name: Creating firewall rules + vultr_firewall_rule: + group: "{{ algo_server_name }}" + protocol: "{{ item.protocol }}" + port: "{{ item.port }}" + ip_version: "{{ item.ip }}" + cidr: "{{ item.cidr }}" + with_items: + - { protocol: tcp, port: "{{ ssh_port }}", ip: v4, cidr: 0.0.0.0/0 } + - { protocol: tcp, port: "{{ ssh_port }}", ip: v6, cidr: "::/0" } + - { protocol: udp, port: 500, ip: v4, cidr: 0.0.0.0/0 } + - { protocol: udp, port: 500, ip: v6, cidr: "::/0" } + - { protocol: udp, port: 4500, ip: v4, cidr: 0.0.0.0/0 } + - { protocol: udp, port: 4500, ip: v6, cidr: "::/0" } + - { protocol: udp, port: "{{ wireguard_port }}", ip: v4, cidr: 0.0.0.0/0 } + - { protocol: udp, port: "{{ wireguard_port }}", ip: v6, cidr: "::/0" } - - name: Upload the startup script - vultr_startup_script: - name: algo-startup - script: | - {{ lookup('template', 'files/cloud-init/base.yml') }} + - name: Upload the startup script + vultr_startup_script: + name: algo-startup + script: | + {{ lookup('template', 'files/cloud-init/base.yml') }} - - name: Creating a server - vultr_server: - name: "{{ algo_server_name }}" - startup_script: algo-startup - hostname: "{{ algo_server_name }}" - os: "{{ cloud_providers.vultr.os }}" - plan: "{{ cloud_providers.vultr.size }}" - region: "{{ algo_vultr_region }}" - firewall_group: "{{ algo_server_name }}" - state: started - tag: Environment:Algo - ipv6_enabled: true - auto_backup_enabled: false - notify_activate: false - register: vultr_server + - name: Creating a server + vultr_server: + name: "{{ algo_server_name }}" + startup_script: algo-startup + hostname: "{{ algo_server_name }}" + os: "{{ cloud_providers.vultr.os }}" + plan: "{{ cloud_providers.vultr.size }}" + region: "{{ algo_vultr_region }}" + firewall_group: "{{ algo_server_name }}" + state: started + tag: Environment:Algo + ipv6_enabled: true + auto_backup_enabled: false + notify_activate: false + register: vultr_server - - set_fact: - cloud_instance_ip: "{{ vultr_server.vultr_server.v4_main_ip }}" - ansible_ssh_user: algo - ansible_ssh_port: "{{ ssh_port }}" - cloudinit: true + - set_fact: + cloud_instance_ip: "{{ vultr_server.vultr_server.v4_main_ip }}" + ansible_ssh_user: algo + ansible_ssh_port: "{{ ssh_port }}" + cloudinit: true environment: VULTR_API_CONFIG: "{{ algo_vultr_config }}" diff --git a/roles/common/handlers/main.yml b/roles/common/handlers/main.yml index 86a2bdb..f590f75 100644 --- a/roles/common/handlers/main.yml +++ b/roles/common/handlers/main.yml @@ -1,3 +1,4 @@ +--- - name: restart rsyslog service: name=rsyslog state=restarted diff --git a/roles/common/tasks/freebsd.yml b/roles/common/tasks/freebsd.yml index 9dbfb18..cb8361e 100644 --- a/roles/common/tasks/freebsd.yml +++ b/roles/common/tasks/freebsd.yml @@ -13,13 +13,12 @@ - name: Gather facts setup: - - name: Gather additional facts import_tasks: facts.yml - name: Set OS specific facts set_fact: - config_prefix: "/usr/local/" + config_prefix: /usr/local/ strongswan_shell: /usr/sbin/nologin strongswan_home: /var/empty root_group: wheel @@ -50,7 +49,7 @@ - name: Loopback included into the rc config blockinfile: dest: /etc/rc.conf - create: yes + create: true block: | cloned_interfaces="lo100" ifconfig_lo100="inet {{ local_service_ip }} netmask 255.255.255.255" diff --git a/roles/common/tasks/iptables.yml b/roles/common/tasks/iptables.yml index e5b1061..463dc38 100644 --- a/roles/common/tasks/iptables.yml +++ b/roles/common/tasks/iptables.yml @@ -1,5 +1,4 @@ --- - - name: Iptables configured template: src: "{{ item.src }}" diff --git a/roles/common/tasks/ubuntu.yml b/roles/common/tasks/ubuntu.yml index 19618d4..caa1d30 100644 --- a/roles/common/tasks/ubuntu.yml +++ b/roles/common/tasks/ubuntu.yml @@ -1,7 +1,6 @@ --- - name: Gather facts setup: - - name: Cloud only tasks block: - name: Install software updates @@ -42,8 +41,8 @@ - name: Disable MOTD on login and SSHD replace: dest="{{ item.file }}" regexp="{{ item.regexp }}" replace="{{ item.line }}" with_items: - - { regexp: '^session.*optional.*pam_motd.so.*', line: '# MOTD DISABLED', file: '/etc/pam.d/login' } - - { regexp: '^session.*optional.*pam_motd.so.*', line: '# MOTD DISABLED', file: '/etc/pam.d/sshd' } + - { regexp: ^session.*optional.*pam_motd.so.*, line: "# MOTD DISABLED", file: /etc/pam.d/login } + - { regexp: ^session.*optional.*pam_motd.so.*, line: "# MOTD DISABLED", file: /etc/pam.d/sshd } - name: Ensure fallback resolvers are set ini_file: @@ -75,7 +74,7 @@ - name: Check apparmor support command: apparmor_status - ignore_errors: yes + ignore_errors: true changed_when: false register: apparmor_status @@ -117,7 +116,7 @@ apt: name: - linux-headers-generic - - "linux-headers-{{ ansible_kernel }}" + - linux-headers-{{ ansible_kernel }} state: present when: install_headers | bool diff --git a/roles/dns/tasks/freebsd.yml b/roles/dns/tasks/freebsd.yml index 0f826c4..e7e6297 100644 --- a/roles/dns/tasks/freebsd.yml +++ b/roles/dns/tasks/freebsd.yml @@ -6,4 +6,4 @@ - name: Enable mac_portacl lineinfile: path: /etc/rc.conf - line: 'dnscrypt_proxy_mac_portacl_enable="YES"' + line: dnscrypt_proxy_mac_portacl_enable="YES" diff --git a/roles/dns/tasks/ubuntu.yml b/roles/dns/tasks/ubuntu.yml index 3ccbdc1..b54e377 100644 --- a/roles/dns/tasks/ubuntu.yml +++ b/roles/dns/tasks/ubuntu.yml @@ -1,22 +1,22 @@ --- - block: - - name: Add the repository - apt_repository: - state: present - codename: "{{ ansible_distribution_release }}" - repo: ppa:shevchuk/dnscrypt-proxy - register: result - until: result is succeeded - retries: 10 - delay: 3 + - name: Add the repository + apt_repository: + state: present + codename: "{{ ansible_distribution_release }}" + repo: ppa:shevchuk/dnscrypt-proxy + register: result + until: result is succeeded + retries: 10 + delay: 3 - - name: Configure unattended-upgrades - copy: - src: 50-dnscrypt-proxy-unattended-upgrades - dest: /etc/apt/apt.conf.d/50-dnscrypt-proxy-unattended-upgrades - owner: root - group: root - mode: 0644 + - name: Configure unattended-upgrades + copy: + src: 50-dnscrypt-proxy-unattended-upgrades + dest: /etc/apt/apt.conf.d/50-dnscrypt-proxy-unattended-upgrades + owner: root + group: root + mode: 0644 when: ansible_facts['distribution_version'] is version('20.04', '<') - name: Install dnscrypt-proxy @@ -26,18 +26,18 @@ update_cache: true - block: - - name: Ubuntu | Configure AppArmor policy for dnscrypt-proxy - copy: - src: apparmor.profile.dnscrypt-proxy - dest: /etc/apparmor.d/usr.bin.dnscrypt-proxy - owner: root - group: root - mode: 0600 - notify: restart dnscrypt-proxy + - name: Ubuntu | Configure AppArmor policy for dnscrypt-proxy + copy: + src: apparmor.profile.dnscrypt-proxy + dest: /etc/apparmor.d/usr.bin.dnscrypt-proxy + owner: root + group: root + mode: 0600 + notify: restart dnscrypt-proxy - - name: Ubuntu | Enforce the dnscrypt-proxy AppArmor policy - command: aa-enforce usr.bin.dnscrypt-proxy - changed_when: false + - name: Ubuntu | Enforce the dnscrypt-proxy AppArmor policy + command: aa-enforce usr.bin.dnscrypt-proxy + changed_when: false tags: apparmor when: apparmor_enabled|default(false)|bool @@ -60,4 +60,4 @@ [Service] AmbientCapabilities=CAP_NET_BIND_SERVICE notify: - - restart dnscrypt-proxy + - restart dnscrypt-proxy diff --git a/roles/local/tasks/prompts.yml b/roles/local/tasks/prompts.yml index d4da709..76d2a4e 100644 --- a/roles/local/tasks/prompts.yml +++ b/roles/local/tasks/prompts.yml @@ -20,25 +20,25 @@ - name: Set the facts set_fact: - cloud_instance_ip: >- + cloud_instance_ip: >- {% if server is defined %}{{ server }} {%- elif _algo_server.user_input %}{{ _algo_server.user_input }} {%- else %}localhost{% endif %} - block: - - pause: - prompt: | - What user should we use to login on the server? (note: passwordless login required, or ignore if you're deploying to localhost) - [root] - register: _algo_ssh_user - when: ssh_user is undefined - - - name: Set the facts - set_fact: - ansible_ssh_user: >- - {% if ssh_user is defined %}{{ ssh_user }} - {%- elif _algo_ssh_user.user_input %}{{ _algo_ssh_user.user_input }} - {%- else %}root{% endif %} + - pause: + prompt: | + What user should we use to login on the server? (note: passwordless login required, or ignore if you're deploying to localhost) + [root] + register: _algo_ssh_user + when: ssh_user is undefined + + - name: Set the facts + set_fact: + ansible_ssh_user: >- + {% if ssh_user is defined %}{{ ssh_user }} + {%- elif _algo_ssh_user.user_input %}{{ _algo_ssh_user.user_input }} + {%- else %}root{% endif %} when: cloud_instance_ip != "localhost" - pause: diff --git a/roles/ssh_tunneling/defaults/main.yml b/roles/ssh_tunneling/defaults/main.yml index 3ed9b59..7c39943 100644 --- a/roles/ssh_tunneling/defaults/main.yml +++ b/roles/ssh_tunneling/defaults/main.yml @@ -1,2 +1,2 @@ --- -ssh_tunnels_config_path: "configs/{{ IP_subject_alt_name }}/ssh-tunnel/" +ssh_tunnels_config_path: configs/{{ IP_subject_alt_name }}/ssh-tunnel/ diff --git a/roles/ssh_tunneling/handlers/main.yml b/roles/ssh_tunneling/handlers/main.yml index 066d960..eae0ef1 100644 --- a/roles/ssh_tunneling/handlers/main.yml +++ b/roles/ssh_tunneling/handlers/main.yml @@ -1,2 +1,3 @@ +--- - name: restart ssh service: name="{{ ssh_service_name|default('ssh') }}" state=restarted diff --git a/roles/ssh_tunneling/tasks/main.yml b/roles/ssh_tunneling/tasks/main.yml index e4adb55..8abdd62 100644 --- a/roles/ssh_tunneling/tasks/main.yml +++ b/roles/ssh_tunneling/tasks/main.yml @@ -2,7 +2,7 @@ - name: Ensure that the sshd_config file has desired options blockinfile: dest: /etc/ssh/sshd_config - marker: '# {mark} ANSIBLE MANAGED BLOCK ssh_tunneling_role' + marker: "# {mark} ANSIBLE MANAGED BLOCK ssh_tunneling_role" block: | Match Group algo AllowTcpForwarding local @@ -28,90 +28,90 @@ group: "{{ root_group|default('root') }}" - block: - - name: Ensure that the SSH users exist - user: - name: "{{ item }}" - group: algo - home: '/var/jail/{{ item }}' - createhome: yes - generate_ssh_key: false - shell: /bin/false - state: present - append: yes - with_items: "{{ users }}" + - name: Ensure that the SSH users exist + user: + name: "{{ item }}" + group: algo + home: /var/jail/{{ item }} + createhome: true + generate_ssh_key: false + shell: /bin/false + state: present + append: true + with_items: "{{ users }}" - - block: - - name: Clean up the ssh-tunnel directory - file: - dest: "{{ ssh_tunnels_config_path }}" - state: absent - when: keys_clean_all|bool + - block: + - name: Clean up the ssh-tunnel directory + file: + dest: "{{ ssh_tunnels_config_path }}" + state: absent + when: keys_clean_all|bool - - name: Ensure the config directories exist - file: - dest: "{{ ssh_tunnels_config_path }}" - state: directory - recurse: yes - mode: '0700' + - name: Ensure the config directories exist + file: + dest: "{{ ssh_tunnels_config_path }}" + state: directory + recurse: true + mode: "0700" - - name: Check if the private keys exist - stat: - path: "{{ ssh_tunnels_config_path }}/{{ item }}.pem" - register: privatekey - with_items: "{{ users }}" + - name: Check if the private keys exist + stat: + path: "{{ ssh_tunnels_config_path }}/{{ item }}.pem" + register: privatekey + with_items: "{{ users }}" - - name: Build ssh private keys - openssl_privatekey: - path: "{{ ssh_tunnels_config_path }}/{{ item.item }}.pem" - passphrase: "{{ p12_export_password }}" - cipher: auto - force: false - no_log: "{{ no_log|bool }}" - when: not item.stat.exists - with_items: "{{ privatekey.results }}" - register: openssl_privatekey + - name: Build ssh private keys + openssl_privatekey: + path: "{{ ssh_tunnels_config_path }}/{{ item.item }}.pem" + passphrase: "{{ p12_export_password }}" + cipher: auto + force: false + no_log: "{{ no_log|bool }}" + when: not item.stat.exists + with_items: "{{ privatekey.results }}" + register: openssl_privatekey - - name: Build ssh public keys - openssl_publickey: - path: "{{ ssh_tunnels_config_path }}/{{ item.item.item }}.pub" - privatekey_path: "{{ ssh_tunnels_config_path }}/{{ item.item.item }}.pem" - privatekey_passphrase: "{{ p12_export_password }}" - format: OpenSSH - force: true - no_log: "{{ no_log|bool }}" - when: item.changed - with_items: "{{ openssl_privatekey.results }}" + - name: Build ssh public keys + openssl_publickey: + path: "{{ ssh_tunnels_config_path }}/{{ item.item.item }}.pub" + privatekey_path: "{{ ssh_tunnels_config_path }}/{{ item.item.item }}.pem" + privatekey_passphrase: "{{ p12_export_password }}" + format: OpenSSH + force: true + no_log: "{{ no_log|bool }}" + when: item.changed + with_items: "{{ openssl_privatekey.results }}" - - name: Build the client ssh config - template: - src: ssh_config.j2 - dest: "{{ ssh_tunnels_config_path }}/{{ item }}.ssh_config" - mode: 0700 - with_items: "{{ users }}" - delegate_to: localhost - become: false + - name: Build the client ssh config + template: + src: ssh_config.j2 + dest: "{{ ssh_tunnels_config_path }}/{{ item }}.ssh_config" + mode: 0700 + with_items: "{{ users }}" + delegate_to: localhost + become: false - - name: The authorized keys file created - authorized_key: - user: "{{ item }}" - key: "{{ lookup('file', ssh_tunnels_config_path + '/' + item + '.pub') }}" - state: present - manage_dir: true - exclusive: true - with_items: "{{ users }}" + - name: The authorized keys file created + authorized_key: + user: "{{ item }}" + key: "{{ lookup('file', ssh_tunnels_config_path + '/' + item + '.pub') }}" + state: present + manage_dir: true + exclusive: true + with_items: "{{ users }}" - - name: Get active users - getent: - database: group - key: algo - split: ':' + - name: Get active users + getent: + database: group + key: algo + split: ":" - - name: Delete non-existing users - user: - name: "{{ item }}" - state: absent - remove: yes - force: yes - when: item not in users - with_items: "{{ getent_group['algo'][2].split(',') }}" + - name: Delete non-existing users + user: + name: "{{ item }}" + state: absent + remove: true + force: true + when: item not in users + with_items: "{{ getent_group['algo'][2].split(',') }}" tags: update-users diff --git a/roles/strongswan/defaults/main.yml b/roles/strongswan/defaults/main.yml index dd50ddf..2483b3a 100644 --- a/roles/strongswan/defaults/main.yml +++ b/roles/strongswan/defaults/main.yml @@ -1,5 +1,5 @@ --- -ipsec_config_path: "configs/{{ IP_subject_alt_name }}/ipsec/" +ipsec_config_path: configs/{{ IP_subject_alt_name }}/ipsec/ ipsec_pki_path: "{{ ipsec_config_path }}/.pki/" strongswan_shell: /usr/sbin/nologin strongswan_home: /var/lib/strongswan @@ -7,7 +7,7 @@ strongswan_service: "{{ 'strongswan-starter' if ansible_facts['distribution_vers BetweenClients_DROP: true algo_ondemand_cellular: false algo_ondemand_wifi: false -algo_ondemand_wifi_exclude: '_null' +algo_ondemand_wifi_exclude: _null algo_dns_adblocking: false ipv6_support: false dns_encryption: true @@ -16,7 +16,7 @@ subjectAltName_type: "{{ 'DNS' if IP_subject_alt_name|regex_search('[a-z]') else subjectAltName: >- {{ subjectAltName_type }}:{{ IP_subject_alt_name }} {%- if ipv6_support -%},IP:{{ ansible_default_ipv6['address'] }}{%- endif -%} -subjectAltName_USER: "email:{{ item }}@{{ openssl_constraint_random_id }}" +subjectAltName_USER: email:{{ item }}@{{ openssl_constraint_random_id }} nameConstraints: >- critical,permitted;{{ subjectAltName_type }}:{{ IP_subject_alt_name }}{{- '/255.255.255.255' if subjectAltName_type == 'IP' else '' -}} {%- if subjectAltName_type == 'IP' -%} diff --git a/roles/strongswan/handlers/main.yml b/roles/strongswan/handlers/main.yml index a3d504f..3e2b035 100644 --- a/roles/strongswan/handlers/main.yml +++ b/roles/strongswan/handlers/main.yml @@ -1,3 +1,4 @@ +--- - name: restart strongswan service: name={{ strongswan_service }} state=restarted diff --git a/roles/strongswan/tasks/client_configs.yml b/roles/strongswan/tasks/client_configs.yml index 74021d9..083e5d7 100644 --- a/roles/strongswan/tasks/client_configs.yml +++ b/roles/strongswan/tasks/client_configs.yml @@ -4,7 +4,7 @@ set -o pipefail cat private/{{ item }}.p12 | base64 - register: PayloadContent + register: PayloadContent changed_when: false args: executable: bash diff --git a/roles/strongswan/tasks/distribute_keys.yml b/roles/strongswan/tasks/distribute_keys.yml index 02df30b..55d1da1 100644 --- a/roles/strongswan/tasks/distribute_keys.yml +++ b/roles/strongswan/tasks/distribute_keys.yml @@ -1,5 +1,4 @@ --- - - name: Copy the keys to the strongswan directory copy: src: "{{ ipsec_pki_path }}/{{ item.src }}" @@ -8,18 +7,18 @@ group: "{{ item.group }}" mode: "{{ item.mode }}" with_items: - - src: "cacert.pem" - dest: "cacerts/ca.crt" + - src: cacert.pem + dest: cacerts/ca.crt owner: strongswan group: "{{ root_group|default('root') }}" mode: "0600" - - src: "certs/{{ IP_subject_alt_name }}.crt" - dest: "certs/{{ IP_subject_alt_name }}.crt" + - src: certs/{{ IP_subject_alt_name }}.crt + dest: certs/{{ IP_subject_alt_name }}.crt owner: strongswan group: "{{ root_group|default('root') }}" mode: "0600" - - src: "private/{{ IP_subject_alt_name }}.key" - dest: "private/{{ IP_subject_alt_name }}.key" + - src: private/{{ IP_subject_alt_name }}.key + dest: private/{{ IP_subject_alt_name }}.key owner: strongswan group: "{{ root_group|default('root') }}" mode: "0600" diff --git a/roles/strongswan/tasks/ipsec_configuration.yml b/roles/strongswan/tasks/ipsec_configuration.yml index d75a93c..7ba44c3 100644 --- a/roles/strongswan/tasks/ipsec_configuration.yml +++ b/roles/strongswan/tasks/ipsec_configuration.yml @@ -1,5 +1,4 @@ --- - - name: Setup the config files from our templates template: src: "{{ item.src }}" @@ -9,22 +8,22 @@ mode: "{{ item.mode }}" with_items: - src: strongswan.conf.j2 - dest: "strongswan.conf" + dest: strongswan.conf owner: root group: "{{ root_group|default('root') }}" mode: "0644" - src: ipsec.conf.j2 - dest: "ipsec.conf" + dest: ipsec.conf owner: root group: "{{ root_group|default('root') }}" mode: "0644" - src: ipsec.secrets.j2 - dest: "ipsec.secrets" + dest: ipsec.secrets owner: strongswan group: "{{ root_group|default('root') }}" mode: "0600" - src: charon.conf.j2 - dest: "strongswan.d/charon.conf" + dest: strongswan.d/charon.conf owner: root group: "{{ root_group|default('root') }}" mode: "0644" @@ -44,8 +43,8 @@ - name: Disable unneeded plugins lineinfile: dest: "{{ config_prefix|default('/') }}etc/strongswan.d/charon/{{ item }}.conf" - regexp: '.*load.*' - line: 'load = no' + regexp: .*load.* + line: load = no state: present notify: - restart strongswan diff --git a/roles/strongswan/tasks/main.yml b/roles/strongswan/tasks/main.yml index 1c4c267..37b4dcb 100644 --- a/roles/strongswan/tasks/main.yml +++ b/roles/strongswan/tasks/main.yml @@ -19,7 +19,7 @@ - import_tasks: distribute_keys.yml - import_tasks: client_configs.yml delegate_to: localhost - become: no + become: false tags: update-users - name: strongSwan started diff --git a/roles/strongswan/tasks/openssl.yml b/roles/strongswan/tasks/openssl.yml index 1ec9498..f51ac9d 100644 --- a/roles/strongswan/tasks/openssl.yml +++ b/roles/strongswan/tasks/openssl.yml @@ -1,239 +1,239 @@ --- - block: - - debug: var=subjectAltName - - - name: Ensure the pki directory does not exist - file: - dest: "{{ ipsec_pki_path }}" - state: absent - when: keys_clean_all|bool - - - name: Ensure the pki directories exist - file: - dest: "{{ ipsec_pki_path }}/{{ item }}" - state: directory - recurse: yes - mode: '0700' - with_items: - - ecparams - - certs - - crl - - newcerts - - private - - public - - reqs - - - name: Ensure the config directories exist - file: - dest: "{{ ipsec_config_path }}/{{ item }}" - state: directory - recurse: yes - mode: '0700' - with_items: - - apple - - manual - - - name: Ensure the files exist - file: - dest: "{{ ipsec_pki_path }}/{{ item }}" - state: touch - with_items: - - ".rnd" - - "private/.rnd" - - "index.txt" - - "index.txt.attr" - - "serial" - - - name: Generate the openssl server configs - template: - src: openssl.cnf.j2 - dest: "{{ ipsec_pki_path }}/openssl.cnf" - - - name: Build the CA pair - shell: > - umask 077; - {{ openssl_bin }} ecparam -name secp384r1 -out ecparams/secp384r1.pem && - {{ openssl_bin }} req -utf8 -new - -newkey ec:ecparams/secp384r1.pem - -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName={{ subjectAltName }}")) - -keyout private/cakey.pem - -out cacert.pem -x509 -days 3650 - -batch - -passout pass:"{{ CA_password }}" && - touch {{ IP_subject_alt_name }}_ca_generated - args: - chdir: "{{ ipsec_pki_path }}" - creates: "{{ IP_subject_alt_name }}_ca_generated" - executable: bash - - - name: Copy the CA certificate - copy: - src: "{{ ipsec_pki_path }}/cacert.pem" - dest: "{{ ipsec_config_path }}/manual/cacert.pem" - - - name: Generate the serial number - shell: echo 01 > serial && touch serial_generated - args: - chdir: "{{ ipsec_pki_path }}" - creates: serial_generated - - - name: Build the server pair - shell: > - umask 077; - {{ openssl_bin }} req -utf8 -new - -newkey ec:ecparams/secp384r1.pem - -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName={{ subjectAltName }}")) - -keyout private/{{ IP_subject_alt_name }}.key - -out reqs/{{ IP_subject_alt_name }}.req -nodes - -passin pass:"{{ CA_password }}" - -subj "/CN={{ IP_subject_alt_name }}" -batch && - {{ openssl_bin }} ca -utf8 - -in reqs/{{ IP_subject_alt_name }}.req - -out certs/{{ IP_subject_alt_name }}.crt - -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName={{ subjectAltName }}")) - -days 3650 -batch - -passin pass:"{{ CA_password }}" - -subj "/CN={{ IP_subject_alt_name }}" && - touch certs/{{ IP_subject_alt_name }}_crt_generated - args: - chdir: "{{ ipsec_pki_path }}" - creates: certs/{{ IP_subject_alt_name }}_crt_generated - executable: bash - - - name: Build the client's pair - shell: > - umask 077; - {{ openssl_bin }} req -utf8 -new - -newkey ec:ecparams/secp384r1.pem - -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName={{ subjectAltName_USER }}")) - -keyout private/{{ item }}.key - -out reqs/{{ item }}.req -nodes - -passin pass:"{{ CA_password }}" - -subj "/CN={{ item }}" -batch && - {{ openssl_bin }} ca -utf8 - -in reqs/{{ item }}.req - -out certs/{{ item }}.crt - -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName={{ subjectAltName_USER }}")) - -days 3650 -batch - -passin pass:"{{ CA_password }}" - -subj "/CN={{ item }}" && - touch certs/{{ item }}_crt_generated - args: - chdir: "{{ ipsec_pki_path }}" - creates: certs/{{ item }}_crt_generated - executable: bash - with_items: "{{ users }}" - - - name: Build the tests pair - shell: > - umask 077; - {{ openssl_bin }} req -utf8 -new - -newkey ec:ecparams/secp384r1.pem - -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName=DNS:google-algo-test-pair.com")) - -keyout private/google-algo-test-pair.com.key - -out reqs/google-algo-test-pair.com.req -nodes - -passin pass:"{{ CA_password }}" - -subj "/CN=google-algo-test-pair.com" -batch && - {{ openssl_bin }} ca -utf8 - -in reqs/google-algo-test-pair.com.req - -out certs/google-algo-test-pair.com.crt - -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName=DNS:google-algo-test-pair.com")) - -days 3650 -batch - -passin pass:"{{ CA_password }}" - -subj "/CN=google-algo-test-pair.com" && - touch certs/google-algo-test-pair.com_crt_generated - args: - chdir: "{{ ipsec_pki_path }}" - creates: certs/google-algo-test-pair.com_crt_generated - executable: bash - when: tests|default(false)|bool - - - name: Build openssh public keys - openssl_publickey: - path: "{{ ipsec_pki_path }}/public/{{ item }}.pub" - privatekey_path: "{{ ipsec_pki_path }}/private/{{ item }}.key" - format: OpenSSH - with_items: "{{ users }}" - - - name: Build the client's p12 - shell: > - umask 077; - {{ openssl_bin }} pkcs12 - -in certs/{{ item }}.crt - -inkey private/{{ item }}.key - -export - -name {{ item }} - -out private/{{ item }}.p12 - -passout pass:"{{ p12_export_password }}" - args: - chdir: "{{ ipsec_pki_path }}" - executable: bash - with_items: "{{ users }}" - register: p12 - - - name: Build the client's p12 with the CA cert included - shell: > - umask 077; - {{ openssl_bin }} pkcs12 - -in certs/{{ item }}.crt - -inkey private/{{ item }}.key - -export - -name {{ item }} - -out private/{{ item }}_ca.p12 - -certfile cacert.pem - -passout pass:"{{ p12_export_password }}" - args: - chdir: "{{ ipsec_pki_path }}" - executable: bash - with_items: "{{ users }}" - register: p12 - - - name: Copy the p12 certificates - copy: - src: "{{ ipsec_pki_path }}/private/{{ item }}.p12" - dest: "{{ ipsec_config_path }}/manual/{{ item }}.p12" - with_items: - - "{{ users }}" - - - name: Get active users - shell: > - grep ^V index.txt | - grep -v "{{ IP_subject_alt_name }}" | - awk '{print $5}' | - sed 's/\/CN=//g' - args: - chdir: "{{ ipsec_pki_path }}" - register: valid_certs - - - name: Revoke non-existing users - shell: > - {{ openssl_bin }} ca -gencrl - -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName={{ subjectAltName_USER }}")) - -passin pass:"{{ CA_password }}" - -revoke certs/{{ item }}.crt - -out crl/{{ item }}.crt - register: gencrl - args: - chdir: "{{ ipsec_pki_path }}" - creates: crl/{{ item }}.crt - executable: bash - when: item.split('@')[0] not in users - with_items: "{{ valid_certs.stdout_lines }}" - - - name: Generate new CRL file - shell: > - {{ openssl_bin }} ca -gencrl - -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName=DNS:{{ IP_subject_alt_name }}")) - -passin pass:"{{ CA_password }}" - -out crl/algo.root.pem - when: - - gencrl is defined - - gencrl.changed - args: - chdir: "{{ ipsec_pki_path }}" - executable: bash + - debug: var=subjectAltName + + - name: Ensure the pki directory does not exist + file: + dest: "{{ ipsec_pki_path }}" + state: absent + when: keys_clean_all|bool + + - name: Ensure the pki directories exist + file: + dest: "{{ ipsec_pki_path }}/{{ item }}" + state: directory + recurse: true + mode: "0700" + with_items: + - ecparams + - certs + - crl + - newcerts + - private + - public + - reqs + + - name: Ensure the config directories exist + file: + dest: "{{ ipsec_config_path }}/{{ item }}" + state: directory + recurse: true + mode: "0700" + with_items: + - apple + - manual + + - name: Ensure the files exist + file: + dest: "{{ ipsec_pki_path }}/{{ item }}" + state: touch + with_items: + - .rnd + - private/.rnd + - index.txt + - index.txt.attr + - serial + + - name: Generate the openssl server configs + template: + src: openssl.cnf.j2 + dest: "{{ ipsec_pki_path }}/openssl.cnf" + + - name: Build the CA pair + shell: > + umask 077; + {{ openssl_bin }} ecparam -name secp384r1 -out ecparams/secp384r1.pem && + {{ openssl_bin }} req -utf8 -new + -newkey ec:ecparams/secp384r1.pem + -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName={{ subjectAltName }}")) + -keyout private/cakey.pem + -out cacert.pem -x509 -days 3650 + -batch + -passout pass:"{{ CA_password }}" && + touch {{ IP_subject_alt_name }}_ca_generated + args: + chdir: "{{ ipsec_pki_path }}" + creates: "{{ IP_subject_alt_name }}_ca_generated" + executable: bash + + - name: Copy the CA certificate + copy: + src: "{{ ipsec_pki_path }}/cacert.pem" + dest: "{{ ipsec_config_path }}/manual/cacert.pem" + + - name: Generate the serial number + shell: echo 01 > serial && touch serial_generated + args: + chdir: "{{ ipsec_pki_path }}" + creates: serial_generated + + - name: Build the server pair + shell: > + umask 077; + {{ openssl_bin }} req -utf8 -new + -newkey ec:ecparams/secp384r1.pem + -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName={{ subjectAltName }}")) + -keyout private/{{ IP_subject_alt_name }}.key + -out reqs/{{ IP_subject_alt_name }}.req -nodes + -passin pass:"{{ CA_password }}" + -subj "/CN={{ IP_subject_alt_name }}" -batch && + {{ openssl_bin }} ca -utf8 + -in reqs/{{ IP_subject_alt_name }}.req + -out certs/{{ IP_subject_alt_name }}.crt + -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName={{ subjectAltName }}")) + -days 3650 -batch + -passin pass:"{{ CA_password }}" + -subj "/CN={{ IP_subject_alt_name }}" && + touch certs/{{ IP_subject_alt_name }}_crt_generated + args: + chdir: "{{ ipsec_pki_path }}" + creates: certs/{{ IP_subject_alt_name }}_crt_generated + executable: bash + + - name: Build the client's pair + shell: > + umask 077; + {{ openssl_bin }} req -utf8 -new + -newkey ec:ecparams/secp384r1.pem + -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName={{ subjectAltName_USER }}")) + -keyout private/{{ item }}.key + -out reqs/{{ item }}.req -nodes + -passin pass:"{{ CA_password }}" + -subj "/CN={{ item }}" -batch && + {{ openssl_bin }} ca -utf8 + -in reqs/{{ item }}.req + -out certs/{{ item }}.crt + -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName={{ subjectAltName_USER }}")) + -days 3650 -batch + -passin pass:"{{ CA_password }}" + -subj "/CN={{ item }}" && + touch certs/{{ item }}_crt_generated + args: + chdir: "{{ ipsec_pki_path }}" + creates: certs/{{ item }}_crt_generated + executable: bash + with_items: "{{ users }}" + + - name: Build the tests pair + shell: > + umask 077; + {{ openssl_bin }} req -utf8 -new + -newkey ec:ecparams/secp384r1.pem + -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName=DNS:google-algo-test-pair.com")) + -keyout private/google-algo-test-pair.com.key + -out reqs/google-algo-test-pair.com.req -nodes + -passin pass:"{{ CA_password }}" + -subj "/CN=google-algo-test-pair.com" -batch && + {{ openssl_bin }} ca -utf8 + -in reqs/google-algo-test-pair.com.req + -out certs/google-algo-test-pair.com.crt + -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName=DNS:google-algo-test-pair.com")) + -days 3650 -batch + -passin pass:"{{ CA_password }}" + -subj "/CN=google-algo-test-pair.com" && + touch certs/google-algo-test-pair.com_crt_generated + args: + chdir: "{{ ipsec_pki_path }}" + creates: certs/google-algo-test-pair.com_crt_generated + executable: bash + when: tests|default(false)|bool + + - name: Build openssh public keys + openssl_publickey: + path: "{{ ipsec_pki_path }}/public/{{ item }}.pub" + privatekey_path: "{{ ipsec_pki_path }}/private/{{ item }}.key" + format: OpenSSH + with_items: "{{ users }}" + + - name: Build the client's p12 + shell: > + umask 077; + {{ openssl_bin }} pkcs12 + -in certs/{{ item }}.crt + -inkey private/{{ item }}.key + -export + -name {{ item }} + -out private/{{ item }}.p12 + -passout pass:"{{ p12_export_password }}" + args: + chdir: "{{ ipsec_pki_path }}" + executable: bash + with_items: "{{ users }}" + register: p12 + + - name: Build the client's p12 with the CA cert included + shell: > + umask 077; + {{ openssl_bin }} pkcs12 + -in certs/{{ item }}.crt + -inkey private/{{ item }}.key + -export + -name {{ item }} + -out private/{{ item }}_ca.p12 + -certfile cacert.pem + -passout pass:"{{ p12_export_password }}" + args: + chdir: "{{ ipsec_pki_path }}" + executable: bash + with_items: "{{ users }}" + register: p12 + + - name: Copy the p12 certificates + copy: + src: "{{ ipsec_pki_path }}/private/{{ item }}.p12" + dest: "{{ ipsec_config_path }}/manual/{{ item }}.p12" + with_items: + - "{{ users }}" + + - name: Get active users + shell: > + grep ^V index.txt | + grep -v "{{ IP_subject_alt_name }}" | + awk '{print $5}' | + sed 's/\/CN=//g' + args: + chdir: "{{ ipsec_pki_path }}" + register: valid_certs + + - name: Revoke non-existing users + shell: > + {{ openssl_bin }} ca -gencrl + -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName={{ subjectAltName_USER }}")) + -passin pass:"{{ CA_password }}" + -revoke certs/{{ item }}.crt + -out crl/{{ item }}.crt + register: gencrl + args: + chdir: "{{ ipsec_pki_path }}" + creates: crl/{{ item }}.crt + executable: bash + when: item.split('@')[0] not in users + with_items: "{{ valid_certs.stdout_lines }}" + + - name: Generate new CRL file + shell: > + {{ openssl_bin }} ca -gencrl + -config <(cat openssl.cnf <(printf "[basic_exts]\nsubjectAltName=DNS:{{ IP_subject_alt_name }}")) + -passin pass:"{{ CA_password }}" + -out crl/algo.root.pem + when: + - gencrl is defined + - gencrl.changed + args: + chdir: "{{ ipsec_pki_path }}" + executable: bash delegate_to: localhost - become: no + become: false vars: ansible_python_interpreter: "{{ ansible_playbook_python }}" diff --git a/roles/strongswan/tasks/ubuntu.yml b/roles/strongswan/tasks/ubuntu.yml index 2510511..424352e 100644 --- a/roles/strongswan/tasks/ubuntu.yml +++ b/roles/strongswan/tasks/ubuntu.yml @@ -2,32 +2,31 @@ - name: Set OS specific facts set_fact: strongswan_additional_plugins: [] - - name: Ubuntu | Install strongSwan apt: name: strongswan state: present - update_cache: yes - install_recommends: yes + update_cache: true + install_recommends: true - block: - # https://bugs.launchpad.net/ubuntu/+source/strongswan/+bug/1826238 - - name: Ubuntu | Charon profile for apparmor configured - copy: - dest: /etc/apparmor.d/local/usr.lib.ipsec.charon - content: ' capability setpcap,' - owner: root - group: root - mode: 0644 - notify: restart strongswan + # https://bugs.launchpad.net/ubuntu/+source/strongswan/+bug/1826238 + - name: Ubuntu | Charon profile for apparmor configured + copy: + dest: /etc/apparmor.d/local/usr.lib.ipsec.charon + content: " capability setpcap," + owner: root + group: root + mode: 0644 + notify: restart strongswan - - name: Ubuntu | Enforcing ipsec with apparmor - command: aa-enforce "{{ item }}" - changed_when: false - with_items: - - /usr/lib/ipsec/charon - - /usr/lib/ipsec/lookip - - /usr/lib/ipsec/stroke + - name: Ubuntu | Enforcing ipsec with apparmor + command: aa-enforce "{{ item }}" + changed_when: false + with_items: + - /usr/lib/ipsec/charon + - /usr/lib/ipsec/lookip + - /usr/lib/ipsec/stroke tags: apparmor when: apparmor_enabled|default(false)|bool diff --git a/roles/wireguard/defaults/main.yml b/roles/wireguard/defaults/main.yml index 171530a..45c4029 100644 --- a/roles/wireguard/defaults/main.yml +++ b/roles/wireguard/defaults/main.yml @@ -1,6 +1,6 @@ --- wireguard_PersistentKeepalive: 0 -wireguard_config_path: "configs/{{ IP_subject_alt_name }}/wireguard/" +wireguard_config_path: configs/{{ IP_subject_alt_name }}/wireguard/ wireguard_pki_path: "{{ wireguard_config_path }}/.pki/" wireguard_interface: wg0 wireguard_port_avoid: 53 @@ -10,7 +10,8 @@ wireguard_dns_servers: >- {% if algo_dns_adblocking|default(false)|bool or dns_encryption|default(false)|bool %} {{ local_service_ip }}{{ ', ' + local_service_ipv6 if ipv6_support else '' }} {% else %} - {% for host in dns_servers.ipv4 %}{{ host }}{% if not loop.last %},{% endif %}{% endfor %}{% if ipv6_support %},{% for host in dns_servers.ipv6 %}{{ host }}{% if not loop.last %},{% endif %}{% endfor %}{% endif %} + {% for host in dns_servers.ipv4 %}{{ host }}{% if not loop.last %},{% endif %}{% endfor %}{% if ipv6_support %},{% for host in dns_servers.ipv6 %}{{ host }}{% if + not loop.last %},{% endif %}{% endfor %}{% endif %} {% endif %} wireguard_client_ip: >- {{ wireguard_network_ipv4 | ipmath(index|int+2) }} diff --git a/roles/wireguard/tasks/keys.yml b/roles/wireguard/tasks/keys.yml index 19f3c1e..e9ce8a3 100644 --- a/roles/wireguard/tasks/keys.yml +++ b/roles/wireguard/tasks/keys.yml @@ -18,24 +18,24 @@ - "{{ IP_subject_alt_name }}" - block: - - name: Save private keys - copy: - dest: "{{ wireguard_pki_path }}/private/{{ item['item'] }}" - content: "{{ item['stdout'] }}" - mode: "0600" - no_log: "{{ no_log|bool }}" - when: item.changed - with_items: "{{ wg_genkey['results'] }}" - delegate_to: localhost - become: false + - name: Save private keys + copy: + dest: "{{ wireguard_pki_path }}/private/{{ item['item'] }}" + content: "{{ item['stdout'] }}" + mode: "0600" + no_log: "{{ no_log|bool }}" + when: item.changed + with_items: "{{ wg_genkey['results'] }}" + delegate_to: localhost + become: false - - name: Touch the lock file - file: - dest: "{{ config_prefix|default('/') }}etc/wireguard/private_{{ item }}.lock" - state: touch - with_items: - - "{{ users }}" - - "{{ IP_subject_alt_name }}" + - name: Touch the lock file + file: + dest: "{{ config_prefix|default('/') }}etc/wireguard/private_{{ item }}.lock" + state: touch + with_items: + - "{{ users }}" + - "{{ IP_subject_alt_name }}" when: wg_genkey.changed - name: Delete the preshared lock files @@ -57,24 +57,24 @@ - "{{ IP_subject_alt_name }}" - block: - - name: Save preshared keys - copy: - dest: "{{ wireguard_pki_path }}/preshared/{{ item['item'] }}" - content: "{{ item['stdout'] }}" - mode: "0600" - no_log: "{{ no_log|bool }}" - when: item.changed - with_items: "{{ wg_genpsk['results'] }}" - delegate_to: localhost - become: false + - name: Save preshared keys + copy: + dest: "{{ wireguard_pki_path }}/preshared/{{ item['item'] }}" + content: "{{ item['stdout'] }}" + mode: "0600" + no_log: "{{ no_log|bool }}" + when: item.changed + with_items: "{{ wg_genpsk['results'] }}" + delegate_to: localhost + become: false - - name: Touch the preshared lock file - file: - dest: "{{ config_prefix|default('/') }}etc/wireguard/preshared_{{ item }}.lock" - state: touch - with_items: - - "{{ users }}" - - "{{ IP_subject_alt_name }}" + - name: Touch the preshared lock file + file: + dest: "{{ config_prefix|default('/') }}etc/wireguard/preshared_{{ item }}.lock" + state: touch + with_items: + - "{{ users }}" + - "{{ IP_subject_alt_name }}" when: wg_genpsk.changed - name: Generate public keys diff --git a/roles/wireguard/tasks/main.yml b/roles/wireguard/tasks/main.yml index 7e1fbc1..4b65a0a 100644 --- a/roles/wireguard/tasks/main.yml +++ b/roles/wireguard/tasks/main.yml @@ -28,61 +28,61 @@ tags: update-users - block: - - block: - - name: WireGuard user list updated - lineinfile: - dest: "{{ wireguard_pki_path }}/index.txt" - create: true - mode: "0600" - insertafter: EOF - line: "{{ item }}" - register: lineinfile - with_items: "{{ users }}" + - block: + - name: WireGuard user list updated + lineinfile: + dest: "{{ wireguard_pki_path }}/index.txt" + create: true + mode: "0600" + insertafter: EOF + line: "{{ item }}" + register: lineinfile + with_items: "{{ users }}" - - set_fact: - wireguard_users: "{{ (lookup('file', wireguard_pki_path + 'index.txt')).split('\n') }}" + - set_fact: + wireguard_users: "{{ (lookup('file', wireguard_pki_path + 'index.txt')).split('\n') }}" - - name: WireGuard users config generated - template: - src: client.conf.j2 - dest: "{{ wireguard_config_path }}/{{ item.1 }}.conf" - mode: "0600" - with_indexed_items: "{{ wireguard_users }}" - when: item.1 in users - vars: - index: "{{ item.0 }}" + - name: WireGuard users config generated + template: + src: client.conf.j2 + dest: "{{ wireguard_config_path }}/{{ item.1 }}.conf" + mode: "0600" + with_indexed_items: "{{ wireguard_users }}" + when: item.1 in users + vars: + index: "{{ item.0 }}" - - include_tasks: mobileconfig.yml - loop: - - ios - - macos - loop_control: - loop_var: system + - include_tasks: mobileconfig.yml + loop: + - ios + - macos + loop_control: + loop_var: system - - name: Generate QR codes - shell: > - umask 077; - which segno && - segno --scale=5 --output={{ item.1 }}.png \ - "{{ lookup('template', 'client.conf.j2') }}" || true - changed_when: false - with_indexed_items: "{{ wireguard_users }}" - when: item.1 in users - vars: - index: "{{ item.0 }}" - ansible_python_interpreter: "{{ ansible_playbook_python }}" - args: - chdir: "{{ wireguard_config_path }}" - executable: bash - become: false - delegate_to: localhost + - name: Generate QR codes + shell: > + umask 077; + which segno && + segno --scale=5 --output={{ item.1 }}.png \ + "{{ lookup('template', 'client.conf.j2') }}" || true + changed_when: false + with_indexed_items: "{{ wireguard_users }}" + when: item.1 in users + vars: + index: "{{ item.0 }}" + ansible_python_interpreter: "{{ ansible_playbook_python }}" + args: + chdir: "{{ wireguard_config_path }}" + executable: bash + become: false + delegate_to: localhost - - name: WireGuard configured - template: - src: server.conf.j2 - dest: "{{ config_prefix|default('/') }}etc/wireguard/{{ wireguard_interface }}.conf" - mode: "0600" - notify: restart wireguard + - name: WireGuard configured + template: + src: server.conf.j2 + dest: "{{ config_prefix|default('/') }}etc/wireguard/{{ wireguard_interface }}.conf" + mode: "0600" + notify: restart wireguard tags: update-users - name: WireGuard enabled and started diff --git a/roles/wireguard/tasks/mobileconfig.yml b/roles/wireguard/tasks/mobileconfig.yml index 0e192b4..d12be4a 100644 --- a/roles/wireguard/tasks/mobileconfig.yml +++ b/roles/wireguard/tasks/mobileconfig.yml @@ -4,7 +4,7 @@ src: mobileconfig.j2 dest: "{{ wireguard_config_path }}/apple/{{ system }}/{{ item.1 }}.mobileconfig" mode: "0600" - with_indexed_items: "{{ wireguard_users }}" + with_indexed_items: "{{ wireguard_users }}" when: item.1 in users vars: index: "{{ item.0 }}" diff --git a/roles/wireguard/tasks/ubuntu.yml b/roles/wireguard/tasks/ubuntu.yml index 700cbd9..8682bb5 100644 --- a/roles/wireguard/tasks/ubuntu.yml +++ b/roles/wireguard/tasks/ubuntu.yml @@ -7,5 +7,5 @@ - name: Set OS specific facts set_fact: - service_name: "wg-quick@{{ wireguard_interface }}" + service_name: wg-quick@{{ wireguard_interface }} tags: always diff --git a/server.yml b/server.yml index 54551eb..18af459 100644 --- a/server.yml +++ b/server.yml @@ -7,117 +7,116 @@ - config.cfg tasks: - block: - - name: Wait until the cloud-init completed - wait_for: - path: /var/lib/cloud/data/result.json - delay: 10 - timeout: 600 - state: present - become: false - when: cloudinit + - name: Wait until the cloud-init completed + wait_for: + path: /var/lib/cloud/data/result.json + delay: 10 + timeout: 600 + state: present + become: false + when: cloudinit - - block: - - name: Ensure the config directory exists - file: - dest: "configs/{{ IP_subject_alt_name }}" - state: directory - mode: "0700" + - block: + - name: Ensure the config directory exists + file: + dest: configs/{{ IP_subject_alt_name }} + state: directory + mode: "0700" - - name: Dump the ssh config - copy: - dest: "configs/{{ IP_subject_alt_name }}/ssh_config" - mode: "0600" - content: | - Host {{ IP_subject_alt_name }} {{ algo_server_name }} - HostName {{ IP_subject_alt_name }} - User {{ ansible_ssh_user }} - Port {{ ansible_ssh_port }} - IdentityFile {{ SSH_keys.private | realpath }} - KeepAlive yes - ServerAliveInterval 30 - when: inventory_hostname != 'localhost' - become: false - delegate_to: localhost + - name: Dump the ssh config + copy: + dest: configs/{{ IP_subject_alt_name }}/ssh_config + mode: "0600" + content: | + Host {{ IP_subject_alt_name }} {{ algo_server_name }} + HostName {{ IP_subject_alt_name }} + User {{ ansible_ssh_user }} + Port {{ ansible_ssh_port }} + IdentityFile {{ SSH_keys.private | realpath }} + KeepAlive yes + ServerAliveInterval 30 + when: inventory_hostname != 'localhost' + become: false + delegate_to: localhost - - import_role: - name: common - tags: common + - import_role: + name: common + tags: common - - import_role: - name: dns - when: - - algo_dns_adblocking or - dns_encryption - tags: dns + - import_role: + name: dns + when: + - algo_dns_adblocking or dns_encryption + tags: dns - - import_role: - name: wireguard - when: wireguard_enabled - tags: wireguard + - import_role: + name: wireguard + when: wireguard_enabled + tags: wireguard - - import_role: - name: strongswan - when: ipsec_enabled - tags: ipsec + - import_role: + name: strongswan + when: ipsec_enabled + tags: ipsec - - import_role: - name: ssh_tunneling - when: algo_ssh_tunneling - tags: ssh_tunneling + - import_role: + name: ssh_tunneling + when: algo_ssh_tunneling + tags: ssh_tunneling - - block: - - name: Dump the configuration - copy: - dest: "configs/{{ IP_subject_alt_name }}/.config.yml" - content: | - server: {{ 'localhost' if inventory_hostname == 'localhost' else inventory_hostname }} - server_user: {{ ansible_ssh_user }} - ansible_ssh_port: "{{ ansible_ssh_port|default(22) }}" - {% if algo_provider != "local" %} - ansible_ssh_private_key_file: {{ SSH_keys.private }} - {% endif %} - algo_provider: {{ algo_provider }} - algo_server_name: {{ algo_server_name }} - algo_ondemand_cellular: {{ algo_ondemand_cellular }} - algo_ondemand_wifi: {{ algo_ondemand_wifi }} - algo_ondemand_wifi_exclude: {{ algo_ondemand_wifi_exclude }} - algo_dns_adblocking: {{ algo_dns_adblocking }} - algo_ssh_tunneling: {{ algo_ssh_tunneling }} - algo_store_pki: {{ algo_store_pki }} - IP_subject_alt_name: {{ IP_subject_alt_name }} - ipsec_enabled: {{ ipsec_enabled }} - wireguard_enabled: {{ wireguard_enabled }} - {% if tests|default(false)|bool %} - ca_password: '{{ CA_password }}' - p12_password: '{{ p12_export_password }}' - {% endif %} - become: false - delegate_to: localhost + - block: + - name: Dump the configuration + copy: + dest: configs/{{ IP_subject_alt_name }}/.config.yml + content: | + server: {{ 'localhost' if inventory_hostname == 'localhost' else inventory_hostname }} + server_user: {{ ansible_ssh_user }} + ansible_ssh_port: "{{ ansible_ssh_port|default(22) }}" + {% if algo_provider != "local" %} + ansible_ssh_private_key_file: {{ SSH_keys.private }} + {% endif %} + algo_provider: {{ algo_provider }} + algo_server_name: {{ algo_server_name }} + algo_ondemand_cellular: {{ algo_ondemand_cellular }} + algo_ondemand_wifi: {{ algo_ondemand_wifi }} + algo_ondemand_wifi_exclude: {{ algo_ondemand_wifi_exclude }} + algo_dns_adblocking: {{ algo_dns_adblocking }} + algo_ssh_tunneling: {{ algo_ssh_tunneling }} + algo_store_pki: {{ algo_store_pki }} + IP_subject_alt_name: {{ IP_subject_alt_name }} + ipsec_enabled: {{ ipsec_enabled }} + wireguard_enabled: {{ wireguard_enabled }} + {% if tests|default(false)|bool %} + ca_password: '{{ CA_password }}' + p12_password: '{{ p12_export_password }}' + {% endif %} + become: false + delegate_to: localhost - - name: Create a symlink if deploying to localhost - file: - src: "{{ IP_subject_alt_name }}" - dest: configs/localhost - state: link - force: true - when: inventory_hostname == 'localhost' + - name: Create a symlink if deploying to localhost + file: + src: "{{ IP_subject_alt_name }}" + dest: configs/localhost + state: link + force: true + when: inventory_hostname == 'localhost' - - name: Import tmpfs tasks - import_tasks: playbooks/tmpfs/umount.yml - become: false - delegate_to: localhost - vars: - facts: "{{ hostvars['localhost'] }}" - when: - - pki_in_tmpfs - - not algo_store_pki + - name: Import tmpfs tasks + import_tasks: playbooks/tmpfs/umount.yml + become: false + delegate_to: localhost + vars: + facts: "{{ hostvars['localhost'] }}" + when: + - pki_in_tmpfs + - not algo_store_pki - - debug: - msg: - - "{{ congrats.common.split('\n') }}" - - " {{ congrats.p12_pass if algo_ssh_tunneling or ipsec_enabled else '' }}" - - " {{ congrats.ca_key_pass if algo_store_pki and ipsec_enabled else '' }}" - - " {{ congrats.ssh_access if algo_provider != 'local' else ''}}" - tags: always + - debug: + msg: + - "{{ congrats.common.split('\n') }}" + - " {{ congrats.p12_pass if algo_ssh_tunneling or ipsec_enabled else '' }}" + - " {{ congrats.ca_key_pass if algo_store_pki and ipsec_enabled else '' }}" + - " {{ congrats.ssh_access if algo_provider != 'local' else ''}}" + tags: always rescue: - include_tasks: playbooks/rescue.yml diff --git a/users.yml b/users.yml index 479c28c..e9e8c08 100644 --- a/users.yml +++ b/users.yml @@ -1,6 +1,6 @@ --- - hosts: localhost - gather_facts: False + gather_facts: false tags: always vars_files: - config.cfg @@ -13,7 +13,7 @@ depth: 2 recurse: true hidden: true - patterns: ".config.yml" + patterns: .config.yml register: _configs_list - name: Verify servers @@ -50,23 +50,23 @@ - name: Import host specific variables include_vars: - file: "configs/{{ algo_server }}/.config.yml" + file: configs/{{ algo_server }}/.config.yml - when: ipsec_enabled block: - - name: CA password prompt - pause: - prompt: Enter the password for the private CA key - echo: false - register: _ca_password - when: ca_password is undefined - - - name: Set facts based on the input - set_fact: - CA_password: >- - {% if ca_password is defined %}{{ ca_password }} - {%- elif _ca_password.user_input %}{{ _ca_password.user_input }} - {%- else %}omit{% endif %} + - name: CA password prompt + pause: + prompt: Enter the password for the private CA key + echo: false + register: _ca_password + when: ca_password is undefined + + - name: Set facts based on the input + set_fact: + CA_password: >- + {% if ca_password is defined %}{{ ca_password }} + {%- elif _ca_password.user_input %}{{ _ca_password.user_input }} + {%- else %}omit{% endif %} - name: Local pre-tasks import_tasks: playbooks/cloud-pre.yml @@ -78,7 +78,7 @@ groups: vpn-host ansible_ssh_user: "{{ server_user|default('root') }}" ansible_connection: "{% if algo_server == 'localhost' %}local{% else %}ssh{% endif %}" - ansible_python_interpreter: "/usr/bin/python3" + ansible_python_interpreter: /usr/bin/python3 CA_password: "{{ CA_password|default(omit) }}" rescue: - include_tasks: playbooks/rescue.yml @@ -89,32 +89,32 @@ become: true vars_files: - config.cfg - - "configs/{{ inventory_hostname }}/.config.yml" + - configs/{{ inventory_hostname }}/.config.yml tasks: - block: - - import_role: - name: common - - - import_role: - name: wireguard - when: wireguard_enabled - - - import_role: - name: strongswan - when: ipsec_enabled - tags: ipsec - - - import_role: - name: ssh_tunneling - when: algo_ssh_tunneling - - - debug: - msg: - - "{{ congrats.common.split('\n') }}" - - " {{ congrats.p12_pass if algo_ssh_tunneling or ipsec_enabled else '' }}" - - " {{ congrats.ca_key_pass if algo_store_pki and ipsec_enabled else '' }}" - - " {{ congrats.ssh_access if algo_provider != 'local' else ''}}" - tags: always + - import_role: + name: common + + - import_role: + name: wireguard + when: wireguard_enabled + + - import_role: + name: strongswan + when: ipsec_enabled + tags: ipsec + + - import_role: + name: ssh_tunneling + when: algo_ssh_tunneling + + - debug: + msg: + - "{{ congrats.common.split('\n') }}" + - " {{ congrats.p12_pass if algo_ssh_tunneling or ipsec_enabled else '' }}" + - " {{ congrats.ca_key_pass if algo_store_pki and ipsec_enabled else '' }}" + - " {{ congrats.ssh_access if algo_provider != 'local' else ''}}" + tags: always rescue: - include_tasks: playbooks/rescue.yml