Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package aws-efs-utils for openSUSE:Factory checked in at 2024-02-16 21:42:49 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/aws-efs-utils (Old) and /work/SRC/openSUSE:Factory/.aws-efs-utils.new.1815 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "aws-efs-utils" Fri Feb 16 21:42:49 2024 rev:16 rq:1147098 version:1.35.1 Changes: -------- --- /work/SRC/openSUSE:Factory/aws-efs-utils/aws-efs-utils.changes 2023-04-01 19:32:15.377351941 +0200 +++ /work/SRC/openSUSE:Factory/.aws-efs-utils.new.1815/aws-efs-utils.changes 2024-02-16 21:42:54.550898560 +0100 @@ -1,0 +2,14 @@ +Tue Feb 13 14:39:45 UTC 2024 - John Paul Adrian Glaubitz <adrian.glaub...@suse.com> + +- Update to version 1.35.1 + * Revert openssl requirement change + * Revert "Update EFS Documentation: Clarify Current FIPS Compliance Status" + * Update EFS Documentation: Clarify Current FIPS Compliance Status + * test: Change repo urls in eol debian9 build + * Check private key file size to skip generation + * test: Fix pytest that failed since commit 3dd89ca + * Fix should_check_efs_utils_version scope + * Add warning if using old version + * Add 'fsap' option as EFS-only option + +------------------------------------------------------------------- Old: ---- efs-utils-1.35.0.tar.gz New: ---- efs-utils-1.35.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ aws-efs-utils.spec ++++++ --- /var/tmp/diff_new_pack.6hS31e/_old 2024-02-16 21:42:55.542934354 +0100 +++ /var/tmp/diff_new_pack.6hS31e/_new 2024-02-16 21:42:55.546934499 +0100 @@ -1,7 +1,7 @@ # # spec file for package aws-efs-utils # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: aws-efs-utils -Version: 1.35.0 +Version: 1.35.1 Release: 0 Summary: Utilities for using the EFS file systems License: MIT ++++++ efs-utils-1.35.0.tar.gz -> efs-utils-1.35.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.35.0/.circleci/config.yml new/efs-utils-1.35.1/.circleci/config.yml --- old/efs-utils-1.35.0/.circleci/config.yml 2023-03-16 19:07:54.000000000 +0100 +++ new/efs-utils-1.35.1/.circleci/config.yml 2024-01-18 16:57:36.000000000 +0100 @@ -33,7 +33,6 @@ path: build build-deb: steps: - - checkout - run: name: Repo update command: | @@ -41,7 +40,12 @@ - run: name: Install dependencies command: | - apt-get -y install binutils + apt-get -y install binutils git + - run: + name: Add local build repo as safe git directory + command: | + git config --global --add safe.directory /tmp/_circleci_local_build_repo + - checkout - run: name: Build DEB command: | @@ -112,6 +116,14 @@ command: | sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* + build-debian-eol-repo: + steps: + - run: + name: change repo url to archive.debian.org and remove updates repo for EOL versions + command: | + sed -i 's/deb.debian.org/archive.debian.org/g' /etc/apt/sources.list + sed -i 's/security.debian.org/archive.debian.org/g' /etc/apt/sources.list + sed -i '/stretch-updates/d' /etc/apt/sources.list jobs: test: parameters: @@ -159,6 +171,16 @@ steps: - build-centos-repo - build-rpm + build-debian-eol-rpm-package: + parameters: + image: + type: string + executor: + name: linux + image: << parameters.image >> + steps: + - build-debian-eol-repo + - build-deb workflows: workflow: jobs: @@ -195,7 +217,7 @@ - build-deb-package: name: ubuntu22 image: ubuntu:22.04 - - build-deb-package: + - build-debian-eol-rpm-package: name: debian9 image: debian:stretch - build-deb-package: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.35.0/README.md new/efs-utils-1.35.1/README.md --- old/efs-utils-1.35.0/README.md 2023-03-16 19:07:54.000000000 +0100 +++ new/efs-utils-1.35.1/README.md 2024-01-18 16:57:36.000000000 +0100 @@ -10,6 +10,7 @@ |----------------------| ----- | --------- | | Amazon Linux 2017.09 | `rpm` | `upstart` | | Amazon Linux 2 | `rpm` | `systemd` | +| Amazon Linux 2023 | `rpm` | `systemd` | | CentOS 7 | `rpm` | `systemd` | | CentOS 8 | `rpm` | `systemd` | | RHEL 7 | `rpm`| `systemd` | @@ -72,6 +73,7 @@ - [The way to access instance metadata](#the-way-to-access-instance-metadata) - [Use the assumed profile credentials for IAM](#use-the-assumed-profile-credentials-for-iam) - [Enabling FIPS Mode](#enabling-fips-mode) + - [Disabling Version Check](#disabling-version-check) - [License Summary](#license-summary) @@ -558,6 +560,18 @@ For more information on how to configure OpenSSL with FIPS see the [OpenSSL FIPS README](https://github.com/openssl/openssl/blob/master/README-FIPS.md). +## Disabling Version Check +By default, once an hour, the watchdog daemon service will check to see if a newer version of amazon-efs-utils is available on github or yum. +You can disable this check by setting the `enable_version_check` field in `/etc/amazon/efs/efs-utils.conf` to `false`. For example, +```bash +sudo sed -i 's/enable_version_check = true/enable_version_check = false/' /etc/amazon/efs/efs-utils.conf +``` +Or on MacOS: +```bash +VERSION=<efs-utils version, e.g. 1.34.1> +sudo sed -i 's/enable_version_check = true/enable_version_check = false/' /usr/local/Cellar/amazon-efs-utils/${VERSION}/libexec/etc/amazon/efs/efs-utils.conf +``` + ## License Summary This code is made available under the MIT license. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.35.0/amazon-efs-utils.spec new/efs-utils-1.35.1/amazon-efs-utils.spec --- old/efs-utils-1.35.0/amazon-efs-utils.spec 2023-03-16 19:07:54.000000000 +0100 +++ new/efs-utils-1.35.1/amazon-efs-utils.spec 2024-01-18 16:57:36.000000000 +0100 @@ -35,7 +35,7 @@ %endif Name : amazon-efs-utils -Version : 1.35.0 +Version : 1.35.1 Release : 1%{platform} Summary : This package provides utilities for simplifying the use of EFS file systems @@ -53,6 +53,7 @@ Requires : stunnel >= 4.56 %endif Requires : %{python_requires} + Requires : openssl >= 1.0.2 Requires : util-linux Requires : which @@ -137,6 +138,12 @@ %clean %changelog +* Wed Jan 10 2024 Sean Zatz <zat...@amazon.com> - 1.35.1 +- Add 'fsap' to ignored mount option list +- Accept openssl 3.0 in rpm spec file +- Watchdog now prints a log message if efs-utils is on an old version +- Regenerate the private key if the file is empty + * Wed Mar 15 2023 Soyeon Ju <mjsoy...@amazon.com> - 1.35.0 - Support MacOS Ventura, Oracle8 distribution - Add debug statement for size of state file write diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.35.0/build-deb.sh new/efs-utils-1.35.1/build-deb.sh --- old/efs-utils-1.35.0/build-deb.sh 2023-03-16 19:07:54.000000000 +0100 +++ new/efs-utils-1.35.1/build-deb.sh 2024-01-18 16:57:36.000000000 +0100 @@ -11,7 +11,7 @@ BASE_DIR=$(pwd) BUILD_ROOT=${BASE_DIR}/build/debbuild -VERSION=1.35.0 +VERSION=1.35.1 RELEASE=1 DEB_SYSTEM_RELEASE_PATH=/etc/os-release diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.35.0/config.ini new/efs-utils-1.35.1/config.ini --- old/efs-utils-1.35.0/config.ini 2023-03-16 19:07:54.000000000 +0100 +++ new/efs-utils-1.35.1/config.ini 2024-01-18 16:57:36.000000000 +0100 @@ -7,5 +7,5 @@ # [global] -version=1.35.0 +version=1.35.1 release=1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.35.0/dist/amazon-efs-utils.control new/efs-utils-1.35.1/dist/amazon-efs-utils.control --- old/efs-utils-1.35.0/dist/amazon-efs-utils.control 2023-03-16 19:07:54.000000000 +0100 +++ new/efs-utils-1.35.1/dist/amazon-efs-utils.control 2024-01-18 16:57:36.000000000 +0100 @@ -1,6 +1,6 @@ Package: amazon-efs-utils Architecture: all -Version: 1.35.0 +Version: 1.35.1 Section: utils Depends: python3, nfs-common, stunnel4 (>= 4.56), openssl (>= 1.0.2), util-linux Priority: optional diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.35.0/dist/efs-utils.conf new/efs-utils-1.35.1/dist/efs-utils.conf --- old/efs-utils-1.35.0/dist/efs-utils.conf 2023-03-16 19:07:54.000000000 +0100 +++ new/efs-utils-1.35.1/dist/efs-utils.conf 2024-01-18 16:57:36.000000000 +0100 @@ -88,6 +88,10 @@ stunnel_health_check_interval_min = 5 stunnel_health_check_command_timeout_sec = 30 +# By default, once an hour, the watchdog process will check the latest version of amazon-efs-utils available +# on yum and github. If we detect that the currently installed version is outdated, we'll log a warning. +enable_version_check = true + [cloudwatch-log] # enabled = true log_group_name = /aws/efs/utils diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.35.0/src/mount_efs/__init__.py new/efs-utils-1.35.1/src/mount_efs/__init__.py --- old/efs-utils-1.35.0/src/mount_efs/__init__.py 2023-03-16 19:07:54.000000000 +0100 +++ new/efs-utils-1.35.1/src/mount_efs/__init__.py 2024-01-18 16:57:36.000000000 +0100 @@ -85,7 +85,7 @@ BOTOCORE_PRESENT = False -VERSION = "1.35.0" +VERSION = "1.35.1" SERVICE = "elasticfilesystem" AMAZON_LINUX_2_RELEASE_ID = "Amazon Linux release 2 (Karoo)" @@ -238,6 +238,7 @@ "verify", "rolearn", "jwtpath", + "fsap", ] UNSUPPORTED_OPTIONS = ["capath"] @@ -1623,11 +1624,11 @@ cert_details["privateKey"] = get_private_key_path() cert_details["fsId"] = fs_id - start_watchdog(init_system) - if not os.path.exists(state_file_dir): create_required_directory(config, state_file_dir) + start_watchdog(init_system) + verify_level = int(options.get("verify", DEFAULT_STUNNEL_VERIFY_LEVEL)) ocsp_enabled = is_ocsp_enabled(config, options) @@ -1760,7 +1761,6 @@ def mount_nfs(config, dns_name, path, mountpoint, options, fallback_ip_address=None): - if "tls" in options: mount_path = "127.0.0.1:%s" % path elif fallback_ip_address: @@ -1826,7 +1826,7 @@ ): def backoff_function(i): """Backoff exponentially and add a constant 0-1 second jitter""" - return (1.5 ** i) + random.random() + return (1.5**i) + random.random() if not get_boolean_config_item_value( config, CONFIG_SECTION, "retry_nfs_mount_command", default_value=True @@ -2089,12 +2089,15 @@ not_before = get_certificate_timestamp(current_time, minutes=-NOT_BEFORE_MINS) not_after = get_certificate_timestamp(current_time, hours=NOT_AFTER_HOURS) - cmd = "openssl ca -startdate %s -enddate %s -selfsign -batch -notext -config %s -in %s -out %s" % ( - not_before, - not_after, - certificate_config, - certificate_signing_request, - certificate, + cmd = ( + "openssl ca -startdate %s -enddate %s -selfsign -batch -notext -config %s -in %s -out %s" + % ( + not_before, + not_after, + certificate_config, + certificate_signing_request, + certificate, + ) ) subprocess_call(cmd, "Failed to create self-signed client-side certificate") return current_time.strftime(CERT_DATETIME_FORMAT) @@ -2147,7 +2150,13 @@ def generate_key(): if os.path.isfile(key): - return + # If the openssl genpkey command is interrupted or isn't successful, + # it will leave behind an empty file. + if os.path.getsize(key) == 0: + logging.warning("Purging empty private key file") + os.remove(key) + else: + return cmd = ( "openssl genpkey -algorithm RSA -out %s -pkeyopt rsa_keygen_bits:3072" % key @@ -3664,7 +3673,6 @@ # NFS client might see a throughput drop in kernel 5.4+, especially for sequential read. # To fix the issue, below function will modify read_ahead_kb to 15 * rsize (1MB by default) after mount. def optimize_readahead_window(mountpoint, options, config): - if not should_revise_readahead(config): return diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.35.0/src/watchdog/__init__.py new/efs-utils-1.35.1/src/watchdog/__init__.py --- old/efs-utils-1.35.0/src/watchdog/__init__.py 2023-03-16 19:07:54.000000000 +0100 +++ new/efs-utils-1.35.1/src/watchdog/__init__.py 2024-01-18 16:57:36.000000000 +0100 @@ -56,13 +56,14 @@ AMAZON_LINUX_2_RELEASE_ID, AMAZON_LINUX_2_PRETTY_NAME, ] -VERSION = "1.35.0" +VERSION = "1.35.1" SERVICE = "elasticfilesystem" CONFIG_FILE = "/etc/amazon/efs/efs-utils.conf" CONFIG_SECTION = "mount-watchdog" MOUNT_CONFIG_SECTION = "mount" CLIENT_INFO_SECTION = "client-info" +ENABLE_VERSION_CHECK = "enable_version_check" CLIENT_SOURCE_STR_LEN_LIMIT = 100 DISABLE_FETCH_EC2_METADATA_TOKEN_ITEM = "disable_fetch_ec2_metadata_token" DEFAULT_UNKNOWN_VALUE = "unknown" @@ -75,6 +76,7 @@ STATE_FILE_DIR = "/var/run/efs" STUNNEL_PID_FILE = "stunnel.pid" +LAST_VERSION_CHECK_FILE = "last_version_check.json" DEFAULT_NFS_PORT = "2049" PRIVATE_KEY_FILE = "/etc/amazon/efs/privateKey.pem" @@ -182,6 +184,255 @@ STUNNEL_INSTALLATION_MESSAGE = "Please install it following the instructions at: https://docs.aws.amazon.com/efs/latest/ug/using-amazon-efs-utils.html#upgrading-stunnel" +def check_if_platform_is_mac(): + return sys.platform in MAC_OS_PLATFORM_LIST + + +def get_system_release_version(): + # MacOS does not maintain paths /etc/os-release and /etc/sys-release + if check_if_platform_is_mac(): + return platform.platform() + + try: + with open(SYSTEM_RELEASE_PATH) as f: + return f.read().strip() + except IOError: + logging.debug("Unable to read %s", SYSTEM_RELEASE_PATH) + + try: + with open(OS_RELEASE_PATH) as f: + for line in f: + if "PRETTY_NAME" in line: + return line.split("=")[1].strip() + except IOError: + logging.debug("Unable to read %s", OS_RELEASE_PATH) + + return DEFAULT_UNKNOWN_VALUE + + +class Version: + """This class is used for the version check logic. An instance of this class represents + a semantic version following the format major.minor.patch. It is useful for comparing versions. + """ + + def __init__(self, version_str): + self.version_str = version_str + + # The version list will have the format [major, minor, patch] + self.version = version_str.split(".") + if len(self.version) != 3: + raise ValueError( + "Version class must be instantiated with a version string that follows the format 'major.minor.patch'." + ) + + def __validate_comparison_input(self, other): + """Assert that other has type Version""" + if not isinstance(other, self.__class__): + raise TypeError( + "Version comparisons are only permitted between Version instances." + ) + + def __lt__(self, other): + """returns True if self < other""" + self.__validate_comparison_input(other) + return (not self.__eq__(other)) and (not self.__gt__(other)) + + def __gt__(self, other): + """returns True if self > other""" + self.__validate_comparison_input(other) + return self.version > other.version + + def __eq__(self, other): + """returns True if self == other""" + self.__validate_comparison_input(other) + return self.version == other.version + + def __str__(self): + return self.version_str + + +class EFSUtilsVersionChecker: + GITHUB_TIMEOUT_SEC = 0.300 + VERSION_CHECK_POLL_INTERVAL_SEC = 3600 + VERSION_CHECK_FILE_KEY = "time" + GITHUB_TAG_API_URL = "https://api.github.com/repos/aws/efs-utils/tags" + SHOULD_CHECK_AMZN_REPOS = "Amazon Linux" in get_system_release_version() + + @staticmethod + def get_latest_version_by_github(): + """Queries the github api and returns a string with the latest tag (version) for efs-utils in the form of (e.g.) 1.34.5""" + logging.debug("Querying github for the latest amazon-efs-utils version") + with urlopen( + EFSUtilsVersionChecker.GITHUB_TAG_API_URL, + timeout=EFSUtilsVersionChecker.GITHUB_TIMEOUT_SEC, + ) as response: + html = response.read() + string = html.decode("utf-8") + json_obj = json.loads(string) + latest_version_dict = json_obj[0] + latest_version_str = latest_version_dict["name"] + logging.debug( + "Latest amazon-efs-utils version found on github: " + + latest_version_str[1:] + ) + return latest_version_str[1:] + + @staticmethod + def get_latest_version_by_yum(): + """ + Queries yum and returns a string with the latest tag (version) for efs-utils in the form of (e.g.) 1.34.5. + Returns an empty string if amazon-efs-utils is not available on Yum + """ + logging.debug("Querying yum for the latest amazon-efs-utils version") + ps_yum = subprocess.Popen( + ["yum", "info", "amazon-efs-utils"], + stdout=subprocess.PIPE, + ) + ps_grep = subprocess.Popen( + ["grep", "Available Packages", "-A", "4"], + stdin=ps_yum.stdout, + stdout=subprocess.PIPE, + ) + latest_version_str = subprocess.check_output( + ["awk", "/Version/ {printf $3}"], stdin=ps_grep.stdout + ).decode("utf-8") + + if not latest_version_str: + logging.debug("amazon-efs-utils was not found by yum") + return "" + + logging.debug( + "Latest amazon-efs-utils version found on yum: " + latest_version_str + ) + return latest_version_str + + @staticmethod + def warn_newer_version_available_yum(current_version, newer_version): + message = ( + "We recommend you upgrade to the latest version of efs-utils by running 'yum update amazon-efs-utils'. " + + "Current version: " + + str(current_version) + + ". Latest version: " + + str(newer_version) + ) + logging.warning(message) + + @staticmethod + def warn_newer_version_available_github(current_version, newer_version): + message = ( + "We recommend you install the latest version of efs-utils from github. " + + "Current version: " + + str(current_version) + + ". Latest version: " + + str(newer_version) + ) + logging.warning(message) + + @staticmethod + def get_last_version_check_time(): + """ + Return the date that the last amazon-efs-utils version check was performed. + Returns None if the version check file does not exist (indicates check hasn't happened yet). + """ + version_check_file = os.path.join(STATE_FILE_DIR, LAST_VERSION_CHECK_FILE) + if not os.path.exists(version_check_file): + return None + + with open(version_check_file, "r") as f: + data = json.load(f) + if EFSUtilsVersionChecker.VERSION_CHECK_FILE_KEY not in data: + return None + last_version_check_time = datetime.strptime( + data[EFSUtilsVersionChecker.VERSION_CHECK_FILE_KEY], + CERT_DATETIME_FORMAT, + ) + + return last_version_check_time + + @staticmethod + def version_check_ready(): + """Inspect the last version check file and return true if the time since last version check + is greater than VERSION_CHECK_POLL_INTERVAL""" + last_version_check_time = EFSUtilsVersionChecker.get_last_version_check_time() + if not last_version_check_time: + return True + + elapsed_seconds = (get_utc_now() - last_version_check_time).total_seconds() + return elapsed_seconds >= EFSUtilsVersionChecker.VERSION_CHECK_POLL_INTERVAL_SEC + + @staticmethod + def update_version_check_file(): + """Write current time into the version check file""" + current_time_str = get_utc_now().strftime(CERT_DATETIME_FORMAT) + dictionary = { + EFSUtilsVersionChecker.VERSION_CHECK_FILE_KEY: current_time_str, + } + + if not os.path.exists(STATE_FILE_DIR): + logging.warning( + "update_version_check_file failed: " + + str(STATE_FILE_DIR) + + " does not exist." + ) + return + + with open(os.path.join(STATE_FILE_DIR, LAST_VERSION_CHECK_FILE), "w+") as f: + json.dump(dictionary, f) + + @staticmethod + def check_if_using_old_version(current_version_string): + """Log a warning and print to console if newer version of amazon-efs-utils is available. + The check will first query yum, and then if that fails, + it will pull the latest tag from the github api. + """ + current_version = Version(current_version_string) + + if EFSUtilsVersionChecker.SHOULD_CHECK_AMZN_REPOS: + try: + latest_yum_version = Version( + EFSUtilsVersionChecker.get_latest_version_by_yum() + ) + if latest_yum_version > current_version: + EFSUtilsVersionChecker.warn_newer_version_available_yum( + current_version, latest_yum_version + ) + EFSUtilsVersionChecker.update_version_check_file() + return + except Exception as err: + logging.debug( + "Failed to query Yum for latest version of amazon-efs-utils. " + + str(err) + ) + pass + + try: + latest_github_version = Version( + EFSUtilsVersionChecker.get_latest_version_by_github() + ) + if latest_github_version > current_version: + EFSUtilsVersionChecker.warn_newer_version_available_github( + current_version, latest_github_version + ) + except Exception as err: + logging.debug( + "Failed to query Github for latest version of amazon-efs-utils. This is expected when Github is not reachable. " + + str(err) + ) + pass + + EFSUtilsVersionChecker.update_version_check_file() + + @staticmethod + def should_check_efs_utils_version(config): + """Returns True if a customer has enabled the amazon-efs-utils version check, + and if the last version check occurred more than VERSION_CHECK_POLL_INTERVAL seconds ago. + """ + version_check_enabled = get_boolean_config_item_value( + config, CONFIG_SECTION, ENABLE_VERSION_CHECK, default_value=True + ) + return version_check_enabled and EFSUtilsVersionChecker.version_check_ready() + + def fatal_error(user_message, log_message=None): if log_message is None: log_message = user_message @@ -714,7 +965,6 @@ def get_nfs_mount_options_on_macos(mount_point, mount_server="127.0.0.1:/"): - if not mount_point: logging.warning("Unable to get local mount options with empty mount point") return None @@ -869,32 +1119,6 @@ return False -def check_if_platform_is_mac(): - return sys.platform in MAC_OS_PLATFORM_LIST - - -def get_system_release_version(): - # MacOS does not maintain paths /etc/os-release and /etc/sys-release - if check_if_platform_is_mac(): - return platform.platform() - - try: - with open(SYSTEM_RELEASE_PATH) as f: - return f.read().strip() - except IOError: - logging.debug("Unable to read %s", SYSTEM_RELEASE_PATH) - - try: - with open(OS_RELEASE_PATH) as f: - for line in f: - if "PRETTY_NAME" in line: - return line.split("=")[1].strip() - except IOError: - logging.debug("Unable to read %s", OS_RELEASE_PATH) - - return DEFAULT_UNKNOWN_VALUE - - def find_command_path(command, install_method): # If not running on macOS, use linux paths if not check_if_platform_is_mac(): @@ -1539,12 +1763,15 @@ not_before = get_certificate_timestamp(current_time, minutes=-NOT_BEFORE_MINS) not_after = get_certificate_timestamp(current_time, hours=NOT_AFTER_HOURS) - cmd = "openssl ca -startdate %s -enddate %s -selfsign -batch -notext -config %s -in %s -out %s" % ( - not_before, - not_after, - certificate_config, - certificate_signing_request, - certificate, + cmd = ( + "openssl ca -startdate %s -enddate %s -selfsign -batch -notext -config %s -in %s -out %s" + % ( + not_before, + not_after, + certificate_config, + certificate_signing_request, + certificate, + ) ) subprocess_call(cmd, "Failed to create self-signed client-side certificate") return current_time.strftime(CERT_DATETIME_FORMAT) @@ -1599,8 +1826,10 @@ def generate_key(): if os.path.isfile(key): + # If the openssl genpkey command is interrupted or isn't successful, + # it will leave behind an empty file. if os.path.getsize(key) == 0: - logging.info("Purging empty private key file") + logging.warning("Purging empty private key file") os.remove(key) else: return @@ -2149,6 +2378,9 @@ ) check_child_procs(child_procs) + if EFSUtilsVersionChecker.should_check_efs_utils_version(config): + EFSUtilsVersionChecker.check_if_using_old_version(VERSION) + time.sleep(poll_interval_sec) else: logging.info("amazon-efs-mount-watchdog is not enabled") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.35.0/test/mount_efs_test/test_create_self_signed_cert.py new/efs-utils-1.35.1/test/mount_efs_test/test_create_self_signed_cert.py --- old/efs-utils-1.35.0/test/mount_efs_test/test_create_self_signed_cert.py 2023-03-16 19:07:54.000000000 +0100 +++ new/efs-utils-1.35.1/test/mount_efs_test/test_create_self_signed_cert.py 2024-01-18 16:57:36.000000000 +0100 @@ -711,3 +711,25 @@ ) assert full_config_body == matching_config_body + + +def test_check_and_create_private_key_key_was_empty(mocker, tmpdir): + pk_path = _get_mock_private_key_path(mocker, tmpdir) + with open(pk_path, "w") as pk_file: + pass + + state_file_dir = str(tmpdir) + mount_efs.check_and_create_private_key(state_file_dir) + assert os.path.getsize(pk_path) > 0 + + +def test_check_and_create_private_key_key_already_exists(mocker, tmpdir): + pk_path = _get_mock_private_key_path(mocker, tmpdir) + with open(pk_path, "w") as pk_file: + pk_file.write("private key file contents") + + call_mock = mocker.patch("mount_efs.subprocess_call") + + state_file_dir = str(tmpdir) + mount_efs.check_and_create_private_key(state_file_dir) + assert call_mock.call_count == 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.35.0/test/mount_efs_test/test_get_nfs_mount_options.py new/efs-utils-1.35.1/test/mount_efs_test/test_get_nfs_mount_options.py --- old/efs-utils-1.35.0/test/mount_efs_test/test_get_nfs_mount_options.py 2023-03-16 19:07:54.000000000 +0100 +++ new/efs-utils-1.35.1/test/mount_efs_test/test_get_nfs_mount_options.py 2024-01-18 16:57:36.000000000 +0100 @@ -91,6 +91,12 @@ assert "tls" not in nfs_opts +def test_fsap_efs_only(): + nfs_opts = mount_efs.get_nfs_mount_options({"fsap": None}) + + assert "fsap" not in nfs_opts + + def test_get_default_nfs_mount_options_macos(mocker): mocker.patch("mount_efs.check_if_platform_is_mac", return_value=True) nfs_opts = mount_efs.get_nfs_mount_options({}) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.35.0/test/mount_efs_test/test_write_stunnel_config_file.py new/efs-utils-1.35.1/test/mount_efs_test/test_write_stunnel_config_file.py --- old/efs-utils-1.35.0/test/mount_efs_test/test_write_stunnel_config_file.py 2023-03-16 19:07:54.000000000 +0100 +++ new/efs-utils-1.35.1/test/mount_efs_test/test_write_stunnel_config_file.py 2024-01-18 16:57:36.000000000 +0100 @@ -41,7 +41,6 @@ stunnel_libwrap_option_supported=True, fips_mode_enabled=False, ): - options = [] if stunnel_check_cert_hostname_supported: options.append(b"checkHost = peer certificate host name pattern") @@ -163,7 +162,6 @@ disable_libwrap=True, fallback_ip_address=None, ): - expected_efs_config = dict(mount_efs.STUNNEL_EFS_CONFIG) expected_efs_config["accept"] = expected_efs_config["accept"] % port if not fallback_ip_address: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.35.0/test/watchdog_test/test_check_if_using_old_version.py new/efs-utils-1.35.1/test/watchdog_test/test_check_if_using_old_version.py --- old/efs-utils-1.35.0/test/watchdog_test/test_check_if_using_old_version.py 1970-01-01 01:00:00.000000000 +0100 +++ new/efs-utils-1.35.1/test/watchdog_test/test_check_if_using_old_version.py 2024-01-18 16:57:36.000000000 +0100 @@ -0,0 +1,200 @@ +# 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 json +import logging +import tempfile +from datetime import date, datetime + +import pytest + +import watchdog + +try: + import ConfigParser +except ImportError: + from configparser import ConfigParser + +OLD_VERSION = "1.34.3" +GITHUB_VERSION = "1.35.9" +YUM_VERSION = "1.35.8" + +CERT_DATETIME_FORMAT = "%y%m%d%H%M%SZ" + + +def test_check_if_using_old_version_yum_works(mocker, caplog): + mocker.patch( + "watchdog.EFSUtilsVersionChecker.get_latest_version_by_yum", + return_value=YUM_VERSION, + ) + mocker.patch( + "watchdog.EFSUtilsVersionChecker.get_latest_version_by_github", + return_value=GITHUB_VERSION, + ) + mocker.patch("watchdog.EFSUtilsVersionChecker.update_version_check_file") + mocker.patch( + "watchdog.EFSUtilsVersionChecker.SHOULD_CHECK_AMZN_REPOS", + return_value=True, + ) + + with caplog.at_level(logging.INFO): + watchdog.EFSUtilsVersionChecker.check_if_using_old_version(OLD_VERSION) + assert ( + "We recommend you upgrade to the latest version of efs-utils by running 'yum update amazon-efs-utils'." + in caplog.text + ) + assert YUM_VERSION in caplog.text + + +def test_check_if_using_old_version_yum_fails(mocker, caplog): + mocker.patch( + "watchdog.EFSUtilsVersionChecker.get_latest_version_by_yum", + side_effect=TimeoutError, + ) + mocker.patch( + "watchdog.EFSUtilsVersionChecker.get_latest_version_by_github", + return_value=GITHUB_VERSION, + ) + mocker.patch("watchdog.EFSUtilsVersionChecker.update_version_check_file") + + with caplog.at_level(logging.INFO): + watchdog.EFSUtilsVersionChecker.check_if_using_old_version(OLD_VERSION) + + assert ( + "We recommend you install the latest version of efs-utils from github" + in caplog.text + ) + assert GITHUB_VERSION in caplog.text + + +def test_check_if_using_old_version_yum_github_fail(mocker, caplog): + mocker.patch( + "watchdog.EFSUtilsVersionChecker.get_latest_version_by_yum", + side_effect=FileNotFoundError("No such file or directory: 'yum'"), + ) + mocker.patch( + "watchdog.EFSUtilsVersionChecker.get_latest_version_by_github", + side_effect=TimeoutError, + ) + mocker.patch("watchdog.EFSUtilsVersionChecker.update_version_check_file") + + with caplog.at_level(logging.WARNING): + watchdog.EFSUtilsVersionChecker.check_if_using_old_version(OLD_VERSION) + + assert not caplog.text + + +def test_get_last_version_check_date(mocker, tmp_path): + current_time_str = datetime.utcnow().strftime(CERT_DATETIME_FORMAT) + dictionary = { + "time": current_time_str, + } + version_check_file = tempfile.NamedTemporaryFile(mode="w+", dir=str(tmp_path)) + json.dump(dictionary, version_check_file) + version_check_file.flush() + + mocker.patch("os.path.join", return_value=version_check_file.name) + last_version_check_date = ( + watchdog.EFSUtilsVersionChecker.get_last_version_check_time() + ) + assert last_version_check_date.strftime(CERT_DATETIME_FORMAT) == current_time_str + + version_check_file.close() + + +def test_get_last_version_check_bad_format(mocker, tmp_path): + """Make sure that watchdog does not crash if the version check file does not have a format we expect""" + current_time_str = datetime.utcnow().strftime(CERT_DATETIME_FORMAT) + dictionary = { + "bad_key": current_time_str, + } + version_check_file = tempfile.NamedTemporaryFile(mode="w+", dir=str(tmp_path)) + json.dump(dictionary, version_check_file) + version_check_file.flush() + + mocker.patch("os.path.join", return_value=version_check_file.name) + last_version_check_date = ( + watchdog.EFSUtilsVersionChecker.get_last_version_check_time() + ) + assert not last_version_check_date + + version_check_file.close() + + +def test_version_check_ready(mocker): + old_datetime = datetime(2000, 2, 3, 5, 35, 2) + mocker.patch( + "watchdog.EFSUtilsVersionChecker.get_last_version_check_time", + return_value=old_datetime, + ) + assert watchdog.EFSUtilsVersionChecker.version_check_ready() + + +def test_update_version_check_file(mocker, tmp_path): + """Write current time into the version check file""" + current_time = datetime.utcnow() + mocker.patch("watchdog.get_utc_now", return_value=current_time) + version_check_file = tempfile.NamedTemporaryFile(mode="w+", dir=str(tmp_path)) + mocker.patch("os.path.join", return_value=version_check_file.name) + mocker.patch("os.path.exists", return_value=True) + + watchdog.EFSUtilsVersionChecker.update_version_check_file() + version_check_file.flush() + + with open(version_check_file.name, "r") as f: + data = json.load(f) + + assert current_time.strftime(CERT_DATETIME_FORMAT) == data["time"] + + +def test_version_gt(): + assert watchdog.Version("1.34.5") > watchdog.Version("0.34.5") + assert watchdog.Version("1.35.5") > watchdog.Version("1.34.5") + assert watchdog.Version("1.34.5") > watchdog.Version("1.34.4") + + assert not watchdog.Version("0.34.5") > watchdog.Version("1.34.5") + assert not watchdog.Version("1.34.5") > watchdog.Version("1.35.5") + assert not watchdog.Version("1.34.4") > watchdog.Version("1.34.5") + + +def test_version_lt(): + assert watchdog.Version("0.34.5") < watchdog.Version("1.34.5") + assert watchdog.Version("1.34.5") < watchdog.Version("1.35.5") + assert watchdog.Version("1.34.4") < watchdog.Version("1.34.5") + + assert not watchdog.Version("1.34.5") < watchdog.Version("0.34.5") + assert not watchdog.Version("1.35.5") < watchdog.Version("1.34.5") + assert not watchdog.Version("1.34.5") < watchdog.Version("1.34.4") + + +def test_version_eq(): + assert watchdog.Version("0.34.5") == watchdog.Version("0.34.5") + assert not watchdog.Version("0.34.5") > watchdog.Version("0.34.5") + assert not watchdog.Version("0.34.5") < watchdog.Version("0.34.5") + + +def test_version_empty_version_str(): + """Assert that an Exception is thrown when we try to construct a Version instance with an empty string""" + with pytest.raises(Exception): + watchdog.Version("") + + +def test_should_check_efs_utils_version(mocker): + mocker.patch("watchdog.get_boolean_config_item_value", return_value=True) + mocker.patch( + "watchdog.EFSUtilsVersionChecker.version_check_ready", return_value=True + ) + config = ConfigParser() + assert watchdog.EFSUtilsVersionChecker.should_check_efs_utils_version(config) + + mocker.patch("watchdog.get_boolean_config_item_value", return_value=False) + assert not watchdog.EFSUtilsVersionChecker.should_check_efs_utils_version(config) + + mocker.patch( + "watchdog.EFSUtilsVersionChecker.version_check_ready", return_value=False + ) + mocker.patch("watchdog.get_boolean_config_item_value", return_value=True) + assert not watchdog.EFSUtilsVersionChecker.should_check_efs_utils_version(config) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/efs-utils-1.35.0/test/watchdog_test/test_refresh_self_signed_certificate.py new/efs-utils-1.35.1/test/watchdog_test/test_refresh_self_signed_certificate.py --- old/efs-utils-1.35.0/test/watchdog_test/test_refresh_self_signed_certificate.py 2023-03-16 19:07:54.000000000 +0100 +++ new/efs-utils-1.35.1/test/watchdog_test/test_refresh_self_signed_certificate.py 2024-01-18 16:57:36.000000000 +0100 @@ -894,3 +894,25 @@ ) assert full_config_body == matching_config_body + + +def test_check_and_create_private_key_key_was_empty(mocker, tmpdir): + pk_path = _get_mock_private_key_path(mocker, tmpdir) + with open(pk_path, "w") as pk_file: + pass + + state_file_dir = str(tmpdir) + watchdog.check_and_create_private_key(state_file_dir) + assert os.path.getsize(pk_path) > 0 + + +def test_check_and_create_private_key_key_already_exists(mocker, tmpdir): + pk_path = _get_mock_private_key_path(mocker, tmpdir) + with open(pk_path, "w") as pk_file: + pk_file.write("private key file contents") + + call_mock = mocker.patch("watchdog.subprocess_call") + + state_file_dir = str(tmpdir) + watchdog.check_and_create_private_key(state_file_dir) + assert call_mock.call_count == 0