diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6e58466f..5cd5fee9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,7 @@ --- name: CI -on: # yamllint disable-line rule:truthy +on: # yamllint disable-line rule:truthy push: branches: - master @@ -9,14 +9,12 @@ on: # yamllint disable-line rule:truthy branches: - master - workflow_dispatch: - jobs: check-syntax: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest name: check-syntax container: - image: diodonfrost/ansible-fedora:35 + image: diodonfrost/ansible-fedora:40 env: container: docker volumes: @@ -33,21 +31,23 @@ jobs: - name: Check syntax of ansible playbook run: ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml --syntax-check - build-fedora: - runs-on: ubuntu-20.04 - name: fedora-${{ matrix.version }} + build-rhel-like: + runs-on: ubuntu-latest + name: rhel-like-${{ matrix.version }} needs: - check-syntax strategy: fail-fast: false matrix: version: - - "33" - - "34" - - "35" + - "centos:stream9" + - "fedora:38" + - "fedora:39" + - "almalinux:9" + - "rockylinux:9" container: - image: diodonfrost/ansible-fedora:${{ matrix.version }} + image: diodonfrost/ansible-${{ matrix.version }} env: container: docker volumes: @@ -71,25 +71,25 @@ jobs: continue-on-error: true run: | ls -lR /etc/openvpn - echo "cat /etc/openvpn/**/openvpn_udp_1194.conf" - cat /etc/openvpn/**/openvpn_udp_1194.conf - echo "cat /etc/openvpn/**/alpha-*.ovpn" - cat /etc/openvpn/**/alpha-*.ovpn + echo "cat openvpn_udp_1194.conf" + find /etc/openvpn/ -maxdepth 3 -name openvpn_udp_1194.conf -type f -exec cat {} \; + echo "cat alpha-*.ovpn" + find /etc/openvpn/ -maxdepth 3 -name "alpha-*.ovpn" -type f -exec cat {} \; - build-centos: - runs-on: ubuntu-20.04 - name: centos-${{ matrix.version }} + build-rhel-legacy: + runs-on: ubuntu-latest + name: rhel-legacy-${{ matrix.version }} needs: - check-syntax strategy: fail-fast: false matrix: version: - - "7" - - "8" + - "almalinux:8" + - "rockylinux:8" container: - image: diodonfrost/ansible-centos:${{ matrix.version }} + image: diodonfrost/ansible-${{ matrix.version }} env: container: docker volumes: @@ -99,6 +99,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v2 + - name: Update ansible + run: dnf install -y python39 && pip3.9 install -U ansible - name: Setup ansible.posix collection for firewalld run: ansible-galaxy collection install ansible.posix - name: Setup community.general collection for ufw @@ -118,19 +120,19 @@ jobs: echo "cat alpha-*.ovpn" find /etc/openvpn/ -maxdepth 3 -name "alpha-*.ovpn" -type f -exec cat {} \; - build-rocky: - runs-on: ubuntu-20.04 - name: rocky-${{ matrix.version }} + # diodonfrost's images are broken for fedora 40 (thinks it's rawhide) and fedora 41 doesn't exist, so I built my own + build-broken-fedora: + runs-on: ubuntu-latest + name: fedora-${{ matrix.version }} needs: - check-syntax strategy: fail-fast: false matrix: version: - - "8" - + - "fedora:40" container: - image: diodonfrost/ansible-rockylinux:${{ matrix.version }} + image: ghcr.io/kyl191/ansible-${{ matrix.version }} env: container: docker volumes: diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6f1734af..00000000 --- a/.travis.yml +++ /dev/null @@ -1,54 +0,0 @@ ---- -language: python -sudo: required - -services: - - docker - -env: - global: COMMAND=/usr/lib/systemd/systemd --system - INSTALL=default - matrix: - - DOCKER_TAG=centos:7 - OS=centos - - DOCKER_TAG=fedora:latest-systemd - OS=fedora - INSTALL=fedora-latest - - DOCKER_TAG=fedora:30 - OS=fedora - - DOCKER_TAG=fedora:29 - OS=fedora - - DOCKER_TAG=fedora:28 - OS=fedora - - DOCKER_TAG=travisci/ubuntu-systemd:18.04 - OS=ubuntu - COMMAND=/lib/systemd/systemd --system - -before_install: - - ./tests/install-${INSTALL} - -install: - - >- - sudo docker run --detach ${DOCKER_ARGS} -e "container=docker" -v /sys/fs/cgroup:/sys/fs/cgroup:ro - --cap-add NET_ADMIN --cap-add SYS_ADMIN --device /dev/net/tun --volume="${PWD}":/etc/ansible/roles/ansible-role-openvpn:ro - --name ${OS} ${DOCKER_TAG} ${COMMAND} - - ./tests/setup-${OS} - - sudo docker exec ${OS} ansible -m setup -c local -i 127.0.0.1, all - -script: - # Check syntax of ansible playbook - - sudo docker exec ${OS} ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml --syntax-check - # Run ansible playbook - - sudo docker exec ${OS} ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv - # Check idempotency - - sudo docker exec ${OS} ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv - -after_script: - - sudo docker exec ${OS} cat /var/log/openvpn.log - - sudo docker exec ${OS} ls /etc/openvpn - - sudo docker exec ${OS} cat /etc/openvpn/openvpn_udp_1194.conf - - sudo docker exec ${OS} cat /etc/openvpn/alpha-127.0.0.1.ovpn - - sudo docker stop ${OS} - -notifications: - webhooks: https://galaxy.ansible.com/api/v1/notifications/ diff --git a/README.md b/README.md index b0d2e01a..27d1cc96 100644 --- a/README.md +++ b/README.md @@ -136,13 +136,13 @@ These options change how OpenVPN itself works. | openvpn_client_config_dir | string | | ccd | Path of `client-config-dir` | | openvpn_client_configs | dict | | {} | Dict of settings custom client configs | -## Logrotate +## Logrotate/Syslog Set your own custom logrotate options -| Variable | Type | Choices | Default | Comment | -|--------------------------|--------|---------|-------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------| -| openvpn_log_dir | string | | /var/log | Set location of openvpn log files. This parameter is a part of `log-append` configuration value. | -| openvpn_log_file | string | | openvpn.log | Set log filename. This parameter is a part of `log-append` configuration value. | -| openvpn_logrotate_config | string | | rotate 4
weekly
missingok
notifempty
sharedscripts
copytruncate
delaycompress | Configure logrotate script. | +| Variable | Type | Choices | Default | Comment | +|--------------------------|--------|---------|-------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------| +| openvpn_log_dir | string | | /var/log | Set location of openvpn log files. This parameter is a part of `log-append` configuration value. | +| openvpn_log_file | string | | openvpn.log | Set log filename. This parameter is a part of `log-append` configuration value. If empty, syslog is used. | +| openvpn_logrotate_config | string | | rotate 4
weekly
missingok
notifempty
sharedscripts
copytruncate
delaycompress | Configure logrotate script. | ## Packaging This role pulls in a bunch of different packages. Override the names as necessary. diff --git a/defaults/main/ldap.yml b/defaults/main/ldap.yml index d5e380c8..649cc5a0 100644 --- a/defaults/main/ldap.yml +++ b/defaults/main/ldap.yml @@ -1,3 +1,4 @@ +--- ldap: url: ldap://host.example.com anonymous_bind: false diff --git a/defaults/main/logrotate.yml b/defaults/main/logrotate.yml index 1b351688..50712705 100644 --- a/defaults/main/logrotate.yml +++ b/defaults/main/logrotate.yml @@ -1,3 +1,4 @@ +--- # Logrotate configuration openvpn_log_dir: /var/log openvpn_log_file: openvpn.log diff --git a/defaults/main/openvpn.yml b/defaults/main/openvpn.yml index 673380bd..3a636923 100644 --- a/defaults/main/openvpn.yml +++ b/defaults/main/openvpn.yml @@ -1,10 +1,10 @@ +--- # Defaults for openvpn # Networking openvpn_client_register_dns: true openvpn_client_to_client: false openvpn_custom_dns: [] -openvpn_dns_servers: [] openvpn_dualstack: true openvpn_keepalive_ping: 5 openvpn_keepalive_timeout: 30 @@ -17,6 +17,7 @@ openvpn_server_netmask: 255.255.255.0 openvpn_server_network: 10.9.0.0 openvpn_set_dns: true openvpn_tun_mtu: +openvpn_lan_source_ip: "{{ ansible_default_ipv4.address }}" # Security openvpn_auth_alg: SHA256 @@ -44,7 +45,6 @@ openvpn_service_group: nogroup openvpn_service_user: nobody openvpn_status_version: 1 - # Client config - settings the server will push openvpn_client_config: false openvpn_client_config_dir: ccd @@ -65,4 +65,3 @@ openvpn_client_configs: {} # - push "route 192.168.1.0 255.255.255.0" # - iroute 192.168.2.0 255.255.255.0 # - iroute 192.168.4.0 255.255.255.0 - diff --git a/defaults/main/packaging.yml b/defaults/main/packaging.yml index 15ff676a..4115add9 100644 --- a/defaults/main/packaging.yml +++ b/defaults/main/packaging.yml @@ -1,3 +1,4 @@ +--- # Packaging defaults for kyl191.openvpn epel_package_name: epel-release iptables_persistent_package_name: iptables-persistent diff --git a/defaults/main/role.yml b/defaults/main/role.yml index fa18c103..69605bf1 100644 --- a/defaults/main/role.yml +++ b/defaults/main/role.yml @@ -1,3 +1,4 @@ +--- # Defaults for the role operation clients: [] @@ -18,6 +19,7 @@ iptables_service: iptables manage_firewall_rules: true openvpn_firewall: auto openvpn_masquerade_not_snat: false +openvpn_no_nat: false # Misc ci_build: false diff --git a/handlers/main.yml b/handlers/main.yml index 4bfa27d8..fb773d1c 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,36 +1,39 @@ --- -- name: restart openvpn - service: +- name: Restart openvpn + ansible.builtin.service: name: "{{ openvpn_service_name }}" state: restarted # Github Actions doesn't allow entrypoints, so PID 1 isn't an init system when: ansible_service_mgr != "tail" -- name: restart iptables - service: +- name: Restart iptables + ansible.builtin.service: name: iptables state: restarted -- name: restart firewalld - service: +- name: Restart firewalld + ansible.builtin.service: name: firewalld state: restarted -- name: restart ufw - service: +- name: Restart ufw + ansible.builtin.service: name: ufw state: restarted -- name: save iptables rules (Debian/Ubuntu and CentOS/RHEL/Fedora) - shell: "{{ iptables_save_command }}" # noqa command-instead-of-shell +- name: Save iptables rules (Debian/Ubuntu and CentOS/RHEL/Fedora) + ansible.builtin.shell: "{{ iptables_save_command }}" # noqa command-instead-of-shell could have shell redirection when: ansible_os_family == 'Debian' or ansible_os_family == 'RedHat' listen: "save iptables" + changed_when: true # always save iptables rules -- name: build and install policy - command: "{{ item }}" +- name: Build and install policy + ansible.builtin.command: "{{ item }}" args: chdir: /var/lib/selinux with_items: - "checkmodule -M -m -o {{ openvpn_selinux_module }}.mod {{ openvpn_selinux_module }}.te" - "semodule_package -o {{ openvpn_selinux_module }}.pp -m {{ openvpn_selinux_module }}.mod" - "semodule -i {{ openvpn_selinux_module }}.pp" + changed_when: true + when: ansible_selinux.status == 'enabled' diff --git a/meta/main.yml b/meta/main.yml index 6ad96782..923b5f50 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -6,22 +6,22 @@ galaxy_info: description: OpenVPN playbook for CentOS/Fedora/RHEL/RHEL clones & Ubuntu/Debian license: MIT - min_ansible_version: 2.9 + min_ansible_version: "2.9" platforms: - name: EL versions: - - 7 - - 8 + - "8" + - "9" - name: Fedora versions: - - 32 - - 33 - - 34 + - "38" + - "39" + - "40" - name: FreeBSD versions: - - 12 - - 13 + - "12" + - "13" - name: Ubuntu versions: - trusty diff --git a/tasks/cert_sync_detection.yml b/tasks/cert_sync_detection.yml index 6432463c..14a457fb 100644 --- a/tasks/cert_sync_detection.yml +++ b/tasks/cert_sync_detection.yml @@ -1,6 +1,6 @@ --- - name: "[cert sync] Get existing certs" - find: + ansible.builtin.find: paths: "{{ openvpn_key_dir }}" patterns: "*.csr" excludes: "server.csr" @@ -11,16 +11,16 @@ # 3. Keep only basename # 4. Remove extension - name: "[cert sync] Create list of existing client with existing certs" - set_fact: + ansible.builtin.set_fact: openvpn_existing_client: "{{ openvpn_existing_cert.files | map(attribute='path') | map('basename') | map('replace', '.csr', '') | sort }}" when: (openvpn_existing_cert.files | length) > 0 # Make difference between 2 list to have only cert to revoke - name: "[cert sync] Create list of cert to revoke" - set_fact: - openvpn_cert_sync_revoke: "{{ (openvpn_existing_client | default([])) | difference(clients | sort ) }}" + ansible.builtin.set_fact: + openvpn_cert_sync_revoke: "{{ (openvpn_existing_client | default([])) | difference(clients | sort) }}" - name: "[cert sync] Debug: Certs to revoke (skipped if none)" - debug: + ansible.builtin.debug: msg: "Will revoke additional certs: {{ openvpn_cert_sync_revoke | join(', ') }}" when: openvpn_cert_sync_revoke | length > 0 diff --git a/tasks/client_keys.yml b/tasks/client_keys.yml index bf464e63..1f47c462 100644 --- a/tasks/client_keys.yml +++ b/tasks/client_keys.yml @@ -1,20 +1,20 @@ --- - name: Create openvpn ovpn file directory - file: + ansible.builtin.file: path: "{{ openvpn_ovpn_dir }}" state: directory - mode: 0755 + mode: "0755" - name: Copy openssl client extensions - copy: + ansible.builtin.copy: src: openssl-client.ext dest: "{{ openvpn_key_dir }}" owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" - mode: 0400 + mode: "0400" - name: Generate client key - command: >- + ansible.builtin.command: >- openssl req -nodes -newkey rsa:{{ openvpn_rsa_bits }} -keyout {{ item }}.key -out {{ item }}.csr -days 3650 -subj /CN=OpenVPN-Client-{{ inventory_hostname[:24] }}-{{ item[:24] }}/ args: @@ -24,14 +24,14 @@ - "{{ clients }}" - name: Protect client keys - file: + ansible.builtin.file: path: "{{ openvpn_key_dir }}/{{ item }}.key" - mode: 0400 + mode: "0400" with_items: - "{{ clients }}" - name: Sign client key - command: openssl x509 -req -in {{ item }}.csr -out {{ item }}.crt -CA ca.crt -CAkey ca-key.pem -sha256 -days 3650 -extfile openssl-client.ext + ansible.builtin.command: openssl x509 -req -in {{ item }}.csr -out {{ item }}.crt -CA ca.crt -CAkey ca-key.pem -sha256 -days 3650 -extfile openssl-client.ext args: chdir: "{{ openvpn_key_dir }}" creates: "{{ item }}.crt" @@ -39,24 +39,24 @@ - "{{ clients }}" - name: Register server ca key - slurp: + ansible.builtin.slurp: src: "{{ openvpn_key_dir }}/ca.crt" register: ca_cert - name: Register tls-auth key - slurp: + ansible.builtin.slurp: src: "{{ openvpn_key_dir }}/ta.key" register: tls_auth - name: Register client certs - slurp: + ansible.builtin.slurp: src: "{{ openvpn_key_dir }}/{{ item }}.crt" with_items: - "{{ clients }}" register: client_certs - name: Register client keys - slurp: + ansible.builtin.slurp: src: "{{ openvpn_key_dir }}/{{ item }}.key" with_items: - "{{ clients }}" @@ -64,18 +64,18 @@ - name: Generate client config no_log: "{{ openvpn_client_config_no_log }}" - template: + ansible.builtin.template: src: client.ovpn.j2 dest: "{{ openvpn_ovpn_dir }}/{{ item.0.item }}-{{ inventory_hostname }}.ovpn" owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" - mode: 0400 + mode: "0400" with_together: - "{{ client_certs.results }}" - "{{ client_keys.results }}" - name: Fetch client config - fetch: + ansible.builtin.fetch: src: "{{ openvpn_ovpn_dir }}/{{ item }}-{{ inventory_hostname }}.ovpn" dest: "{{ openvpn_fetch_client_configs_dir }}/{{ item }}/{{ inventory_hostname }}{{ openvpn_fetch_client_configs_suffix }}.ovpn" flat: true diff --git a/tasks/compile_ldap_plugin.yml b/tasks/compile_ldap_plugin.yml index 251a19d4..0d7c4a06 100644 --- a/tasks/compile_ldap_plugin.yml +++ b/tasks/compile_ldap_plugin.yml @@ -1,23 +1,25 @@ --- - name: Gather specific variables - include_vars: "../vars/compile_ldap_plugin.yml" - + ansible.builtin.include_vars: "../vars/compile_ldap_plugin.yml" - name: Check package re2c already exists become: true - stat: + ansible.builtin.stat: path: "{{ re2c_bin_path }}" register: re2c_bin - name: Check package openvpn-auth-ldap already exists become: true - stat: + ansible.builtin.stat: path: "{{ openvpn_auth_ldap_bin_path }}" register: openvpn_auth_ldap_bin -- block: +- name: Compile openvpn-auth-ldap plugin + when: + - not openvpn_auth_ldap_bin.stat.exists or not re2c_bin.stat.exists + block: - name: Install gcc objc repo become: true - yum_repository: + ansible.builtin.yum_repository: name: csi-gcc description: gcc compiler suite, with Objective-C which is removed from official Red Hat EL8 releases. baseurl: "{{ gcc_objc_repo.base_url }}" @@ -27,15 +29,18 @@ - name: Install dev packages become: true - package: + ansible.builtin.package: name: "{{ compile_develop_packages }}" state: present - name: Install re2c + when: + - not re2c_bin.stat.exists + block: - name: Download and unpack re2c become: true - unarchive: + ansible.builtin.unarchive: src: "https://github.com/skvadrik/re2c/archive/{{ re2c_version }}.tar.gz" dest: "{{ compile_source_dir }}" creates: "{{ compile_source_dir }}/re2c-{{ re2c_version }}" @@ -43,7 +48,7 @@ - name: Compile re2c become: true - shell: | + ansible.builtin.shell: | autoreconf -i -W all ./configure make @@ -51,14 +56,14 @@ args: chdir: "{{ compile_source_dir }}/re2c-{{ re2c_version }}" creates: "{{ re2c_bin_path }}" + - name: Install openvpn-auth-ldap when: - - not re2c_bin.stat.exists + - not openvpn_auth_ldap_bin.stat.exists - - name: Install openvpn-auth-ldap block: - name: Download and unpack openvpn-auth-ldap become: true - unarchive: + ansible.builtin.unarchive: src: "https://github.com/threerings/openvpn-auth-ldap/archive/auth-ldap-{{ openvpn_auth_ldap_version }}.tar.gz" dest: "{{ compile_source_dir }}" creates: "{{ compile_source_dir }}/openvpn-auth-ldap-auth-ldap-{{ openvpn_auth_ldap_version }}" @@ -66,18 +71,18 @@ - name: Create module directory become: true - file: + ansible.builtin.file: path: "{{ openvpn_auth_ldap_bin_path | dirname }}" owner: root group: root - mode: 0750 + mode: "0750" state: directory - name: Compile become: true environment: PATH: "{{ re2c_bin_path | dirname }}:{{ lookup('env', 'PATH') }}" - shell: | + ansible.builtin.shell: | autoconf autoheader ./configure --prefix={{ openvpn_auth_ldap_plugin_dir_path }} --with-openvpn=/sbin/openvpn CFLAGS="-fPIC" OBJCFLAGS="-std=gnu11" @@ -86,12 +91,9 @@ args: chdir: "{{ compile_source_dir }}/openvpn-auth-ldap-auth-ldap-{{ openvpn_auth_ldap_version }}" creates: "{{ openvpn_auth_ldap_bin_path }}" - when: - - not openvpn_auth_ldap_bin.stat.exists - - name: Cleanup dev packages become: true - package: + ansible.builtin.package: name: "{{ compile_develop_packages }}" state: absent when: @@ -99,10 +101,8 @@ - name: Remove gcc objc repo become: true - yum_repository: + ansible.builtin.yum_repository: name: csi-gcc state: absent when: - compile_cleanup_dev_packages - when: - - not openvpn_auth_ldap_bin.stat.exists or not re2c_bin.stat.exists diff --git a/tasks/config.yml b/tasks/config.yml index a0272018..fba0aeb8 100644 --- a/tasks/config.yml +++ b/tasks/config.yml @@ -1,57 +1,57 @@ --- - name: Create openvpn config file - template: + ansible.builtin.template: src: server.conf.j2 dest: "{{ openvpn_base_dir }}/{{ openvpn_config_file }}.conf" owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" mode: "0644" notify: - - restart openvpn + - Restart openvpn - name: Copy up script if defined - copy: + ansible.builtin.copy: src: "{{ openvpn_script_up }}" dest: "{{ openvpn_base_dir }}/up.sh" mode: a+x when: openvpn_script_up is defined - name: Copy down script if defined - copy: + ansible.builtin.copy: src: "{{ openvpn_script_down }}" dest: "{{ openvpn_base_dir }}/down.sh" mode: a+x when: openvpn_script_down is defined - name: Copy client-connect script if defined - copy: + ansible.builtin.copy: src: "{{ openvpn_script_client_connect }}" dest: "{{ openvpn_base_dir }}/client_connect.sh" mode: a+x when: openvpn_script_client_connect is defined - name: Copy client-disconnect script if defined - copy: + ansible.builtin.copy: src: "{{ openvpn_script_client_disconnect }}" dest: "{{ openvpn_base_dir }}/client_disconnect.sh" mode: a+x when: openvpn_script_client_disconnect is defined - name: Ensure auth folder exist in openvpn dir - file: + ansible.builtin.file: path: "{{ openvpn_base_dir }}/auth" state: directory - mode: 0755 + mode: "0755" when: openvpn_use_ldap - name: Delete auth folder in openvpn dir - file: + ansible.builtin.file: path: "{{ openvpn_base_dir }}/auth" state: absent when: not openvpn_use_ldap - name: Install LDAP config - template: + ansible.builtin.template: src: ldap.conf.j2 dest: "{{ openvpn_base_dir }}/auth/ldap.conf" owner: "{{ openvpn_conf_user }}" @@ -60,48 +60,48 @@ when: openvpn_use_ldap - name: Create log directory - file: + ansible.builtin.file: dest: "{{ openvpn_log_dir }}" owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" - mode: 0755 + mode: "0755" - name: Copy openvpn logrotate config file - template: + ansible.builtin.template: src: openvpn_logrotate.conf.j2 dest: /etc/logrotate.d/openvpn-{{ openvpn_config_file }}.conf owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" - mode: 0400 + mode: "0400" when: openvpn_use_logrotate - name: Create client config directory - file: + ansible.builtin.file: state: directory path: "{{ openvpn_base_dir }}/{{ openvpn_client_config_dir }}" owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" - mode: 0755 + mode: "0755" when: openvpn_client_config - name: Create client configs - template: + ansible.builtin.template: src: client_ccd.j2 dest: "{{ openvpn_base_dir }}/{{ openvpn_client_config_dir }}/{{ item.key }}" owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" - mode: 0644 + mode: "0644" when: openvpn_client_config with_dict: "{{ openvpn_client_configs }}" - name: List client config directory - shell: "ls -1 {{ openvpn_base_dir }}/{{ openvpn_client_config_dir }}" + ansible.builtin.command: "ls -1 {{ openvpn_base_dir }}/{{ openvpn_client_config_dir }}" register: __ccd_contents changed_when: false when: openvpn_client_config - name: Delete undeclared configs in client config directory - file: + ansible.builtin.file: path: "{{ openvpn_base_dir }}/{{ openvpn_client_config_dir }}/{{ item }}" state: absent when: @@ -110,13 +110,13 @@ with_items: "{{ __ccd_contents.stdout_lines | default([]) }}" - name: Delete client config directory - file: + ansible.builtin.file: path: "{{ openvpn_base_dir }}/{{ openvpn_client_config_dir }}" state: absent when: not openvpn_client_config - name: Setup openvpn auto-start & start - service: + ansible.builtin.service: name: "{{ openvpn_service_name }}" enabled: true state: started diff --git a/tasks/firewall.yml b/tasks/firewall.yml index 7a998ec7..b41a8f31 100644 --- a/tasks/firewall.yml +++ b/tasks/firewall.yml @@ -1,51 +1,51 @@ --- - name: Check for firewalld - command: which firewall-cmd + ansible.builtin.command: which firewall-cmd register: firewalld check_mode: false - changed_when: false # Never report as changed + changed_when: false # Never report as changed failed_when: false - name: Check for ufw - command: which ufw + ansible.builtin.command: which ufw register: ufw check_mode: false - changed_when: false # Never report as changed + changed_when: false # Never report as changed failed_when: false - name: Check for iptables - command: which iptables + ansible.builtin.command: which iptables register: iptables check_mode: false - changed_when: false # Never report as changed + changed_when: false # Never report as changed failed_when: false - name: Fail on both firewalld & ufw - fail: + ansible.builtin.fail: msg: "Both FirewallD and UFW are detected, firewall situation is unknown" when: openvpn_firewall == 'auto' and firewalld.rc == 0 and ufw.rc == 0 - name: Fail on no firewall detected - fail: + ansible.builtin.fail: msg: "No firewall detected, install one before proceeding (firewalld||ufw||iptables)" when: firewalld.rc != 0 and ufw.rc != 0 and iptables.rc != 0 - name: Add port rules (iptables) - include_tasks: iptables.yml + ansible.builtin.include_tasks: iptables.yml when: >- (openvpn_firewall == 'iptables') or (openvpn_firewall == 'auto' and firewalld.rc != 0 and ufw.rc != 0 and iptables.rc == 0) - name: Add port rules (firewalld) - include_tasks: firewalld.yml + ansible.builtin.include_tasks: firewalld.yml when: >- (openvpn_firewall == 'firewalld') or (openvpn_firewall == 'auto' and firewalld.rc == 0 and ufw.rc != 0) - name: Add port rules (ufw) - include_tasks: ufw.yml + ansible.builtin.include_tasks: ufw.yml when: >- (openvpn_firewall == 'ufw') or diff --git a/tasks/firewalld.yml b/tasks/firewalld.yml index e19a257f..ecd90cfe 100644 --- a/tasks/firewalld.yml +++ b/tasks/firewalld.yml @@ -1,13 +1,13 @@ --- - name: Enable firewalld - service: + ansible.builtin.service: name: firewalld enabled: true masked: false state: started - name: Install python2-firewall (Fedora) - package: + ansible.builtin.package: name: "{{ python_firewall_package_name }}" state: present when: @@ -47,17 +47,17 @@ # Workaround ansible issue: https://github.com/ansible/ansible/pull/21693 # immediate: true notify: - - restart firewalld + - Restart firewalld # workaround for --permanent not working on non-NetworkManager managed ifaces # https://bugzilla.redhat.com/show_bug.cgi?id=1112742 -- name: Check if ifcfg-{{ ansible_default_ipv4.interface }} exists - stat: +- name: Check if ifcfg file exists for {{ ansible_default_ipv4.interface }} + ansible.builtin.stat: path: "/etc/sysconfig/network-scripts/ifcfg-{{ ansible_default_ipv4.interface }}" register: ifcfg - name: Persist default interface in ifcfg file - lineinfile: + ansible.builtin.lineinfile: dest: /etc/sysconfig/network-scripts/ifcfg-{{ ansible_default_ipv4.interface }} regexp: "^ZONE=" line: "ZONE={{ firewalld_default_interface_zone }}" diff --git a/tasks/install.yml b/tasks/install.yml index 2665147d..ca3e13db 100644 --- a/tasks/install.yml +++ b/tasks/install.yml @@ -1,25 +1,25 @@ --- - name: Install EPEL for CentOS - package: + ansible.builtin.package: name: "{{ epel_package_name }}" state: present - when: ansible_distribution == "CentOS" or ansible_distribution=="Rocky" + when: ansible_distribution == "CentOS" or ansible_distribution=="Rocky" or ansible_distribution=="AlmaLinux" - name: Install EPEL for RHEL - yum: - name: https://dl.fedoraproject.org/pub/epel/epel-release-latest-{{ansible_distribution_major_version}}.noarch.rpm + ansible.builtin.dnf: + name: https://dl.fedoraproject.org/pub/epel/epel-release-latest-{{ ansible_distribution_major_version }}.noarch.rpm state: present - disable_gpg_check: yes + disable_gpg_check: true when: ansible_distribution=="RedHat" and ansible_distribution_major_version == "8" - name: Enable extra repos for RHEL 8 - rhsm_repository: + community.general.rhsm_repository: name: "codeready-builder-for-rhel-8-{{ ansible_architecture }}-rpms" state: enabled when: ansible_distribution=="RedHat" and ansible_distribution_major_version == "8" - name: Enable extra repos for RHEL 7 - rhsm_repository: + community.general.rhsm_repository: name: "{{ item }}" state: enabled with_items: @@ -29,7 +29,7 @@ when: ansible_distribution=="RedHat" and ansible_distribution_major_version == "7" - name: Install python2-dnf for Fedora dnf support - raw: dnf install -y python2-dnf + ansible.builtin.raw: dnf install -y python2-dnf when: - ansible_distribution == "Fedora" - ansible_python.version.major == 2 @@ -37,7 +37,7 @@ changed_when: '"Nothing to do." not in fedora_dnf.stdout' - name: Install openvpn - package: + ansible.builtin.package: name: "{{ item }}" state: present with_items: @@ -46,7 +46,7 @@ - name: Install LDAP plugin become: true - package: + ansible.builtin.package: name: "{{ openvpn_ldap_plugin_package_name }}" state: present when: @@ -54,7 +54,7 @@ - ansible_distribution == "CentOS" and ansible_distribution_major_version != "8" or ansible_distribution != "CentOS" - name: Compile LDAP plugin - include_tasks: compile_ldap_plugin.yml + ansible.builtin.include_tasks: compile_ldap_plugin.yml when: - openvpn_use_ldap - ansible_distribution == "CentOS" and ansible_distribution_major_version == "8" @@ -62,7 +62,7 @@ # RHEL has the group 'nobody', 'Debian/Ubuntu' have 'nogroup' # standardize on 'nogroup' - name: Ensure group 'nogroup' is present - group: + ansible.builtin.group: name: nogroup state: present system: true diff --git a/tasks/iptables.yml b/tasks/iptables.yml index 16c730e2..d17f709b 100644 --- a/tasks/iptables.yml +++ b/tasks/iptables.yml @@ -1,6 +1,6 @@ --- - name: Change facts to use netfilter-persistent on Debian >= 9 or Ubuntu >= 16 - set_fact: + ansible.builtin.set_fact: iptables_save_command: "/usr/sbin/netfilter-persistent save" iptables_service: netfilter-persistent when: >- @@ -9,21 +9,21 @@ (ansible_distribution == 'Ubuntu' and ansible_lsb.major_release|int >= 16) - name: Install iptables-persistent (Debian/Ubuntu) - package: + ansible.builtin.package: name: "{{ iptables_persistent_package_name }}" state: present register: __iptables_installed when: ansible_os_family == "Debian" - name: Install iptables-services (RedHat/CentOS) - package: + ansible.builtin.package: name: "{{ iptables_services_package_name }}" state: present register: __iptables_installed when: ansible_os_family == "RedHat" - name: Allow VPN forwarding - iptables - iptables: + ansible.builtin.iptables: chain: FORWARD source: "{{ openvpn_server_network }}/24" jump: ACCEPT @@ -32,7 +32,7 @@ notify: "save iptables" - name: Allow incoming SSH connections - iptables - iptables: + ansible.builtin.iptables: chain: INPUT protocol: tcp destination_port: "{{ ansible_port | default(22) }}" @@ -42,7 +42,7 @@ notify: "save iptables" - name: Allow incoming VPN connections - iptables - iptables: + ansible.builtin.iptables: chain: INPUT protocol: "{{ openvpn_proto }}" destination_port: "{{ openvpn_port }}" @@ -52,7 +52,7 @@ notify: "save iptables" - name: Accept packets from VPN tunnel adaptor - iptables - iptables: + ansible.builtin.iptables: chain: INPUT in_interface: tun0 jump: ACCEPT @@ -61,34 +61,38 @@ notify: "save iptables" - name: Perform NAT readdressing - iptables - iptables: + ansible.builtin.iptables: table: nat chain: POSTROUTING source: "{{ openvpn_server_network }}/24" + destination: "! {{ openvpn_server_network }}/24" to_source: "{{ ansible_default_ipv4.address }}" jump: SNAT action: insert comment: "Perform NAT readdressing" - when: not openvpn_masquerade_not_snat + when: not openvpn_masquerade_not_snat and not openvpn_no_nat notify: "save iptables" - name: Perform NAT readdressing with MASQUERADE - iptables - iptables: + ansible.builtin.iptables: table: nat chain: POSTROUTING source: "{{ openvpn_server_network }}/24" + destination: "! {{ openvpn_server_network }}/24" jump: MASQUERADE action: insert comment: "Perform NAT readdressing" - when: openvpn_masquerade_not_snat - notify: "save iptables" + when: openvpn_masquerade_not_snat and not openvpn_no_nat + notify: + - Save iptables - name: Save existing iptables rule before start iptables service - shell: "{{ iptables_save_command }}" # noqa command-instead-of-shell - when: __iptables_installed.changed | bool # noqa no-handler + ansible.builtin.shell: "{{ iptables_save_command }}" # noqa command-instead-of-shell + when: __iptables_installed.changed | bool # noqa no-handler + changed_when: true - name: Enable iptables - service: + ansible.builtin.service: name: "{{ iptables_service }}" enabled: true state: started diff --git a/tasks/main.yml b/tasks/main.yml index d1dd28d2..642adde2 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,6 +1,6 @@ --- - name: Include vars for OpenVPN installation - include_vars: "{{ item }}" + ansible.builtin.include_vars: "{{ item }}" with_first_found: - "../vars/{{ ansible_distribution }}{{ ansible_distribution_major_version }}.yml" - "../vars/{{ ansible_distribution }}.yml" @@ -8,26 +8,25 @@ - "../vars/empty.yml" - name: Set facts - import_tasks: set_facts.yml - + ansible.builtin.import_tasks: set_facts.yml - name: Uninstall OpenVPN - import_tasks: uninstall.yml + ansible.builtin.import_tasks: uninstall.yml when: openvpn_uninstall - name: Install OpenVPN - import_tasks: install.yml + ansible.builtin.import_tasks: install.yml tags: - install - name: Copy or Generate server keys - import_tasks: server_keys.yml + ansible.builtin.import_tasks: server_keys.yml # ignoreerrors is required for CentOS/RHEL 6 # http://serverfault.com/questions/477718/sysctl-p-etc-sysctl-conf-returns-error - name: Enable ipv4 forwarding ansible.posix.sysctl: name: net.ipv4.ip_forward - value: '1' + value: "1" ignoreerrors: true failed_when: false when: not ci_build @@ -35,12 +34,12 @@ - name: Enable ipv6 forwarding ansible.posix.sysctl: name: net.ipv6.conf.all.forwarding - value: '1' + value: "1" ignoreerrors: true when: openvpn_server_ipv6_network is defined and not ci_build - name: Detect firewall type - import_tasks: firewall.yml + ansible.builtin.import_tasks: firewall.yml when: - not ci_build - manage_firewall_rules @@ -48,26 +47,28 @@ - firewall - name: Configure SELinux - import_tasks: selinux.yml + ansible.builtin.import_tasks: selinux.yml when: - ansible_selinux.status == "enabled" - name: Compare existing certs against 'clients' variable - import_tasks: cert_sync_detection.yml + ansible.builtin.import_tasks: cert_sync_detection.yml when: openvpn_sync_certs tags: - sync_certs - name: Generate client configs - import_tasks: client_keys.yml + ansible.builtin.import_tasks: client_keys.yml when: clients is defined + tags: + - openvpn_generate_clients - name: Generate revocation list and clean up - import_tasks: revocation.yml + ansible.builtin.import_tasks: revocation.yml when: >- (openvpn_revoke_these_certs is defined) or (openvpn_sync_certs and cert_sync_certs_to_revoke.stdout_lines | length > 0) - name: Configure OpenVPN server - import_tasks: config.yml + ansible.builtin.import_tasks: config.yml diff --git a/tasks/revocation.yml b/tasks/revocation.yml index 61195562..658fd4be 100644 --- a/tasks/revocation.yml +++ b/tasks/revocation.yml @@ -1,36 +1,36 @@ --- - name: Remove client config - file: + ansible.builtin.file: path: "{{ openvpn_ovpn_dir }}/{{ item }}-{{ inventory_hostname }}.ovpn" state: absent force: true with_items: - - '{{ openvpn_revoke_these_certs }}' - - '{{ openvpn_cert_sync_revoke | default([]) }}' + - "{{ openvpn_revoke_these_certs }}" + - "{{ openvpn_cert_sync_revoke | default([]) }}" - name: Revoke certificates - command: sh revoke.sh {{ item }}.crt + ansible.builtin.command: sh revoke.sh {{ item }}.crt changed_when: true args: chdir: "{{ openvpn_key_dir }}" with_items: - - '{{ openvpn_revoke_these_certs }}' - - '{{ openvpn_cert_sync_revoke | default([]) }}' + - "{{ openvpn_revoke_these_certs }}" + - "{{ openvpn_cert_sync_revoke | default([]) }}" - name: Remove client key - file: + ansible.builtin.file: path: "{{ openvpn_key_dir }}/{{ item }}.key" state: absent force: true with_items: - - '{{ openvpn_revoke_these_certs }}' - - '{{ openvpn_cert_sync_revoke | default([]) }}' + - "{{ openvpn_revoke_these_certs }}" + - "{{ openvpn_cert_sync_revoke | default([]) }}" - name: Remove client csr - file: + ansible.builtin.file: path: "{{ openvpn_key_dir }}/{{ item }}.csr" state: absent force: true with_items: - - '{{ openvpn_revoke_these_certs }}' - - '{{ openvpn_cert_sync_revoke | default([]) }}' + - "{{ openvpn_revoke_these_certs }}" + - "{{ openvpn_cert_sync_revoke | default([]) }}" diff --git a/tasks/selinux.yml b/tasks/selinux.yml index 511ed806..94b7e0bf 100644 --- a/tasks/selinux.yml +++ b/tasks/selinux.yml @@ -1,15 +1,15 @@ --- - name: SELinux - check if module was loaded - command: semodule --list-modules + ansible.builtin.command: semodule --list-modules register: semodule_loaded - changed_when: 'openvpn_selinux_module not in semodule_loaded.stdout' + changed_when: "openvpn_selinux_module not in semodule_loaded.stdout" notify: - - build and install policy + - Build and install policy - name: SELinux - copy type enforcement file - template: + ansible.builtin.template: src: "selinux_module.te.j2" dest: /var/lib/selinux/{{ openvpn_selinux_module }}.te - mode: 0644 + mode: "0644" notify: - - build and install policy + - Build and install policy diff --git a/tasks/server_keys.yml b/tasks/server_keys.yml index 6e38c6ad..8b69ed38 100644 --- a/tasks/server_keys.yml +++ b/tasks/server_keys.yml @@ -1,37 +1,37 @@ --- - name: Create openvpn key directory - file: + ansible.builtin.file: path: "{{ openvpn_key_dir }}" state: directory - mode: 0755 + mode: "0755" - name: Copy openssl server/ca extensions - copy: + ansible.builtin.copy: src: "{{ item }}" dest: "{{ openvpn_key_dir }}" owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" - mode: 0400 + mode: "0400" with_items: - openssl-server.ext - openssl-ca.ext - name: Copy CA key - copy: + ansible.builtin.copy: content: "{{ openvpn_ca_key.key }}" dest: "{{ openvpn_key_dir }}/ca-key.pem" - mode: 0400 + mode: "0400" when: openvpn_ca_key is defined - name: Copy CA cert - copy: + ansible.builtin.copy: content: "{{ openvpn_ca_key.crt }}" dest: "{{ openvpn_key_dir }}/ca.crt" - mode: 0444 + mode: "0444" when: openvpn_ca_key is defined - name: Generate CA key - command: >- + ansible.builtin.command: >- openssl req -nodes -newkey rsa:{{ openvpn_rsa_bits }} -keyout ca-key.pem -out ca-csr.pem -days 3650 -subj /CN=OpenVPN-CA-{{ inventory_hostname[:53] }}/ args: @@ -40,20 +40,20 @@ when: openvpn_ca_key is not defined - name: Protect CA key - file: + ansible.builtin.file: path: "{{ openvpn_key_dir }}/ca-key.pem" - mode: 0400 + mode: "0400" when: openvpn_ca_key is not defined - name: Sign CA key - command: openssl x509 -req -in ca-csr.pem -out ca.crt -CAcreateserial -signkey ca-key.pem -sha256 -days 3650 -extfile openssl-ca.ext + ansible.builtin.command: openssl x509 -req -in ca-csr.pem -out ca.crt -CAcreateserial -signkey ca-key.pem -sha256 -days 3650 -extfile openssl-ca.ext args: chdir: "{{ openvpn_key_dir }}" creates: ca.crt when: openvpn_ca_key is not defined - name: Generate server key - command: >- + ansible.builtin.command: >- openssl req -nodes -newkey rsa:{{ openvpn_rsa_bits }} -keyout server.key -out server.csr -days 3650 -subj /CN=OpenVPN-Server-{{ inventory_hostname[:49] }}/ args: @@ -61,25 +61,28 @@ creates: server.key - name: Protect server key - file: + ansible.builtin.file: path: "{{ openvpn_key_dir }}/server.key" - mode: 0400 + mode: "0400" - name: Sign server key - command: openssl x509 -req -in server.csr -out server.crt -CA ca.crt -CAkey ca-key.pem -sha256 -days 3650 -CAcreateserial -extfile openssl-server.ext + ansible.builtin.command: > + openssl x509 -req -in server.csr -out server.crt + -CA ca.crt -CAkey ca-key.pem -sha256 -days 3650 + -CAcreateserial -extfile openssl-server.ext args: chdir: "{{ openvpn_key_dir }}" creates: server.crt - name: Copy tls-auth key - copy: + ansible.builtin.copy: content: "{{ openvpn_tls_auth_key }}" dest: "{{ openvpn_key_dir }}/ta.key" - mode: 0400 + mode: "0400" when: openvpn_tls_auth_key is defined - name: Generate tls-auth key - command: openvpn --genkey --secret ta.key + ansible.builtin.command: openvpn --genkey --secret ta.key args: chdir: "{{ openvpn_key_dir }}" creates: ta.key @@ -88,81 +91,81 @@ # not a security issue, params aren't secret, just not generated by an attacker # per http://security.stackexchange.com/questions/42415/openvpn-dhparam/42418#42418 - name: Copy pre-generated DH params - copy: + ansible.builtin.copy: src: dh.pem dest: "{{ openvpn_key_dir }}" owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" - mode: 0400 + mode: "0400" when: openvpn_use_pregenerated_dh_params|bool # Alternatively, if you're concerned about logjam attacks - name: Generate dh params - command: openssl dhparam -out {{ openvpn_key_dir }}/dh.pem {{ openvpn_rsa_bits }} + ansible.builtin.command: openssl dhparam -out {{ openvpn_key_dir }}/dh.pem {{ openvpn_rsa_bits }} args: chdir: "{{ openvpn_key_dir }}" creates: dh.pem when: not (openvpn_use_pregenerated_dh_params|bool) - name: Install ca.conf config file - template: + ansible.builtin.template: src: ca.conf.j2 dest: "{{ openvpn_key_dir }}/ca.conf" owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" - mode: 0744 + mode: "0744" - name: Create initial certificate revocation list squence number - shell: "echo 00 > crl_number" + ansible.builtin.shell: "echo 00 > crl_number" args: chdir: "{{ openvpn_key_dir }}" creates: crl_number - name: Generate tls-auth key - command: openvpn --genkey --secret ta.key + ansible.builtin.command: openvpn --genkey --secret ta.key args: chdir: "{{ openvpn_key_dir }}" creates: ta.key when: openvpn_tls_auth_key is not defined - name: Install revocation script - template: + ansible.builtin.template: src: revoke.sh.j2 dest: "{{ openvpn_key_dir }}/revoke.sh" owner: "{{ openvpn_script_user }}" group: "{{ openvpn_script_group }}" - mode: 0744 + mode: "0744" - name: Check if certificate revocation list database exists - stat: + ansible.builtin.stat: path: "{{ openvpn_key_dir }}/index.txt" register: file_result - name: Create certificate revocation list database if required - file: + ansible.builtin.file: path: "{{ openvpn_key_dir }}/index.txt" state: touch - mode: 0644 + mode: "0644" when: not file_result.stat.exists - name: Set up certificate revocation list - command: sh revoke.sh + ansible.builtin.command: sh revoke.sh args: chdir: "{{ openvpn_key_dir }}" creates: "{{ openvpn_key_dir }}/ca-crl.pem" - name: Install crl-cron script - template: + ansible.builtin.template: src: crl-cron.sh.j2 dest: "{{ openvpn_base_dir }}/crl-cron.sh" owner: "{{ openvpn_script_user }}" group: "{{ openvpn_script_group }}" - mode: 0744 + mode: "0744" # This should eventually be switched to use a systemd timer # eg /usr/local/lib/systemd/system/openvpn-crl.timer - name: Check for crontab - command: which crontab + ansible.builtin.command: which crontab register: crontab check_mode: false changed_when: false diff --git a/tasks/set_facts.yml b/tasks/set_facts.yml index 879cb3b7..c8cf6d79 100644 --- a/tasks/set_facts.yml +++ b/tasks/set_facts.yml @@ -1,18 +1,18 @@ --- - name: Check systemd existence as Docker Guest - stat: + ansible.builtin.stat: path: /bin/systemctl when: ansible_virtualization_role is defined and ansible_virtualization_type == "docker" and ansible_virtualization_role == "guest" register: docker_stat_result - name: Set systemd openvpn service name - set_fact: + ansible.builtin.set_fact: openvpn_service_name: "openvpn@{{ openvpn_config_file }}.service" when: ansible_service_mgr == "systemd" or (docker_stat_result.stat is defined and docker_stat_result.stat.exists) # Fedora and CentOS 8 separate OpenVPN into client and server - name: Set Fedora 27+ and CentOS 8 service name - set_fact: + ansible.builtin.set_fact: openvpn_service_name: "openvpn-server@{{ openvpn_config_file }}.service" when: >- (ansible_distribution == "Fedora" and ansible_distribution_version|int >= 27) @@ -24,7 +24,7 @@ ) - name: Set Fedora 27+ and CentOS 8 OpenVPN base path - set_fact: + ansible.builtin.set_fact: openvpn_base_dir: "/etc/openvpn/server" when: >- (ansible_distribution == "Fedora" and ansible_distribution_version|int >= 27) diff --git a/tasks/ufw.yml b/tasks/ufw.yml index cb18d47d..ee4d0a84 100644 --- a/tasks/ufw.yml +++ b/tasks/ufw.yml @@ -1,6 +1,6 @@ --- - name: Start ufw service - service: + ansible.builtin.service: name: ufw enabled: true state: started @@ -12,7 +12,7 @@ policy: allow - name: Enable forwarding - ufw - lineinfile: + ansible.builtin.lineinfile: dest: /etc/default/ufw regexp: "^DEFAULT_FORWARD_POLICY=" line: DEFAULT_FORWARD_POLICY="ACCEPT" @@ -31,7 +31,7 @@ rule: allow - name: Setup nat table rules - ufw - blockinfile: + ansible.builtin.blockinfile: dest: /etc/ufw/before.rules state: present insertbefore: \*filter @@ -39,14 +39,14 @@ # OpenVPN config *nat :POSTROUTING ACCEPT [0:0] - -A POSTROUTING -s {{ openvpn_server_network }}/24 -j SNAT --to-source {{ ansible_default_ipv4.address }} + -A POSTROUTING -s {{ openvpn_server_network }}/24 ! -d {{ openvpn_server_network }}/24 -j SNAT --to-source {{ openvpn_lan_source_ip }} COMMIT when: not openvpn_masquerade_not_snat notify: - - restart ufw + - Restart ufw - name: Setup nat table rules with MASQUERADE - ufw - blockinfile: + ansible.builtin.blockinfile: dest: /etc/ufw/before.rules state: present insertbefore: \*filter @@ -54,8 +54,8 @@ # OpenVPN config *nat :POSTROUTING ACCEPT [0:0] - -A POSTROUTING -s {{ openvpn_server_network }}/24 -j MASQUERADE + -A POSTROUTING -s {{ openvpn_server_network }}/24 ! -d {{ openvpn_server_network }}/24 -j MASQUERADE COMMIT when: openvpn_masquerade_not_snat notify: - - restart ufw + - Restart ufw diff --git a/tasks/uninstall.yml b/tasks/uninstall.yml index deb5747e..c45e330d 100644 --- a/tasks/uninstall.yml +++ b/tasks/uninstall.yml @@ -1,31 +1,31 @@ --- - name: Disable openvpn auto-start & start - service: + ansible.builtin.service: name: "{{ openvpn_service_name }}" enabled: false state: stopped - name: Wipe out config directory - file: + ansible.builtin.file: path: "{{ openvpn_base_dir }}" state: absent - name: Remove openvpn logrotate config file - file: + ansible.builtin.file: path: /etc/logrotate.d/openvpn.conf state: absent - name: Uninstall OpenVPN - package: + ansible.builtin.package: name: "{{ openvpn_package_name }}" state: absent - name: Uninstall LDAP plugin - package: + ansible.builtin.package: name: "{{ openvpn_ldap_plugin_package_name }}" state: absent when: openvpn_use_ldap - name: Terminate playbook - fail: + ansible.builtin.fail: msg: "OpenVPN uninstalled, playbook stopped" diff --git a/templates/server.conf.j2 b/templates/server.conf.j2 index 086a14a4..87f7b9b5 100644 --- a/templates/server.conf.j2 +++ b/templates/server.conf.j2 @@ -60,8 +60,8 @@ client-config-dir {{ openvpn_client_config_dir }} push "redirect-gateway def1 bypass-dhcp" {% endif %} {% if openvpn_set_dns %} -{% if openvpn_custom_dns %} -{% for srv in openvpn_dns_servers %} +{% if openvpn_custom_dns|length > 0 %} +{% for srv in openvpn_custom_dns %} push "dhcp-option DNS {{ srv }}" {% endfor %} {% else %} @@ -91,7 +91,12 @@ group {{ openvpn_service_group }} status status-{{ openvpn_config_file }}.log status-version {{ openvpn_status_version }} + +{% if openvpn_log_file is defined %} log-append {{ openvpn_log_dir }}/{{ openvpn_log_file }} +{% else %} +syslog openvpn +{% endif %} verb 3 {% if openvpn_verify_cn|bool %} @@ -111,7 +116,11 @@ management-client-user {{ openvpn_management_client_user }} {% if ansible_os_family == 'Debian' %} plugin /usr/lib/openvpn/openvpn-auth-ldap.so "{{ openvpn_base_dir }}/auth/ldap.conf" {% elif ansible_machine == "x86_64" %} +{% if ansible_distribution in ['RedHat','Rocky'] and (ansible_distribution_major_version | int >= 8) %} +plugin /usr/lib64/openvpn/plugins/openvpn-auth-ldap.so "{{ openvpn_base_dir }}/auth/ldap.conf" +{% else %} plugin /usr/lib64/openvpn/plugin/lib/openvpn-auth-ldap.so "{{ openvpn_base_dir }}/auth/ldap.conf" +{% endif %} {% else %} plugin /usr/lib/openvpn/plugin/lib/openvpn-auth-ldap.so "{{ openvpn_base_dir }}/auth/ldap.conf" {% endif %} diff --git a/tests/ansible-role-openvpn b/tests/ansible-role-openvpn new file mode 120000 index 00000000..a96aa0ea --- /dev/null +++ b/tests/ansible-role-openvpn @@ -0,0 +1 @@ +.. \ No newline at end of file diff --git a/tests/fedora-40.Dockerfile b/tests/fedora-40.Dockerfile new file mode 100644 index 00000000..5cde8a30 --- /dev/null +++ b/tests/fedora-40.Dockerfile @@ -0,0 +1,39 @@ +FROM fedora:40 +LABEL org.opencontainers.image.source=https://github.com/kyl191/ansible-role-openvpn +LABEL org.opencontainers.image.title="Fedora 40 with Ansible" +LABEL org.opencontainers.image.description="Fedora 40 with Ansible, duplicate of https://github.com/diodonfrost/docker-ansible/blob/master/fedora-ansible/Dockerfile.fedora-40, just rebuilt so it's not using the rawhide release" + +# Update Fedora +RUN dnf -y update && dnf clean all + +# Install systemd +RUN dnf -y install systemd && dnf clean all; \ +(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \ +rm -f /lib/systemd/system/multi-user.target.wants/*; \ +rm -f /etc/systemd/system/*.wants/*; \ +rm -f /lib/systemd/system/local-fs.target.wants/*; \ +rm -f /lib/systemd/system/sockets.target.wants/*udev*; \ +rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \ +rm -f /lib/systemd/system/basic.target.wants/*; \ +rm -f /lib/systemd/system/anaconda.target.wants/*; + +RUN dnf -y install \ + git \ + ansible \ + sudo \ + which \ + openssh-server openssh-clients \ + findutils \ + unzip \ + rsync \ + libxcrypt-compat \ + fuse-libs \ + && dnf clean all + +RUN sed -i -e 's/^\(Defaults\s*requiretty\)/#--- \1/' /etc/sudoers + +RUN echo -e '[local]\nlocalhost ansible_connection=local' > /etc/ansible/hosts + +VOLUME ["/sys/fs/cgroup"] + +CMD ["/usr/sbin/init"] diff --git a/tests/fedora-41.Dockerfile b/tests/fedora-41.Dockerfile new file mode 100644 index 00000000..0d6d2f37 --- /dev/null +++ b/tests/fedora-41.Dockerfile @@ -0,0 +1,39 @@ +FROM fedora:41 +LABEL org.opencontainers.image.source=https://github.com/kyl191/ansible-role-openvpn +LABEL org.opencontainers.image.title="Fedora 41 with Ansible" +LABEL org.opencontainers.image.description="Fedora 41 with Ansible, based off https://github.com/diodonfrost/docker-ansible/blob/master/fedora-ansible/Dockerfile.fedora-40" + +# Update Fedora +RUN dnf -y update && dnf clean all + +# Install systemd +RUN dnf -y install systemd && dnf clean all; \ +(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \ +rm -f /lib/systemd/system/multi-user.target.wants/*; \ +rm -f /etc/systemd/system/*.wants/*; \ +rm -f /lib/systemd/system/local-fs.target.wants/*; \ +rm -f /lib/systemd/system/sockets.target.wants/*udev*; \ +rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \ +rm -f /lib/systemd/system/basic.target.wants/*; \ +rm -f /lib/systemd/system/anaconda.target.wants/*; + +RUN dnf -y install \ + git \ + ansible \ + sudo \ + which \ + openssh-server openssh-clients \ + findutils \ + unzip \ + rsync \ + libxcrypt-compat \ + fuse-libs \ + && dnf clean all + +RUN sed -i -e 's/^\(Defaults\s*requiretty\)/#--- \1/' /etc/sudoers + +RUN echo -e '[local]\nlocalhost ansible_connection=local' > /etc/ansible/hosts + +VOLUME ["/sys/fs/cgroup"] + +CMD ["/usr/sbin/init"] diff --git a/tests/test.yml b/tests/test.yml index a13f3506..de436ade 100644 --- a/tests/test.yml +++ b/tests/test.yml @@ -1,5 +1,6 @@ --- -- hosts: 127.0.0.1 +- name: Run CI tests + hosts: 127.0.0.1 connection: local vars: ci_build: true