diff --git a/tasks/assertions.yml b/tasks/assertions.yml index e7f7b8c..58fe1fd 100644 --- a/tasks/assertions.yml +++ b/tasks/assertions.yml @@ -1,13 +1,13 @@ --- - name: Check OS is supported - assert: + ansible.builtin.assert: that: - "ansible_os_family in ['Debian', 'RedHat']" msg: "{{ ansible_os_family }} is not supported" - name: Check use of deprecated variables - assert: + ansible.builtin.assert: that: - "not lookup('vars', _openvpn__deprecated_var.name, default='')" fail_msg: >- @@ -22,4 +22,3 @@ replacement: openpvpn_compression - name: openvpn_cipher replacement: openvpn_ncp_ciphers - diff --git a/tasks/authentication/ldap.yml b/tasks/authentication/ldap.yml index 5fbb1eb..58fa242 100644 --- a/tasks/authentication/ldap.yml +++ b/tasks/authentication/ldap.yml @@ -1,7 +1,7 @@ --- - name: Setup LDAP - template: + ansible.builtin.template: src: authentication/auth-ldap.conf.j2 dest: /etc/openvpn/auth-ldap.conf mode: 0o644 diff --git a/tasks/authentication/pam.yml b/tasks/authentication/pam.yml index 44a1afe..cd2ba82 100644 --- a/tasks/authentication/pam.yml +++ b/tasks/authentication/pam.yml @@ -1,14 +1,14 @@ --- - name: Setup PAM - template: + ansible.builtin.template: src: authentication/openvpn.pam.j2 dest: /etc/pam.d/openvpn mode: 0o644 when: openvpn_use_pam | bool - name: Configure users - htpasswd: + community.general.htpasswd: path: "{{ openvpn_etcdir }}/users" name: "{{ _openvpn__pam_user.name }}" password: "{{ _openvpn__pam_user.password }}" diff --git a/tasks/authentication/simple.yml b/tasks/authentication/simple.yml index 654694f..926e1fd 100644 --- a/tasks/authentication/simple.yml +++ b/tasks/authentication/simple.yml @@ -1,7 +1,7 @@ --- - name: Setup simple authentication - template: + ansible.builtin.template: src: authentication/auth-client.sh.j2 dest: "{{ openvpn_etcdir }}/auth-client.sh" mode: 0o755 diff --git a/tasks/authentication/tls.yml b/tasks/authentication/tls.yml index 1439a58..dc298ad 100644 --- a/tasks/authentication/tls.yml +++ b/tasks/authentication/tls.yml @@ -1,7 +1,7 @@ --- - name: Generate tls-auth key - command: + ansible.builtin.command: openvpn --genkey --secret "{{ openvpn_etcdir }}/ovpns/{{ openvpn_tls_key }}" args: creates: "{{ openvpn_etcdir }}/ovpns/{{ openvpn_tls_key }}" diff --git a/tasks/core/clients.yml b/tasks/core/clients.yml index 6bbbb6a..79443a4 100644 --- a/tasks/core/clients.yml +++ b/tasks/core/clients.yml @@ -1,17 +1,17 @@ --- - name: Generate client configurations - template: + ansible.builtin.template: src: "{{ openvpn_client_conf_template }}" dest: "{{ openvpn_etcdir }}/ovpns/{{ _openvpn__client }}.ovpn" - mode: 0o644 + mode: "0600" loop: "{{ openvpn_clients }}" loop_control: loop_var: _openvpn__client register: openvpn_clients_changed - name: Pack clients - command: >- + ansible.builtin.command: >- zip -j {{ _openvpn__client }}.zip {{ openvpn_keydir }}/issued/{{ _openvpn__client }}.crt @@ -28,9 +28,9 @@ when: openvpn_clients_changed.results[index] is changed - name: Download client credentials - fetch: + ansible.builtin.fetch: src: "{{ openvpn_etcdir }}/ovpns/{{ _openvpn__client }}.zip" - dest: "{{ openvpn_download_dir }}" + dest: "{{ openvpn_download_dir }}/{{ openvpn_host }}/" flat: true validate_checksum: true loop: "{{ openvpn_clients }}" @@ -40,10 +40,23 @@ when: openvpn_download_clients | bool tags: openvpn-download +- name: Create client directory before extraction on localhost + ansible.builtin.file: + path: "{{ openvpn_download_dir }}{{ openvpn_host }}/{{ _openvpn__client }}" + state: directory + mode: "0700" + loop: "{{ openvpn_clients }}" + loop_control: + loop_var: _openvpn__client + delegate_to: localhost + become: false + tags: openvpn-download + when: openvpn_download_clients | bool + - name: Extract client credentials - unarchive: - src: "{{ openvpn_download_dir }}/{{ _openvpn__client }}.zip" - dest: "{{ openvpn_download_dir }}" + ansible.builtin.unarchive: + src: "{{ openvpn_download_dir }}{{ openvpn_host }}/{{ _openvpn__client }}.zip" + dest: "{{ openvpn_download_dir }}{{ openvpn_host }}/{{ _openvpn__client }}" loop: "{{ openvpn_clients }}" loop_control: loop_var: _openvpn__client @@ -55,22 +68,22 @@ tags: openvpn-download - name: Create ccd directory - file: + ansible.builtin.file: path: "{{ openvpn_ccd }}" state: directory - mode: 0o755 + mode: "0700" - name: Upload ccd configs - copy: + ansible.builtin.copy: content: "{{ _openvpn__ccd_config.content }}" dest: "{{ openvpn_ccd }}/{{ _openvpn__ccd_config.name }}" - mode: 0o644 + mode: "0o644" loop: "{{ openvpn_ccd_configs }}" loop_control: loop_var: _openvpn__ccd_config - name: Disable client-to-client at the IP layer - iptables: + ansible.builtin.iptables: chain: FORWARD in_interface: "{{ openvpn_dev }}+" out_interface: "{{ openvpn_dev }}+" diff --git a/tasks/core/configure.yml b/tasks/core/configure.yml index ccee69f..10b4ee5 100644 --- a/tasks/core/configure.yml +++ b/tasks/core/configure.yml @@ -1,19 +1,19 @@ --- - name: Ensure openvpn key dir has the right permission - file: + ansible.builtin.file: path: "{{ openvpn_keydir }}" state: directory mode: 0o700 owner: "{{ openvpn_user }}" - name: Check if crl.pem exists - stat: + ansible.builtin.stat: path: "{{ openvpn_keydir }}/crl.pem" register: crl_pem_file - name: Configure server - template: + ansible.builtin.template: src: server.conf.j2 dest: "{{ openvpn_etcdir }}/server.conf" mode: 0o644 @@ -23,7 +23,7 @@ # here to avoid repeating it twice in both places where the tls and # client-config tasks are located. - name: Create client configuration directory - file: + ansible.builtin.file: path: "{{ openvpn_etcdir }}/ovpns" state: directory mode: 0o755 diff --git a/tasks/core/install/Debian.yml b/tasks/core/install/Debian.yml index 80f5810..a68aecf 100644 --- a/tasks/core/install/Debian.yml +++ b/tasks/core/install/Debian.yml @@ -1,19 +1,19 @@ --- - name: Add OpenVPN repo GPG key - apt_key: + ansible.builtin.apt_key: id: E158C569 url: https://swupdate.openvpn.net/repos/repo-public.gpg when: openvpn_use_external_repo | bool - name: Add OpenVPN repo sources - apt_repository: + ansible.builtin.apt_repository: filename: openvpn repo: deb http://swupdate.openvpn.net/apt "{{ ansible_lsb.codename }}" main when: openvpn_use_external_repo | bool - name: Install requirements - apt: + ansible.builtin.apt: name: "{{ requirements }}" update_cache: true force: true @@ -25,7 +25,7 @@ - zip - name: Install PAM dependencies - apt: + ansible.builtin.apt: name: "{{ dependencies }}" force: true when: openvpn_use_pam_users | length > 0 @@ -35,12 +35,12 @@ - python-passlib - name: Install LDAP dependencies - apt: + ansible.builtin.apt: name: openvpn-auth-ldap force: true when: openvpn_use_ldap | bool - name: Install bridge dependencies - apt: + ansible.builtin.apt: name: bridge-utils when: openvpn_bridge | bool diff --git a/tasks/core/install/RedHat.yml b/tasks/core/install/RedHat.yml index c56f20d..21fe414 100644 --- a/tasks/core/install/RedHat.yml +++ b/tasks/core/install/RedHat.yml @@ -1,7 +1,7 @@ --- - name: Install requirements - yum: + ansible.builtin.yum: name: "{{ requirements }}" update_cache: true vars: @@ -11,16 +11,16 @@ - zip - name: Install PAM dependencies - yum: + ansible.builtin.yum: name: python-passlib when: openvpn_use_pam_users | length > 0 - name: Install LDAP dependencies - yum: + ansible.builtin.yum: name: openvpn-auth-ldap when: openvpn_use_ldap | bool - name: Install bridge dependencies - yum: + ansible.builtin.yum: name: bridge-utils when: openvpn_bridge| bool diff --git a/tasks/core/management.yml b/tasks/core/management.yml index 3f0396b..d4947ec 100644 --- a/tasks/core/management.yml +++ b/tasks/core/management.yml @@ -1,7 +1,7 @@ --- - name: Create management password file - copy: + ansible.builtin.copy: content: "{{ openvpn_management_pass }}" dest: "{{ openvpn_etcdir }}/mgmt.pw" owner: "{{ openvpn_user }}" @@ -16,7 +16,7 @@ }} - name: Add management directive to OpenVPN config - set_fact: + ansible.builtin.set_fact: openvpn_server_options: "{{ openvpn_server_options + _mgmt_option }}" vars: diff --git a/tasks/core/read-client-files.yml b/tasks/core/read-client-files.yml index 6f2cae9..c021268 100644 --- a/tasks/core/read-client-files.yml +++ b/tasks/core/read-client-files.yml @@ -1,12 +1,12 @@ --- - name: Read CA file - command: cat "{{ openvpn_keydir }}/ca.crt" + ansible.builtin.command: cat "{{ openvpn_keydir }}/ca.crt" no_log: true register: openvpn_read_ca_file_results changed_when: false - name: Read TLS-auth key - slurp: + ansible.builtin.slurp: src: "{{ openvpn_etcdir }}/ovpns/{{ openvpn_tls_key }}" no_log: true register: openvpn_read_tlsauth_file_results @@ -14,12 +14,10 @@ when: openvpn_tls_auth - name: Read client cert files - command: >- + ansible.builtin.command: >- sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' {{ openvpn_keydir }}/issued/{{ _openvpn__client }}.crt - args: - warn: false no_log: true changed_when: false register: openvpn_read_client_cert_files_results @@ -28,7 +26,7 @@ loop_var: _openvpn__client - name: Read client key files - command: cat {{ openvpn_keydir }}/private/{{ _openvpn__client }}.key + ansible.builtin.command: cat {{ openvpn_keydir }}/private/{{ _openvpn__client }}.key no_log: true changed_when: false register: openvpn_read_client_key_files_results @@ -37,7 +35,7 @@ loop_var: _openvpn__client - name: Set client cert and CA info as fact - set_fact: + ansible.builtin.set_fact: openvpn_ca_file_contents: "{{ openvpn_read_ca_file_results.stdout }}" openvpn_client_cert_output: @@ -46,7 +44,7 @@ "{{ openvpn_read_client_key_files_results.results }}" - name: Set tls auth file contents as fact - set_fact: + ansible.builtin.set_fact: openvpn_tls_auth_file_contents: >- {{ openvpn_read_tlsauth_file_results['content'] diff --git a/tasks/main.yml b/tasks/main.yml index f2a1f42..b98691d 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,5 +1,6 @@ --- -- import_tasks: openvpn.yml +- name: Import tasks openvpn.yml + ansible.builtin.import_tasks: openvpn.yml when: openvpn_enabled | bool tags: openvpn diff --git a/tasks/openvpn.yml b/tasks/openvpn.yml index 28a1965..d20096c 100644 --- a/tasks/openvpn.yml +++ b/tasks/openvpn.yml @@ -1,47 +1,64 @@ ---- +- name: Include Variable Definitions + ansible.builtin.include_tasks: variables.yml -- include_tasks: variables.yml +- name: Include Assertion Checks + ansible.builtin.include_tasks: assertions.yml -- include_tasks: assertions.yml +- name: Include OS Specific Installation Tasks + ansible.builtin.include_tasks: "core/install/{{ ansible_os_family }}.yml" -- include_tasks: "core/install/{{ ansible_os_family }}.yml" - -- include_tasks: core/management.yml +- name: Include Management Configuration Tasks + ansible.builtin.include_tasks: core/management.yml when: openvpn_management_enable | bool -- include_tasks: core/configure.yml +- name: Include OpenVPN Core Configuration Tasks + ansible.builtin.include_tasks: core/configure.yml -- include_tasks: system/forwarding.yml +- name: Include Network Forwarding Configuration Tasks + ansible.builtin.include_tasks: system/forwarding.yml -- include_tasks: system/firewall-deps.yml +- name: Include Firewall Dependency Configuration Tasks + ansible.builtin.include_tasks: system/firewall-deps.yml when: openvpn_open_firewall | bool or openvpn_route_traffic | bool or openvpn_client_to_client_via_ip | bool -- include_tasks: system/firewall-open.yml +- name: Open Firewall Ports for OpenVPN + ansible.builtin.include_tasks: system/firewall-open.yml when: openvpn_open_firewall | bool -- include_tasks: system/routing.yml +- name: Include Routing Configuration Tasks + ansible.builtin.include_tasks: system/routing.yml when: openvpn_route_traffic | bool -- include_tasks: core/read-client-files.yml +- name: Read Unified Client Profile Files + ansible.builtin.include_tasks: core/read-client-files.yml when: openvpn_unified_client_profiles -- include_tasks: authentication/ldap.yml +- name: Include LDAP Authentication Configuration + ansible.builtin.include_tasks: authentication/ldap.yml -- include_tasks: authentication/pam.yml +- name: Include PAM Authentication Configuration + ansible.builtin.include_tasks: authentication/pam.yml -- include_tasks: authentication/simple.yml +- name: Include Simple Authentication Configuration + ansible.builtin.include_tasks: authentication/simple.yml -- include_tasks: authentication/tls.yml +- name: Include TLS Authentication Configuration + ansible.builtin.include_tasks: authentication/tls.yml -- import_tasks: core/clients.yml +- name: Include Client-Specific Configuration Tasks + ansible.builtin.import_tasks: core/clients.yml -- include_tasks: scripts.yml +- name: Include Custom Scripting Tasks + ansible.builtin.include_tasks: scripts.yml -- include_tasks: "system/bridge/{{ ansible_os_family }}.yml" +- name: Include OS Specific Bridging Configuration Tasks (1) + ansible.builtin.include_tasks: "system/bridge/{{ ansible_os_family }}.yml" -- include_tasks: "system/bridge/{{ ansible_os_family }}.yml" +- name: Include OS Specific Bridging Configuration Tasks (2) + ansible.builtin.include_tasks: "system/bridge/{{ ansible_os_family }}.yml" -- include_tasks: service.yml +- name: Include Service Configuration and Management Tasks + ansible.builtin.include_tasks: service.yml diff --git a/tasks/scripts.yml b/tasks/scripts.yml index b5981cd..1ef86fe 100644 --- a/tasks/scripts.yml +++ b/tasks/scripts.yml @@ -1,23 +1,22 @@ --- - name: Create directories for the scripts to write into - file: + ansible.builtin.file: path: "{{ _openvpn__output_dir }}" state: directory mode: '753' - # The openvpn user (the 'other') needs to write and execute the script dirs. loop: "{{ openvpn_script_output_directories }}" loop_control: loop_var: _openvpn__output_dir - name: Create scripts directory - file: + ansible.builtin.file: path: "{{ openvpn_scripts_dir }}" state: directory mode: 0o755 - name: Upload script files - template: + ansible.builtin.template: src: "{{ _openvpn__script }}" dest: "{{ openvpn_scripts_dir }}/{{ _openvpn__script | basename | replace('.j2', '') }}" owner: "{{ openvpn_user }}" @@ -28,7 +27,7 @@ loop_var: _openvpn__script - name: Upload inline scripts - copy: + ansible.builtin.copy: content: "{{ _openvpn__script.content }}" dest: "{{ openvpn_scripts_dir }}/{{ _openvpn__script.name }}" owner: "{{ openvpn_user }}" diff --git a/tasks/service.yml b/tasks/service.yml index a4507bb..cccceb1 100644 --- a/tasks/service.yml +++ b/tasks/service.yml @@ -1,7 +1,7 @@ --- - name: Ensure OpenVPN is started - service: + ansible.builtin.service: name: "{{ openvpn_service }}" state: started enabled: true diff --git a/tasks/system/bridge/Debian.yml b/tasks/system/bridge/Debian.yml index 0ae4cc9..36b6bc3 100644 --- a/tasks/system/bridge/Debian.yml +++ b/tasks/system/bridge/Debian.yml @@ -1,7 +1,7 @@ --- - name: Setup bridge - template: + ansible.builtin.template: src: bridge/bridge-interface.deb.j2 dest: "/etc/network/interfaces.d/{{ openvpn_dev }}" mode: 0o0644 @@ -11,7 +11,7 @@ notify: restart networking debian - name: Remove interface configuration for "{{ openvpn_dev }}" - file: + ansible.builtin.file: path: "/etc/network/interfaces.d/{{ openvpn_dev }}" state: absent when: openvpn_bridge is not defined or openvpn_bridge | length == 0 diff --git a/tasks/system/bridge/RedHat.yml b/tasks/system/bridge/RedHat.yml index 9ca4b65..aa6c008 100644 --- a/tasks/system/bridge/RedHat.yml +++ b/tasks/system/bridge/RedHat.yml @@ -1,30 +1,31 @@ --- -- block: +- name: Configure network bridge for OpenVPN on RedHat + when: + - openvpn_bridge is defined + - openvpn_bridge | length > 0 + notify: restart networking redhat + block: - name: Setup up script - template: + ansible.builtin.template: src: bridge/up.sh.j2 dest: "{{ openvpn_scripts_dir }}/up.sh" mode: o+x - name: Setup down script - template: + ansible.builtin.template: src: bridge/down.sh.j2 dest: "{{ openvpn_scripts_dir }}/down.sh" mode: o+x - name: Setup bridge - template: + ansible.builtin.template: src: bridge/bridge-interface.rh.j2 dest: "/etc/sysconfig/network-scripts/ifcfg-br-{{ openvpn_dev }}" mode: 0o0644 - when: - - openvpn_bridge is defined - - openvpn_bridge | length > 0 - notify: restart networking redhat - name: Remove interface configuration for "{{ openvpn_dev }}" - file: + ansible.builtin.file: path: "/etc/sysconfig/network-scripts/ifcfg-br-{{ openvpn_dev }}" state: absent when: openvpn_bridge is not defined or openvpn_bridge | length == 0 diff --git a/tasks/system/firewall-deps.yml b/tasks/system/firewall-deps.yml index ebef53f..7e7c0ef 100644 --- a/tasks/system/firewall-deps.yml +++ b/tasks/system/firewall-deps.yml @@ -1,7 +1,7 @@ --- - name: Install firewall dependencies (Debian) - apt: + ansible.builtin.apt: name: "{{ packages }}" when: ansible_os_family == "Debian" vars: @@ -10,7 +10,7 @@ - iptables-persistent - name: Install more firewall deps - apt: + ansible.builtin.apt: name: module-init-tools when: ansible_distribution_release == 'jessie' diff --git a/tasks/system/firewall-open.yml b/tasks/system/firewall-open.yml index 5f5dadb..7410e8a 100644 --- a/tasks/system/firewall-open.yml +++ b/tasks/system/firewall-open.yml @@ -1,7 +1,7 @@ --- - name: Allow connections to the OpenVPN server - iptables: + ansible.builtin.iptables: chain: INPUT in_interface: "{{ openvpn_out_interface | default(omit, true) }}" ctstate: NEW diff --git a/tasks/system/forwarding.yml b/tasks/system/forwarding.yml index 5690068..afab868 100644 --- a/tasks/system/forwarding.yml +++ b/tasks/system/forwarding.yml @@ -1,10 +1,10 @@ --- - name: Set ip forwarding in the sysctl file and reload if necessary - sysctl: + ansible.posix.sysctl: name: net.ipv4.ip_forward value: '1' sysctl_set: true state: present reload: true - when: not lookup('env', 'IN_MOLECULE') | d(true, true) | bool + when: lookup('env', 'IN_MOLECULE') | default(false, true) | ternary(false, true) diff --git a/tasks/system/routing.yml b/tasks/system/routing.yml index 3e50ee6..d992e45 100644 --- a/tasks/system/routing.yml +++ b/tasks/system/routing.yml @@ -1,7 +1,7 @@ --- - name: Allow forwarding from tun/tap to interface - iptables: + ansible.builtin.iptables: chain: FORWARD in_interface: "{{ openvpn_dev }}+" out_interface: "{{ openvpn_out_interface | default(omit, true) }}" @@ -11,7 +11,7 @@ when: _openvpn_iptables_rules.stdout.find("forward_tun_tap") == -1 - name: Allow forwarding from interface to tun/tap - iptables: + ansible.builtin.iptables: chain: FORWARD in_interface: "{{ openvpn_out_interface | default(omit, true) }}" out_interface: "{{ openvpn_dev }}+" @@ -21,7 +21,7 @@ when: _openvpn_iptables_rules.stdout.find("forward_reverse") == -1 - name: Allow NATing outgoing vpn traffic - iptables: + ansible.builtin.iptables: table: nat chain: POSTROUTING source: >- diff --git a/tasks/variables.yml b/tasks/variables.yml index b08e713..ad6dc5e 100644 --- a/tasks/variables.yml +++ b/tasks/variables.yml @@ -1,7 +1,7 @@ --- - name: Include OS-specific variables. - include_vars: + ansible.builtin.include_vars: file: "{{ lookup('first_found', params) }}" vars: params: diff --git a/templates/client.conf.j2 b/templates/client.conf.j2 index 37fd9c4..f9ea447 100644 --- a/templates/client.conf.j2 +++ b/templates/client.conf.j2 @@ -43,11 +43,16 @@ persist-tun {{ openvpn_ca_file_contents }} -{{ openvpn_client_cert_output |default([{'item':client,'stdout':''}])|selectattr('item', 'match', client)|map(attribute='stdout')|list|first }} +{% for cert in openvpn_client_cert_output |default([]) if cert[cert.ansible_loop_var | default('no_loop_var')] == client %} +{{ cert.stdout }} +{% endfor %} -{{ openvpn_client_keys_output |default([{'item':client,'stdout':''}])|selectattr('item', 'match', client)|map(attribute='stdout')|list|first }} +{% for key in openvpn_client_keys_output |default([]) if key[key.ansible_loop_var | default('no_loop_var')] == client %} +{{ key.stdout }} +{% endfor %} + {% if openvpn_tls_auth %} key-direction 1