From 305b591f006d07981ab39410bfd8420d4bd9215a Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Sun, 22 Dec 2024 18:50:28 +0000 Subject: [PATCH 01/66] Move OS-specific variables into /vars/os subfolder --- tasks/main.yml | 6 +++--- vars/{ => os}/Debian.yml | 0 vars/{ => os}/FreeBSD.yml | 0 vars/{ => os}/RedHat.yml | 0 vars/{ => os}/Solaris.yml | 0 5 files changed, 3 insertions(+), 3 deletions(-) rename vars/{ => os}/Debian.yml (100%) rename vars/{ => os}/FreeBSD.yml (100%) rename vars/{ => os}/RedHat.yml (100%) rename vars/{ => os}/Solaris.yml (100%) diff --git a/tasks/main.yml b/tasks/main.yml index 642adde2..01e72cae 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -2,9 +2,9 @@ - name: Include vars for OpenVPN installation ansible.builtin.include_vars: "{{ item }}" with_first_found: - - "../vars/{{ ansible_distribution }}{{ ansible_distribution_major_version }}.yml" - - "../vars/{{ ansible_distribution }}.yml" - - "../vars/{{ ansible_os_family }}.yml" + - "../vars/os/{{ ansible_distribution }}{{ ansible_distribution_major_version }}.yml" + - "../vars/os/{{ ansible_distribution }}.yml" + - "../vars/os/{{ ansible_os_family }}.yml" - "../vars/empty.yml" - name: Set facts diff --git a/vars/Debian.yml b/vars/os/Debian.yml similarity index 100% rename from vars/Debian.yml rename to vars/os/Debian.yml diff --git a/vars/FreeBSD.yml b/vars/os/FreeBSD.yml similarity index 100% rename from vars/FreeBSD.yml rename to vars/os/FreeBSD.yml diff --git a/vars/RedHat.yml b/vars/os/RedHat.yml similarity index 100% rename from vars/RedHat.yml rename to vars/os/RedHat.yml diff --git a/vars/Solaris.yml b/vars/os/Solaris.yml similarity index 100% rename from vars/Solaris.yml rename to vars/os/Solaris.yml From c270f153416cc88c25ebd151a4527ac2ee7b5e66 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Sun, 22 Dec 2024 18:52:59 +0000 Subject: [PATCH 02/66] Remove centos6 workaround --- tasks/main.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index 01e72cae..3434b8c2 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -21,21 +21,16 @@ - name: Copy or Generate server keys 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" - ignoreerrors: true - failed_when: false when: not ci_build - name: Enable ipv6 forwarding ansible.posix.sysctl: name: net.ipv6.conf.all.forwarding value: "1" - ignoreerrors: true when: openvpn_server_ipv6_network is defined and not ci_build - name: Detect firewall type From cf3f15501e2b6e4708d1261fc411fffe51698d94 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Sun, 22 Dec 2024 18:54:39 +0000 Subject: [PATCH 03/66] Move firewall tasks to firewall subfolder --- tasks/{ => firewall}/firewall.yml | 0 tasks/{ => firewall}/firewalld.yml | 0 tasks/{ => firewall}/iptables.yml | 0 tasks/{ => firewall}/ufw.yml | 0 tasks/main.yml | 2 +- 5 files changed, 1 insertion(+), 1 deletion(-) rename tasks/{ => firewall}/firewall.yml (100%) rename tasks/{ => firewall}/firewalld.yml (100%) rename tasks/{ => firewall}/iptables.yml (100%) rename tasks/{ => firewall}/ufw.yml (100%) diff --git a/tasks/firewall.yml b/tasks/firewall/firewall.yml similarity index 100% rename from tasks/firewall.yml rename to tasks/firewall/firewall.yml diff --git a/tasks/firewalld.yml b/tasks/firewall/firewalld.yml similarity index 100% rename from tasks/firewalld.yml rename to tasks/firewall/firewalld.yml diff --git a/tasks/iptables.yml b/tasks/firewall/iptables.yml similarity index 100% rename from tasks/iptables.yml rename to tasks/firewall/iptables.yml diff --git a/tasks/ufw.yml b/tasks/firewall/ufw.yml similarity index 100% rename from tasks/ufw.yml rename to tasks/firewall/ufw.yml diff --git a/tasks/main.yml b/tasks/main.yml index 3434b8c2..485d4da1 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -34,7 +34,7 @@ when: openvpn_server_ipv6_network is defined and not ci_build - name: Detect firewall type - ansible.builtin.import_tasks: firewall.yml + ansible.builtin.import_tasks: firewall/firewall.yml when: - not ci_build - manage_firewall_rules From c8ae1f3d7a4c74f2cf101275498b8aa46ae8c1ee Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Sun, 22 Dec 2024 19:00:46 +0000 Subject: [PATCH 04/66] Drop workaround for Python2 on Fedora --- tasks/install.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tasks/install.yml b/tasks/install.yml index ca3e13db..510746fb 100644 --- a/tasks/install.yml +++ b/tasks/install.yml @@ -28,14 +28,6 @@ - "rhel-ha-for-rhel-*-server-rpms" when: ansible_distribution=="RedHat" and ansible_distribution_major_version == "7" -- name: Install python2-dnf for Fedora dnf support - ansible.builtin.raw: dnf install -y python2-dnf - when: - - ansible_distribution == "Fedora" - - ansible_python.version.major == 2 - register: fedora_dnf - changed_when: '"Nothing to do." not in fedora_dnf.stdout' - - name: Install openvpn ansible.builtin.package: name: "{{ item }}" From 0075c009602d52593458c6fed4b086b9a33b2cf5 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Sun, 22 Dec 2024 20:18:17 +0000 Subject: [PATCH 05/66] Do not compile LDAP plugin, use compiled packages --- defaults/main/role.yml | 1 + tasks/compile_ldap_plugin.yml | 108 ---------------------------------- tasks/install.yml | 13 ++-- vars/compile_ldap_plugin.yml | 30 ---------- 4 files changed, 6 insertions(+), 146 deletions(-) delete mode 100644 tasks/compile_ldap_plugin.yml delete mode 100644 vars/compile_ldap_plugin.yml diff --git a/defaults/main/role.yml b/defaults/main/role.yml index 69605bf1..d4e7e3ee 100644 --- a/defaults/main/role.yml +++ b/defaults/main/role.yml @@ -34,4 +34,5 @@ openvpn_service_name: openvpn openvpn_sync_certs: false openvpn_uninstall: false openvpn_use_ldap: false +openvpn_use_prebuilt_ldap_plugin: true openvpn_use_logrotate: true diff --git a/tasks/compile_ldap_plugin.yml b/tasks/compile_ldap_plugin.yml deleted file mode 100644 index 0d7c4a06..00000000 --- a/tasks/compile_ldap_plugin.yml +++ /dev/null @@ -1,108 +0,0 @@ ---- -- name: Gather specific variables - ansible.builtin.include_vars: "../vars/compile_ldap_plugin.yml" -- name: Check package re2c already exists - become: true - ansible.builtin.stat: - path: "{{ re2c_bin_path }}" - register: re2c_bin - -- name: Check package openvpn-auth-ldap already exists - become: true - ansible.builtin.stat: - path: "{{ openvpn_auth_ldap_bin_path }}" - register: openvpn_auth_ldap_bin - -- 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 - 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 }}" - gpgkey: "{{ gcc_objc_repo.key }}" - gpgcheck: true - enabled: true - - - name: Install dev packages - become: true - 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 - 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 }}" - remote_src: true - - - name: Compile re2c - become: true - ansible.builtin.shell: | - autoreconf -i -W all - ./configure - make - make install - args: - chdir: "{{ compile_source_dir }}/re2c-{{ re2c_version }}" - creates: "{{ re2c_bin_path }}" - - name: Install openvpn-auth-ldap - when: - - not openvpn_auth_ldap_bin.stat.exists - - block: - - name: Download and unpack openvpn-auth-ldap - become: true - 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 }}" - remote_src: true - - - name: Create module directory - become: true - ansible.builtin.file: - path: "{{ openvpn_auth_ldap_bin_path | dirname }}" - owner: root - group: root - mode: "0750" - state: directory - - - name: Compile - become: true - environment: - PATH: "{{ re2c_bin_path | dirname }}:{{ lookup('env', 'PATH') }}" - ansible.builtin.shell: | - autoconf - autoheader - ./configure --prefix={{ openvpn_auth_ldap_plugin_dir_path }} --with-openvpn=/sbin/openvpn CFLAGS="-fPIC" OBJCFLAGS="-std=gnu11" - make - make install - args: - chdir: "{{ compile_source_dir }}/openvpn-auth-ldap-auth-ldap-{{ openvpn_auth_ldap_version }}" - creates: "{{ openvpn_auth_ldap_bin_path }}" - - name: Cleanup dev packages - become: true - ansible.builtin.package: - name: "{{ compile_develop_packages }}" - state: absent - when: - - compile_cleanup_dev_packages - - - name: Remove gcc objc repo - become: true - ansible.builtin.yum_repository: - name: csi-gcc - state: absent - when: - - compile_cleanup_dev_packages diff --git a/tasks/install.yml b/tasks/install.yml index 510746fb..a79fccac 100644 --- a/tasks/install.yml +++ b/tasks/install.yml @@ -36,20 +36,17 @@ - "{{ openvpn_package_name }}" - "{{ openssl_package_name }}" +# Use the built version: +# Fedora/EPEL: https://packages.fedoraproject.org/pkgs/openvpn-auth-ldap/openvpn-auth-ldap/index.html +# Debian: https://packages.debian.org/search?keywords=openvpn-auth-ldap +# Ubuntu: https://launchpad.net/ubuntu/+source/openvpn-auth-ldap - name: Install LDAP plugin - become: true ansible.builtin.package: name: "{{ openvpn_ldap_plugin_package_name }}" state: present when: - openvpn_use_ldap - - ansible_distribution == "CentOS" and ansible_distribution_major_version != "8" or ansible_distribution != "CentOS" - -- name: Compile LDAP plugin - ansible.builtin.include_tasks: compile_ldap_plugin.yml - when: - - openvpn_use_ldap - - ansible_distribution == "CentOS" and ansible_distribution_major_version == "8" + - openvpn_use_prebuilt_ldap_plugin # RHEL has the group 'nobody', 'Debian/Ubuntu' have 'nogroup' # standardize on 'nogroup' diff --git a/vars/compile_ldap_plugin.yml b/vars/compile_ldap_plugin.yml deleted file mode 100644 index 4d6863e9..00000000 --- a/vars/compile_ldap_plugin.yml +++ /dev/null @@ -1,30 +0,0 @@ ---- -compile_develop_packages: - - autoconf - - automake - - glibc-devel - - libtool - - make - - pkgconf - - pkgconf-m4 - - pkgconf-pkg-config - - openldap-devel - - openvpn-devel - - openssl-devel - - gcc-objc - - gcc-objc++ - -re2c_version: 2.0.3 -re2c_bin_path: /usr/local/bin/re2c - -openvpn_auth_ldap_version: 2.0.4 -openvpn_auth_ldap_plugin_dir_path: "{{ (ansible_machine == 'x86_64') | ternary('/usr/lib64/openvpn/plugin', '/usr/lib/openvpn/plugin') }}" -openvpn_auth_ldap_bin_path: "{{ openvpn_auth_ldap_plugin_dir_path }}/lib/openvpn-auth-ldap.so" - -compile_source_dir: /usr/local/src - -compile_cleanup_dev_packages: true - -gcc_objc_repo: - base_url: https://dl.cloudsmith.io/public/csi/gcc/rpm/el/8/$basearch - key: https://dl.cloudsmith.io/public/csi/gcc/cfg/gpg/gpg.7E04A007BA668C3C.key From 4b35ef2a821bf9a756b1a53706bc43b36382eeb6 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Sun, 22 Dec 2024 20:19:39 +0000 Subject: [PATCH 06/66] Cleanup EPEL install steps --- tasks/install.yml | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/tasks/install.yml b/tasks/install.yml index a79fccac..d2aee38f 100644 --- a/tasks/install.yml +++ b/tasks/install.yml @@ -1,32 +1,25 @@ --- -- name: Install EPEL for CentOS +# Install the EPEL repo RPM on RedHat-like machines +# https://docs.fedoraproject.org/en-US/epel/getting-started/ +# Thankfully openvpn is available in the base EPEL repo and +# I don't appear to have to worry about CRB/powertools/other repos +# https://wiki.almalinux.org/repos/AlmaLinux.html#almalinux-repositories +# https://wiki.rockylinux.org/rocky/repo/#base-repositories +# Also ignoring the request to install epel-next on CentOS Stream +# because that's only requested for CentOS Stream 9 +- name: Install EPEL for CentOS & other RHEL clones ansible.builtin.package: name: "{{ epel_package_name }}" state: present - when: ansible_distribution == "CentOS" or ansible_distribution=="Rocky" or ansible_distribution=="AlmaLinux" + when: ansible_os_family == "RedHat" and ansible_distribution != "Fedora" and ansible_distribution !="RedHat" +# EPEL install is different for RHEL specifically: https://www.redhat.com/en/blog/install-epel-linux - name: Install EPEL for RHEL ansible.builtin.dnf: name: https://dl.fedoraproject.org/pub/epel/epel-release-latest-{{ ansible_distribution_major_version }}.noarch.rpm state: present disable_gpg_check: true - when: ansible_distribution=="RedHat" and ansible_distribution_major_version == "8" - -- name: Enable extra repos for RHEL 8 - 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 - community.general.rhsm_repository: - name: "{{ item }}" - state: enabled - with_items: - - "rhel-*-optional-rpms" - - "rhel-*-extras-rpms" - - "rhel-ha-for-rhel-*-server-rpms" - when: ansible_distribution=="RedHat" and ansible_distribution_major_version == "7" + when: ansible_distribution == "RedHat" - name: Install openvpn ansible.builtin.package: From 0f48e148e243153248f6d66bec074aec3386b9df Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Sun, 22 Dec 2024 20:51:13 +0000 Subject: [PATCH 07/66] Move systemd service setting into defaults since Ubuntu and Debian use the same server disambiguation now --- defaults/main/openvpn.yml | 1 + defaults/main/role.yml | 7 +++++-- tasks/set_facts.yml | 25 ------------------------- 3 files changed, 6 insertions(+), 27 deletions(-) diff --git a/defaults/main/openvpn.yml b/defaults/main/openvpn.yml index 3a636923..0056903d 100644 --- a/defaults/main/openvpn.yml +++ b/defaults/main/openvpn.yml @@ -44,6 +44,7 @@ openvpn_push: [] openvpn_service_group: nogroup openvpn_service_user: nobody openvpn_status_version: 1 +openvpn_service_name: "openvpn-server@{{ openvpn_config_file }}.service" # Client config - settings the server will push openvpn_client_config: false diff --git a/defaults/main/role.yml b/defaults/main/role.yml index d4e7e3ee..43301135 100644 --- a/defaults/main/role.yml +++ b/defaults/main/role.yml @@ -4,8 +4,11 @@ clients: [] # Directories -openvpn_base_dir: /etc/openvpn -openvpn_key_dir: /etc/openvpn/keys +# Fedora, CentOS 8+, Debian and Ubuntu separate OpenVPN into client and server +# /lib/systemd/system/openvpn-server@.service and /lib/systemd/system/openvpn-client@.service +# We only care about the server directory +openvpn_base_dir: "/etc/openvpn/server" +openvpn_key_dir: "{{ openvpn_base_dir }}/keys" openvpn_ovpn_dir: "{{ openvpn_base_dir }}" # Config fetch settings diff --git a/tasks/set_facts.yml b/tasks/set_facts.yml index c8cf6d79..c89314db 100644 --- a/tasks/set_facts.yml +++ b/tasks/set_facts.yml @@ -9,28 +9,3 @@ 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 - ansible.builtin.set_fact: - openvpn_service_name: "openvpn-server@{{ openvpn_config_file }}.service" - when: >- - (ansible_distribution == "Fedora" and ansible_distribution_version|int >= 27) - or - ( - ( (ansible_distribution == "CentOS") or (ansible_distribution == "Rocky") or (ansible_distribution == "RedHat") ) - and - (ansible_distribution_version | int) >= 8 - ) - -- name: Set Fedora 27+ and CentOS 8 OpenVPN base path - ansible.builtin.set_fact: - openvpn_base_dir: "/etc/openvpn/server" - when: >- - (ansible_distribution == "Fedora" and ansible_distribution_version|int >= 27) - or - ( - (ansible_distribution == "CentOS" or ansible_distribution == "Rocky" or ansible_distribution == "RedHat" ) - and - (ansible_distribution_version | int) >= 8 - ) From 6e7098cac4ecd0486e3170c6deaed7ffe13d9945 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Sun, 22 Dec 2024 20:53:33 +0000 Subject: [PATCH 08/66] Move openvpn config file var into defaults --- defaults/main/openvpn.yml | 1 + vars/main.yml | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) delete mode 100644 vars/main.yml diff --git a/defaults/main/openvpn.yml b/defaults/main/openvpn.yml index 0056903d..d0c86323 100644 --- a/defaults/main/openvpn.yml +++ b/defaults/main/openvpn.yml @@ -44,6 +44,7 @@ openvpn_push: [] openvpn_service_group: nogroup openvpn_service_user: nobody openvpn_status_version: 1 +openvpn_config_file: "openvpn_{{ openvpn_proto }}_{{ openvpn_port }}" openvpn_service_name: "openvpn-server@{{ openvpn_config_file }}.service" # Client config - settings the server will push diff --git a/vars/main.yml b/vars/main.yml deleted file mode 100644 index 664493da..00000000 --- a/vars/main.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -# vars file for openvpn -openvpn_config_file: "openvpn_{{ openvpn_proto }}_{{ openvpn_port }}" From 749ed5a5556042661355c8530c978f04be1449ba Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Sun, 22 Dec 2024 20:58:49 +0000 Subject: [PATCH 09/66] Replace openvpn_service_name witht he systemd variant --- defaults/main/role.yml | 1 - vars/os/FreeBSD.yml | 1 + vars/os/Solaris.yml | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/defaults/main/role.yml b/defaults/main/role.yml index 43301135..fe8f0419 100644 --- a/defaults/main/role.yml +++ b/defaults/main/role.yml @@ -33,7 +33,6 @@ openvpn_script_group: root openvpn_client_config_no_log: true openvpn_revoke_these_certs: [] openvpn_selinux_module: my-openvpn-server -openvpn_service_name: openvpn openvpn_sync_certs: false openvpn_uninstall: false openvpn_use_ldap: false diff --git a/vars/os/FreeBSD.yml b/vars/os/FreeBSD.yml index be9aa284..8f5d8707 100644 --- a/vars/os/FreeBSD.yml +++ b/vars/os/FreeBSD.yml @@ -7,3 +7,4 @@ openvpn_conf_user: root openvpn_conf_group: wheel openvpn_script_group: wheel openvpn_use_logrotate: false +openvpn_service_name: openvpn diff --git a/vars/os/Solaris.yml b/vars/os/Solaris.yml index 4f9395d3..ac441c53 100644 --- a/vars/os/Solaris.yml +++ b/vars/os/Solaris.yml @@ -4,3 +4,4 @@ openvpn_base_dir: /opt/local/etc/openvpn openvpn_key_dir: /opt/local/etc/openvpn/keys openvpn_use_ldap: false openvpn_use_logrotate: false +openvpn_service_name: openvpn From 28c60f07f45e75c7b2b05868cd41d3e01e98ff5c Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Sun, 22 Dec 2024 21:03:46 +0000 Subject: [PATCH 10/66] Delete unneeded set_facts tasks now that it defaults to systemd style units --- tasks/main.yml | 2 -- tasks/set_facts.yml | 11 ----------- 2 files changed, 13 deletions(-) delete mode 100644 tasks/set_facts.yml diff --git a/tasks/main.yml b/tasks/main.yml index 485d4da1..e0951910 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -7,8 +7,6 @@ - "../vars/os/{{ ansible_os_family }}.yml" - "../vars/empty.yml" -- name: Set facts - ansible.builtin.import_tasks: set_facts.yml - name: Uninstall OpenVPN ansible.builtin.import_tasks: uninstall.yml when: openvpn_uninstall diff --git a/tasks/set_facts.yml b/tasks/set_facts.yml deleted file mode 100644 index c89314db..00000000 --- a/tasks/set_facts.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -- name: Check systemd existence as Docker Guest - 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 - 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) From 0d545e30f5b5f83cbe7872bd9c043ee1c9ae81e8 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Sun, 22 Dec 2024 21:17:33 +0000 Subject: [PATCH 11/66] Move dependency declaration to requirements.yml --- .github/workflows/ci.yml | 43 +++++++++++----------------------------- meta/main.yml | 8 +++----- meta/requirements.yml | 5 +++++ 3 files changed, 20 insertions(+), 36 deletions(-) create mode 100644 meta/requirements.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5cd5fee9..8f21d90e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,23 +13,10 @@ jobs: check-syntax: runs-on: ubuntu-latest name: check-syntax - container: - image: diodonfrost/ansible-fedora:40 - env: - container: docker - volumes: - - /sys/fs/cgroup:/sys/fs/cgroup - - ${{ github.workspace }}:/etc/ansible/roles/ansible-role-openvpn - options: "--cap-add NET_ADMIN --cap-add SYS_ADMIN --device /dev/net/tun" steps: - - name: Checkout repository - uses: actions/checkout@v2 - - name: Setup ansible.posix collection for firewalld - run: ansible-galaxy collection install ansible.posix - - name: Setup community.general collection for ufw - run: ansible-galaxy collection install community.general - - name: Check syntax of ansible playbook - run: ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml --syntax-check + - uses: actions/checkout@v4 + - name: Run ansible-lint + uses: ansible/ansible-lint@main build-rhel-like: runs-on: ubuntu-latest @@ -56,11 +43,9 @@ jobs: options: "--cap-add NET_ADMIN --cap-add SYS_ADMIN --device /dev/net/tun" steps: - name: Checkout repository - uses: actions/checkout@v2 - - name: Setup ansible.posix collection for firewalld - run: ansible-galaxy collection install ansible.posix - - name: Setup community.general collection for ufw - run: ansible-galaxy collection install community.general + uses: actions/checkout@v4 + - name: Install required dependencies + run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/meta/requirements.yml - name: Make sure ansible connection is sane run: ansible -m setup -c local -i 127.0.0.1, all - name: Run ansible playbook @@ -98,13 +83,11 @@ jobs: options: "--cap-add NET_ADMIN --cap-add SYS_ADMIN --device /dev/net/tun" steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - 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 - run: ansible-galaxy collection install community.general + - name: Install required dependencies + run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/meta/requirements.yml - name: Make sure ansible connection is sane run: ansible -m setup -c local -i 127.0.0.1, all - name: Run ansible playbook @@ -141,11 +124,9 @@ jobs: options: "--cap-add NET_ADMIN --cap-add SYS_ADMIN --device /dev/net/tun" steps: - name: Checkout repository - uses: actions/checkout@v2 - - name: Setup ansible.posix collection for firewalld - run: ansible-galaxy collection install ansible.posix - - name: Setup community.general collection for ufw - run: ansible-galaxy collection install community.general + uses: actions/checkout@v4 + - name: Install required dependencies + run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/meta/requirements.yml - name: Make sure ansible connection is sane run: ansible -m setup -c local -i 127.0.0.1, all - name: Run ansible playbook diff --git a/meta/main.yml b/meta/main.yml index 923b5f50..76a8c626 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -6,7 +6,7 @@ galaxy_info: description: OpenVPN playbook for CentOS/Fedora/RHEL/RHEL clones & Ubuntu/Debian license: MIT - min_ansible_version: "2.9" + min_ansible_version: "2.13" platforms: - name: EL @@ -20,12 +20,10 @@ galaxy_info: - "40" - name: FreeBSD versions: - - "12" - - "13" + - "12.0" + - "13.0" - name: Ubuntu versions: - trusty galaxy_tags: - networking - -dependencies: [] diff --git a/meta/requirements.yml b/meta/requirements.yml new file mode 100644 index 00000000..0276a604 --- /dev/null +++ b/meta/requirements.yml @@ -0,0 +1,5 @@ +collections: + - ansible.posix + - community.general + +roles: [] From d3993ace4b062d5a87ab885cf84d78559b32089b Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Sun, 22 Dec 2024 21:42:50 +0000 Subject: [PATCH 12/66] Fix uncapitalized notify name --- tasks/firewall/iptables.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tasks/firewall/iptables.yml b/tasks/firewall/iptables.yml index d17f709b..5864d8f6 100644 --- a/tasks/firewall/iptables.yml +++ b/tasks/firewall/iptables.yml @@ -29,7 +29,7 @@ jump: ACCEPT action: insert comment: "Allow VPN forwarding" - notify: "save iptables" + notify: "Save iptables" - name: Allow incoming SSH connections - iptables ansible.builtin.iptables: @@ -39,7 +39,7 @@ jump: ACCEPT action: insert comment: "Allow incoming SSH connection" - notify: "save iptables" + notify: "Save iptables" - name: Allow incoming VPN connections - iptables ansible.builtin.iptables: @@ -49,7 +49,7 @@ jump: ACCEPT action: insert comment: "Allow incoming VPN connection" - notify: "save iptables" + notify: "Save iptables" - name: Accept packets from VPN tunnel adaptor - iptables ansible.builtin.iptables: @@ -58,7 +58,7 @@ jump: ACCEPT action: insert comment: "Accept packets from VPN tunnel adaptor" - notify: "save iptables" + notify: "Save iptables" - name: Perform NAT readdressing - iptables ansible.builtin.iptables: @@ -71,7 +71,7 @@ action: insert comment: "Perform NAT readdressing" when: not openvpn_masquerade_not_snat and not openvpn_no_nat - notify: "save iptables" + notify: "Save iptables" - name: Perform NAT readdressing with MASQUERADE - iptables ansible.builtin.iptables: From 3afaafc39d193a9f2ccf1194aaf319ffb2756f9b Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Sun, 22 Dec 2024 21:43:04 +0000 Subject: [PATCH 13/66] Drop python2 compat task --- tasks/firewall/firewalld.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tasks/firewall/firewalld.yml b/tasks/firewall/firewalld.yml index ecd90cfe..5b81357d 100644 --- a/tasks/firewall/firewalld.yml +++ b/tasks/firewall/firewalld.yml @@ -6,14 +6,6 @@ masked: false state: started -- name: Install python2-firewall (Fedora) - ansible.builtin.package: - name: "{{ python_firewall_package_name }}" - state: present - when: - - ansible_distribution == "Fedora" - - ansible_python.version.major == 2 - - name: Enable OpenVPN Port (firewalld) ansible.posix.firewalld: port: "{{ openvpn_port }}/{{ openvpn_proto }}" From 65310c5539ec6811ba6a221b5942bfedb6f6ed7c Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Sun, 22 Dec 2024 21:46:26 +0000 Subject: [PATCH 14/66] Move requirements.yml to the top level directory --- meta/requirements.yml => requirements.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename meta/requirements.yml => requirements.yml (100%) diff --git a/meta/requirements.yml b/requirements.yml similarity index 100% rename from meta/requirements.yml rename to requirements.yml From 54d16a7ad595744dd7dffc08d3cc95082a0203cb Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Sun, 22 Dec 2024 21:48:14 +0000 Subject: [PATCH 15/66] Update requirements path in CI --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f21d90e..eea8a113 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Install required dependencies - run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/meta/requirements.yml + run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/requirements.yml - name: Make sure ansible connection is sane run: ansible -m setup -c local -i 127.0.0.1, all - name: Run ansible playbook @@ -87,7 +87,7 @@ jobs: - name: Update ansible run: dnf install -y python39 && pip3.9 install -U ansible - name: Install required dependencies - run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/meta/requirements.yml + run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/requirements.yml - name: Make sure ansible connection is sane run: ansible -m setup -c local -i 127.0.0.1, all - name: Run ansible playbook @@ -126,7 +126,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Install required dependencies - run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/meta/requirements.yml + run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/requirements.yml - name: Make sure ansible connection is sane run: ansible -m setup -c local -i 127.0.0.1, all - name: Run ansible playbook From 69f8f5f558c719dbbd34bc6f2dce608e084f32bd Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 00:36:30 +0000 Subject: [PATCH 16/66] Switch CRL cronjob to systemd timer --- files/openvpn-crl-refresh.timer | 9 +++++ tasks/server_keys.yml | 45 ++++++++++++------------ templates/openvpn-crl-refresh.service.j2 | 12 +++++++ 3 files changed, 43 insertions(+), 23 deletions(-) create mode 100644 files/openvpn-crl-refresh.timer create mode 100644 templates/openvpn-crl-refresh.service.j2 diff --git a/files/openvpn-crl-refresh.timer b/files/openvpn-crl-refresh.timer new file mode 100644 index 00000000..722cbbde --- /dev/null +++ b/files/openvpn-crl-refresh.timer @@ -0,0 +1,9 @@ +[Unit] +Description=OpenVPN CRL refresh timer + +[Timer] +OnCalendar=daily +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/tasks/server_keys.yml b/tasks/server_keys.yml index 8b69ed38..64580c8d 100644 --- a/tasks/server_keys.yml +++ b/tasks/server_keys.yml @@ -162,26 +162,25 @@ group: "{{ openvpn_script_group }}" 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 - ansible.builtin.command: which crontab - register: crontab - check_mode: false - changed_when: false - failed_when: false - -- name: Install cronie - ansible.builtin.package: - name: cronie - state: present - when: ansible_os_family == "RedHat" and crontab.rc != 0 - -- name: Add cron to check every Saturday if the CRL needs to be renewed - ansible.builtin.cron: - name: "check if CRL will expire soon" - special_time: weekly - job: "sh {{ openvpn_base_dir }}/crl-cron.sh" - cron_file: /etc/cron.d/openvpn-crl - user: root - when: not ci_build +- name: Install crl-cron service + ansible.builtin.template: + src: openvpn-crl-refresh.service.j2 + dest: /etc/systemd/system/openvpn-crl-refresh.service + owner: "{{ openvpn_script_user }}" + group: "{{ openvpn_script_group }}" + mode: "0744" + +- name: Install crl-cron systemd timer + ansible.builtin.copy: + src: openvpn-crl-refresh.timer + dest: /etc/systemd/system/openvpn-crl-refresh.timer + owner: "{{ openvpn_script_user }}" + group: "{{ openvpn_script_group }}" + mode: "0744" + +- name: Activate systemd timer to check daily if the CRL needs to be renewed + ansible.builtin.systemd: + name: openvpn-crl-refresh.timer + enabled: true + state: started + daemon_reload: true diff --git a/templates/openvpn-crl-refresh.service.j2 b/templates/openvpn-crl-refresh.service.j2 new file mode 100644 index 00000000..b829dd53 --- /dev/null +++ b/templates/openvpn-crl-refresh.service.j2 @@ -0,0 +1,12 @@ +[Unit] +Description=Run the OpenVPN CRL check & refresh script + +[Service] +Type=oneshot +ExecStart={{ openvpn_base_dir }}/crl-cron.sh + +[Exec] +WorkingDirectory={{ openvpn_base_dir }} +User={{ openvpn_script_user }} +ProtectSystem=strict +ReadWritePaths={{ openvpn_base_dir }} From 71b9c5a3ea9b47e33ef730b603f30678e73c1d71 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 00:37:10 +0000 Subject: [PATCH 17/66] Force an apt refresh to workaround stale apt cache --- tasks/install.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tasks/install.yml b/tasks/install.yml index d2aee38f..77eeb625 100644 --- a/tasks/install.yml +++ b/tasks/install.yml @@ -21,6 +21,11 @@ disable_gpg_check: true when: ansible_distribution == "RedHat" +- name: Refresh apt cache + ansible.builtin.apt: + update_cache: yes + when: ansible_pkg_mgr == "apt" + - name: Install openvpn ansible.builtin.package: name: "{{ item }}" From daf5e076d553f3047ad7fa7e6b707d6698e555a0 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 01:52:02 +0000 Subject: [PATCH 18/66] Fix missed uppercase in handler --- handlers/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/handlers/main.yml b/handlers/main.yml index fb773d1c..44135027 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -24,7 +24,7 @@ - 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" + listen: "Save iptables" changed_when: true # always save iptables rules - name: Build and install policy From 64d1b27a11746f73224f7b15860c06a3c91009c2 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 01:59:00 +0000 Subject: [PATCH 19/66] Move the hardcoded DNS servers to a variable --- defaults/main/openvpn.yml | 2 +- templates/server.conf.j2 | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/defaults/main/openvpn.yml b/defaults/main/openvpn.yml index d0c86323..82ddc4ba 100644 --- a/defaults/main/openvpn.yml +++ b/defaults/main/openvpn.yml @@ -4,7 +4,7 @@ # Networking openvpn_client_register_dns: true openvpn_client_to_client: false -openvpn_custom_dns: [] +openvpn_custom_dns: ["1.0.0.1", "1.1.1.1", "8.8.8.8", "8.8.4.4"] openvpn_dualstack: true openvpn_keepalive_ping: 5 openvpn_keepalive_timeout: 30 diff --git a/templates/server.conf.j2 b/templates/server.conf.j2 index 87f7b9b5..e5798367 100644 --- a/templates/server.conf.j2 +++ b/templates/server.conf.j2 @@ -59,17 +59,10 @@ client-config-dir {{ openvpn_client_config_dir }} {% if openvpn_redirect_gateway|bool %} push "redirect-gateway def1 bypass-dhcp" {% endif %} -{% if openvpn_set_dns %} -{% if openvpn_custom_dns|length > 0 %} +{% if openvpn_set_dns and openvpn_custom_dns|length > 0%} {% for srv in openvpn_custom_dns %} push "dhcp-option DNS {{ srv }}" {% endfor %} -{% else %} -push "dhcp-option DNS 1.0.0.1" -push "dhcp-option DNS 1.1.1.1" -push "dhcp-option DNS 8.8.8.8" -push "dhcp-option DNS 8.8.4.4" -{% endif %} {% endif %} {% if openvpn_push is defined %} {% for opt in openvpn_push %} From c2c634394d5abd6e36e7cd7ec32fd696e2469a31 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 02:11:06 +0000 Subject: [PATCH 20/66] Clean up readme --- README.md | 82 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 27d1cc96..2a9b1205 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,50 @@ -OpenVPN -========= -Github Actions (PRs & mainline): ![Github CI](https://github.com/kyl191/ansible-role-openvpn/workflows/CI/badge.svg) +# OpenVPN -Travis CI (Actually launching openvpn): [![Build Status](https://travis-ci.org/kyl191/ansible-role-openvpn.svg?branch=master)](https://travis-ci.org/kyl191/ansible-role-openvpn) +Github Actions (PRs & mainline): ![Github CI](https://github.com/kyl191/ansible-role-openvpn/workflows/CI/badge.svg) This role installs OpenVPN, configures it as a server, sets up networking and firewalls (primarily firewalld, ufw and iptables are best effort), and can optionally create client certificates. OSes in CI build: -- Fedora 32+ -- CentOS 7 & 8 + +- Fedora 38+ +- CentOS 9 Note: I am providing code in the repository to you under an open source license. Because this is my personal repository, the license you receive to my code is from me and not my employer. -# Requirements -OpenVPN must be available as a package in yum/dnf/apt! For CentOS users, this role will run `yum install epel-release` to ensure openvpn is available. +## Requirements -Ubuntu precise has a [weird bug](https://bugs.launchpad.net/ubuntu/+source/iptables-persistent/+bug/1002078) that might make the iptables-persistent install fail. There is a [workaround](https://forum.linode.com/viewtopic.php?p=58233#p58233). +OpenVPN must be available as a package in yum/dnf/apt! For CentOS users, this role will run `dnf install epel-release` to ensure openvpn is available. -## Ansible 2.10 and higher -With the release of Ansible 2.10, modules have been moved into collections. With the exception of ansible.builtin modules, this means additonal collections must be installed in order to use modules such as seboolean (now ansible.posix.seboolean). This collections is now required: `ansible.posix` and this collection is required if using ufw: `community.general`. Installing the collections: +### Ansible 2.10 and higher -``` -ansible-galaxy collection install ansible.posix -ansible-galaxy collection install community.general +With the release of Ansible 2.10, modules have been moved into collections. Two collections are now required: + +- `ansible.posix` +- `community.general` + +Install the collections with: + +```bash +ansible-galaxy install -r /path/to/ansible-role-openvpn/requirements.yml ``` -# Support Notes/Expectations -I personally use this role to manage OpenVPN on CentOS 8. I try to keep the role on that platform fully functional with the default config. +## Support Notes/Expectations + +I personally use this role to manage OpenVPN on CentOS Stream 9. I try to keep the role on that platform fully functional with the default config. Please recognise that I am a single person, and I have a full time job and other commitments. Responses to any issues will be on a best effort basis on my part, including the possibility that I don't respond at all. Issues arising from use of the non-defaults (including any of the major community contributions) will be deprioritized. Major community contributions: -* Functionality to revoke certs -* All of the LDAP support -# Role Variables -## Role options +- Functionality to revoke certs +- All of the LDAP support + +## Role Variables + These options change how the role works. This is a catch-all group, specific groups are broken out below. + | Variable | Type | Choices | Default | Comment | |------------------------------|---------|-------------|-------------------|-------------------------------------------------------------------------------| | clients | list | | [] | List of clients to add to OpenVPN | @@ -52,8 +58,11 @@ These options change how the role works. This is a catch-all group, specific gro | openvpn_sync_certs | boolean | true, false | false | Revoke certificates not explicitly defined in 'clients' | | openvpn_uninstall | boolean | true, false | false | Set to true to uninstall the OpenVPN service | | openvpn_use_ldap | boolean | true, false | false | Active LDAP backend for authentication. Client certificate not needed anymore | + ### Config fetching + Change these options if you need to adjust how the configs are download to your local system + | Variable | Type | Choices | Default | Comment | |-------------------------------------|---------|-------------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------| | openvpn_fetch_client_configs | boolean | true, false | true | Download generated client configurations to the local system | @@ -61,7 +70,9 @@ Change these options if you need to adjust how the configs are download to your | openvpn_fetch_client_configs_suffix | string | | "" | If openvpn_fetch_client_configs is true, the suffix to append to the downloaded client config files before the trailing `.ovpn` extension | ### Firewall + Change these options if you need to force a particular firewall or change how the playbook interacts with the firewall. + | Variable | Type | Choices | Default | Comment | |----------------------------------|---------|--------------------------------|----------|-------------------------------------------------------------------------------------------------------------| | firewalld_default_interface_zone | string | | public | Firewalld zone where the "ansible_default_ipv4.interface" will be pushed into | @@ -69,9 +80,13 @@ Change these options if you need to force a particular firewall or change how th | manage_firewall_rules | boolean | true, false | true | Allow playbook to manage iptables | | openvpn_firewall | string | auto, firewalld, ufw, iptables | auto | The firewall software to configure network rules. "auto" will attempt to detect it by inspecting the system | | openvpn_masquerade_not_snat | boolean | true, false | false | Set to true if you want to set up MASQUERADE instead of the default SNAT in iptables. | + ## OpenVPN Config Options + These options change how OpenVPN itself works. + ### Networking + | Variable | Type | Choices | Default | Comment | |-----------------------------|--------------|-------------------|----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------| | openvpn_client_register_dns | boolean | true, false | true | Add `register-dns` option to client config (Windows only). | @@ -91,7 +106,9 @@ These options change how OpenVPN itself works. | openvpn_server_network | string | | 10.9.0.0 | Private network used by OpenVPN service | | openvpn_set_dns | boolean | true, false | true | Will push DNS to the client (Cloudflare and Google) | | openvpn_tun_mtu | int | | `unset` | Set `tun-mtu` value. Empty for default. | + ### Security + | Variable | Type | Choices | Default | Comment | |------------------------------------|---------|-------------|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| | openvpn_auth_alg | string | | SHA256 | Set `auth` authentication algoritm. | @@ -108,7 +125,9 @@ These options change how OpenVPN itself works. | openvpn_use_pregenerated_dh_params | boolean | true, false | false | DH params are generted with the install by default | | openvpn_verify_cn | boolean | true, false | false | Check that the CN of the certificate match the FQDN | | tls_auth_required | boolean | true, false | true | Ask the client to push the generated ta.key of the server during the connection | + ### Operations + | Variable | Type | Choices | Default | Comment | |------------------------------------|---------|-------------|--------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | openvpn_addl_client_options | list | | empty | List of user-defined client options that are not already present in the client template. (e.g. `- mssfix 1400`) | @@ -130,6 +149,7 @@ These options change how OpenVPN itself works. | openvpn_topology | string | | `unset` | the "topology" keyword will be set in the server config with the specified value. | ### OpenVPN custom client config (server pushed) + | Variable | Type | Choices | Default | Comment | |---------------------------|---------|---------|---------|------------------------------------------------------| | openvpn_client_config | Boolean | | false | Set to true if enable client configuration directory | @@ -137,15 +157,19 @@ These options change how OpenVPN itself works. | openvpn_client_configs | dict | | {} | Dict of settings custom client configs | ## 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. If empty, syslog is used. | -| openvpn_logrotate_config | string | | rotate 4
weekly
missingok
notifempty
sharedscripts
copytruncate
delaycompress | Configure logrotate script. | +| openvpn_logrotate_config | string | | rotate 4\\nweekly\\nmissingok\\nnotifempty\\nsharedscripts\\ncopytruncate\\ndelaycompress | Configure logrotate script. | ## Packaging + This role pulls in a bunch of different packages. Override the names as necessary. + | Variable | Type | Choices | Default | Comment | |----------------------------------|--------|---------|---------------------|-----------------------------------------------------------------------------| | epel_package_name | string | | epel-release | Name of the epel-release package to install from the package manager | @@ -157,6 +181,7 @@ This role pulls in a bunch of different packages. Override the names as necessar | python_firewall_package_name | string | | python-firewall | Name of the python-firewall package to install from the package manager | ## LDAP object + | Variable | Type | Choices | Default | Comment | |---------------------|--------|---------------------------|-----------------------------------------|----------------------------------------------------------------------------------------------| | ldap | dict | | | Dictionary that contain LDAP configuration | @@ -175,13 +200,16 @@ This role pulls in a bunch of different packages. Override the names as necessar | group_search_filter | string | | ((cn=developers)(cn=artists)) | Precise valid groups | | verify_client_cert | string | none , optional , require | client-cert-not-required | In OpenVPN 2.4+ `client-cert-not-required` is deprecated. Use `verify-client-cert` instead. | -# Dependencies +## Dependencies + Does not depend on any other roles -# Example Playbook -``` +## Example Playbook + +```yaml - hosts: vpn gather_facts: true + become: true roles: - role: kyl191.openvpn openvpn_port: 4300 @@ -191,10 +219,10 @@ Does not depend on any other roles - client2 ``` -> **Note:** As the role will need to know the remote used platform (32 or 64 bits), you must set `gather_facts` to `true` in your play. +## License -# License MIT -# Author Information +## Author Information + Written by Kyle Lexmond From 93a435df2ac66cd373ac966deec14e8f78771069 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 02:17:51 +0000 Subject: [PATCH 21/66] Go back to using
in readme, and suppress warnings using markdownlint.yml --- .markdownlint.yml | 2 ++ README.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 .markdownlint.yml diff --git a/.markdownlint.yml b/.markdownlint.yml new file mode 100644 index 00000000..ee0ceb79 --- /dev/null +++ b/.markdownlint.yml @@ -0,0 +1,2 @@ +MD013: false +MD033: false diff --git a/README.md b/README.md index 2a9b1205..56f3a253 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,7 @@ Set your own custom logrotate options |--------------------------|--------|---------|-------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------| | 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\\nweekly\\nmissingok\\nnotifempty\\nsharedscripts\\ncopytruncate\\ndelaycompress | Configure logrotate script. | +| openvpn_logrotate_config | string | | rotate 4
weekly
missingok
notifempty
sharedscripts
copytruncate
delaycompress | Configure logrotate script. | ## Packaging From 4f0176ff33739ef6c7d60b673b1dab7da60f8d95 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 02:53:46 +0000 Subject: [PATCH 22/66] Add Debian, Ubuntu and RHEL 9 to CI --- .github/workflows/ci.yml | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eea8a113..43baf68d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,6 +32,7 @@ jobs: - "fedora:39" - "almalinux:9" - "rockylinux:9" + - "ubi-minimal:9" container: image: diodonfrost/ansible-${{ matrix.version }} @@ -141,3 +142,44 @@ jobs: 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-debian-like: + runs-on: ubuntu-latest + name: rhel-like-${{ matrix.version }} + needs: + - check-syntax + strategy: + fail-fast: false + matrix: + version: + - "ubuntu:22.04" + - "debian:12" + - "debian:testing" + + container: + image: diodonfrost/ansible-${{ matrix.version }} + env: + container: docker + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup + - ${{ github.workspace }}:/etc/ansible/roles/ansible-role-openvpn + options: "--cap-add NET_ADMIN --cap-add SYS_ADMIN --device /dev/net/tun" + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install required dependencies + run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/requirements.yml + - name: Make sure ansible connection is sane + run: ansible -m setup -c local -i 127.0.0.1, all + - name: Run ansible playbook + run: ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv + - name: Check idempotency + run: ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv + - name: Container state debug output + continue-on-error: true + run: | + ls -lR /etc/openvpn + 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 {} \; From d9f1824229c70672b48d9c8adffa40e81c9fb39a Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 03:29:01 +0000 Subject: [PATCH 23/66] Add selinux policy to allow openvpn to use reserved ports --- templates/selinux_module.te.j2 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/templates/selinux_module.te.j2 b/templates/selinux_module.te.j2 index 6cf1f45e..e3b9328c 100644 --- a/templates/selinux_module.te.j2 +++ b/templates/selinux_module.te.j2 @@ -1,12 +1,15 @@ -module {{ openvpn_selinux_module }} 1.0; +module {{ openvpn_selinux_module }} 1.1; require { type openvpn_t; + type reserved_port_t; type unreserved_port_t; class udp_socket name_bind; class tcp_socket name_bind; } #============= openvpn_t ============== +allow openvpn_t reserved_port_t:udp_socket name_bind; +allow openvpn_t reserved_port_t:tcp_socket name_bind; allow openvpn_t unreserved_port_t:udp_socket name_bind; allow openvpn_t unreserved_port_t:tcp_socket name_bind; From cdaceb055e9b7383f6d73c1c364d672e8911c159 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 03:54:21 +0000 Subject: [PATCH 24/66] Update cipher to use the default openvpn ciphers (Fixes #196) --- README.md | 2 +- defaults/main/openvpn.yml | 2 +- templates/client.ovpn.j2 | 4 +++- templates/server.conf.j2 | 4 +++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 56f3a253..201b8c5b 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ These options change how OpenVPN itself works. |------------------------------------|---------|-------------|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| | openvpn_auth_alg | string | | SHA256 | Set `auth` authentication algoritm. | | openvpn_ca_key | dict | | `unset` | Contain "crt" and "key". If not set, CA cert and key will be automatically generated on the target system. | -| openvpn_cipher | string | | AES-256-CBC | Set `cipher` option for server and client. | +| openvpn_cipher | string | | `unset` | Set `data-cipher` option for server and client. | | openvpn_crl_path | string | | `unset` | Define a path to the CRL file for server revocation check. | | openvpn_duplicate_cn | boolean | true, false | false | Add `duplicate-cn` option to server config - this allows clients to connect multiple times with the one key. NOTE: client ip addresses won't be static anymore! | | openvpn_rsa_bits | int | | 2048 | Number of bits used to protect generated certificates | diff --git a/defaults/main/openvpn.yml b/defaults/main/openvpn.yml index 82ddc4ba..ecffa2db 100644 --- a/defaults/main/openvpn.yml +++ b/defaults/main/openvpn.yml @@ -21,7 +21,7 @@ openvpn_lan_source_ip: "{{ ansible_default_ipv4.address }}" # Security openvpn_auth_alg: SHA256 -openvpn_cipher: AES-256-CBC +openvpn_cipher: ~ openvpn_duplicate_cn: false openvpn_rsa_bits: 2048 openvpn_use_crl: false diff --git a/templates/client.ovpn.j2 b/templates/client.ovpn.j2 index efa9d337..222c3172 100644 --- a/templates/client.ovpn.j2 +++ b/templates/client.ovpn.j2 @@ -2,7 +2,9 @@ client tls-client auth {{ openvpn_auth_alg }} -cipher {{ openvpn_cipher }} +{% if openvpn_cipher %} +data-ciphers {{ openvpn_cipher }} +{% endif %} remote-cert-tls server {% if openvpn_use_modern_tls %} tls-version-min 1.2 diff --git a/templates/server.conf.j2 b/templates/server.conf.j2 index e5798367..9a773eb5 100644 --- a/templates/server.conf.j2 +++ b/templates/server.conf.j2 @@ -26,7 +26,9 @@ tls-auth {{ openvpn_key_dir }}/ta.key 0 {% endif %} tls-server auth {{ openvpn_auth_alg | default('SHA256') }} -cipher {{ openvpn_cipher }} +{% if openvpn_cipher %} +data-ciphers {{ openvpn_cipher }} +{% endif %} {% if openvpn_tun_mtu %} tun-mtu {{ openvpn_tun_mtu }} {% endif %} From 1adc4a84065a52d042d8d0e8c9a9befc73f9d481 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 03:56:44 +0000 Subject: [PATCH 25/66] Change openvpn_compression default to unset --- README.md | 2 +- defaults/main/openvpn.yml | 2 +- templates/client.ovpn.j2 | 2 +- templates/server.conf.j2 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 201b8c5b..33ea2877 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ These options change how OpenVPN itself works. |------------------------------------|---------|-------------|--------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | openvpn_addl_client_options | list | | empty | List of user-defined client options that are not already present in the client template. (e.g. `- mssfix 1400`) | | openvpn_addl_server_options | list | | empty | List of user-defined server options that are not already present in the server template. (e.g. `- ping-timer-rem`) | -| openvpn_compression | string | | lzo | Set `compress` compression option. Empty for no compression. | +| openvpn_compression | string | | `unset` | Set `compress` compression option. Empty for no compression. | | openvpn_config_file | string | | openvpn_{{ openvpn\_proto }}\_{{ openvpn_port }} | The config file name you want to use (set in vars/main.yml) | | openvpn_enable_management | boolean | true, false | false | | | openvpn_ifconfig_pool_persist_file | string | | ipp.txt | | diff --git a/defaults/main/openvpn.yml b/defaults/main/openvpn.yml index ecffa2db..921d7e91 100644 --- a/defaults/main/openvpn.yml +++ b/defaults/main/openvpn.yml @@ -35,7 +35,7 @@ openvpn_script_security: 1 # Operations openvpn_addl_client_options: [] openvpn_addl_server_options: [] -openvpn_compression: lzo +openvpn_compression: ~ openvpn_enable_management: false openvpn_ifconfig_pool_persist_file: ipp.txt openvpn_management_bind: /var/run/openvpn/management unix diff --git a/templates/client.ovpn.j2 b/templates/client.ovpn.j2 index 222c3172..31bd0743 100644 --- a/templates/client.ovpn.j2 +++ b/templates/client.ovpn.j2 @@ -17,7 +17,7 @@ dev tun resolv-retry {{ openvpn_resolv_retry }} nobind keepalive {{ openvpn_keepalive_ping }} {{ openvpn_keepalive_timeout }} -{% if openvpn_compression is not undefined and openvpn_compression != "" %} +{% if openvpn_compression %} compress {{ openvpn_compression }} {% endif %} persist-key diff --git a/templates/server.conf.j2 b/templates/server.conf.j2 index 9a773eb5..bc0d0bc5 100644 --- a/templates/server.conf.j2 +++ b/templates/server.conf.j2 @@ -72,7 +72,7 @@ push "{{ opt }}" {% endfor %} {% endif %} keepalive {{ openvpn_keepalive_ping }} {{ openvpn_keepalive_timeout }} -{% if openvpn_compression is not undefined and openvpn_compression != "" %} +{% if openvpn_compression %} compress {{ openvpn_compression }} {% endif %} persist-key From 193946bb005ddfcf3bdcba61bed443bbfe402206 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 03:58:03 +0000 Subject: [PATCH 26/66] Fix ansible-lint complaint about yes vs true --- tasks/install.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/install.yml b/tasks/install.yml index 77eeb625..f4e4e409 100644 --- a/tasks/install.yml +++ b/tasks/install.yml @@ -23,7 +23,7 @@ - name: Refresh apt cache ansible.builtin.apt: - update_cache: yes + update_cache: true when: ansible_pkg_mgr == "apt" - name: Install openvpn From 39426bbd305f14440528acad605bab636bfca62b Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 04:08:17 +0000 Subject: [PATCH 27/66] Disable activating the crl timer in ci_build --- tasks/server_keys.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/server_keys.yml b/tasks/server_keys.yml index 64580c8d..ea3d9166 100644 --- a/tasks/server_keys.yml +++ b/tasks/server_keys.yml @@ -184,3 +184,4 @@ enabled: true state: started daemon_reload: true + when: not ci_build From 08dc617a15a6ff82cc6cd7c2574ec40433c841cd Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 18:32:54 +0000 Subject: [PATCH 28/66] Set the default cipher for better backward compatibility --- defaults/main/openvpn.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaults/main/openvpn.yml b/defaults/main/openvpn.yml index 921d7e91..caf0b0cf 100644 --- a/defaults/main/openvpn.yml +++ b/defaults/main/openvpn.yml @@ -21,7 +21,7 @@ openvpn_lan_source_ip: "{{ ansible_default_ipv4.address }}" # Security openvpn_auth_alg: SHA256 -openvpn_cipher: ~ +openvpn_cipher: AES-256-GCM:AES-128-GCM:AES-256-CBC openvpn_duplicate_cn: false openvpn_rsa_bits: 2048 openvpn_use_crl: false From bc382c994cf8238b9da779387caa59bad2a65b2a Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 18:34:17 +0000 Subject: [PATCH 29/66] Remove a default value that's already covered in the default vars --- templates/server.conf.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/server.conf.j2 b/templates/server.conf.j2 index bc0d0bc5..dc3eb789 100644 --- a/templates/server.conf.j2 +++ b/templates/server.conf.j2 @@ -25,7 +25,7 @@ crl-verify {{ openvpn_key_dir }}/ca-crl.pem tls-auth {{ openvpn_key_dir }}/ta.key 0 {% endif %} tls-server -auth {{ openvpn_auth_alg | default('SHA256') }} +auth {{ openvpn_auth_alg }} {% if openvpn_cipher %} data-ciphers {{ openvpn_cipher }} {% endif %} From 4d6d59d47070f0c79f9f7fd0f34c09fd209b1f7c Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 19:21:38 +0000 Subject: [PATCH 30/66] Use minimum ansible version instead of minimum ansible-core version --- meta/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/main.yml b/meta/main.yml index 76a8c626..19ddb583 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -6,7 +6,7 @@ galaxy_info: description: OpenVPN playbook for CentOS/Fedora/RHEL/RHEL clones & Ubuntu/Debian license: MIT - min_ansible_version: "2.13" + min_ansible_version: "6.0" platforms: - name: EL From 4f670751f0ebeca9a20ec61e19e5844275fe9717 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 19:31:46 +0000 Subject: [PATCH 31/66] Adjust list of supported OSes on Galaxy listing --- meta/main.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/meta/main.yml b/meta/main.yml index 19ddb583..b4b28237 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -11,19 +11,17 @@ galaxy_info: platforms: - name: EL versions: - - "8" - "9" - name: Fedora versions: - "38" - "39" - "40" - - name: FreeBSD + - name: Debian versions: - - "12.0" - - "13.0" + - bookworm - name: Ubuntu versions: - - trusty + - jammy galaxy_tags: - networking From 8b5091990c221ca92061be3feb094ec5dd2bb275 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 20:00:35 +0000 Subject: [PATCH 32/66] Stop markdownlint complaining about the multiple H1 headings in CHANGELOG --- .markdownlint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.markdownlint.yml b/.markdownlint.yml index ee0ceb79..429cc7c3 100644 --- a/.markdownlint.yml +++ b/.markdownlint.yml @@ -1,2 +1,3 @@ MD013: false +MD025: false MD033: false From 32dcbba9cb48f164614a0315d25f3ec25846e868 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 21:54:58 +0000 Subject: [PATCH 33/66] Add notes on end to end testing --- tests/end to end.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tests/end to end.md diff --git a/tests/end to end.md b/tests/end to end.md new file mode 100644 index 00000000..b7528f77 --- /dev/null +++ b/tests/end to end.md @@ -0,0 +1,29 @@ +# End to End Testing notes + +Loose idea is will need to start a bunch of VMs, 1 for each distro under test. + +Separate client will: + +1. take the config produced by the Ansible run +2. start the OpenVPN client using the config file +3. curl `icanhazip.com` + +Timeout/failure indicates that the OpenVPN connection didn't work for some reason. The IP address returned by #3 should be the IP address of the server, not the test client. + +Test client could fetch `icanhazip.com` again + +## Implementation + +Need to spin up different distros, so probably AWS or GCP (or Azure). + +AWS: [t4g.small instances are free for 750 hours till Dec 31 2025](https://aws.amazon.com/ec2/instance-types/t4/) + +Potential for the test client to be an existing VPS? Would want to test different OpenVPN versions though? + +Spinning up is ~easy - Terraform can handle setting it up (and VPC and tagging). + +Having one system run the ansible playbook is also ~straightforward. + +But should the system running the ansible playbook be the system testing the client connections? Potentially, but then there could be issues recovering from network misconfigurations (admittedly probably not). + +Having a separate script that SSHes to a test node would be better... except SSH outgoing packets might get caught and forced to go via the VPN tunnel? From 7a836f4d70795c32d0a5c46acf365817a1aa8021 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 23:01:14 +0000 Subject: [PATCH 34/66] ansible-core 2.14.11 is complaining about not being able to load 'bool', see if adding spaces does anything --- tasks/server_keys.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/server_keys.yml b/tasks/server_keys.yml index ea3d9166..7907db41 100644 --- a/tasks/server_keys.yml +++ b/tasks/server_keys.yml @@ -97,7 +97,7 @@ owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" mode: "0400" - when: openvpn_use_pregenerated_dh_params|bool + when: openvpn_use_pregenerated_dh_params | bool # Alternatively, if you're concerned about logjam attacks - name: Generate dh params @@ -105,7 +105,7 @@ args: chdir: "{{ openvpn_key_dir }}" creates: dh.pem - when: not (openvpn_use_pregenerated_dh_params|bool) + when: not (openvpn_use_pregenerated_dh_params | bool) - name: Install ca.conf config file ansible.builtin.template: From 7129cdb490771cf2732496ba8bc3f0dd6cc06afd Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 23:22:16 +0000 Subject: [PATCH 35/66] Try upgrading ansible and ansible-core in the debian like repos --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 43baf68d..9edbe782 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -145,7 +145,7 @@ jobs: build-debian-like: runs-on: ubuntu-latest - name: rhel-like-${{ matrix.version }} + name: debian-like-${{ matrix.version }} needs: - check-syntax strategy: @@ -167,6 +167,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + - name: Upgrade ansible + run: pip install --upgrade ansible ansible-core - name: Install required dependencies run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/requirements.yml - name: Make sure ansible connection is sane From e5f8044407453c9758a808d2e06ff1f2bc43fab4 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Mon, 23 Dec 2024 23:40:28 +0000 Subject: [PATCH 36/66] Debian packages use apt instead of pip, use apt for upgrades --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9edbe782..d7a972fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -168,7 +168,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Upgrade ansible - run: pip install --upgrade ansible ansible-core + run: apt update && apt-get install --only-upgrade ansible -y - name: Install required dependencies run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/requirements.yml - name: Make sure ansible connection is sane From e3602aabf1af981fccac2ab879f4edcc0fc9e0d4 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 00:25:39 +0000 Subject: [PATCH 37/66] Use ubi9-init instead of ubi9-minimal in CI, see if systemd works --- .github/workflows/ci.yml | 39 +++++++++++++++++++++++++++++++++++++- tests/ubi9-init.Dockerfile | 22 +++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 tests/ubi9-init.Dockerfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d7a972fe..90823569 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,6 @@ jobs: - "fedora:39" - "almalinux:9" - "rockylinux:9" - - "ubi-minimal:9" container: image: diodonfrost/ansible-${{ matrix.version }} @@ -185,3 +184,41 @@ jobs: 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-rhel-systemd: + runs-on: ubuntu-latest + name: rhel-systemd-${{ matrix.version }} + needs: + - check-syntax + strategy: + fail-fast: false + matrix: + version: + - "ubi9-init" + container: + image: ghcr.io/kyl191/ansible-${{ matrix.version }} + env: + container: docker + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup + - ${{ github.workspace }}:/etc/ansible/roles/ansible-role-openvpn + options: "--cap-add NET_ADMIN --cap-add SYS_ADMIN --device /dev/net/tun" + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install required dependencies + run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/requirements.yml + - name: Make sure ansible connection is sane + run: ansible -m setup -c local -i 127.0.0.1, all + - name: Run ansible playbook + run: ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv -e ci_build=False + # - name: Check idempotency + # run: ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv + - name: Container state debug output + continue-on-error: true + run: | + ls -lR /etc/openvpn + 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 {} \; diff --git a/tests/ubi9-init.Dockerfile b/tests/ubi9-init.Dockerfile new file mode 100644 index 00000000..b3a46542 --- /dev/null +++ b/tests/ubi9-init.Dockerfile @@ -0,0 +1,22 @@ +FROM redhat/ubi9-init:latest + +RUN dnf -y install \ + git \ + python3-pip \ + sudo \ + unzip \ + rsync \ + which \ + && dnf clean all + +RUN python3 -m pip install --upgrade pip && \ + python3 -m pip install ansible + +RUN sed -i -e 's/^\(Defaults\s*requiretty\)/#--- \1/' /etc/sudoers + +RUN mkdir /etc/ansible && \ + echo -e '[local]\nlocalhost ansible_connection=local' > /etc/ansible/hosts + +VOLUME ["/sys/fs/cgroup"] + +CMD ["/usr/sbin/init"] From e7440c8b97d7d5e86b8e2aadcf3cf38605e1479a Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 01:11:43 +0000 Subject: [PATCH 38/66] Add label to ubi9 dockerfile so it's associated with the repo --- tests/ubi9-init.Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/ubi9-init.Dockerfile b/tests/ubi9-init.Dockerfile index b3a46542..5b5b4fe6 100644 --- a/tests/ubi9-init.Dockerfile +++ b/tests/ubi9-init.Dockerfile @@ -1,4 +1,7 @@ FROM redhat/ubi9-init:latest +LABEL org.opencontainers.image.source=https://github.com/kyl191/ansible-role-openvpn +LABEL org.opencontainers.image.title="RHEL UBI 9-init with Ansible" + RUN dnf -y install \ git \ From cb92dfc518e8b6a0a09c3cc03ee5fa1ff4f4859c Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 01:12:06 +0000 Subject: [PATCH 39/66] Add debug option for CI test --- tasks/main.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tasks/main.yml b/tasks/main.yml index e0951910..5c984512 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -7,6 +7,10 @@ - "../vars/os/{{ ansible_os_family }}.yml" - "../vars/empty.yml" +- name: debug + ansible.builtin.debug: + var: ci_build + - name: Uninstall OpenVPN ansible.builtin.import_tasks: uninstall.yml when: openvpn_uninstall From e70392bd4e6759bebb4cd8e7e02df466fe53c9b6 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 01:17:53 +0000 Subject: [PATCH 40/66] debug ansible_service_mgr as well --- tasks/main.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tasks/main.yml b/tasks/main.yml index 5c984512..f8a25ea9 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -7,10 +7,14 @@ - "../vars/os/{{ ansible_os_family }}.yml" - "../vars/empty.yml" -- name: debug +- name: debug ci_build ansible.builtin.debug: var: ci_build +- name: debug ansible_service_mgr + ansible.builtin.debug: + var: ansible_service_mgr + - name: Uninstall OpenVPN ansible.builtin.import_tasks: uninstall.yml when: openvpn_uninstall From 742865e8fd5b5d52ec348e8f28122a437e29dfb6 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 01:19:17 +0000 Subject: [PATCH 41/66] urgh, ansible-lint triggered on not-capital letters --- tasks/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index f8a25ea9..ba8b5ab9 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -7,11 +7,11 @@ - "../vars/os/{{ ansible_os_family }}.yml" - "../vars/empty.yml" -- name: debug ci_build +- name: Debug ci_build ansible.builtin.debug: var: ci_build -- name: debug ansible_service_mgr +- name: Debug ansible_service_mgr ansible.builtin.debug: var: ansible_service_mgr From 078c0541801bab1fe7c950ac1a42b7b3ceb1d9af Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 01:25:28 +0000 Subject: [PATCH 42/66] Add debug ssh connection --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90823569..9ae540ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -214,6 +214,8 @@ jobs: run: ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv -e ci_build=False # - name: Check idempotency # run: ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 - name: Container state debug output continue-on-error: true run: | From 370d5fb1a6e5bbd3acaae3ce02c993caa24b7135 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 01:32:09 +0000 Subject: [PATCH 43/66] Move ssh debug outside of the container --- .github/workflows/ci.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ae540ca..af731f39 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -214,8 +214,6 @@ jobs: run: ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv -e ci_build=False # - name: Check idempotency # run: ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - name: Container state debug output continue-on-error: true run: | @@ -224,3 +222,10 @@ jobs: 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 {} \; + ssh-debug: + runs-on: ubuntu-latest + name: ssh-debug + steps: + - uses: actions/checkout@v4 + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 From 9c5bae6a3d7c1bdffc7d7c065146ea3f9d329b57 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 01:34:52 +0000 Subject: [PATCH 44/66] Allow global access for ssh debug --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af731f39..50dda451 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -229,3 +229,5 @@ jobs: - uses: actions/checkout@v4 - name: Setup tmate session uses: mxschmitt/action-tmate@v3 + with: + limit-access-to-actor: false From 649fc00b3e0225e4d1bed186acf901042ab44556 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 02:32:33 +0000 Subject: [PATCH 45/66] Cast ci_build to a bool before comparing it --- tasks/main.yml | 6 +++--- tasks/server_keys.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index ba8b5ab9..f62beeb3 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -31,18 +31,18 @@ ansible.posix.sysctl: name: net.ipv4.ip_forward value: "1" - when: not ci_build + when: not (ci_build|bool) - name: Enable ipv6 forwarding ansible.posix.sysctl: name: net.ipv6.conf.all.forwarding value: "1" - when: openvpn_server_ipv6_network is defined and not ci_build + when: openvpn_server_ipv6_network is defined and not (ci_build|bool) - name: Detect firewall type ansible.builtin.import_tasks: firewall/firewall.yml when: - - not ci_build + - not (ci_build|bool) - manage_firewall_rules tags: - firewall diff --git a/tasks/server_keys.yml b/tasks/server_keys.yml index 7907db41..36a00e15 100644 --- a/tasks/server_keys.yml +++ b/tasks/server_keys.yml @@ -184,4 +184,4 @@ enabled: true state: started daemon_reload: true - when: not ci_build + when: not (ci_build|bool) From 7830661a5e867ed0cf2c862ebadd4f9daed9bb0a Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 02:33:29 +0000 Subject: [PATCH 46/66] Remove debug variables --- tasks/main.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index f62beeb3..94629156 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -7,14 +7,6 @@ - "../vars/os/{{ ansible_os_family }}.yml" - "../vars/empty.yml" -- name: Debug ci_build - ansible.builtin.debug: - var: ci_build - -- name: Debug ansible_service_mgr - ansible.builtin.debug: - var: ansible_service_mgr - - name: Uninstall OpenVPN ansible.builtin.import_tasks: uninstall.yml when: openvpn_uninstall From e919d66bfbd13f6dc1df8a90d56a21364fcd6e3a Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 02:57:17 +0000 Subject: [PATCH 47/66] Convert systemd containers to manual podman --- .github/workflows/ci.yml | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 50dda451..b5bac9c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -185,9 +185,9 @@ jobs: echo "cat alpha-*.ovpn" find /etc/openvpn/ -maxdepth 3 -name "alpha-*.ovpn" -type f -exec cat {} \; - build-rhel-systemd: + build-systemd: runs-on: ubuntu-latest - name: rhel-systemd-${{ matrix.version }} + name: systemd-${{ matrix.version }} needs: - check-syntax strategy: @@ -195,38 +195,32 @@ jobs: matrix: version: - "ubi9-init" - container: - image: ghcr.io/kyl191/ansible-${{ matrix.version }} - env: - container: docker - volumes: - - /sys/fs/cgroup:/sys/fs/cgroup - - ${{ github.workspace }}:/etc/ansible/roles/ansible-role-openvpn - options: "--cap-add NET_ADMIN --cap-add SYS_ADMIN --device /dev/net/tun" steps: - name: Checkout repository uses: actions/checkout@v4 + - name: Login to GHCR + run: echo "${{ secrets.GITHUB_TOKEN }}" | sudo podman login ghcr.io -u kyl191 --password-stdin + - name: Create container + run: sudo podman create --name ${{ matrix.version }} --privileged --device /dev/net/tun --cgroupns=host --network=host --systemd=always --volume=${GITHUB_WORKSPACE}:/etc/ansible/roles/ansible-role-openvpn --user=root ghcr.io/kyl191/ansible-${{ matrix.version }} + - name: Start container + run: sudo podman start ${{ matrix.version }} - name: Install required dependencies - run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/requirements.yml + run: sudo podman exec ${{ matrix.version }} ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/requirements.yml - name: Make sure ansible connection is sane - run: ansible -m setup -c local -i 127.0.0.1, all + run: sudo podman exec ${{ matrix.version }} ansible -m setup -c local -i 127.0.0.1, all - name: Run ansible playbook - run: ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv -e ci_build=False - # - name: Check idempotency - # run: ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv + run: sudo podman exec ${{ matrix.version }} ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv -e ci_build=False + - name: Check idempotency + run: sudo podman exec ${{ matrix.version }} ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv - name: Container state debug output continue-on-error: true run: | - ls -lR /etc/openvpn + sudo podman exec ${{ matrix.version }} ls -lR /etc/openvpn echo "cat openvpn_udp_1194.conf" - find /etc/openvpn/ -maxdepth 3 -name openvpn_udp_1194.conf -type f -exec cat {} \; + sudo podman exec ${{ matrix.version }} 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 {} \; - ssh-debug: - runs-on: ubuntu-latest - name: ssh-debug - steps: - - uses: actions/checkout@v4 + sudo podman exec ${{ matrix.version }} find /etc/openvpn/ -maxdepth 3 -name "alpha-*.ovpn" -type f -exec cat {} \; + sudo podman exec ${{ matrix.version }} cat /var/log/openvpn.log - name: Setup tmate session uses: mxschmitt/action-tmate@v3 with: From 776d549dca94f09031c17c6a1e57915694367aee Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 03:01:50 +0000 Subject: [PATCH 48/66] Add ansible-lint ignore file to skip CI failures --- .ansible-lint-ignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .ansible-lint-ignore diff --git a/.ansible-lint-ignore b/.ansible-lint-ignore new file mode 100644 index 00000000..725464b3 --- /dev/null +++ b/.ansible-lint-ignore @@ -0,0 +1,2 @@ +# This file contains ignores rule violations for ansible-lint +.github/workflows/ci.yml yaml[line-length] From 0510525beb9f4b959cd07b255dfb36443f93bbfc Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 04:06:24 +0000 Subject: [PATCH 49/66] Run the fedora builds as systemd since they have the proper entrypoint setup --- .github/workflows/ci.yml | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b5bac9c7..f1e859f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,7 +44,7 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 - - name: Install required dependencies + - name: Install required dependencies from Ansible Galaxy run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/requirements.yml - name: Make sure ansible connection is sane run: ansible -m setup -c local -i 127.0.0.1, all @@ -86,7 +86,7 @@ jobs: uses: actions/checkout@v4 - name: Update ansible run: dnf install -y python39 && pip3.9 install -U ansible - - name: Install required dependencies + - name: Install required dependencies from Ansible Galaxy run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/requirements.yml - name: Make sure ansible connection is sane run: ansible -m setup -c local -i 127.0.0.1, all @@ -113,7 +113,9 @@ jobs: fail-fast: false matrix: version: - - "fedora:40" + # ubi9-init is https://catalog.redhat.com/software/containers/ubi9-init/6183297540a2d8e95c82e8bd + # plus ansible + - "ubi9-init" container: image: ghcr.io/kyl191/ansible-${{ matrix.version }} env: @@ -125,7 +127,7 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 - - name: Install required dependencies + - name: Install required dependencies from Ansible Galaxy run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/requirements.yml - name: Make sure ansible connection is sane run: ansible -m setup -c local -i 127.0.0.1, all @@ -168,7 +170,7 @@ jobs: uses: actions/checkout@v4 - name: Upgrade ansible run: apt update && apt-get install --only-upgrade ansible -y - - name: Install required dependencies + - name: Install required dependencies from Ansible Galaxy run: ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/requirements.yml - name: Make sure ansible connection is sane run: ansible -m setup -c local -i 127.0.0.1, all @@ -194,17 +196,20 @@ jobs: fail-fast: false matrix: version: - - "ubi9-init" + - "fedora:40" + - "fedora:41" steps: - name: Checkout repository uses: actions/checkout@v4 - name: Login to GHCR - run: echo "${{ secrets.GITHUB_TOKEN }}" | sudo podman login ghcr.io -u kyl191 --password-stdin + run: echo "${{ secrets.GITHUB_TOKEN }}" | sudo podman login ghcr.io -u ${{ github.actor }} --password-stdin - name: Create container run: sudo podman create --name ${{ matrix.version }} --privileged --device /dev/net/tun --cgroupns=host --network=host --systemd=always --volume=${GITHUB_WORKSPACE}:/etc/ansible/roles/ansible-role-openvpn --user=root ghcr.io/kyl191/ansible-${{ matrix.version }} - name: Start container run: sudo podman start ${{ matrix.version }} - - name: Install required dependencies + - name: Install firewalld + run: sudo podman exec ${{ matrix.version }} dnf -y install firewalld python3-firewall + - name: Install required dependencies from Ansible Galaxy run: sudo podman exec ${{ matrix.version }} ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/requirements.yml - name: Make sure ansible connection is sane run: sudo podman exec ${{ matrix.version }} ansible -m setup -c local -i 127.0.0.1, all From 8fde4aff124c068e6ee7c1dda83093dc9d640957 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 04:11:31 +0000 Subject: [PATCH 50/66] Change CI version setup so podman doesn't complain about : being in the name --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f1e859f4..f2b0f7dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -196,15 +196,15 @@ jobs: fail-fast: false matrix: version: - - "fedora:40" - - "fedora:41" + - "40" + - "41" steps: - name: Checkout repository uses: actions/checkout@v4 - name: Login to GHCR run: echo "${{ secrets.GITHUB_TOKEN }}" | sudo podman login ghcr.io -u ${{ github.actor }} --password-stdin - name: Create container - run: sudo podman create --name ${{ matrix.version }} --privileged --device /dev/net/tun --cgroupns=host --network=host --systemd=always --volume=${GITHUB_WORKSPACE}:/etc/ansible/roles/ansible-role-openvpn --user=root ghcr.io/kyl191/ansible-${{ matrix.version }} + run: sudo podman create --name ${{ matrix.version }} --privileged --device /dev/net/tun --cgroupns=host --network=host --systemd=always --volume=${GITHUB_WORKSPACE}:/etc/ansible/roles/ansible-role-openvpn --user=root ghcr.io/kyl191/ansible-fedora:${{ matrix.version }} - name: Start container run: sudo podman start ${{ matrix.version }} - name: Install firewalld From ef20a567fb16a6afbda3f3de2aa2e567d3e2874e Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 04:18:49 +0000 Subject: [PATCH 51/66] Add more end to end notes --- tests/end to end.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/end to end.md b/tests/end to end.md index b7528f77..e7a3ad69 100644 --- a/tests/end to end.md +++ b/tests/end to end.md @@ -10,7 +10,7 @@ Separate client will: Timeout/failure indicates that the OpenVPN connection didn't work for some reason. The IP address returned by #3 should be the IP address of the server, not the test client. -Test client could fetch `icanhazip.com` again +Test client could fetch `icanhazip.com` again to make sure the IP address changes as well. ## Implementation @@ -27,3 +27,9 @@ Having one system run the ansible playbook is also ~straightforward. But should the system running the ansible playbook be the system testing the client connections? Potentially, but then there could be issues recovering from network misconfigurations (admittedly probably not). Having a separate script that SSHes to a test node would be better... except SSH outgoing packets might get caught and forced to go via the VPN tunnel? + +## Github Runner not suitable + +We can probably mess with the network settings directly on the machine [since sudo is usable](https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#administrative-privileges), but that doesn't help with triggering the client test. + +Maybe Github Actions could be the test runner that triggers the AWS build then tests locally? From 4489d8e596b550b1f76f67c47a5823dccdf23535 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 04:59:08 +0000 Subject: [PATCH 52/66] Install procps-ng for /sbin/sysctl --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f2b0f7dd..f12eef06 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -208,7 +208,7 @@ jobs: - name: Start container run: sudo podman start ${{ matrix.version }} - name: Install firewalld - run: sudo podman exec ${{ matrix.version }} dnf -y install firewalld python3-firewall + run: sudo podman exec ${{ matrix.version }} dnf -y install firewalld python3-firewall procps-ng - name: Install required dependencies from Ansible Galaxy run: sudo podman exec ${{ matrix.version }} ansible-galaxy install -r /etc/ansible/roles/ansible-role-openvpn/requirements.yml - name: Make sure ansible connection is sane From 3557e18fa426be44f510719d980243175b1cc001 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 05:17:40 +0000 Subject: [PATCH 53/66] Run more values through truthy/falsy to force evaluation as true/false Ref: https://www.trueneutral.eu/2019/ansible-truthy-filter.html --- tasks/client_keys.yml | 2 +- tasks/config.yml | 20 ++++++++++---------- tasks/firewall/iptables.yml | 6 +++--- tasks/firewall/ufw.yml | 4 ++-- tasks/install.yml | 4 ++-- tasks/main.yml | 12 ++++++------ tasks/uninstall.yml | 2 +- templates/client.ovpn.j2 | 2 +- templates/server.conf.j2 | 18 +++++++++--------- 9 files changed, 35 insertions(+), 35 deletions(-) diff --git a/tasks/client_keys.yml b/tasks/client_keys.yml index 1f47c462..a6db8543 100644 --- a/tasks/client_keys.yml +++ b/tasks/client_keys.yml @@ -79,6 +79,6 @@ 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 - when: openvpn_fetch_client_configs + when: openvpn_fetch_client_configs is truthy with_items: - "{{ clients }}" diff --git a/tasks/config.yml b/tasks/config.yml index fba0aeb8..1813994a 100644 --- a/tasks/config.yml +++ b/tasks/config.yml @@ -42,13 +42,13 @@ path: "{{ openvpn_base_dir }}/auth" state: directory mode: "0755" - when: openvpn_use_ldap + when: openvpn_use_ldap is truthy - name: Delete auth folder in openvpn dir ansible.builtin.file: path: "{{ openvpn_base_dir }}/auth" state: absent - when: not openvpn_use_ldap + when: openvpn_use_ldap is falsy - name: Install LDAP config ansible.builtin.template: @@ -57,7 +57,7 @@ owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" mode: "0644" - when: openvpn_use_ldap + when: openvpn_use_ldap is truthy - name: Create log directory ansible.builtin.file: @@ -73,7 +73,7 @@ owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" mode: "0400" - when: openvpn_use_logrotate + when: openvpn_use_logrotate is truthy - name: Create client config directory ansible.builtin.file: @@ -82,7 +82,7 @@ owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" mode: "0755" - when: openvpn_client_config + when: openvpn_client_config is truthy - name: Create client configs ansible.builtin.template: @@ -91,29 +91,29 @@ owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" mode: "0644" - when: openvpn_client_config + when: openvpn_client_config is truthy with_dict: "{{ openvpn_client_configs }}" - name: List client config directory ansible.builtin.command: "ls -1 {{ openvpn_base_dir }}/{{ openvpn_client_config_dir }}" register: __ccd_contents changed_when: false - when: openvpn_client_config + when: openvpn_client_config is truthy - name: Delete undeclared configs in client config directory ansible.builtin.file: path: "{{ openvpn_base_dir }}/{{ openvpn_client_config_dir }}/{{ item }}" state: absent when: - - item not in openvpn_client_configs.keys() | list - - openvpn_client_config + - item not in (openvpn_client_configs.keys() | list) + - openvpn_client_config is truthy with_items: "{{ __ccd_contents.stdout_lines | default([]) }}" - name: Delete client config directory ansible.builtin.file: path: "{{ openvpn_base_dir }}/{{ openvpn_client_config_dir }}" state: absent - when: not openvpn_client_config + when: openvpn_client_config is falsy - name: Setup openvpn auto-start & start ansible.builtin.service: diff --git a/tasks/firewall/iptables.yml b/tasks/firewall/iptables.yml index 5864d8f6..151a0b52 100644 --- a/tasks/firewall/iptables.yml +++ b/tasks/firewall/iptables.yml @@ -70,7 +70,7 @@ jump: SNAT action: insert comment: "Perform NAT readdressing" - when: not openvpn_masquerade_not_snat and not openvpn_no_nat + when: openvpn_masquerade_not_snat is falsy and openvpn_no_nat is falsy notify: "Save iptables" - name: Perform NAT readdressing with MASQUERADE - iptables @@ -82,13 +82,13 @@ jump: MASQUERADE action: insert comment: "Perform NAT readdressing" - when: openvpn_masquerade_not_snat and not openvpn_no_nat + when: openvpn_masquerade_not_snat is truthy and openvpn_no_nat is falsy notify: - Save iptables - name: Save existing iptables rule before start iptables service ansible.builtin.shell: "{{ iptables_save_command }}" # noqa command-instead-of-shell - when: __iptables_installed.changed | bool # noqa no-handler + when: __iptables_installed.changed is truthy # noqa no-handler changed_when: true - name: Enable iptables diff --git a/tasks/firewall/ufw.yml b/tasks/firewall/ufw.yml index ee4d0a84..9f8eabc0 100644 --- a/tasks/firewall/ufw.yml +++ b/tasks/firewall/ufw.yml @@ -41,7 +41,7 @@ :POSTROUTING ACCEPT [0:0] -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 + when: openvpn_masquerade_not_snat is falsy notify: - Restart ufw @@ -56,6 +56,6 @@ :POSTROUTING ACCEPT [0:0] -A POSTROUTING -s {{ openvpn_server_network }}/24 ! -d {{ openvpn_server_network }}/24 -j MASQUERADE COMMIT - when: openvpn_masquerade_not_snat + when: openvpn_masquerade_not_snat is truthy notify: - Restart ufw diff --git a/tasks/install.yml b/tasks/install.yml index f4e4e409..927c9126 100644 --- a/tasks/install.yml +++ b/tasks/install.yml @@ -43,8 +43,8 @@ name: "{{ openvpn_ldap_plugin_package_name }}" state: present when: - - openvpn_use_ldap - - openvpn_use_prebuilt_ldap_plugin + - openvpn_use_ldap is truthy + - openvpn_use_prebuilt_ldap_plugin is truthy # RHEL has the group 'nobody', 'Debian/Ubuntu' have 'nogroup' # standardize on 'nogroup' diff --git a/tasks/main.yml b/tasks/main.yml index 94629156..25c1312c 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -9,7 +9,7 @@ - name: Uninstall OpenVPN ansible.builtin.import_tasks: uninstall.yml - when: openvpn_uninstall + when: openvpn_uninstall is truthy - name: Install OpenVPN ansible.builtin.import_tasks: install.yml @@ -23,18 +23,18 @@ ansible.posix.sysctl: name: net.ipv4.ip_forward value: "1" - when: not (ci_build|bool) + when: ci_build is falsy - name: Enable ipv6 forwarding ansible.posix.sysctl: name: net.ipv6.conf.all.forwarding value: "1" - when: openvpn_server_ipv6_network is defined and not (ci_build|bool) + when: openvpn_server_ipv6_network is defined and ci_build is falsy - name: Detect firewall type ansible.builtin.import_tasks: firewall/firewall.yml when: - - not (ci_build|bool) + - ci_build is falsy - manage_firewall_rules tags: - firewall @@ -46,7 +46,7 @@ - name: Compare existing certs against 'clients' variable ansible.builtin.import_tasks: cert_sync_detection.yml - when: openvpn_sync_certs + when: openvpn_sync_certs is truthy tags: - sync_certs @@ -61,7 +61,7 @@ when: >- (openvpn_revoke_these_certs is defined) or - (openvpn_sync_certs and cert_sync_certs_to_revoke.stdout_lines | length > 0) + (openvpn_sync_certs is truthy and cert_sync_certs_to_revoke.stdout_lines | length > 0) - name: Configure OpenVPN server ansible.builtin.import_tasks: config.yml diff --git a/tasks/uninstall.yml b/tasks/uninstall.yml index c45e330d..a97f0ca7 100644 --- a/tasks/uninstall.yml +++ b/tasks/uninstall.yml @@ -24,7 +24,7 @@ ansible.builtin.package: name: "{{ openvpn_ldap_plugin_package_name }}" state: absent - when: openvpn_use_ldap + when: openvpn_use_ldap is truthy - name: Terminate playbook ansible.builtin.fail: diff --git a/templates/client.ovpn.j2 b/templates/client.ovpn.j2 index 31bd0743..eaeda54e 100644 --- a/templates/client.ovpn.j2 +++ b/templates/client.ovpn.j2 @@ -59,6 +59,6 @@ key-direction 1 {{ item.1.content|b64decode }} -{% if openvpn_verify_cn|bool %} +{% if openvpn_verify_cn is truthy %} verify-x509-name OpenVPN-Server-{{ inventory_hostname[:49] }} name {% endif %} diff --git a/templates/server.conf.j2 b/templates/server.conf.j2 index dc3eb789..9a40ab92 100644 --- a/templates/server.conf.j2 +++ b/templates/server.conf.j2 @@ -18,7 +18,7 @@ dh {{ openvpn_key_dir }}/dh.pem {% if openvpn_crl_path is defined %} crl-verify {{ openvpn_crl_path }} {% endif %} -{% if openvpn_use_crl|bool %} +{% if openvpn_use_crl is truthy %} crl-verify {{ openvpn_key_dir }}/ca-crl.pem {% endif %} {% if tls_auth_required %} @@ -32,17 +32,17 @@ data-ciphers {{ openvpn_cipher }} {% if openvpn_tun_mtu %} tun-mtu {{ openvpn_tun_mtu }} {% endif %} -{% if openvpn_use_hardened_tls|bool %} +{% if openvpn_use_hardened_tls is truthy %} tls-version-min 1.2 {% endif %} {# Using Mozilla's modern cipher list + DHE for older clients #} -{% if openvpn_use_modern_tls|bool %} +{% if openvpn_use_modern_tls is truthy %} tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384:TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256 {% endif %} -{% if openvpn_duplicate_cn|bool %} +{% if openvpn_duplicate_cn is truthy %} duplicate-cn {% endif %} -{% if openvpn_client_to_client|bool %} +{% if openvpn_client_to_client is truthy %} client-to-client {% endif %} @@ -58,7 +58,7 @@ ifconfig-pool-persist {{ openvpn_ifconfig_pool_persist_file }} client-config-dir {{ openvpn_client_config_dir }} {% endif %} -{% if openvpn_redirect_gateway|bool %} +{% if openvpn_redirect_gateway is truthy %} push "redirect-gateway def1 bypass-dhcp" {% endif %} {% if openvpn_set_dns and openvpn_custom_dns|length > 0%} @@ -94,19 +94,19 @@ syslog openvpn {% endif %} verb 3 -{% if openvpn_verify_cn|bool %} +{% if openvpn_verify_cn is truthy %} verify-x509-name OpenVPN-Client-{{ inventory_hostname[:24] }} name-prefix remote-cert-tls client {% endif %} -{% if openvpn_enable_management|bool %} +{% if openvpn_enable_management is truthy %} management {{ openvpn_management_bind }} {% if openvpn_management_client_user %} management-client-user {{ openvpn_management_client_user }} {% endif %} {% endif %} -{% if openvpn_use_ldap|bool %} +{% if openvpn_use_ldap is truthy %} ### LDAP AUTH ### {% if ansible_os_family == 'Debian' %} plugin /usr/lib/openvpn/openvpn-auth-ldap.so "{{ openvpn_base_dir }}/auth/ldap.conf" From fd0b70795809f51828315ac18423e76a5e92871b Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 05:39:16 +0000 Subject: [PATCH 54/66] Fix double space --- tasks/cert_sync_detection.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/cert_sync_detection.yml b/tasks/cert_sync_detection.yml index 14a457fb..002760e2 100644 --- a/tasks/cert_sync_detection.yml +++ b/tasks/cert_sync_detection.yml @@ -10,7 +10,7 @@ # 2. Extract path attribute from dict list # 3. Keep only basename # 4. Remove extension -- name: "[cert sync] Create list of existing client with existing certs" +- name: "[cert sync] Create list of existing client with existing certs" 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 From 833feb191f79515f08244ec35907da63f009f20a Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 06:02:27 +0000 Subject: [PATCH 55/66] Add a wait for systemd container to start steo to the CI --- .github/workflows/ci.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f12eef06..28a443ab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -201,12 +201,19 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + with: + limit-access-to-actor: false + detached: true - name: Login to GHCR run: echo "${{ secrets.GITHUB_TOKEN }}" | sudo podman login ghcr.io -u ${{ github.actor }} --password-stdin - name: Create container run: sudo podman create --name ${{ matrix.version }} --privileged --device /dev/net/tun --cgroupns=host --network=host --systemd=always --volume=${GITHUB_WORKSPACE}:/etc/ansible/roles/ansible-role-openvpn --user=root ghcr.io/kyl191/ansible-fedora:${{ matrix.version }} - name: Start container run: sudo podman start ${{ matrix.version }} + - name: Wait for container to start + run: sudo podman exec ${{ matrix.version }} /bin/bash while [ "$(systemctl is-system-running)" != "running" ]; do sleep 5; done - name: Install firewalld run: sudo podman exec ${{ matrix.version }} dnf -y install firewalld python3-firewall procps-ng - name: Install required dependencies from Ansible Galaxy @@ -226,7 +233,3 @@ jobs: echo "cat alpha-*.ovpn" sudo podman exec ${{ matrix.version }} find /etc/openvpn/ -maxdepth 3 -name "alpha-*.ovpn" -type f -exec cat {} \; sudo podman exec ${{ matrix.version }} cat /var/log/openvpn.log - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - with: - limit-access-to-actor: false From 3b9c632752d2757f9ece399018134126af294c35 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 06:08:09 +0000 Subject: [PATCH 56/66] Fix bad CI command --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 28a443ab..ee8fec5e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -213,7 +213,7 @@ jobs: - name: Start container run: sudo podman start ${{ matrix.version }} - name: Wait for container to start - run: sudo podman exec ${{ matrix.version }} /bin/bash while [ "$(systemctl is-system-running)" != "running" ]; do sleep 5; done + run: while [ "$(sudo podman exec ${{ matrix.version }} systemctl is-system-running)" != "running" ]; do sleep 5; done - name: Install firewalld run: sudo podman exec ${{ matrix.version }} dnf -y install firewalld python3-firewall procps-ng - name: Install required dependencies from Ansible Galaxy From 02a1519d887754663ec8bd7630af997a9ab84ccc Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 06:36:16 +0000 Subject: [PATCH 57/66] Add a note next to the register_dns client entry --- templates/client.ovpn.j2 | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/client.ovpn.j2 b/templates/client.ovpn.j2 index eaeda54e..8b13ee43 100644 --- a/templates/client.ovpn.j2 +++ b/templates/client.ovpn.j2 @@ -35,6 +35,7 @@ auth-user-pass route-method exe route-delay 2 {% if openvpn_client_register_dns %} +# Note: This is a Windows-specific directive, remove it if this is meant to be used on non-Windows register-dns {% endif %} From d9bd9fd4e19bbc9010a865ae7af9e57f293fc010 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 06:55:33 +0000 Subject: [PATCH 58/66] Start an openvpn connection in the systemd containers --- .github/workflows/ci.yml | 9 +++++++++ tests/test.yml | 1 + 2 files changed, 10 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ee8fec5e..2da93f8f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -224,6 +224,14 @@ jobs: run: sudo podman exec ${{ matrix.version }} ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv -e ci_build=False - name: Check idempotency run: sudo podman exec ${{ matrix.version }} ansible-playbook /etc/ansible/roles/ansible-role-openvpn/tests/test.yml -vv + - name: Move generated client config file + run: sudo podman exec ${{ matrix.version }} cp /etc/openvpn/server/alpha-localhost.ovpn /etc/openvpn/client/alpha-localhost.conf + - name: Attempt openvpn connection + run: sudo podman exec ${{ matrix.version }} systemctl start openvpn-client@alpha-localhost.service + - name: Wait for a bit + run: sleep 5 + - name: Attempt openvpn connection + run: sudo podman exec ${{ matrix.version }} systemctl stop openvpn-client@alpha-localhost.service - name: Container state debug output continue-on-error: true run: | @@ -233,3 +241,4 @@ jobs: echo "cat alpha-*.ovpn" sudo podman exec ${{ matrix.version }} find /etc/openvpn/ -maxdepth 3 -name "alpha-*.ovpn" -type f -exec cat {} \; sudo podman exec ${{ matrix.version }} cat /var/log/openvpn.log + sudo podman exec ${{ matrix.version }} journalctl -u openvpn-client@alpha-localhost.service diff --git a/tests/test.yml b/tests/test.yml index de436ade..697b26c0 100644 --- a/tests/test.yml +++ b/tests/test.yml @@ -4,6 +4,7 @@ connection: local vars: ci_build: true + openvpn_client_register_dns: false openvpn_use_pregenerated_dh_params: true roles: - role: ansible-role-openvpn From 8504544795c6805349fd0b8ce483fd8f90d33444 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 07:04:23 +0000 Subject: [PATCH 59/66] Add some signposting to CI logging --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2da93f8f..2a718ecb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -212,6 +212,7 @@ jobs: run: sudo podman create --name ${{ matrix.version }} --privileged --device /dev/net/tun --cgroupns=host --network=host --systemd=always --volume=${GITHUB_WORKSPACE}:/etc/ansible/roles/ansible-role-openvpn --user=root ghcr.io/kyl191/ansible-fedora:${{ matrix.version }} - name: Start container run: sudo podman start ${{ matrix.version }} + # https://www.jeffgeerling.com/blog/2020/resolving-fedora-dnf-error-no-such-file-or-directory-varlibdnfrpmdblockpid - name: Wait for container to start run: while [ "$(sudo podman exec ${{ matrix.version }} systemctl is-system-running)" != "running" ]; do sleep 5; done - name: Install firewalld @@ -230,7 +231,7 @@ jobs: run: sudo podman exec ${{ matrix.version }} systemctl start openvpn-client@alpha-localhost.service - name: Wait for a bit run: sleep 5 - - name: Attempt openvpn connection + - name: Stop openvpn connection run: sudo podman exec ${{ matrix.version }} systemctl stop openvpn-client@alpha-localhost.service - name: Container state debug output continue-on-error: true @@ -240,5 +241,7 @@ jobs: sudo podman exec ${{ matrix.version }} find /etc/openvpn/ -maxdepth 3 -name openvpn_udp_1194.conf -type f -exec cat {} \; echo "cat alpha-*.ovpn" sudo podman exec ${{ matrix.version }} find /etc/openvpn/ -maxdepth 3 -name "alpha-*.ovpn" -type f -exec cat {} \; + echo cat /var/log/openvpn.log sudo podman exec ${{ matrix.version }} cat /var/log/openvpn.log + echo journalctl -u openvpn-client@alpha-localhost.service sudo podman exec ${{ matrix.version }} journalctl -u openvpn-client@alpha-localhost.service From b73aa45a27cd4aa1f06808c9154425b0c72bf9f4 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 07:15:36 +0000 Subject: [PATCH 60/66] Add some missed truthy/falsy checks --- tasks/server_keys.yml | 6 +++--- templates/client.ovpn.j2 | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tasks/server_keys.yml b/tasks/server_keys.yml index 36a00e15..215b0cbf 100644 --- a/tasks/server_keys.yml +++ b/tasks/server_keys.yml @@ -97,7 +97,7 @@ owner: "{{ openvpn_conf_user }}" group: "{{ openvpn_conf_group }}" mode: "0400" - when: openvpn_use_pregenerated_dh_params | bool + when: openvpn_use_pregenerated_dh_params is truthy # Alternatively, if you're concerned about logjam attacks - name: Generate dh params @@ -105,7 +105,7 @@ args: chdir: "{{ openvpn_key_dir }}" creates: dh.pem - when: not (openvpn_use_pregenerated_dh_params | bool) + when: openvpn_use_pregenerated_dh_params is falsy - name: Install ca.conf config file ansible.builtin.template: @@ -184,4 +184,4 @@ enabled: true state: started daemon_reload: true - when: not (ci_build|bool) + when: ci_build is falsy diff --git a/templates/client.ovpn.j2 b/templates/client.ovpn.j2 index 8b13ee43..5a92bf9f 100644 --- a/templates/client.ovpn.j2 +++ b/templates/client.ovpn.j2 @@ -2,11 +2,11 @@ client tls-client auth {{ openvpn_auth_alg }} -{% if openvpn_cipher %} +{% if openvpn_cipher is truthy %} data-ciphers {{ openvpn_cipher }} {% endif %} remote-cert-tls server -{% if openvpn_use_modern_tls %} +{% if openvpn_use_modern_tls is truthy %} tls-version-min 1.2 {% endif %} @@ -17,14 +17,14 @@ dev tun resolv-retry {{ openvpn_resolv_retry }} nobind keepalive {{ openvpn_keepalive_ping }} {{ openvpn_keepalive_timeout }} -{% if openvpn_compression %} +{% if openvpn_compression is truthy %} compress {{ openvpn_compression }} {% endif %} persist-key persist-tun verb 3 -{% if openvpn_use_ldap %} +{% if openvpn_use_ldap is truthy %} auth-user-pass {% endif %} @@ -34,19 +34,19 @@ auth-user-pass route-method exe route-delay 2 -{% if openvpn_client_register_dns %} +{% if openvpn_client_register_dns is truthy %} # Note: This is a Windows-specific directive, remove it if this is meant to be used on non-Windows register-dns {% endif %} -{% if tls_auth_required %} +{% if tls_auth_required is truthy %} key-direction 1 {% endif %} {{ ca_cert.content|b64decode }} -{% if tls_auth_required %} +{% if tls_auth_required is truthy %} {{ tls_auth.content|b64decode }} From ee75e0f90db14563efec73dae479b47f3c64f5fb Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 07:15:53 +0000 Subject: [PATCH 61/66] Add changes in CHANGELOG --- CHANGELOG.md | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5605b05c..5a4eef3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,102 @@ +# Version 3.0 (2024-12-26) + +## Updated to latest Ansible recommendations + +ansible-lint isn't complaining anymore. It's also added to the CI system so the role shouldn't regress. + +I've also added `truthy/falsy` to clauses to make sure the value is always coerced to a bool + +## Changed Supported OS Versions + +Actually supported - I make sure an OpenVPN connection works before putting up a Ansible Galaxy release: + +* Fedora 38+ ([OpenVPN 2.6](https://packages.fedoraproject.org/pkgs/openvpn/openvpn/)) +* CentOS Stream 9/AlmaLinux/Rocky/RHEL 9+ ([OpenVPN 2.5](https://packages.fedoraproject.org/pkgs/openvpn/openvpn/)) + +Kind of supported - CI does sanity checks: + +* Ubuntu 22.04+ ([OpenVPN 2.5](https://launchpad.net/ubuntu/+source/openvpn), [list of distro releases](https://wiki.ubuntu.com/Releases)) +* Debian 12 ([OpenVPN 2.6](https://packages.debian.org/search?keywords=openvpn), [list of distro releases](https://www.debian.org/releases/)) + +Community contributions - no automated checks, they might work: + +* FreeBSD +* Solaris + +Older OSes might work - there's no explicit blocking, but workarounds will be removed with EOLed OSes to simplify the role. + +### Removed Workarounds + +* CentOS 6 - no longer [ignore errors when setting sysctls](http://serverfault.com/questions/477718/sysctl-p-etc-sysctl-conf-returns-error) +* CentOS 7 - Potentially affected by defaulting service name to the systemd style +* Fedora <33 - no longer installing `python2-dnf` and `python2-firewalld` for Ansible to run on Python 2. + +### RHEL-alike 8 notes + +Known issue: RHEL-alike 8 [can't manage packages using ansible-core >=2.17.0](https://github.com/ansible/ansible/issues/82068#issuecomment-2123567229), you will need to use an earlier version of Ansible. + +Other notes on RHEL-alike 8 variants: + +* AlmaLinux 8 and Rocky Linux 8 need an out-of-band python upgrade with `dnf install python3.9` and setting the `ansible_python_interpreter` value to `/usr/bin/python3.9` +* CentOS 8 and CentOS Stream 8 packages were vaulted ([CentOS 8](https://www.centos.org/centos-linux-eol/), [Stream 8](https://blog.centos.org/2023/04/end-dates-are-coming-for-centos-stream-8-and-centos-linux-7/)), which breaks Yum downloading packages + +## Assuming OpenVPN 2.5+ + +Biggest change (as far as I can tell) is OpenVPN deprecated `cipher` and replaced it with `data-cipher`. All the supported OSes are OpenVPN2.5+, so I've updated the server config to use `data-cipher` when `openvpn_cipher` is set. + +If the event you need fallback support on the server for older clients, set the value `data-ciphers-fallback` through the playbook option `openvpn_addl_server_options`. + +If you're forced to use OpenVPN 2.4 or earlier, this should work: + +* Unset `openvpn_cipher` in your vars file, eg `openvpn_cipher: ~` +* Include `cipher` in `openvpn_addl_server_options`, eg `openvpn_addl_server_options: ["cipher AES-256-CBC"]` + +Similarly on the client, you can use `openvpn_addl_client_options` to set `cipher` if needed. + +Discussion in [this issue](https://github.com/kyl191/ansible-role-openvpn/issues/196). + +## LDAP plugin no longer built by default + +This thing has honestly made me nervous since merging it because I don't have anything that uses LDAP. I trust that it functions, but it seemed unecessarily complex to have in an Ansible playbook. Turns out Fedora/EPEL, Debian, and Ubuntu all provide packages for openvpn-auth-ldap so I'm dropping the compilation. + +* Fedora/EPEL: +* Debian: +* Ubuntu: + +If you need it and there's no prebuilt package, manually build & configure it yourself and set the variable `openvpn_use_prebuilt_ldap_plugin` to False to skip the failing package install. + +## systemd by default + +CentOS 8+, Ubuntu 22.04 and Debian 12 are all using systemd service units, so I've updated the default `openvpn_service_name` to be systemd style. I've kept the existing `openvpn` value for Solaris and FreeBSD, hopefully it works there. + +The CRL crontab is also replaced by a systemd timer. + +## Future changes + +### Dropping iptables in a future release + +Fedora/CentOS use firewalld and Debian [recommends firewalld](https://wiki.debian.org/nftables#Use_firewalld). Ubuntu is alone in [using ufw](https://documentation.ubuntu.com/server/how-to/security/firewalls/) + +nftables is the replacement for iptables, [firewalld uses nftables as the default backend](https://firewalld.org/2018/07/nftables-backend). Unfortunately there is [no nftables support in Ansible yet](https://forum.ansible.com/t/is-there-an-official-or-defacto-nftables-module-or-collection/7023), so I'm choosing to drop iptables and suggest firewalld as the replacement. + +This will realistically be done when `iptables` starts requiring more maintenance than it does right now. + +### Help wanted: Develop end to end testing + +The Fedora & CentOS connection testing is currently manual. (This is also blocking the better testing of the Debian & Ubuntu distros). + +### Switch to testing against multiple `ansible-core` releases + +The CI currently tests the role on AlmaLinux/Rocky Linux 8 using the highest supported Ansible version for [CentOS 8 as a control node - ansible-8.7.0/ansible-core-2.15.13](https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html#ansible-core-support-matrix), but this is limited to running the playbook without attempting an OpenVPN connection. + +This is partly because the minimum ansible-core version for this role is 2.11 - if this run starts failing, I'll know the minimum ansible-core version will need to be bumped. + +At some point in the future I'll switch to testing different ansible-core versions explicitly, and drop the RHEL-alike 8 CI builds at that time. + # Version 2.0 (2016-04-11) + ## Improving TLS Security + 1. Added `auth SHA256` so MACs on the individual packets are done with SHA256 instead of SHA1. 2. Added `tls-version-min 1.2` to drop SSL3 + TLS v1.0 support. This breaks older clients (2.3.2+), but those versions have been out for a while. @@ -13,22 +110,27 @@ Points 2 & 3 are gated by the `openvpn_use_modern_tls` variable, which defaults to `true`. ## Adding Cert Validations + OpenVPN has at least two kinds of certification validation available: (Extended) Key Usage checks, and certificate content validation. ### EKU + Previously only the client was verifying that the server cert had the correct usage, now the verification is bi-directional. ### Certificate content + Added the ability to verify the common name that is part of each certificate. This required changing the common names that each certificate is generated with, which means that the ability to wipe out the existing keys was added as well. Again, both these changes are gated by a variable (`openvpn_verify_cn`). Because this requires rather large client changes, it is off by default. ## Wiping out & reinstalling + Added the ability to wipe out & reinstall OpenVPN. Currently it leaves firewall rules behind, but other than that everything is removed. Use `ansible-playbook -v openvpn.yml --extra-vars="openvpn_uninstall=true" --tags uninstall` to just run the uninstall portion. ## Connect over IPv6 + Previously, you had to explicitly use `udp6` or `tcp6` to use IPv6. OpenVPN isn't dual stacked if you use plain `udp`/`tcp`, which results in being unable to connect to the OpenVPN server if it has an AAAA record, on your device has a functional IPv6 connection, since the client will choose which stack to use if you just use plain `udp`/`tcp`. -Since this playbook is only on Linux, which supports IPv4 connections on IPv6 sockets, the server config is now IPv6 by default (https://github.com/OpenVPN/openvpn/blob/master/README.IPv6#L50), by means of using `{{ openvpn_proto }}6` in the server template. Specifying a `*6` protocol for `openvpn_proto` is now an error, and will cause OpenVPN to fail to start. +Since this playbook is only on Linux, which supports IPv4 connections on IPv6 sockets, the server config is now IPv6 by default (), by means of using `{{ openvpn_proto }}6` in the server template. Specifying a `*6` protocol for `openvpn_proto` is now an error, and will cause OpenVPN to fail to start. From 215a9f6a7927b0a4870e859b09e349f870145299 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 07:21:21 +0000 Subject: [PATCH 62/66] Few more clarification changes to the changelog --- CHANGELOG.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a4eef3c..622504ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ansible-lint isn't complaining anymore. It's also added to the CI system so the role shouldn't regress. -I've also added `truthy/falsy` to clauses to make sure the value is always coerced to a bool +I've also added `truthy/falsy` to clauses to make sure a value is always coerced to a bool. ## Changed Supported OS Versions @@ -38,7 +38,7 @@ Known issue: RHEL-alike 8 [can't manage packages using ansible-core >=2.17.0](ht Other notes on RHEL-alike 8 variants: * AlmaLinux 8 and Rocky Linux 8 need an out-of-band python upgrade with `dnf install python3.9` and setting the `ansible_python_interpreter` value to `/usr/bin/python3.9` -* CentOS 8 and CentOS Stream 8 packages were vaulted ([CentOS 8](https://www.centos.org/centos-linux-eol/), [Stream 8](https://blog.centos.org/2023/04/end-dates-are-coming-for-centos-stream-8-and-centos-linux-7/)), which breaks Yum downloading packages +* CentOS 8 and CentOS Stream 8 packages were vaulted ([CentOS 8 announcement](https://www.centos.org/centos-linux-eol/), [Stream 8 announcement](https://blog.centos.org/2023/04/end-dates-are-coming-for-centos-stream-8-and-centos-linux-7/)), which breaks Yum downloading packages ## Assuming OpenVPN 2.5+ @@ -57,7 +57,9 @@ Discussion in [this issue](https://github.com/kyl191/ansible-role-openvpn/issues ## LDAP plugin no longer built by default -This thing has honestly made me nervous since merging it because I don't have anything that uses LDAP. I trust that it functions, but it seemed unecessarily complex to have in an Ansible playbook. Turns out Fedora/EPEL, Debian, and Ubuntu all provide packages for openvpn-auth-ldap so I'm dropping the compilation. +This thing has honestly made me nervous since merging it because I don't have anything that uses LDAP. I trust that it functions, but [a compliation issue was reported](https://github.com/kyl191/ansible-role-openvpn/issues/174). + +Turns out Fedora/EPEL, Debian, and Ubuntu all provide packages for openvpn-auth-ldap so I'm dropping the compilation step to simplify the role. * Fedora/EPEL: * Debian: From 42f3ee8edeeaba7a52975466c0d577cb6b359c95 Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 20:56:47 +0000 Subject: [PATCH 63/66] min_ansible_version apparently references ansible-core, not ansible Updating based on https://github.com/ansible/galaxy/issues/3114 --- meta/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/main.yml b/meta/main.yml index b4b28237..f075a0f3 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -6,7 +6,7 @@ galaxy_info: description: OpenVPN playbook for CentOS/Fedora/RHEL/RHEL clones & Ubuntu/Debian license: MIT - min_ansible_version: "6.0" + min_ansible_version: "2.13" platforms: - name: EL From 76bfdcf828ac0e345d94274906a3605c27f2255b Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 21:04:49 +0000 Subject: [PATCH 64/66] Activate systemd timer when the service mgr is systemd, instead of relying on ci_build variable --- tasks/server_keys.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/server_keys.yml b/tasks/server_keys.yml index 215b0cbf..0ce11c91 100644 --- a/tasks/server_keys.yml +++ b/tasks/server_keys.yml @@ -184,4 +184,4 @@ enabled: true state: started daemon_reload: true - when: ci_build is falsy + when: ansible_service_mgr == "systemd" From 5006b5e355e62f1a8fb7073cf75e02162fcc479e Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 21:05:13 +0000 Subject: [PATCH 65/66] Update variable default values in readme --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 33ea2877..66b99058 100644 --- a/README.md +++ b/README.md @@ -48,16 +48,17 @@ These options change how the role works. This is a catch-all group, specific gro | Variable | Type | Choices | Default | Comment | |------------------------------|---------|-------------|-------------------|-------------------------------------------------------------------------------| | clients | list | | [] | List of clients to add to OpenVPN | -| openvpn_base_dir | string | | /etc/openvpn | Path where your OpenVPN config will be stored | +| openvpn_base_dir | string | | /etc/openvpn/server | Path where your OpenVPN config will be stored | | openvpn_client_config_no_log | boolean | true, false | true | Prevent client configuration files to be logged to stdout by Ansible | | openvpn_key_dir | string | | /etc/openvpn/keys | Path where your server private keys and CA will be stored | | openvpn_ovpn_dir | string | | /etc/openvpn | Path where your client configurations will be stored | | openvpn_revoke_these_certs | list | | [] | List of client certificates to revoke. | | openvpn_selinux_module | string | | my-openvpn-server | Set the SELinux module name | -| openvpn_service_name | string | | openvpn | Name of the service. Used by systemctl to start the service | +| openvpn_service_name | string | | openvpn-server@{{ openvpn_config_file }}.service | Name of the service. Used by systemctl to start the service | | openvpn_sync_certs | boolean | true, false | false | Revoke certificates not explicitly defined in 'clients' | | openvpn_uninstall | boolean | true, false | false | Set to true to uninstall the OpenVPN service | | openvpn_use_ldap | boolean | true, false | false | Active LDAP backend for authentication. Client certificate not needed anymore | +| openvpn_use_prebuilt_ldap_plugin | boolean | true, false | true | Use a distro-distributed version of the LDAP plugin | ### Config fetching @@ -91,7 +92,7 @@ These options change how OpenVPN itself works. |-----------------------------|--------------|-------------------|----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------| | openvpn_client_register_dns | boolean | true, false | true | Add `register-dns` option to client config (Windows only). | | openvpn_client_to_client | boolean | true, false | false | Set to true if you want clients to access each other. | -| openvpn_custom_dns | list[string] | | [] | List of DNS servers, only applied if `openvpn_set_dns` is set to true | +| openvpn_custom_dns | list[string] | | ["1.0.0.1", "1.1.1.1", "8.8.8.8", "8.8.4.4"] | List of DNS servers, only applied if `openvpn_set_dns` is set to true | | openvpn_dualstack | boolean | | true | Whether or not to use a dualstack (IPv4 + v6) socket | | openvpn_keepalive_ping | int | | 5 | Set `keepalive` ping interval seconds. | | openvpn_keepalive_timeout | int | | 30 | Set `keepalive` timeout seconds | @@ -113,7 +114,7 @@ These options change how OpenVPN itself works. |------------------------------------|---------|-------------|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| | openvpn_auth_alg | string | | SHA256 | Set `auth` authentication algoritm. | | openvpn_ca_key | dict | | `unset` | Contain "crt" and "key". If not set, CA cert and key will be automatically generated on the target system. | -| openvpn_cipher | string | | `unset` | Set `data-cipher` option for server and client. | +| openvpn_cipher | string | | `AES-256-GCM:AES-128-GCM:AES-256-CBC` | Set `data-cipher` option for server and client. | | openvpn_crl_path | string | | `unset` | Define a path to the CRL file for server revocation check. | | openvpn_duplicate_cn | boolean | true, false | false | Add `duplicate-cn` option to server config - this allows clients to connect multiple times with the one key. NOTE: client ip addresses won't be static anymore! | | openvpn_rsa_bits | int | | 2048 | Number of bits used to protect generated certificates | From c07e3fed2bfaefaf3a3188d153528c72c9d4d0cc Mon Sep 17 00:00:00 2001 From: Kyle Lexmond Date: Tue, 24 Dec 2024 21:09:51 +0000 Subject: [PATCH 66/66] Remove tmate (remote ssh waiter) from systemd ci build --- .github/workflows/ci.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2a718ecb..670faa8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -201,11 +201,6 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - with: - limit-access-to-actor: false - detached: true - name: Login to GHCR run: echo "${{ secrets.GITHUB_TOKEN }}" | sudo podman login ghcr.io -u ${{ github.actor }} --password-stdin - name: Create container