Hello community, here is the log from the commit of package aws-efs-utils for openSUSE:Factory checked in at 2019-12-18 14:45:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/aws-efs-utils (Old) and /work/SRC/openSUSE:Factory/.aws-efs-utils.new.4691 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "aws-efs-utils" Wed Dec 18 14:45:06 2019 rev:4 rq:757622 version:1.17 Changes: -------- --- /work/SRC/openSUSE:Factory/aws-efs-utils/aws-efs-utils.changes 2019-04-11 08:48:00.800542966 +0200 +++ /work/SRC/openSUSE:Factory/.aws-efs-utils.new.4691/aws-efs-utils.changes 2019-12-18 14:48:19.621938854 +0100 @@ -1,0 +2,38 @@ +Tue Dec 17 20:14:25 UTC 2019 - John Paul Adrian Glaubitz <[email protected]> + +- Update to version 1.17 + + Added support for Python 3 +- Enable testsuite which now passes on Python 3 +- Update BuildRequires from requirements.txt + +------------------------------------------------------------------- +Thu Dec 5 11:42:38 UTC 2019 - John Paul Adrian Glaubitz <[email protected]> + +- Update to version 1.16 + + Support Python 3 for tests +- from version 1.15 + + Properly support Python3 +- from version 1.14 + + Tolerate EFS state directory existing during mount +- from version 1.13 + + Change watchdog configuration so it stops after all file systems are unmounted +- from version 1.12 + + Update stunnel idle timeout + * The default stunnel idle timeout is many hours. By setting it to a value based + on the NFS lease length we can recover from network partitions sooner. +- from version 1.11 + + Add support for RHEL8 + * Fixes Python shebangs to work on systems without a default "python" version. + * Fixes watchdog process not being properly started on systemd systems. +- from version 1.10 + + Update to default configuration that disables OCSP + * To use OCSP, the client accessing EFS must be able to reach the Amazon Certificate + Authority (CA). To maximize file system availability in the event that the CA is + not reachable from your VPC, the EFS mount helper no longer enables OCSP by default. +- Don't enable testsuite as it is currently failing + + https://github.com/aws/efs-utils/issues/24 +- Drop patches merged upstream + + efs-switchparser.patch +- Update BuildRequires from requirements.txt + +------------------------------------------------------------------- Old: ---- efs-switchparser.patch v1.7.tar.gz New: ---- v1.17.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ aws-efs-utils.spec ++++++ --- /var/tmp/diff_new_pack.XQu5q4/_old 2019-12-18 14:48:20.001939028 +0100 +++ /var/tmp/diff_new_pack.XQu5q4/_new 2019-12-18 14:48:20.001939028 +0100 @@ -1,7 +1,7 @@ # # spec file for package aws-efs-utils # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,14 +17,29 @@ Name: aws-efs-utils -Version: 1.7 +Version: 1.17 Release: 0 Summary: Utilities for using the EFS file systems License: MIT Group: System/Management -Url: https://github.com/aws/efs-utils +URL: https://github.com/aws/efs-utils Source0: https://github.com/aws/efs-utils/archive/v%{version}.tar.gz -Patch: efs-switchparser.patch +BuildRequires: python3-attrs >= 17.4.0 +BuildRequires: python3-coverage >= 4.5 +BuildRequires: python3-flake8 >= 3.7.9 +BuildRequires: python3-mccabe >= 0.6.1 +BuildRequires: python3-mock >= 2.0.0 +BuildRequires: python3-pbr >= 3.1.1 +BuildRequires: python3-pluggy >= 0.13.0 +BuildRequires: python3-py >= 1.8.0 +BuildRequires: python3-pycodestyle >= 2.5.0 +BuildRequires: python3-pyflakes >= 2.1.1 +BuildRequires: python3-pytest >= 4.6.7 +BuildRequires: python3-pytest-cov >= 2.8.1 +BuildRequires: python3-pytest-html >= 1.19.0 +BuildRequires: python3-pytest-metadata >= 1.7.0 +BuildRequires: python3-pytest-mock >= 1.11.2 +BuildRequires: python3-six >= 1.11.0 BuildRequires: systemd BuildRequires: systemd-rpm-macros Requires: nfs-utils @@ -38,11 +53,13 @@ %prep %setup -n efs-utils-%{version} find . -name "*.py" -exec sed -i 's/env python/python3/' {} + -%patch -p1 %build # No build required +%check +make test + %install mkdir -p %{buildroot}%{_sysconfdir}/amazon/efs mkdir -p %{buildroot}%{_unitdir} ++++++ v1.7.tar.gz -> v1.17.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/Makefile new/efs-utils-1.17/Makefile --- old/efs-utils-1.7/Makefile 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/Makefile 2019-12-17 19:21:01.000000000 +0100 @@ -45,6 +45,10 @@ .PHONY: sources sources: tarball specfile +.PHONY: rhel8-support +rhel8-support: + ./rhel8-support.sh + .PHONY: rpm-only rpm-only: mkdir -p $(BUILD_DIR)/{SPECS,COORD_SOURCES,DATA_SOURCES,BUILD,RPMS,SOURCES,SRPMS} @@ -54,7 +58,7 @@ cp $(BUILD_DIR)/RPMS/*/*rpm build .PHONY: rpm -rpm: sources rpm-only +rpm: rhel8-support sources rpm-only .PHONY: deb deb: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/README.md new/efs-utils-1.17/README.md --- old/efs-utils-1.7/README.md 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/README.md 2019-12-17 19:21:01.000000000 +0100 @@ -10,6 +10,7 @@ | Amazon Linux 2 | `rpm` | `systemd` | | CentOS 7 | `rpm` | `systemd` | | RHEL 7 | `rpm`| `systemd` | +| RHEL 8 | `rpm`| `systemd` | | Debian 9 | `deb` | `systemd` | | Ubuntu 16.04 | `deb` | `systemd` | @@ -112,7 +113,7 @@ ## Upgrading stunnel for RHEL/CentOS -By default, when using the EFS mount helper with TLS, it enforces use of the Online Certificate Status Protocol (OCSP) and certificate hostname checking. The EFS mount helper uses the `stunnel` program for its TLS functionality. Please note that some versions of Linux do not include a version of `stunnel` that supports these TLS features by default. When using such a Linux version, mounting an EFS file system using TLS will fail. +By default, when using the EFS mount helper with TLS, it enforces certificate hostname checking. The EFS mount helper uses the `stunnel` program for its TLS functionality. Please note that some versions of Linux do not include a version of `stunnel` that supports TLS features by default. When using such a Linux version, mounting an EFS file system using TLS will fail. Once you’ve installed the `amazon-efs-utils` package, to upgrade your system’s version of `stunnel`, see [Upgrading Stunnel](https://docs.aws.amazon.com/efs/latest/ug/using-amazon-efs-utils.html#upgrading-stunnel). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/build-deb.sh new/efs-utils-1.17/build-deb.sh --- old/efs-utils-1.7/build-deb.sh 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/build-deb.sh 2019-12-17 19:21:01.000000000 +0100 @@ -11,7 +11,7 @@ BASE_DIR=$(pwd) BUILD_ROOT=${BASE_DIR}/build/debbuild -VERSION=1.7 +VERSION=1.17 echo 'Cleaning deb build workspace' rm -rf ${BUILD_ROOT} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/dist/amazon-efs-mount-watchdog.service new/efs-utils-1.17/dist/amazon-efs-mount-watchdog.service --- old/efs-utils-1.7/dist/amazon-efs-mount-watchdog.service 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/dist/amazon-efs-mount-watchdog.service 2019-12-17 19:21:01.000000000 +0100 @@ -8,6 +8,7 @@ [Unit] Description=amazon-efs-mount-watchdog +Before=remote-fs-pre.target [Service] Type=simple diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/dist/amazon-efs-utils.control new/efs-utils-1.17/dist/amazon-efs-utils.control --- old/efs-utils-1.7/dist/amazon-efs-utils.control 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/dist/amazon-efs-utils.control 2019-12-17 19:21:01.000000000 +0100 @@ -1,6 +1,6 @@ Package: amazon-efs-utils Architecture: all -Version: 1.7 +Version: 1.17 Section: utils Depends: python|python2, nfs-common, stunnel4 (>= 4.56) Priority: optional diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/dist/amazon-efs-utils.spec new/efs-utils-1.17/dist/amazon-efs-utils.spec --- old/efs-utils-1.7/dist/amazon-efs-utils.spec 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/dist/amazon-efs-utils.spec 2019-12-17 19:21:01.000000000 +0100 @@ -20,7 +20,7 @@ %endif Name : amazon-efs-utils -Version : 1.7 +Version : 1.17 Release : 1%{?dist} Summary : This package provides utilities for simplifying the use of EFS file systems diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/dist/efs-utils.conf new/efs-utils-1.17/dist/efs-utils.conf --- old/efs-utils-1.7/dist/efs-utils.conf 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/dist/efs-utils.conf 2019-12-17 19:21:01.000000000 +0100 @@ -21,7 +21,7 @@ stunnel_check_cert_hostname = true # Use OCSP to check certificate validity. This option is not supported by certain stunnel versions. -stunnel_check_cert_validity = true +stunnel_check_cert_validity = false # Define the port range that the TLS tunnel will choose from port_range_lower_bound = 20049 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/man/mount.efs.8 new/efs-utils-1.17/man/mount.efs.8 --- old/efs-utils-1.7/man/mount.efs.8 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/man/mount.efs.8 2019-12-17 19:21:01.000000000 +0100 @@ -76,6 +76,11 @@ \fBverify=\fR\fIn\fR Verify TLS certificates using the specified stunnel verify level\&. For \ more information, see \fBstunnel(8)\fR\&. +.TP +\fBocsp / noocsp\fR +Selects whether to perform OCSP validation on TLS certificates\&, \ +overriding /etc/amazon/efs/efs-utils.conf. \ +For more information, see \fBstunnel(8)\fR\&. .if n \{\ .RE .\} @@ -97,6 +102,10 @@ Mount an EFS file system with file system ID "fs-abcd1234" at mount point \ "/mnt/efs" using encryption of data in transit and a verify level of 0\&. .TP +sudo mount -t efs -o tls,ocsp fs-abcd1234 /mnt/efs +Mount an EFS file system with file system ID "fs-abcd1234" at mount point \ +"/mnt/efs" using encryption of data in transit and with OCSP validation enabled\&. +.TP sudo mount -t efs custom-cname.example.com /mnt/efs Mount an EFS file system using the custom DNS name \ "custom-cname\&.example\&.com" \(em which has to \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/requirements.txt new/efs-utils-1.17/requirements.txt --- old/efs-utils-1.7/requirements.txt 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/requirements.txt 2019-12-17 19:21:01.000000000 +0100 @@ -2,18 +2,18 @@ configparser==3.5.0 coverage==4.5 enum34==1.1.6 -flake8==3.5.0 +flake8==3.7.9 funcsigs==1.0.2 mccabe==0.6.1 mock==2.0.0 pbr==3.1.1 -pluggy==0.6.0 -py==1.5.2 -pycodestyle==2.3.1 -pyflakes==1.6.0 -pytest==3.4.0 -pytest-cov==2.5.1 -pytest-html==1.16.1 -pytest-metadata==1.6.0 -pytest-mock==1.6.3 +pluggy==0.13.0 +py==1.8.0 +pycodestyle==2.5.0 +pyflakes==2.1.1 +pytest==4.6.7 +pytest-cov==2.8.1 +pytest-html==1.19.0 +pytest-metadata==1.7.0 +pytest-mock==1.11.2 six==1.11.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/rhel8-support.sh new/efs-utils-1.17/rhel8-support.sh --- old/efs-utils-1.7/rhel8-support.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/efs-utils-1.17/rhel8-support.sh 2019-12-17 19:21:01.000000000 +0100 @@ -0,0 +1,9 @@ +#!/bin/bash + +SYSTEM_RELEASE_PATH=/etc/system-release + +if [ -f $SYSTEM_RELEASE_PATH ] && [[ "$(cat $SYSTEM_RELEASE_PATH)" =~ "Red Hat Enterprise Linux release 8" ]]; then + # Replace the first line in .py to "#!/usr/bin/env python2" no matter what it was before + sed -i -e '1 s/^.*$/\#!\/usr\/bin\/env python2/' src/watchdog/__init__.py + sed -i -e '1 s/^.*$/\#!\/usr\/bin\/env python2/' src/mount_efs/__init__.py +fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/src/mount_efs/__init__.py new/efs-utils-1.17/src/mount_efs/__init__.py --- old/efs-utils-1.7/src/mount_efs/__init__.py 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/src/mount_efs/__init__.py 2019-12-17 19:21:01.000000000 +0100 @@ -30,6 +30,7 @@ # # The script will add recommended mount options, if not provided in fstab. +import errno import json import logging import os @@ -44,6 +45,11 @@ from logging.handlers import RotatingFileHandler try: + from ConfigParser import NoOptionError +except Exception: + from configparser import NoOptionError + +try: import ConfigParser except ImportError: from configparser import ConfigParser @@ -54,7 +60,7 @@ from urllib.error import URLError from urllib.request import urlopen -VERSION = '1.7' +VERSION = '1.17' CONFIG_FILE = '/etc/amazon/efs/efs-utils.conf' CONFIG_SECTION = 'mount' @@ -65,7 +71,7 @@ STATE_FILE_DIR = '/var/run/efs' FS_ID_RE = re.compile('^(?P<fs_id>fs-[0-9a-f]+)$') -EFS_FQDN_RE = re.compile('^(?P<fs_id>fs-[0-9a-f]+)\.efs\.(?P<region>[a-z0-9-]+)\.amazonaws.com$') +EFS_FQDN_RE = re.compile(r'^(?P<fs_id>fs-[0-9a-f]+)\.efs\.(?P<region>[a-z0-9-]+)\.amazonaws.com$') INSTANCE_METADATA_SERVICE_URL = 'http://169.254.169.254/latest/dynamic/instance-identity/document/' @@ -76,6 +82,8 @@ 'tls', 'tlsport', 'verify', + 'ocsp', + 'noocsp' ] UNSUPPORTED_OPTIONS = [ @@ -100,11 +108,13 @@ 'renegotiation': 'no', 'TIMEOUTbusy': '20', 'TIMEOUTclose': '0', - 'libwrap': 'no', + 'TIMEOUTidle': '70', 'delay': 'yes', } WATCHDOG_SERVICE = 'amazon-efs-mount-watchdog' +SYSTEM_RELEASE_PATH = '/etc/system-release' +RHEL8_RELEASE_NAME = 'Red Hat Enterprise Linux release 8' def fatal_error(user_message, log_message=None, exit_code=1): @@ -169,19 +179,24 @@ return lower_bound, upper_bound -def choose_tls_port(config): - lower_bound, upper_bound = get_tls_port_range(config) +def choose_tls_port(config, options): + if 'tlsport' in options: + try: + ports_to_try = [int(options['tlsport'])] + except ValueError: + fatal_error('tlsport option [%s] is not an integer' % options['tlsport']) + else: + lower_bound, upper_bound = get_tls_port_range(config) - tls_ports = list(range(lower_bound, upper_bound)) + tls_ports = list(range(lower_bound, upper_bound)) - # Choose a random midpoint, and then try ports in-order from there - mid = random.randrange(len(tls_ports)) + # Choose a random midpoint, and then try ports in-order from there + mid = random.randrange(len(tls_ports)) - ports_to_try = tls_ports[mid:] + tls_ports[:mid] - assert len(tls_ports) == len(ports_to_try) + ports_to_try = tls_ports[mid:] + tls_ports[:mid] + assert len(tls_ports) == len(ports_to_try) sock = socket.socket() - for tls_port in ports_to_try: try: sock.bind(('localhost', tls_port)) @@ -192,9 +207,22 @@ sock.close() - fatal_error('Failed to locate an available port in the range [%d, %d], ' - 'try specifying a different port range in %s' - % (lower_bound, upper_bound, CONFIG_FILE)) + if 'tlsport' in options: + fatal_error('Specified port [%s] is unavailable. Try selecting a different port.' % options['tlsport']) + else: + fatal_error('Failed to locate an available port in the range [%d, %d], try specifying a different port range in %s' + % (lower_bound, upper_bound, CONFIG_FILE)) + + +def is_ocsp_enabled(config, options): + if 'ocsp' in options and 'noocsp' in options: + fatal_error('The "ocsp" and "noocsp" options are mutually exclusive') + elif 'ocsp' in options: + return True + elif 'noocsp' in options: + return False + else: + return config.getboolean(CONFIG_SECTION, 'stunnel_check_cert_validity') def get_mount_specific_filename(fs_id, mountpoint, tls_port): @@ -232,7 +260,7 @@ break if not supported: - logging.warn('stunnel does not support "%s"', stunnel_option_name) + logging.warning('stunnel does not support "%s"', stunnel_option_name) return supported @@ -250,7 +278,19 @@ return check_host_supported, ocsp_aia_supported -def write_stunnel_config_file(config, state_file_dir, fs_id, mountpoint, tls_port, dns_name, verify_level, log_dir=LOG_DIR): +def get_system_release_version(): + system_release_version = 'unknown' + try: + with open(SYSTEM_RELEASE_PATH) as f: + system_release_version = f.read().strip() + except IOError: + logging.debug('Unable to read %s', SYSTEM_RELEASE_PATH) + + return system_release_version + + +def write_stunnel_config_file(config, state_file_dir, fs_id, mountpoint, tls_port, dns_name, verify_level, ocsp_enabled, + log_dir=LOG_DIR): """ Serializes stunnel configuration to a file. Unfortunately this does not conform to Python's config file format, so we have to hand-serialize it. @@ -282,12 +322,16 @@ else: fatal_error(tls_controls_message % 'stunnel_check_cert_hostname') - if config.getboolean(CONFIG_SECTION, 'stunnel_check_cert_validity'): + # Only use the config setting if the override is not set + if ocsp_enabled: if ocsp_aia_supported: efs_config['OCSPaia'] = 'yes' else: fatal_error(tls_controls_message % 'stunnel_check_cert_validity') + if RHEL8_RELEASE_NAME not in get_system_release_version(): + efs_config['libwrap'] = 'no' + stunnel_config = '\n'.join(serialize_stunnel_config(global_config) + serialize_stunnel_config(efs_config, 'efs')) logging.debug('Writing stunnel configuration:\n%s', stunnel_config) @@ -352,11 +396,7 @@ return init_system -def check_network_status(fs_id, init_system): - if init_system != 'systemd': - logging.debug('Not testing network on non-systemd init systems') - return - +def check_network_target(fs_id): with open(os.devnull, 'w') as devnull: rc = subprocess.call(['systemctl', 'status', 'network.target'], stdout=devnull, stderr=devnull, close_fds=True) @@ -365,6 +405,14 @@ exit_code=0) +def check_network_status(fs_id, init_system): + if init_system != 'systemd': + logging.debug('Not testing network on non-systemd init systems') + return + + check_network_target(fs_id) + + def start_watchdog(init_system): if init_system == 'init': proc = subprocess.Popen( @@ -397,11 +445,15 @@ try: mode = int(mode_str, 8) except ValueError: - logging.warn('Bad state_file_dir_mode "%s" in config file "%s"', mode_str, CONFIG_FILE) - except ConfigParser.NoOptionError: + logging.warning('Bad state_file_dir_mode "%s" in config file "%s"', mode_str, CONFIG_FILE) + except NoOptionError: pass - os.makedirs(state_file_dir, mode) + try: + os.makedirs(state_file_dir, mode) + except OSError as e: + if errno.EEXIST != e.errno or not os.path.isdir(state_file_dir): + raise @contextmanager @@ -411,12 +463,17 @@ if not os.path.exists(state_file_dir): create_state_file_dir(config, state_file_dir) - tls_port = choose_tls_port(config) + tls_port = choose_tls_port(config, options) + + # override the tlsport option so that we can later override the port the NFS client uses to connect to stunnel. + # if the user has specified tlsport=X at the command line this will just re-set tlsport to X. options['tlsport'] = tls_port + verify_level = int(options.get('verify', DEFAULT_STUNNEL_VERIFY_LEVEL)) - options['verify'] = verify_level + ocsp_enabled = is_ocsp_enabled(config, options) - stunnel_config_file = write_stunnel_config_file(config, state_file_dir, fs_id, mountpoint, tls_port, dns_name, verify_level) + stunnel_config_file = write_stunnel_config_file(config, state_file_dir, fs_id, mountpoint, tls_port, dns_name, verify_level, + ocsp_enabled) tunnel_args = ['stunnel', stunnel_config_file] @@ -537,7 +594,10 @@ def read_config(config_file=CONFIG_FILE): - p = ConfigParser.SafeConfigParser() + try: + p = ConfigParser.SafeConfigParser() + except AttributeError: + p = ConfigParser() p.read(config_file) return p @@ -617,7 +677,7 @@ try: primary, secondaries, _ = socket.gethostbyname_ex(remote) - hostnames = filter(lambda e: e is not None, [primary] + secondaries) + hostnames = list(filter(lambda e: e is not None, [primary] + secondaries)) except socket.gaierror: fatal_error( 'Failed to resolve "%s" - check that the specified DNS name is a CNAME record resolving to a valid EFS DNS ' @@ -662,7 +722,7 @@ warn_message = 'The "%s" option is not supported and has been ignored, as amazon-efs-utils relies on a built-in ' \ 'trust store.' % unsupported_option sys.stderr.write('WARN: %s\n' % warn_message) - logging.warn(warn_message) + logging.warning(warn_message) del options[unsupported_option] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/src/watchdog/__init__.py new/efs-utils-1.17/src/watchdog/__init__.py --- old/efs-utils-1.7/src/watchdog/__init__.py 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/src/watchdog/__init__.py 2019-12-17 19:21:01.000000000 +0100 @@ -25,7 +25,7 @@ except ImportError: from configparser import ConfigParser -VERSION = '1.7' +VERSION = '1.17' CONFIG_FILE = '/etc/amazon/efs/efs-utils.conf' CONFIG_SECTION = 'mount-watchdog' @@ -248,7 +248,7 @@ if is_running: logging.debug('TLS tunnel for %s is running', state_file) else: - logging.warn('TLS tunnel for %s is not running', state_file) + logging.warning('TLS tunnel for %s is not running', state_file) restart_tls_tunnel(child_procs, state, state_file_dir, state_file) @@ -256,7 +256,7 @@ for proc in child_procs: proc.poll() if proc.returncode is not None: - logging.warn('Child TLS tunnel process %d has exited, returncode=%d', proc.pid, proc.returncode) + logging.warning('Child TLS tunnel process %d has exited, returncode=%d', proc.pid, proc.returncode) child_procs.remove(proc) @@ -280,7 +280,10 @@ def read_config(config_file=CONFIG_FILE): - p = ConfigParser.SafeConfigParser() + try: + p = ConfigParser.SafeConfigParser() + except AttributeError: + p = ConfigParser() p.read(config_file) return p diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/test/mount_efs_test/test_bootstrap_tls.py new/efs-utils-1.17/test/mount_efs_test/test_bootstrap_tls.py --- old/efs-utils-1.7/test/mount_efs_test/test_bootstrap_tls.py 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/test/mount_efs_test/test_bootstrap_tls.py 2019-12-17 19:21:01.000000000 +0100 @@ -10,8 +10,6 @@ import os import tempfile -import pytest - from mock import MagicMock FS_ID = 'fs-deadbeef' @@ -28,27 +26,25 @@ MOCK_CONFIG = MagicMock() [email protected](autouse=True) -def setup(mocker): +def setup_mocks(mocker): mocker.patch('mount_efs.start_watchdog') mocker.patch('mount_efs.get_tls_port_range', return_value=(DEFAULT_TLS_PORT, DEFAULT_TLS_PORT + 10)) - mocker.patch('mount_efs.choose_tls_port', return_value=DEFAULT_TLS_PORT) - mocker.patch('mount_efs.write_tls_tunnel_state_file') - mocker.patch('mount_efs.write_stunnel_config_file', return_value=EXPECTED_STUNNEL_CONFIG_FILE) + mocker.patch('socket.socket', return_value=MagicMock()) + mocker.patch('mount_efs.write_tls_tunnel_state_file', return_value="~mocktempfile") mocker.patch('os.rename') + mocker.patch('os.kill') - -def _mock_popen(mocker, returncode=0): - popen_mock = MagicMock() - popen_mock.communicate.return_value = ('stdout', 'stderr', ) - popen_mock.returncode = returncode - - return mocker.patch('subprocess.Popen', return_value=popen_mock) + process_mock = MagicMock() + process_mock.communicate.return_value = ('stdout', 'stderr', ) + process_mock.returncode = 0 + + popen_mock = mocker.patch('subprocess.Popen', return_value=process_mock) + write_config_mock = mocker.patch('mount_efs.write_stunnel_config_file', return_value=EXPECTED_STUNNEL_CONFIG_FILE) + return popen_mock, write_config_mock def test_bootstrap_tls_state_file_dir_exists(mocker, tmpdir): - popen_mock = _mock_popen(mocker) - mocker.patch('os.kill') + popen_mock, _ = setup_mocks(mocker) state_file_dir = str(tmpdir) with mount_efs.bootstrap_tls(MOCK_CONFIG, INIT_SYSTEM, DNS_NAME, FS_ID, MOUNT_POINT, {}, state_file_dir): @@ -62,8 +58,7 @@ def test_bootstrap_tls_state_file_nonexistent_dir(mocker, tmpdir): - _mock_popen(mocker) - mocker.patch('os.kill') + popen_mock, _ = setup_mocks(mocker) state_file_dir = str(tmpdir.join(tempfile.mktemp())) def config_get_side_effect(section, field): @@ -83,32 +78,83 @@ def test_bootstrap_tls_non_default_port(mocker, tmpdir): - popen_mock = _mock_popen(mocker) - mocker.patch('os.kill') + popen_mock, write_config_mock = setup_mocks(mocker) state_file_dir = str(tmpdir) tls_port = 1000 with mount_efs.bootstrap_tls(MOCK_CONFIG, INIT_SYSTEM, DNS_NAME, FS_ID, MOUNT_POINT, {'tlsport': tls_port}, state_file_dir): pass - args, _ = popen_mock.call_args - args = args[0] - - assert 'stunnel' in args - assert EXPECTED_STUNNEL_CONFIG_FILE in args + popen_args, _ = popen_mock.call_args + popen_args = popen_args[0] + write_config_args, _ = write_config_mock.call_args + + assert 'stunnel' in popen_args + assert EXPECTED_STUNNEL_CONFIG_FILE in popen_args + assert 1000 == write_config_args[4] # positional argument for tls_port def test_bootstrap_tls_non_default_verify_level(mocker, tmpdir): - popen_mock = _mock_popen(mocker) - mocker.patch('os.kill') + popen_mock, write_config_mock = setup_mocks(mocker) state_file_dir = str(tmpdir) verify = 0 with mount_efs.bootstrap_tls(MOCK_CONFIG, INIT_SYSTEM, DNS_NAME, FS_ID, MOUNT_POINT, {'verify': verify}, state_file_dir): pass - args, _ = popen_mock.call_args - args = args[0] + popen_args, _ = popen_mock.call_args + popen_args = popen_args[0] + write_config_args, _ = write_config_mock.call_args - assert 'stunnel' in args - assert EXPECTED_STUNNEL_CONFIG_FILE in args + assert 'stunnel' in popen_args + assert EXPECTED_STUNNEL_CONFIG_FILE in popen_args + assert 0 == write_config_args[6] # positional argument for verify_level + + +def test_bootstrap_tls_ocsp_option(mocker, tmpdir): + popen_mock, write_config_mock = setup_mocks(mocker) + state_file_dir = str(tmpdir) + + with mount_efs.bootstrap_tls(MOCK_CONFIG, INIT_SYSTEM, DNS_NAME, FS_ID, MOUNT_POINT, {'ocsp': None}, state_file_dir): + pass + + popen_args, _ = popen_mock.call_args + popen_args = popen_args[0] + write_config_args, _ = write_config_mock.call_args + + assert 'stunnel' in popen_args + assert EXPECTED_STUNNEL_CONFIG_FILE in popen_args + # positional argument for ocsp_override + assert write_config_args[7] is True + + +def test_bootstrap_tls_noocsp_option(mocker, tmpdir): + popen_mock, write_config_mock = setup_mocks(mocker) + state_file_dir = str(tmpdir) + + with mount_efs.bootstrap_tls(MOCK_CONFIG, INIT_SYSTEM, DNS_NAME, FS_ID, MOUNT_POINT, {'noocsp': None}, state_file_dir): + pass + + popen_args, _ = popen_mock.call_args + popen_args = popen_args[0] + write_config_args, _ = write_config_mock.call_args + + assert 'stunnel' in popen_args + assert EXPECTED_STUNNEL_CONFIG_FILE in popen_args + # positional argument for ocsp_override + assert write_config_args[7] is False + + +def test_bootstrap_tls_ocsp_and_noocsp_option(mocker, tmpdir): + setup_mocks(mocker) + state_file_dir = str(tmpdir) + + exception_thrown = False + try: + with mount_efs.bootstrap_tls(MOCK_CONFIG, INIT_SYSTEM, DNS_NAME, FS_ID, MOUNT_POINT, {'ocsp': None, 'noocsp': None}, + state_file_dir): + pass + except SystemExit: + exception_thrown = True + + assert exception_thrown diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/test/mount_efs_test/test_check_unsupported_options.py new/efs-utils-1.17/test/mount_efs_test/test_check_unsupported_options.py --- old/efs-utils-1.7/test/mount_efs_test/test_check_unsupported_options.py 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/test/mount_efs_test/test_check_unsupported_options.py 2019-12-17 19:21:01.000000000 +0100 @@ -7,14 +7,6 @@ # import mount_efs -import tempfile - - -def create_temp_file(tmpdir, content=''): - temp_file = tmpdir.join(tempfile.mktemp()) - temp_file.write(content, ensure=True) - return temp_file - def test_no_unsupported_options(capsys): options = {} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/test/mount_efs_test/test_choose_tls_port.py new/efs-utils-1.17/test/mount_efs_test/test_choose_tls_port.py --- old/efs-utils-1.7/test/mount_efs_test/test_choose_tls_port.py 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/test/mount_efs_test/test_choose_tls_port.py 2019-12-17 19:21:01.000000000 +0100 @@ -7,19 +7,26 @@ # import mount_efs -import ConfigParser import socket import pytest from mock import MagicMock +try: + import ConfigParser +except ImportError: + from configparser import ConfigParser + DEFAULT_TLS_PORT_RANGE_LOW = 20049 DEFAULT_TLS_PORT_RANGE_HIGH = 20449 def _get_config(): - config = ConfigParser.SafeConfigParser() + try: + config = ConfigParser.SafeConfigParser() + except AttributeError: + config = ConfigParser() config.add_section(mount_efs.CONFIG_SECTION) config.set(mount_efs.CONFIG_SECTION, 'port_range_lower_bound', str(DEFAULT_TLS_PORT_RANGE_LOW)) config.set(mount_efs.CONFIG_SECTION, 'port_range_upper_bound', str(DEFAULT_TLS_PORT_RANGE_HIGH)) @@ -28,8 +35,9 @@ def test_choose_tls_port_first_try(mocker): mocker.patch('socket.socket', return_value=MagicMock()) + options = {} - tls_port = mount_efs.choose_tls_port(_get_config()) + tls_port = mount_efs.choose_tls_port(_get_config(), options) assert DEFAULT_TLS_PORT_RANGE_LOW <= tls_port <= DEFAULT_TLS_PORT_RANGE_HIGH @@ -37,10 +45,11 @@ def test_choose_tls_port_second_try(mocker): bad_sock = MagicMock() bad_sock.bind.side_effect = [socket.error, None] + options = {} mocker.patch('socket.socket', return_value=bad_sock) - tls_port = mount_efs.choose_tls_port(_get_config()) + tls_port = mount_efs.choose_tls_port(_get_config(), options) assert DEFAULT_TLS_PORT_RANGE_LOW <= tls_port <= DEFAULT_TLS_PORT_RANGE_HIGH assert 2 == bad_sock.bind.call_count @@ -49,11 +58,12 @@ def test_choose_tls_port_never_succeeds(mocker, capsys): bad_sock = MagicMock() bad_sock.bind.side_effect = socket.error() + options = {} mocker.patch('socket.socket', return_value=bad_sock) with pytest.raises(SystemExit) as ex: - mount_efs.choose_tls_port(_get_config()) + mount_efs.choose_tls_port(_get_config(), options) assert 0 != ex.value.code @@ -61,3 +71,30 @@ assert 'Failed to locate an available port' in err assert DEFAULT_TLS_PORT_RANGE_HIGH - DEFAULT_TLS_PORT_RANGE_LOW == bad_sock.bind.call_count + + +def test_choose_tls_port_option_specified(mocker): + mocker.patch('socket.socket', return_value=MagicMock()) + options = {'tlsport': 1000} + + tls_port = mount_efs.choose_tls_port(_get_config(), options) + + assert 1000 == tls_port + + +def test_choose_tls_port_option_specified_unavailable(mocker, capsys): + bad_sock = MagicMock() + bad_sock.bind.side_effect = socket.error() + options = {'tlsport': 1000} + + mocker.patch('socket.socket', return_value=bad_sock) + + with pytest.raises(SystemExit) as ex: + mount_efs.choose_tls_port(_get_config(), options) + + assert 0 != ex.value.code + + out, err = capsys.readouterr() + assert 'Specified port [1000] is unavailable' in err + + assert 1 == bad_sock.bind.call_count diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/test/mount_efs_test/test_create_state_file_dir.py new/efs-utils-1.17/test/mount_efs_test/test_create_state_file_dir.py --- old/efs-utils-1.7/test/mount_efs_test/test_create_state_file_dir.py 1970-01-01 01:00:00.000000000 +0100 +++ new/efs-utils-1.17/test/mount_efs_test/test_create_state_file_dir.py 2019-12-17 19:21:01.000000000 +0100 @@ -0,0 +1,78 @@ +# +# Copyright 2017-2018 Amazon.com, Inc. and its affiliates. All Rights Reserved. +# +# Licensed under the MIT License. See the LICENSE accompanying this file +# for the specific language governing permissions and limitations under +# the License. +# + +import errno +import mount_efs +import os +import tempfile + +import pytest + +try: + import ConfigParser +except ImportError: + from configparser import ConfigParser + + +def _get_config(mode=None): + try: + config = ConfigParser.SafeConfigParser() + except AttributeError: + config = ConfigParser() + config.add_section(mount_efs.CONFIG_SECTION) + + if mode is not None: + config.set(mount_efs.CONFIG_SECTION, 'state_file_dir_mode', mode) + + return config + + +def test_create_state_file_dir(tmpdir): + state_file_dir = str(tmpdir.join('efs')) + + mount_efs.create_state_file_dir(_get_config(), state_file_dir) + + assert os.path.isdir(state_file_dir) + assert '0750' == oct(os.stat(state_file_dir).st_mode)[-4:] + + +def test_create_state_file_dir_exists(tmpdir): + state_file_dir = str(tmpdir.join('efs')) + os.makedirs(state_file_dir) + + mount_efs.create_state_file_dir(_get_config(), state_file_dir) + + assert os.path.isdir(state_file_dir) + + +def test_create_state_file_dir_exists_as_file(tmpdir): + state_file = tmpdir.join('efs') + state_file.write('', ensure=True) + + with pytest.raises(OSError) as ex: + mount_efs.create_state_file_dir(_get_config(), str(state_file)) + + assert errno.EEXIST == ex.value.errno + + +def test_create_state_file_dir_overridden_mode(tmpdir): + state_file_dir = str(tmpdir.join('efs')) + + mount_efs.create_state_file_dir(_get_config(mode=str(755)), state_file_dir) + + assert os.path.isdir(state_file_dir) + assert '0755' == oct(os.stat(state_file_dir).st_mode)[-4:] + + +def test_create_state_file_dir_overridden_bad_mode(tmpdir): + state_file_dir = str(tmpdir.join('efs')) + + mount_efs.create_state_file_dir(_get_config(mode='invalid-mode'), state_file_dir) + + assert os.path.isdir(state_file_dir) + assert '0750' == oct(os.stat(state_file_dir).st_mode)[-4:] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/test/mount_efs_test/test_get_dns_name.py new/efs-utils-1.17/test/mount_efs_test/test_get_dns_name.py --- old/efs-utils-1.7/test/mount_efs_test/test_get_dns_name.py 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/test/mount_efs_test/test_get_dns_name.py 2019-12-17 19:21:01.000000000 +0100 @@ -63,7 +63,7 @@ with pytest.raises(ValueError) as ex: mount_efs.get_dns_name(config, FS_ID) - assert 'must include' in ex.value.message + assert 'must include' in str(ex.value) def test_get_dns_name_bad_format_too_many_specifiers_1(mocker): @@ -72,7 +72,7 @@ with pytest.raises(ValueError) as ex: mount_efs.get_dns_name(config, FS_ID) - assert 'incorrect number' in ex.value.message + assert 'incorrect number' in str(ex.value) def test_get_dns_name_bad_format_too_many_specifiers_2(mocker): @@ -81,7 +81,7 @@ with pytest.raises(ValueError) as ex: mount_efs.get_dns_name(config, FS_ID) - assert 'incorrect number' in ex.value.message + assert 'incorrect number' in str(ex.value) def test_get_dns_name_unresolvable(mocker, capsys): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/test/mount_efs_test/test_get_region.py new/efs-utils-1.17/test/mount_efs_test/test_get_region.py --- old/efs-utils-1.7/test/mount_efs_test/test_get_region.py 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/test/mount_efs_test/test_get_region.py 2019-12-17 19:21:01.000000000 +0100 @@ -11,7 +11,10 @@ import pytest -from urllib2 import URLError +try: + from urllib2 import URLError +except ImportError: + from urllib.error import URLError INSTANCE_DATA = { 'devpayProductCodes': None, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/test/mount_efs_test/test_is_ocsp_enabled.py new/efs-utils-1.17/test/mount_efs_test/test_is_ocsp_enabled.py --- old/efs-utils-1.7/test/mount_efs_test/test_is_ocsp_enabled.py 1970-01-01 01:00:00.000000000 +0100 +++ new/efs-utils-1.17/test/mount_efs_test/test_is_ocsp_enabled.py 2019-12-17 19:21:01.000000000 +0100 @@ -0,0 +1,86 @@ +# +# Copyright 2017-2018 Amazon.com, Inc. and its affiliates. All Rights Reserved. +# +# Licensed under the MIT License. See the LICENSE accompanying this file +# for the specific language governing permissions and limitations under +# the License. +# + +import mount_efs + +import pytest + +try: + import ConfigParser +except ImportError: + from configparser import ConfigParser + + +def _get_config(stunnel_check_cert_validity): + try: + config = ConfigParser.SafeConfigParser() + except AttributeError: + config = ConfigParser() + config.add_section(mount_efs.CONFIG_SECTION) + if stunnel_check_cert_validity is not None: + config.set(mount_efs.CONFIG_SECTION, 'stunnel_check_cert_validity', str(stunnel_check_cert_validity)) + return config + + +def test_is_ocsp_enabled_config_false_no_cli(): + options = {} + + ocsp_enabled = mount_efs.is_ocsp_enabled(_get_config(False), options) + + assert ocsp_enabled is False + + +def test_is_ocsp_enabled_config_true_no_cli(): + options = {} + + ocsp_enabled = mount_efs.is_ocsp_enabled(_get_config(True), options) + + assert ocsp_enabled is True + + +def test_is_ocsp_enabled_config_false_cli_true(): + options = {'ocsp': None} + + ocsp_enabled = mount_efs.is_ocsp_enabled(_get_config(False), options) + + assert ocsp_enabled is True + + +def test_is_ocsp_enabled_config_true_cli_true(): + options = {'ocsp': None} + + ocsp_enabled = mount_efs.is_ocsp_enabled(_get_config(True), options) + + assert ocsp_enabled is True + + +def test_is_ocsp_enabled_config_false_cli_false(): + options = {'noocsp': None} + + ocsp_enabled = mount_efs.is_ocsp_enabled(_get_config(False), options) + + assert ocsp_enabled is False + + +def test_is_ocsp_enabled_config_true_cli_false(): + options = {'noocsp': None} + + ocsp_enabled = mount_efs.is_ocsp_enabled(_get_config(True), options) + + assert ocsp_enabled is False + + +def test_is_ocsp_enabled_cli_both_options(capsys): + options = {'noocsp': None, 'ocsp': None} + + with pytest.raises(SystemExit) as ex: + mount_efs.is_ocsp_enabled(_get_config(True), options) + + assert 0 != ex.value.code + out, err = capsys.readouterr() + assert 'The "ocsp" and "noocsp" options are mutually exclusive' in err diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/test/mount_efs_test/test_main.py new/efs-utils-1.17/test/mount_efs_test/test_main.py --- old/efs-utils-1.7/test/mount_efs_test/test_main.py 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/test/mount_efs_test/test_main.py 2019-12-17 19:21:01.000000000 +0100 @@ -12,6 +12,7 @@ from contextlib import contextmanager +from mock import patch @contextmanager def dummy_contextmanager(*args, **kwargs): @@ -48,11 +49,13 @@ bootstrap_tls_mock.assert_not_called() -def test_main_tls(mocker): +@patch('mount_efs.check_network_target') +def test_main_tls(check_network, mocker): _test_main(mocker, tls=True) -def test_main_no_tls(mocker): +@patch('mount_efs.check_network_target') +def test_main_no_tls(check_network, mocker): _test_main(mocker, tls=False) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/test/mount_efs_test/test_parse_arguments.py new/efs-utils-1.17/test/mount_efs_test/test_parse_arguments.py --- old/efs-utils-1.7/test/mount_efs_test/test_parse_arguments.py 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/test/mount_efs_test/test_parse_arguments.py 2019-12-17 19:21:01.000000000 +0100 @@ -78,8 +78,8 @@ def test_parse_arguments_verbose(): - fsid, path, mountpoint, options = mount_efs.parse_arguments(None, - ['mount', 'fs-deadbeef:/home', '/dir', '-v', '-o', 'foo,bar=baz,quux']) + fsid, path, mountpoint, options = mount_efs.parse_arguments(None, ['mount', 'fs-deadbeef:/home', '/dir', '-v', '-o', + 'foo,bar=baz,quux']) assert 'fs-deadbeef' == fsid assert '/home' == path diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.7/test/mount_efs_test/test_write_stunnel_config_file.py new/efs-utils-1.17/test/mount_efs_test/test_write_stunnel_config_file.py --- old/efs-utils-1.7/test/mount_efs_test/test_write_stunnel_config_file.py 2019-04-09 20:27:34.000000000 +0200 +++ new/efs-utils-1.17/test/mount_efs_test/test_write_stunnel_config_file.py 2019-12-17 19:21:01.000000000 +0100 @@ -7,21 +7,26 @@ # import mount_efs -import ConfigParser import os import pytest +try: + import ConfigParser +except ImportError: + from configparser import ConfigParser + FS_ID = 'fs-deadbeef' DNS_NAME = 'fs-deadbeef.com' MOUNT_POINT = '/mnt' PORT = 12345 VERIFY_LEVEL = 2 +OCSP_ENABLED = False def _get_config(mocker, stunnel_debug_enabled=False, stunnel_check_cert_hostname_supported=True, stunnel_check_cert_validity_supported=True, stunnel_check_cert_hostname=None, - stunnel_check_cert_validity=None): + stunnel_check_cert_validity=False): mocker.patch('mount_efs.get_version_specific_stunnel_options', return_value=(stunnel_check_cert_hostname_supported, stunnel_check_cert_validity_supported, )) @@ -32,7 +37,10 @@ if stunnel_check_cert_validity is None: stunnel_check_cert_validity = stunnel_check_cert_validity_supported - config = ConfigParser.SafeConfigParser() + try: + config = ConfigParser.SafeConfigParser() + except AttributeError: + config = ConfigParser() config.add_section(mount_efs.CONFIG_SECTION) config.set(mount_efs.CONFIG_SECTION, 'stunnel_debug_enabled', str(stunnel_debug_enabled)) config.set(mount_efs.CONFIG_SECTION, 'stunnel_check_cert_hostname', str(stunnel_check_cert_hostname)) @@ -81,7 +89,8 @@ def _get_expected_efs_config(port=PORT, dns_name=DNS_NAME, verify=mount_efs.DEFAULT_STUNNEL_VERIFY_LEVEL, - check_cert_hostname=True, check_cert_validity=True): + ocsp_override=True, check_cert_hostname=True, check_cert_validity=False, + disable_libwrap=True): expected_efs_config = dict(mount_efs.STUNNEL_EFS_CONFIG) expected_efs_config['accept'] = expected_efs_config['accept'] % port @@ -91,9 +100,12 @@ if check_cert_hostname: expected_efs_config['checkHost'] = dns_name - if check_cert_validity: + if check_cert_validity and ocsp_override: expected_efs_config['OCSPaia'] = 'yes' + if disable_libwrap: + expected_efs_config['libwrap'] = 'no' + return expected_efs_config @@ -104,7 +116,7 @@ config_file = mount_efs.write_stunnel_config_file( _get_config(mocker, stunnel_check_cert_hostname_supported=stunnel_check_cert_hostname_supported, stunnel_check_cert_hostname=stunnel_check_cert_hostname), - str(tmpdir), FS_ID, MOUNT_POINT, PORT, DNS_NAME, VERIFY_LEVEL) + str(tmpdir), FS_ID, MOUNT_POINT, PORT, DNS_NAME, VERIFY_LEVEL, OCSP_ENABLED) ca_mocker.assert_called_once() @@ -117,9 +129,8 @@ ca_mocker = mocker.patch('mount_efs.add_stunnel_ca_options') config_file = mount_efs.write_stunnel_config_file( - _get_config(mocker, stunnel_check_cert_validity_supported=stunnel_check_cert_validity_supported, - stunnel_check_cert_validity=stunnel_check_cert_validity), - str(tmpdir), FS_ID, MOUNT_POINT, PORT, DNS_NAME, VERIFY_LEVEL) + _get_config(mocker, stunnel_check_cert_validity_supported=stunnel_check_cert_validity_supported), + str(tmpdir), FS_ID, MOUNT_POINT, PORT, DNS_NAME, VERIFY_LEVEL, stunnel_check_cert_validity) ca_mocker.assert_called_once() @@ -132,18 +143,29 @@ state_file_dir = str(tmpdir) config_file = mount_efs.write_stunnel_config_file(_get_config(mocker), state_file_dir, FS_ID, MOUNT_POINT, PORT, DNS_NAME, - VERIFY_LEVEL) + VERIFY_LEVEL, OCSP_ENABLED) ca_mocker.assert_called_once() _validate_config(config_file, mount_efs.STUNNEL_GLOBAL_CONFIG, _get_expected_efs_config()) +def _test_disable_libwrap(mocker, tmpdir, system_release='unknown', disable_libwrap=True): + mocker.patch('mount_efs.add_stunnel_ca_options') + ver_mocker = mocker.patch('mount_efs.get_system_release_version', return_value=system_release) + + config_file = mount_efs.write_stunnel_config_file(_get_config(mocker), str(tmpdir), FS_ID, MOUNT_POINT, PORT, DNS_NAME, + VERIFY_LEVEL, OCSP_ENABLED) + + ver_mocker.assert_called_once() + _validate_config(config_file, mount_efs.STUNNEL_GLOBAL_CONFIG, _get_expected_efs_config(disable_libwrap=disable_libwrap)) + + def test_write_stunnel_config_with_debug(mocker, tmpdir): ca_mocker = mocker.patch('mount_efs.add_stunnel_ca_options') state_file_dir = str(tmpdir) config_file = mount_efs.write_stunnel_config_file(_get_config(mocker, stunnel_debug_enabled=True), state_file_dir, FS_ID, - MOUNT_POINT, PORT, DNS_NAME, VERIFY_LEVEL) + MOUNT_POINT, PORT, DNS_NAME, VERIFY_LEVEL, OCSP_ENABLED) ca_mocker.assert_called_once() expected_global_config = dict(mount_efs.STUNNEL_GLOBAL_CONFIG) @@ -186,7 +208,7 @@ with pytest.raises(SystemExit) as ex: mount_efs.write_stunnel_config_file(_get_config(mocker, stunnel_check_cert_hostname_supported=False, stunnel_check_cert_hostname=True), str(tmpdir), FS_ID, MOUNT_POINT, PORT, DNS_NAME, - VERIFY_LEVEL) + VERIFY_LEVEL, OCSP_ENABLED) assert 0 != ex.value.code @@ -195,38 +217,28 @@ assert 'stunnel_check_cert_hostname' in err -def test_write_stunnel_config_check_cert_validity_supported_flag_not_set(mocker, capsys, tmpdir): - _test_check_cert_validity(mocker, tmpdir, stunnel_check_cert_validity_supported=True, stunnel_check_cert_validity=None, - expected_check_cert_validity_config_value=True) - - -def test_write_stunnel_config_check_cert_validity_supported_flag_set_false(mocker, capsys, tmpdir): - _test_check_cert_validity(mocker, tmpdir, stunnel_check_cert_validity_supported=True, stunnel_check_cert_validity=False, - expected_check_cert_validity_config_value=False) - - -def test_write_stunnel_config_check_cert_validity_supported_flag_set_true(mocker, tmpdir): +def test_write_stunnel_config_check_cert_validity_supported_ocsp_enabled(mocker, capsys, tmpdir): _test_check_cert_validity(mocker, tmpdir, stunnel_check_cert_validity_supported=True, stunnel_check_cert_validity=True, expected_check_cert_validity_config_value=True) -def test_write_stunnel_config_check_cert_validity_not_supported_flag_not_set(mocker, capsys, tmpdir): - _test_check_cert_validity(mocker, tmpdir, stunnel_check_cert_validity_supported=False, stunnel_check_cert_validity=None, +def test_write_stunnel_config_check_cert_validity_supported_ocsp_disabled(mocker, capsys, tmpdir): + _test_check_cert_validity(mocker, tmpdir, stunnel_check_cert_validity_supported=True, stunnel_check_cert_validity=False, expected_check_cert_validity_config_value=False) -def test_write_stunnel_config_check_cert_validity_not_supported_flag_set_false(mocker, capsys, tmpdir): - _test_check_cert_validity(mocker, tmpdir, stunnel_check_cert_validity_supported=False, stunnel_check_cert_validity=False, +def test_write_stunnel_config_check_cert_validity_not_supported_ocsp_disabled(mocker, capsys, tmpdir): + _test_check_cert_validity(mocker, tmpdir, stunnel_check_cert_validity_supported=True, stunnel_check_cert_validity=False, expected_check_cert_validity_config_value=False) -def test_write_stunnel_config_check_cert_validity_not_supported_flag_set_true(mocker, capsys, tmpdir): +def test_write_stunnel_config_check_cert_validity_not_supported_ocsp_enabled(mocker, capsys, tmpdir): mocker.patch('mount_efs.add_stunnel_ca_options') with pytest.raises(SystemExit) as ex: mount_efs.write_stunnel_config_file(_get_config(mocker, stunnel_check_cert_validity_supported=False, stunnel_check_cert_validity=True), str(tmpdir), FS_ID, MOUNT_POINT, PORT, DNS_NAME, - VERIFY_LEVEL) + VERIFY_LEVEL, ocsp_enabled=True) assert 0 != ex.value.code @@ -240,8 +252,20 @@ verify = 0 config_file = mount_efs.write_stunnel_config_file(_get_config(mocker, stunnel_check_cert_validity=True), str(tmpdir), FS_ID, - MOUNT_POINT, PORT, DNS_NAME, verify) + MOUNT_POINT, PORT, DNS_NAME, verify, OCSP_ENABLED) ca_mocker.assert_not_called() _validate_config(config_file, mount_efs.STUNNEL_GLOBAL_CONFIG, - _get_expected_efs_config(check_cert_validity=True, verify=verify)) + _get_expected_efs_config(check_cert_validity=False, verify=verify)) + + +def test_write_stunnel_config_for_rhel8_disable_libwrap(mocker, tmpdir): + _test_disable_libwrap(mocker, tmpdir, system_release='Red Hat Enterprise Linux release 8.0 (Ootpa)', disable_libwrap=False) + + +def test_write_stunnel_config_for_unknown_system_enable_libwrap(mocker, tmpdir): + _test_disable_libwrap(mocker, tmpdir, system_release='unknown', disable_libwrap=True) + + +def test_write_stunnel_config_for_non_rhel8_enable_libwrap(mocker, tmpdir): + _test_disable_libwrap(mocker, tmpdir, system_release='Amazon Linux release 2 (Karoo)', disable_libwrap=True)
