From dd0138ba2127eac0e809d68e00ae117df56db77e Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Wed, 6 Dec 2023 17:10:56 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=AA=20Replace=20GitHub=20SVN=20integra?= =?UTF-8?q?tion=20test=20with=20local=20TLS=20(#82334)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Run svn integration test locally with TLS This patch uses a `trustme` to make an ephemeral CA, and server, and client TLS artifacts for testing. These are integrated into the Apache web server via it's `mod_ssl`. Resolves #82207 * Replace GitHub SVN HTTPS URL w/ localhost over TLS This change gets rid of the need to use GitHub, which is just about to drop support for SVN [[1]]. Moreover, it eliminates the need to use external network for any SVN commands in the test. [1]: https://github.blog/2023-01-20-sunsetting-subversion-support/ --- .../roles/subversion/defaults/main.yml | 5 +- .../roles/subversion/tasks/setup.yml | 50 +++++++++++++++++++ .../roles/subversion/tasks/tests.yml | 32 ++++++++---- .../subversion/templates/subversion.conf.j2 | 12 ++++- .../targets/subversion/vars/Alpine.yml | 1 + .../targets/subversion/vars/RedHat.yml | 1 + .../targets/subversion/vars/Ubuntu-20.yml | 2 + 7 files changed, 89 insertions(+), 14 deletions(-) diff --git a/test/integration/targets/subversion/roles/subversion/defaults/main.yml b/test/integration/targets/subversion/roles/subversion/defaults/main.yml index e647d598b60..02ecd1ea4d6 100644 --- a/test/integration/targets/subversion/roles/subversion/defaults/main.yml +++ b/test/integration/targets/subversion/roles/subversion/defaults/main.yml @@ -3,8 +3,7 @@ apache_port: 11386 # cannot use 80 as httptester overrides this subversion_test_dir: /tmp/ansible-svn-test-dir subversion_server_dir: /tmp/ansible-svn # cannot use a path in the home dir without userdir or granting exec permission to the apache user subversion_repo_name: ansible-test-repo -subversion_repo_url: http://127.0.0.1:{{ apache_port }}/svn/{{ subversion_repo_name }} -subversion_repo_auth_url: http://127.0.0.1:{{ apache_port }}/svnauth/{{ subversion_repo_name }} +subversion_repo_url: https://localhost:{{ apache_port }}/svn/{{ subversion_repo_name }} # svn can't verify TLS certificates against IP addresses +subversion_repo_auth_url: https://localhost:{{ apache_port }}/svnauth/{{ subversion_repo_name }} subversion_username: subsvn_user''' subversion_password: Password123! -subversion_external_repo_url: https://github.com/ansible/ansible.github.com # GitHub serves SVN diff --git a/test/integration/targets/subversion/roles/subversion/tasks/setup.yml b/test/integration/targets/subversion/roles/subversion/tasks/setup.yml index 92806ebe88d..e673645931e 100644 --- a/test/integration/targets/subversion/roles/subversion/tasks/setup.yml +++ b/test/integration/targets/subversion/roles/subversion/tasks/setup.yml @@ -29,6 +29,45 @@ path: '{{ subversion_server_dir }}' state: directory +- name: Generate CA and TLS certificates via trustme + vars: + venv_path: >- + {{ subversion_server_dir }}/.venv + venv_python: >- + {{ subversion_server_dir }}/.venv/bin/python + block: + - name: trustme -- provision a venv + command: >- + {{ ansible_python_interpreter }} -Im venv + {{ venv_path }} + - name: trustme -- install tool + pip: + name: trustme + virtualenv: >- + {{ venv_path }} + - name: trustme -- generate CA and TLS certs + command: + argv: + - >- + {{ venv_python }} + - -Im + - trustme + - --dir={{ subversion_server_dir }} + +- name: symlink trustme certificates into apache config dir - Red Hat + when: ansible_os_family in ['RedHat'] + file: + src: /tmp/ansible-svn/server.{{ item.trustme_filetype }} + dest: /etc/pki/tls/{{ item.apache_target_path }} + state: link + loop: + - apache_target_path: certs/localhost.crt + trustme_filetype: pem + - apache_target_path: certs/server-chain.crt + trustme_filetype: pem + - apache_target_path: private/localhost.key + trustme_filetype: key + - name: template out configuration file template: src: subversion.conf.j2 @@ -62,3 +101,14 @@ async: 3600 # We kill apache manually in the clean up phase poll: 0 when: ansible_os_family in ['RedHat'] + +- lineinfile: + dest: >- + {{ ansible_env.HOME }}/.subversion/servers + regexp: >- + ^#\s*ssl-authority-files\s*=\s* + line: >- + ssl-authority-files = {{ subversion_server_dir }}/client.pem + insertafter: >- + ^\[global\] + state: present diff --git a/test/integration/targets/subversion/roles/subversion/tasks/tests.yml b/test/integration/targets/subversion/roles/subversion/tasks/tests.yml index b8f85d95c7e..70737a19fc4 100644 --- a/test/integration/targets/subversion/roles/subversion/tasks/tests.yml +++ b/test/integration/targets/subversion/roles/subversion/tasks/tests.yml @@ -18,10 +18,11 @@ # checks out every branch so using a small repo -- name: initial checkout +- name: initial checkout with validate_certs=true subversion: repo: '{{ subversion_repo_url }}' dest: '{{ subversion_test_dir }}/svn' + validate_certs: yes register: subverted - name: check if dir was checked out @@ -130,16 +131,27 @@ - "export_branches.stat.isdir" - "subverted4.changed" -- name: clone a small external repo with validate_certs=true +- name: unconfigure client-side TLS trust + block: + - name: remove TLS CA chain file path from the SVN config + lineinfile: + dest: >- + {{ ansible_env.HOME }}/.subversion/servers + regexp: >- + ^(?:#)?\s*ssl-authority-files\s*=\s* + state: absent + - name: drop the client TLS CA chain file + file: + path: >- + {{ subversion_server_dir }}/client.pem + state: absent + +- name: >- + clone a HTTPS-accessible repo with validate_certs=false + and untrusted CA over TLS subversion: - repo: "{{ subversion_external_repo_url }}" - dest: "{{ subversion_test_dir }}/svn-external1" - validate_certs: yes - -- name: clone a small external repo with validate_certs=false - subversion: - repo: "{{ subversion_external_repo_url }}" - dest: "{{ subversion_test_dir }}/svn-external2" + repo: '{{ subversion_repo_url }}' + dest: '{{ subversion_test_dir }}/svn-untrusted-tls' validate_certs: no # TBA: test for additional options or URL variants welcome diff --git a/test/integration/targets/subversion/roles/subversion/templates/subversion.conf.j2 b/test/integration/targets/subversion/roles/subversion/templates/subversion.conf.j2 index 86f40707419..ad5f8d9cda5 100644 --- a/test/integration/targets/subversion/roles/subversion/templates/subversion.conf.j2 +++ b/test/integration/targets/subversion/roles/subversion/templates/subversion.conf.j2 @@ -19,6 +19,7 @@ LogFormat "%h %l %u %t \"%r\" %>s %O" common LogFormat "%{Referer}i -> %U" referer LogFormat "%{User-agent}i" agent +Include mods-available/ssl.load IncludeOptional mods-enabled/*.load IncludeOptional mods-enabled/*.conf IncludeOptional conf-enabled/*.conf @@ -32,11 +33,13 @@ IncludeOptional sites-enabled/*conf {% elif ansible_os_family == "FreeBSD" %} Include /usr/local/etc/apache24/httpd.conf +LoadModule ssl_module libexec/apache24/mod_ssl.so LoadModule dav_module libexec/apache24/mod_dav.so LoadModule dav_svn_module libexec/apache24/mod_dav_svn.so LoadModule authz_svn_module libexec/apache24/mod_authz_svn.so {% elif ansible_os_family == "Suse" %} Include /etc/apache2/httpd.conf +Include mods-available/ssl.load LoadModule dav_module /usr/lib64/apache2/mod_dav.so LoadModule dav_svn_module /usr/lib64/apache2/mod_dav_svn.so {% elif ansible_os_family == "Alpine" %} @@ -48,7 +51,14 @@ Include /etc/httpd/conf/httpd.conf {% endif %} PidFile {{ subversion_server_dir }}/apache.pid -Listen 127.0.0.1:{{ apache_port }} +Listen 127.0.0.1:{{ apache_port }} https +{% if ansible_distribution not in ["Alpine", "Fedora", "Ubuntu"] %} +Listen [::1]:{{ apache_port }} https +{% endif %} +SSLEngine on +SSLCertificateFile {{ subversion_server_dir }}/server.pem +SSLCertificateKeyFile {{ subversion_server_dir }}/server.key +SSLCertificateChainFile {{ subversion_server_dir }}/server.pem ErrorLog {{ subversion_server_dir }}/apache2-error.log diff --git a/test/integration/targets/subversion/vars/Alpine.yml b/test/integration/targets/subversion/vars/Alpine.yml index e224c13c495..71077b12054 100644 --- a/test/integration/targets/subversion/vars/Alpine.yml +++ b/test/integration/targets/subversion/vars/Alpine.yml @@ -5,5 +5,6 @@ subversion_packages: - apache2-webdav - apache2-utils - apache2-ctl +- apache2-ssl apache_user: apache apache_group: apache diff --git a/test/integration/targets/subversion/vars/RedHat.yml b/test/integration/targets/subversion/vars/RedHat.yml index 3e3f9109389..a3298318a02 100644 --- a/test/integration/targets/subversion/vars/RedHat.yml +++ b/test/integration/targets/subversion/vars/RedHat.yml @@ -1,6 +1,7 @@ --- subversion_packages: - mod_dav_svn +- mod_ssl - subversion upgrade_packages: # prevent sqlite from being out-of-sync with the version subversion was compiled with diff --git a/test/integration/targets/subversion/vars/Ubuntu-20.yml b/test/integration/targets/subversion/vars/Ubuntu-20.yml index dfe131b0e22..bfd880fd581 100644 --- a/test/integration/targets/subversion/vars/Ubuntu-20.yml +++ b/test/integration/targets/subversion/vars/Ubuntu-20.yml @@ -1,5 +1,7 @@ --- subversion_packages: +- apache2 # /usr/sbin/apachectl +- apache2-utils # htpasswd - subversion - libapache2-mod-svn apache_user: www-data