From 8a754e0858d922e955e71b253c139e071ecec432 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 18:04:21 +0200 Subject: Adding upstream version 2.14.3. Signed-off-by: Daniel Baumann --- .../targets/prepare_http_tests/defaults/main.yml | 5 + .../targets/prepare_http_tests/handlers/main.yml | 4 + .../prepare_http_tests/library/httptester_kinit.py | 138 +++++++++++++++++++++ .../targets/prepare_http_tests/meta/main.yml | 3 + .../targets/prepare_http_tests/tasks/default.yml | 55 ++++++++ .../targets/prepare_http_tests/tasks/kerberos.yml | 65 ++++++++++ .../targets/prepare_http_tests/tasks/main.yml | 35 ++++++ .../targets/prepare_http_tests/tasks/windows.yml | 33 +++++ .../prepare_http_tests/templates/krb5.conf.j2 | 25 ++++ .../targets/prepare_http_tests/vars/Alpine.yml | 3 + .../targets/prepare_http_tests/vars/Debian.yml | 3 + .../targets/prepare_http_tests/vars/FreeBSD.yml | 2 + .../targets/prepare_http_tests/vars/RedHat-9.yml | 4 + .../targets/prepare_http_tests/vars/Suse.yml | 3 + .../targets/prepare_http_tests/vars/default.yml | 3 + .../targets/prepare_http_tests/vars/httptester.yml | 6 + 16 files changed, 387 insertions(+) create mode 100644 test/integration/targets/prepare_http_tests/defaults/main.yml create mode 100644 test/integration/targets/prepare_http_tests/handlers/main.yml create mode 100644 test/integration/targets/prepare_http_tests/library/httptester_kinit.py create mode 100644 test/integration/targets/prepare_http_tests/meta/main.yml create mode 100644 test/integration/targets/prepare_http_tests/tasks/default.yml create mode 100644 test/integration/targets/prepare_http_tests/tasks/kerberos.yml create mode 100644 test/integration/targets/prepare_http_tests/tasks/main.yml create mode 100644 test/integration/targets/prepare_http_tests/tasks/windows.yml create mode 100644 test/integration/targets/prepare_http_tests/templates/krb5.conf.j2 create mode 100644 test/integration/targets/prepare_http_tests/vars/Alpine.yml create mode 100644 test/integration/targets/prepare_http_tests/vars/Debian.yml create mode 100644 test/integration/targets/prepare_http_tests/vars/FreeBSD.yml create mode 100644 test/integration/targets/prepare_http_tests/vars/RedHat-9.yml create mode 100644 test/integration/targets/prepare_http_tests/vars/Suse.yml create mode 100644 test/integration/targets/prepare_http_tests/vars/default.yml create mode 100644 test/integration/targets/prepare_http_tests/vars/httptester.yml (limited to 'test/integration/targets/prepare_http_tests') diff --git a/test/integration/targets/prepare_http_tests/defaults/main.yml b/test/integration/targets/prepare_http_tests/defaults/main.yml new file mode 100644 index 0000000..217b3db --- /dev/null +++ b/test/integration/targets/prepare_http_tests/defaults/main.yml @@ -0,0 +1,5 @@ +badssl_host: wrong.host.badssl.com +self_signed_host: self-signed.ansible.http.tests +httpbin_host: httpbin.org +sni_host: ci-files.testing.ansible.com +badssl_host_substring: wrong.host.badssl.com diff --git a/test/integration/targets/prepare_http_tests/handlers/main.yml b/test/integration/targets/prepare_http_tests/handlers/main.yml new file mode 100644 index 0000000..172cab7 --- /dev/null +++ b/test/integration/targets/prepare_http_tests/handlers/main.yml @@ -0,0 +1,4 @@ +- name: Remove python gssapi + pip: + name: gssapi + state: absent diff --git a/test/integration/targets/prepare_http_tests/library/httptester_kinit.py b/test/integration/targets/prepare_http_tests/library/httptester_kinit.py new file mode 100644 index 0000000..4f7b7ad --- /dev/null +++ b/test/integration/targets/prepare_http_tests/library/httptester_kinit.py @@ -0,0 +1,138 @@ +#!/usr/bin/python + +# Copyright: (c) 2020, Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = r''' +--- +module: httptester_kinit +short_description: Get Kerberos ticket +description: Get Kerberos ticket using kinit non-interactively. +options: + username: + description: The username to get the ticket for. + required: true + type: str + password: + description: The password for I(username). + required; true + type: str +author: +- Ansible Project +''' + +EXAMPLES = r''' +# +''' + +RETURN = r''' +# +''' + +import contextlib +import errno +import os +import subprocess + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.common.text.converters import to_bytes, to_text + +try: + import configparser +except ImportError: + import ConfigParser as configparser + + +@contextlib.contextmanager +def env_path(name, value, default_value): + """ Adds a value to a PATH-like env var and preserve the existing value if present. """ + orig_value = os.environ.get(name, None) + os.environ[name] = '%s:%s' % (value, orig_value or default_value) + try: + yield + + finally: + if orig_value: + os.environ[name] = orig_value + + else: + del os.environ[name] + + +@contextlib.contextmanager +def krb5_conf(module, config): + """ Runs with a custom krb5.conf file that extends the existing config if present. """ + if config: + ini_config = configparser.ConfigParser() + for section, entries in config.items(): + ini_config.add_section(section) + for key, value in entries.items(): + ini_config.set(section, key, value) + + config_path = os.path.join(module.tmpdir, 'krb5.conf') + with open(config_path, mode='wt') as config_fd: + ini_config.write(config_fd) + + with env_path('KRB5_CONFIG', config_path, '/etc/krb5.conf'): + yield + + else: + yield + + +def main(): + module_args = dict( + username=dict(type='str', required=True), + password=dict(type='str', required=True, no_log=True), + ) + module = AnsibleModule( + argument_spec=module_args, + required_together=[('username', 'password')], + ) + + # Heimdal has a few quirks that we want to paper over in this module + # 1. KRB5_TRACE does not work in any released version (<=7.7), we need to use a custom krb5.config to enable it + # 2. When reading the password it reads from the pty not stdin by default causing an issue with subprocess. We + # can control that behaviour with '--password-file=STDIN' + # Also need to set the custom path to krb5-config and kinit as FreeBSD relies on the newer Heimdal version in the + # port package. + sysname = os.uname()[0] + prefix = '/usr/local/bin/' if sysname == 'FreeBSD' else '' + is_heimdal = sysname in ['Darwin', 'FreeBSD'] + + # Debugging purposes, get the Kerberos version. On platforms like OpenSUSE this may not be on the PATH. + try: + process = subprocess.Popen(['%skrb5-config' % prefix, '--version'], stdout=subprocess.PIPE) + stdout, stderr = process.communicate() + version = to_text(stdout) + except OSError as e: + if e.errno != errno.ENOENT: + raise + version = 'Unknown (no krb5-config)' + + kinit_args = ['%skinit' % prefix] + config = {} + if is_heimdal: + kinit_args.append('--password-file=STDIN') + config['logging'] = {'krb5': 'FILE:/dev/stdout'} + kinit_args.append(to_text(module.params['username'], errors='surrogate_or_strict')) + + with krb5_conf(module, config): + # Weirdly setting KRB5_CONFIG in the modules environment block does not work unless we pass it in explicitly. + # Take a copy of the existing environment to make sure the process has the same env vars as ours. Also set + # KRB5_TRACE to output and debug logs helping to identify problems when calling kinit with MIT. + kinit_env = os.environ.copy() + kinit_env['KRB5_TRACE'] = '/dev/stdout' + + process = subprocess.Popen(kinit_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + env=kinit_env) + stdout, stderr = process.communicate(to_bytes(module.params['password'], errors='surrogate_or_strict') + b'\n') + rc = process.returncode + + module.exit_json(changed=True, stdout=to_text(stdout), stderr=to_text(stderr), rc=rc, version=version) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/prepare_http_tests/meta/main.yml b/test/integration/targets/prepare_http_tests/meta/main.yml new file mode 100644 index 0000000..c2c543a --- /dev/null +++ b/test/integration/targets/prepare_http_tests/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - setup_remote_tmp_dir + - setup_remote_constraints diff --git a/test/integration/targets/prepare_http_tests/tasks/default.yml b/test/integration/targets/prepare_http_tests/tasks/default.yml new file mode 100644 index 0000000..2fb26a1 --- /dev/null +++ b/test/integration/targets/prepare_http_tests/tasks/default.yml @@ -0,0 +1,55 @@ +- name: RedHat - Enable the dynamic CA configuration feature + command: update-ca-trust force-enable + when: ansible_os_family == 'RedHat' + +- name: RedHat - Retrieve test cacert + get_url: + url: "http://ansible.http.tests/cacert.pem" + dest: "/etc/pki/ca-trust/source/anchors/ansible.pem" + when: ansible_os_family == 'RedHat' + +- name: Get client cert/key + get_url: + url: "http://ansible.http.tests/{{ item }}" + dest: "{{ remote_tmp_dir }}/{{ item }}" + with_items: + - client.pem + - client.key + +- name: Suse - Retrieve test cacert + get_url: + url: "http://ansible.http.tests/cacert.pem" + dest: "/etc/pki/trust/anchors/ansible.pem" + when: ansible_os_family == 'Suse' + +- name: Debian/Alpine - Retrieve test cacert + get_url: + url: "http://ansible.http.tests/cacert.pem" + dest: "/usr/local/share/ca-certificates/ansible.crt" + when: ansible_os_family in ['Debian', 'Alpine'] + +- name: Redhat - Update ca trust + command: update-ca-trust extract + when: ansible_os_family == 'RedHat' + +- name: Debian/Alpine/Suse - Update ca certificates + command: update-ca-certificates + when: ansible_os_family in ['Debian', 'Alpine', 'Suse'] + +- name: Update cacert + when: ansible_os_family in ['FreeBSD', 'Darwin'] + block: + - name: Retrieve test cacert + uri: + url: "http://ansible.http.tests/cacert.pem" + return_content: true + register: cacert_pem + + - name: Locate cacert + command: '{{ ansible_python_interpreter }} -c "import ssl; print(ssl.get_default_verify_paths().cafile)"' + register: cafile_path + + - name: Update cacert + blockinfile: + path: "{{ cafile_path.stdout_lines|first }}" + block: "{{ cacert_pem.content }}" diff --git a/test/integration/targets/prepare_http_tests/tasks/kerberos.yml b/test/integration/targets/prepare_http_tests/tasks/kerberos.yml new file mode 100644 index 0000000..2678b46 --- /dev/null +++ b/test/integration/targets/prepare_http_tests/tasks/kerberos.yml @@ -0,0 +1,65 @@ +- set_fact: + krb5_config: '{{ remote_tmp_dir }}/krb5.conf' + krb5_realm: '{{ httpbin_host.split(".")[1:] | join(".") | upper }}' + krb5_provider: '{{ (ansible_facts.os_family == "FreeBSD" or ansible_facts.distribution == "MacOSX") | ternary("Heimdal", "MIT") }}' + +- set_fact: + krb5_username: admin@{{ krb5_realm }} + +- name: Create krb5.conf file + template: + src: krb5.conf.j2 + dest: '{{ krb5_config }}' + +- name: Include distribution specific variables + include_vars: '{{ lookup("first_found", params) }}' + vars: + params: + files: + - '{{ ansible_facts.distribution }}-{{ ansible_facts.distribution_major_version }}.yml' + - '{{ ansible_facts.os_family }}-{{ ansible_facts.distribution_major_version }}.yml' + - '{{ ansible_facts.distribution }}.yml' + - '{{ ansible_facts.os_family }}.yml' + - default.yml + paths: + - '{{ role_path }}/vars' + +- name: Install Kerberos sytem packages + package: + name: '{{ krb5_packages }}' + state: present + when: ansible_facts.distribution not in ['Alpine', 'MacOSX'] + +# apk isn't available on ansible-core so just call command +- name: Alpine - Install Kerberos system packages + command: apk add {{ krb5_packages | join(' ') }} + when: ansible_facts.distribution == 'Alpine' + +- name: Install python gssapi + pip: + name: + - decorator < 5.0.0 ; python_version < '3.5' # decorator 5.0.5 and later require python 3.5 or later + - gssapi < 1.6.0 ; python_version <= '2.7' # gssapi 1.6.0 and later require python 3 or later + - gssapi ; python_version > '2.7' + - importlib ; python_version < '2.7' + state: present + extra_args: '-c {{ remote_constraints }}' + environment: + # Put /usr/local/bin for FreeBSD as we need to use the heimdal port over the builtin version + # https://github.com/pythongssapi/python-gssapi/issues/228 + # Need the /usr/lib/mit/bin custom path for OpenSUSE as krb5-config is placed there + PATH: '/usr/local/bin:{{ ansible_facts.env.PATH }}:/usr/lib/mit/bin' + notify: Remove python gssapi + +- name: test the environment to make sure Kerberos is working properly + httptester_kinit: + username: '{{ krb5_username }}' + password: '{{ krb5_password }}' + environment: + KRB5_CONFIG: '{{ krb5_config }}' + KRB5CCNAME: FILE:{{ remote_tmp_dir }}/krb5.cc + +- name: remove test credential cache + file: + path: '{{ remote_tmp_dir }}/krb5.cc' + state: absent diff --git a/test/integration/targets/prepare_http_tests/tasks/main.yml b/test/integration/targets/prepare_http_tests/tasks/main.yml new file mode 100644 index 0000000..8d34a3c --- /dev/null +++ b/test/integration/targets/prepare_http_tests/tasks/main.yml @@ -0,0 +1,35 @@ +# The docker --link functionality gives us an ENV var we can key off of to see if we have access to +# the httptester container +- set_fact: + has_httptester: "{{ lookup('env', 'HTTPTESTER') != '' }}" + +- name: make sure we have the ansible_os_family and ansible_distribution_version facts + setup: + gather_subset: distribution + when: ansible_facts == {} + +# If we are running with access to a httptester container, grab it's cacert and install it +- block: + # Override hostname defaults with httptester linked names + - include_vars: httptester.yml + + - include_tasks: "{{ lookup('first_found', files)}}" + vars: + files: + - "{{ ansible_os_family | lower }}-{{ ansible_distribution_major_version }}.yml" + - "{{ ansible_os_family | lower }}.yml" + - "default.yml" + when: + - has_httptester|bool + # skip the setup if running on Windows Server 2008 as httptester is not available + - ansible_os_family != 'Windows' or (ansible_os_family == 'Windows' and not ansible_distribution_version.startswith("6.0.")) + +- set_fact: + krb5_password: "{{ lookup('env', 'KRB5_PASSWORD') }}" + +- name: setup Kerberos client + include_tasks: kerberos.yml + when: + - has_httptester|bool + - ansible_os_family != 'Windows' + - krb5_password != '' diff --git a/test/integration/targets/prepare_http_tests/tasks/windows.yml b/test/integration/targets/prepare_http_tests/tasks/windows.yml new file mode 100644 index 0000000..da8b0eb --- /dev/null +++ b/test/integration/targets/prepare_http_tests/tasks/windows.yml @@ -0,0 +1,33 @@ +# Server 2008 R2 uses a 3rd party program to foward the ports and it may +# not be ready straight away, we give it at least 5 minutes before +# conceding defeat +- name: Windows - make sure the port forwarder is active + win_wait_for: + host: ansible.http.tests + port: 80 + state: started + timeout: 300 + +- name: Windows - Get client cert/key + win_get_url: + url: http://ansible.http.tests/{{ item }} + dest: '{{ remote_tmp_dir }}\{{ item }}' + register: win_download + # Server 2008 R2 is slightly slower, we attempt 5 retries + retries: 5 + until: win_download is successful + with_items: + - client.pem + - client.key + +- name: Windows - Retrieve test cacert + win_get_url: + url: http://ansible.http.tests/cacert.pem + dest: '{{ remote_tmp_dir }}\cacert.pem' + +- name: Windows - Update ca trust + win_certificate_store: + path: '{{ remote_tmp_dir }}\cacert.pem' + state: present + store_location: LocalMachine + store_name: Root diff --git a/test/integration/targets/prepare_http_tests/templates/krb5.conf.j2 b/test/integration/targets/prepare_http_tests/templates/krb5.conf.j2 new file mode 100644 index 0000000..3ddfe5e --- /dev/null +++ b/test/integration/targets/prepare_http_tests/templates/krb5.conf.j2 @@ -0,0 +1,25 @@ +[libdefaults] + default_realm = {{ krb5_realm | upper }} + dns_lookup_realm = false + dns_lookup_kdc = false + rdns = false + +[realms] + {{ krb5_realm | upper }} = { +{% if krb5_provider == 'Heimdal' %} +{# Heimdal seems to only use UDP unless TCP is explicitly set and we must use TCP as the SSH tunnel only supports TCP. #} +{# The hostname doesn't seem to work when using the alias, just use localhost as that works. #} + kdc = tcp/127.0.0.1 + admin_server = tcp/127.0.0.1 +{% else %} + kdc = {{ httpbin_host }} + admin_server = {{ httpbin_host }} +{% endif %} + } + +[domain_realm] + .{{ krb5_realm | lower }} = {{ krb5_realm | upper }} + {{ krb5_realm | lower }} = {{ krb5_realm | upper }} + +[logging] + krb5 = FILE:/dev/stdout diff --git a/test/integration/targets/prepare_http_tests/vars/Alpine.yml b/test/integration/targets/prepare_http_tests/vars/Alpine.yml new file mode 100644 index 0000000..2ac6a38 --- /dev/null +++ b/test/integration/targets/prepare_http_tests/vars/Alpine.yml @@ -0,0 +1,3 @@ +krb5_packages: +- krb5 +- krb5-dev diff --git a/test/integration/targets/prepare_http_tests/vars/Debian.yml b/test/integration/targets/prepare_http_tests/vars/Debian.yml new file mode 100644 index 0000000..2b6f9b8 --- /dev/null +++ b/test/integration/targets/prepare_http_tests/vars/Debian.yml @@ -0,0 +1,3 @@ +krb5_packages: +- krb5-user +- libkrb5-dev diff --git a/test/integration/targets/prepare_http_tests/vars/FreeBSD.yml b/test/integration/targets/prepare_http_tests/vars/FreeBSD.yml new file mode 100644 index 0000000..752b536 --- /dev/null +++ b/test/integration/targets/prepare_http_tests/vars/FreeBSD.yml @@ -0,0 +1,2 @@ +krb5_packages: +- heimdal diff --git a/test/integration/targets/prepare_http_tests/vars/RedHat-9.yml b/test/integration/targets/prepare_http_tests/vars/RedHat-9.yml new file mode 100644 index 0000000..2618233 --- /dev/null +++ b/test/integration/targets/prepare_http_tests/vars/RedHat-9.yml @@ -0,0 +1,4 @@ +krb5_packages: +- krb5-devel +- krb5-workstation +- redhat-rpm-config # needed for gssapi install diff --git a/test/integration/targets/prepare_http_tests/vars/Suse.yml b/test/integration/targets/prepare_http_tests/vars/Suse.yml new file mode 100644 index 0000000..0e159c4 --- /dev/null +++ b/test/integration/targets/prepare_http_tests/vars/Suse.yml @@ -0,0 +1,3 @@ +krb5_packages: +- krb5-client +- krb5-devel diff --git a/test/integration/targets/prepare_http_tests/vars/default.yml b/test/integration/targets/prepare_http_tests/vars/default.yml new file mode 100644 index 0000000..5bc07d5 --- /dev/null +++ b/test/integration/targets/prepare_http_tests/vars/default.yml @@ -0,0 +1,3 @@ +krb5_packages: +- krb5-devel +- krb5-workstation diff --git a/test/integration/targets/prepare_http_tests/vars/httptester.yml b/test/integration/targets/prepare_http_tests/vars/httptester.yml new file mode 100644 index 0000000..26acf11 --- /dev/null +++ b/test/integration/targets/prepare_http_tests/vars/httptester.yml @@ -0,0 +1,6 @@ +# these are fake hostnames provided by docker link for the httptester container +badssl_host: fail.ansible.http.tests +httpbin_host: ansible.http.tests +sni_host: sni1.ansible.http.tests +badssl_host_substring: HTTP Client Testing Service +self_signed_host: self-signed.ansible.http.tests -- cgit v1.2.3