Merge 3003 changes forward to the master branch (#59879)

* Merge 3002.6 bugfix changes (#59822)

* Pass `CI_RUN` as an environment variable to the test run.

This allows us to know if we're running the test suite under a CI
environment or not and adapt/adjust if needed

* Migrate `unit.setup` to PyTest

* Backport ae36b15 just for test_install.py

* Only skip tests on CI runs

* Always store git sha in _version.py during installation

* Fix PEP440 compliance.

The wheel metadata version 1.2 states that the package version MUST be
PEP440 compliant.

This means that instead of `3002.2-511-g033c53eccb`, the salt version
string should look like `3002.2+511.g033c53eccb`, a post release of
`3002.2` ahead by 511 commits with the git sha `033c53eccb`

* Fix and migrate `tests/unit/test_version.py` to PyTest

* Skip test if `easy_install` is not available

* We also need to be PEP440 compliant when there's no git history

* Allow extra_filerefs as sanitized kwargs for SSH client

* Fix regression on cmd.run when passing tuples as cmd

Co-authored-by: Alexander Graul <agraul@suse.com>

* Add unit tests to ensure cmd.run accepts tuples

* Add unit test to check for extra_filerefs on SSH opts

* Add changelog file

* Fix comment for test case

* Fix unit test to avoid failing on Windows

* Skip failing test on windows

* Fix test to work on Windows

* Add all ssh kwargs to sanitize_kwargs method

* Run pre-commit

* Fix pylint

* Fix cmdmod loglevel and module_names tests

* Fix pre-commit

* Skip ssh tests if binary does not exist

* Use setup_loader for cmdmod test

* Prevent argument injection in restartcheck

* Add changelog for restartcheck fix

* docs_3002.6

* Add back tests removed in merge

Co-authored-by: Pedro Algarvio <pedro@algarvio.me>
Co-authored-by: Megan Wilhite <megan.wilhite@gmail.com>
Co-authored-by: Bryce Larson <brycel@vmware.com>
Co-authored-by: Pablo Suárez Hernández <psuarezhernandez@suse.com>
Co-authored-by: Alexander Graul <agraul@suse.com>
Co-authored-by: Frode Gundersen <fgundersen@saltstack.com>

* Remove glance state module in favor of glance_image

* update wording in changelog

* bump deprecation warning to Silicon.

* Updating warnutil version to Phosphorous.

* Update salt/modules/keystone.py

Co-authored-by: Megan Wilhite <megan.wilhite@gmail.com>

* Check $HOMEBREW_PREFIX when linking against libcrypto

When loading `libcrypto`, Salt checks for a Homebrew installation of `openssl`
at Homebrew's default prefix of `/usr/local`. However, on Apple Silicon Macs,
Homebrew's default installation prefix is `/opt/homebrew`. On all platforms,
the prefix is configurable.  If Salt doesn't find one of those `libcrypto`s,
it will fall back on the un-versioned `/usr/lib/libcrypto.dylib`, which will
cause the following crash:

    Application Specific Information:
    /usr/lib/libcrypto.dylib
    abort() called
    Invalid dylib load. Clients should not load the unversioned libcrypto dylib as it does not have a stable ABI.

This commit checks $HOMEBREW_PREFIX instead of hard-coding `/usr/local`.

* Add test case

* Add changelog for 59808

* Add changelog entry

* Make _find_libcrypto fail on Big Sur if it can't find a library

Right now, if `_find_libcrypto` can't find any externally-managed versions of
libcrypto, it will fall back on the pre-Catalina un-versioned system libcrypto.
This does not exist on Big Sur and it would be better to raise an exception
here rather than crashing later when trying to open it.

* Update _find_libcrypto tests

This commit simplifies the unit tests for _find_libcrypto by mocking out the
host's filesystem and testing the common libcrypto installations (brew, ports,
etc.) on Big Sur. It simplifies the tests for falling back on system versions
of libcrypto on previous versions of macOS.

* Fix description of test_find_libcrypto_with_system_before_catalina

* Patch sys.platform for test_rsax931 tests

* modules/match: add missing "minion_id" in Pillar example

The documented Pillar example for `match.filter_by` lacks the `minion_id` parameter. Without it, the assignment won't work as expected.
- fix documentation
- add tests:
  - to prove the misbehavior of the documented example
  - to prove the proper behaviour when supplying `minion_id`
  - to ensure some misbehaviour observed with compound matchers doesn't occur

* Fix for issue #59773

- When instantiating the loader grab values of grains and pillars if
  they are NamedLoaderContext instances.
- The loader uses a copy of opts.
- Impliment deepcopy on NamedLoaderContext instances.

* Add changelog for #59773

* _get_initial_pillar function returns pillar

* Fix linter issues

* Clean up test

* Bump deprecation release for neutron

* Uncomment Sulfur release name

* Removing the _ext_nodes deprecation warning and alias.

* Adding changelog.

* Renaming changelog file.

* Update 59804.removed

* Initial pass at fips_mode config option

* Fix pre-commit

* Fix tests and add changelog

* update docs 3003

* update docs 3003 - newline

* Fix warts in changelog

Co-authored-by: Pedro Algarvio <pedro@algarvio.me>
Co-authored-by: Megan Wilhite <megan.wilhite@gmail.com>
Co-authored-by: Bryce Larson <brycel@vmware.com>
Co-authored-by: Pablo Suárez Hernández <psuarezhernandez@suse.com>
Co-authored-by: Alexander Graul <agraul@suse.com>
Co-authored-by: Frode Gundersen <fgundersen@saltstack.com>
Co-authored-by: Gareth J. Greenaway <gareth@saltstack.com>
Co-authored-by: Gareth J. Greenaway <gareth@wiked.org>
Co-authored-by: Hoa-Long Tam <hoalong@apple.com>
Co-authored-by: krionbsd <krion@freebsd.org>
Co-authored-by: Elias Probst <e.probst@ssc-services.de>
Co-authored-by: Frode Gundersen <frogunder@gmail.com>
This commit is contained in:
Daniel Wozniak 2021-03-24 07:52:25 -07:00 committed by GitHub
parent 10c4da25c2
commit 0b5a3536c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 707 additions and 123 deletions

View file

@ -13,6 +13,9 @@ Salt 3003 (2021-03-05)
Removed
-------
- Removed the deprecated glance state and execution module in favor of the glance_image
state module and the glanceng execution module. (#59079)
- Removing the _ext_nodes deprecation warning and alias to the master_tops function. This change will break compatibility with a Salt master running versions 2017.7.8 and older and Salt minions running versions 3003 and newer. (#59804)
- removed the arg `managed_private_key` from 'salt.states.x509.certificate_managed' (#59247)
- Drop support for python 3.5 on Windows (#59479)
@ -22,7 +25,6 @@ Deprecated
- Added deprecation warning for grains.get_or_set_hash (#59425)
Changed
-------
@ -35,6 +37,9 @@ Changed
Fixed
-----
- When instantiating the loader grab values of grains and pillars if
they are NamedLoaderContext instances. (#59773)
- Fixed installation on Apple Silicon Macs by checking $HOMEBREW_PREFIX for `libcrypto` instead of assuming /usr/local. (#59808)
- Fix incorrect documentation for pillar_source_merging_strategy (#26396)
- Don't iterate through cloud map errors (#34033)
- Supress noisy warnings when very old pyzmq is used. (#50327)
@ -135,6 +140,7 @@ Fixed
Added
-----
- Added "fips_mode" config option to master and minion configs. (#59427)
- Adding the ability to clear and show the pillar cache enabled when pillar_cache is True. (#37080)
- SCRAM-SHA-256 support for PostgreSQL passwords.
Pass encrypted=scram-sha-256 to the postgres_user.present (or postgres_group.present) state. (#51271)
@ -169,6 +175,24 @@ Added
binary ELF files in the package. (#59569)
Salt 3002.6 (2021-03-10)
========================
Changed
-------
- Store git sha in salt/_version.py when installing from a tag so it can be found if needed later. (#59137)
Fixed
-----
- Fix argument injection bug in restartcheck.restartcheck. This change hardens
the fix for CVE-2020-28243. (#200)
- Allow "extra_filerefs" as sanitized kwargs for SSH client.
Fix regression on "cmd.run" when passing tuples as cmd. (#59664)
- Allow all ssh kwargs as sanitized kwargs for SSH client. (#59748)
Salt 3002.5 (2021-02-25)
========================
@ -480,6 +504,18 @@ Added
This flag will be deprecated in the Phosphorus release when this functionality
becomes the default. (#58652)
Salt 3001.7 (2021-03-10)
========================
Fixed
-----
- Fix argument injection bug in restartcheck.restartcheck. This change hardens
the fix for CVE-2020-28243. (#200)
- Allow "extra_filerefs" as sanitized kwargs for SSH client.
Fix regression on "cmd.run" when passing tuples as cmd. (#59664)
- Allow all ssh kwargs as sanitized kwargs for SSH client. (#59748)
Salt 3001.6 (2021-02-09)
========================
@ -971,6 +1007,18 @@ Added
- [#56637](https://github.com/saltstack/salt/pull/56637) - Add ``win_wua.installed`` to the ``win_wua`` execution module
- Clarify how to get the master fingerprint (#54699)
Salt 3000.9 (2021-03-10)
========================
Fixed
-----
- Allow "extra_filerefs" as sanitized kwargs for SSH client.
Fix regression on "cmd.run" when passing tuples as cmd. (#59664)
- Allow all ssh kwargs as sanitized kwargs for SSH client. (#59748)
- Fix argument injection bug in restartcheck.restartcheck. This change hardens
the fix for CVE-2020-28243.
Salt 3000.8 (2021-02-09)
========================

View file

@ -0,0 +1,17 @@
.. _release-3000-9:
===========================
Salt 3000.9 Release Notes
===========================
Version 3000.9 is a bug fix release for :ref:`3000 <release-3000>`.
Fixed
-----
- Allow "extra_filerefs" as sanitized kwargs for SSH client.
Fix regression on "cmd.run" when passing tuples as cmd. (#59664)
- Allow all ssh kwargs as sanitized kwargs for SSH client. (#59748)
- Fix argument injection bug in restartcheck.restartcheck. This change hardens
the fix for CVE-2020-28243.

View file

@ -0,0 +1,17 @@
.. _release-3001-7:
=========================
Salt 3001.7 Release Notes
=========================
Version 3001.7 is a bug fix release for :ref:`3001 <release-3001>`.
Fixed
-----
- Allow "extra_filerefs" as sanitized kwargs for SSH client.
Fix regression on "cmd.run" when passing tuples as cmd. (#59664)
- Allow all ssh kwargs as sanitized kwargs for SSH client. (#59748)
- Fix argument injection bug in restartcheck.restartcheck. This change hardens
the fix for CVE-2020-28243.

View file

@ -0,0 +1,24 @@
.. _release-3002-6:
=========================
Salt 3002.6 Release Notes
=========================
Version 3002.6 is a bug fix release for :ref:`3002 <release-3002>`.
Changed
-------
- Store git sha in salt/_version.py when installing from a tag so it can be found if needed later. (#59137)
Fixed
-----
- Fix argument injection bug in restartcheck.restartcheck. This change hardens
the fix for CVE-2020-28243. (#200)
- Allow "extra_filerefs" as sanitized kwargs for SSH client.
Fix regression on "cmd.run" when passing tuples as cmd. (#59664)
- Allow all ssh kwargs as sanitized kwargs for SSH client. (#59748)

View file

@ -4,8 +4,6 @@
Salt 3003 Release Notes - Codename Aluminium
============================================
Salt 3003 is an *unreleased* upcoming feature release.
New Features
============
@ -22,6 +20,9 @@ previous storage methods.
Removed
-------
- Removed the deprecated glance state and execution module in favor of the glance_image
state module and the glanceng execution module. (#59079)
- Removing the _ext_nodes deprecation warning and alias to the master_tops function. This change will break compatibility with a Salt master running versions 2017.7.8 and older and Salt minions running versions 3003 and newer. (#59804)
- removed the arg `managed_private_key` from 'salt.states.x509.certificate_managed' (#59247)
- Drop support for python 3.5 on Windows (#59479)
@ -50,6 +51,9 @@ Changed
Fixed
-----
- When instantiating the loader grab values of grains and pillars if
they are NamedLoaderContext instances. (#59773)
- Fixed installation on Apple Silicon Macs by checking $HOMEBREW_PREFIX for `libcrypto` instead of assuming /usr/local. (#59808)
- The Google Cloud Engine salt-cloud provider now requires `apache-libcloud>=2.5.0`. Service account authentication is broken on older versions.
- Fix incorrect documentation for pillar_source_merging_strategy (#26396)
- Don't iterate through cloud map errors (#34033)
@ -151,6 +155,7 @@ Fixed
Added
-----
- Added "fips_mode" config option to master and minion configs. (#59427)
- Firewall groups support to Vultr Salt Cloud provider
- Adding the ability to clear and show the pillar cache enabled when pillar_cache is True. (#37080)
- SCRAM-SHA-256 support for PostgreSQL passwords.

View file

@ -52,11 +52,34 @@ class SSHClient:
("ssh_identities_only", bool),
("ssh_remote_port_forwards", str),
("ssh_options", list),
("ssh_max_procs", int),
("ssh_askpass", bool),
("ssh_key_deploy", bool),
("ssh_update_roster", bool),
("ssh_scan_ports", str),
("ssh_scan_timeout", int),
("ssh_timeout", int),
("ssh_log_file", str),
("raw_shell", bool),
("refresh_cache", bool),
("roster", str),
("roster_file", str),
("rosters", list),
("ignore_host_keys", bool),
("raw_shell", bool),
("extra_filerefs", str),
("min_extra_mods", str),
("thin_extra_mods", str),
("verbose", bool),
("static", bool),
("ssh_wipe", bool),
("rand_thin_dir", bool),
("regen_thin", bool),
("python2_bin", str),
("python3_bin", str),
("ssh_run_pre_flight", bool),
("no_host_keys", bool),
("saltfile", str),
]
sane_kwargs = {}
for name, kind in roster_vals:

View file

@ -952,6 +952,7 @@ VALID_OPTS = immutabletypes.freeze(
"disabled_requisites": (str, list),
# Feature flag config
"features": dict,
"fips_mode": bool,
}
)
@ -1254,6 +1255,7 @@ DEFAULT_MINION_OPTS = immutabletypes.freeze(
"ssh_merge_pillar": True,
"disabled_requisites": [],
"reactor_niceness": None,
"fips_mode": False,
}
)
@ -1590,6 +1592,7 @@ DEFAULT_MASTER_OPTS = immutabletypes.freeze(
"minion_data_cache_events": True,
"enable_ssh_minions": False,
"netapi_allow_raw_shell": False,
"fips_mode": False,
}
)

View file

@ -1404,15 +1404,7 @@ class RemoteClient(Client):
"""
Return the metadata derived from the master_tops system
"""
log.debug(
"The _ext_nodes master function has been renamed to _master_tops. "
"To ensure compatibility when using older Salt masters we will "
"continue to invoke the function as _ext_nodes until the "
"3002 release."
)
# TODO: Change back to _master_tops
# for 3002 release
load = {"cmd": "_ext_nodes", "id": self.opts["id"], "opts": self.opts}
load = {"cmd": "_master_tops", "id": self.opts["id"], "opts": self.opts}
if self.auth:
load["tok"] = self.auth.gen_token(b"salt")
return self.channel.send(load)

View file

@ -1314,6 +1314,12 @@ class LazyLoader(salt.utils.lazy.LazyDict):
self.pack[i] = self.pack[i].value()
if opts is None:
opts = {}
opts = copy.deepcopy(opts)
for i in ["pillar", "grains"]:
if i in opts and isinstance(
opts[i], salt.loader_context.NamedLoaderContext
):
opts[i] = opts[i].value()
threadsafety = not opts.get("multiprocessing")
self.context_dict = salt.utils.context.ContextDict(threadsafe=threadsafety)
self.opts = self.__prep_mod_opts(opts)

View file

@ -4,6 +4,7 @@ Manage the context a module loaded by Salt's loader
import collections.abc
import contextlib
import contextvars
import copy
DEFAULT_CTX_VAR = "loader_ctxvar"
@ -112,6 +113,10 @@ class NamedLoaderContext(collections.abc.MutableMapping):
def __getattr__(self, name):
return getattr(self.value(), name)
def __deepcopy__(self, memo):
default = copy.deepcopy(self.default)
return self.__class__(self.name, self.loader_context, default)
def missing_fun_string(self, name):
return self.loader().missing_fun_string(name)

View file

@ -1204,7 +1204,6 @@ class AESFuncs(TransportMethods):
expose_methods = (
"verify_minion",
"_master_tops",
"_ext_nodes",
"_master_opts",
"_mine_get",
"_mine",
@ -1429,9 +1428,6 @@ class AESFuncs(TransportMethods):
return {}
return self.masterapi._master_tops(load, skip_verify=True)
# Needed so older minions can request master_tops
_ext_nodes = _master_tops
def _master_opts(self, load):
"""
Return the master options to the minion

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
This module helps include encrypted passwords in pillars, grains and salt state files.
@ -150,16 +149,15 @@ Optional small program to encrypt data without needing salt modules.
"""
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals
# Import Salt libs
import salt.utils.nacl
__virtualname__ = "nacl"
def __virtual__():
if __opts__["fips_mode"] is True:
return False, "nacl module not available in FIPS mode"
return salt.utils.nacl.check_requirements()

View file

@ -11,7 +11,6 @@ https://packages.debian.org/debian-goodies) and psdel by Sam Morris.
"""
import os
import re
import shlex
import subprocess
import sys
import time
@ -495,17 +494,17 @@ def restartcheck(ignorelist=None, blacklist=None, excludepid=None, **kwargs):
verbose = kwargs.pop("verbose", True)
timeout = kwargs.pop("timeout", 5)
if __grains__.get("os_family") == "Debian":
cmd_pkg_query = "dpkg-query --listfiles "
cmd_pkg_query = ["dpkg-query", "--listfiles"]
systemd_folder = "/lib/systemd/system/"
systemd = "/bin/systemd"
kernel_versions = _kernel_versions_debian()
elif __grains__.get("os_family") == "RedHat":
cmd_pkg_query = "repoquery -l "
cmd_pkg_query = ["repoquery", "-l"]
systemd_folder = "/usr/lib/systemd/system/"
systemd = "/usr/bin/systemctl"
kernel_versions = _kernel_versions_redhat()
elif __grains__.get("os_family") == NILRT_FAMILY_NAME:
cmd_pkg_query = "opkg files "
cmd_pkg_query = ["opkg", "files"]
systemd = ""
kernel_versions = _kernel_versions_nilrt()
else:
@ -613,8 +612,8 @@ def restartcheck(ignorelist=None, blacklist=None, excludepid=None, **kwargs):
for package in packages:
_check_timeout(start_time, timeout)
cmd = cmd_pkg_query + package
cmd = shlex.split(cmd)
cmd = cmd_pkg_query[:]
cmd.append(package)
paths = subprocess.Popen(cmd, stdout=subprocess.PIPE)
while True:

View file

@ -425,7 +425,7 @@ def _check_queue(queue, kwargs):
def _get_initial_pillar(opts):
return (
__pillar__
__pillar__.value()
if __opts__.get("__cli", None) == "salt-call"
and opts["pillarenv"] == __opts__["pillarenv"]
else None

View file

@ -568,7 +568,6 @@ def read_certificate(certificate):
"Key Size": cert.get_pubkey().size() * 8,
"Serial Number": _dec2hex(cert.get_serial_number()),
"SHA-256 Finger Print": _pretty_hex(cert.get_fingerprint(md="sha256")),
"MD5 Finger Print": _pretty_hex(cert.get_fingerprint(md="md5")),
"SHA1 Finger Print": _pretty_hex(cert.get_fingerprint(md="sha1")),
"Subject": _parse_subject(cert.get_subject()),
"Subject Hash": _dec2hex(cert.get_subject().as_hash()),
@ -580,7 +579,8 @@ def read_certificate(certificate):
"Not After": cert.get_not_after().get_datetime().strftime("%Y-%m-%d %H:%M:%S"),
"Public Key": get_public_key(cert),
}
if __opts__["fips_mode"] is False:
ret["MD5 Finger Print"] = _pretty_hex(cert.get_fingerprint(md="md5"))
exts = OrderedDict()
for ext_index in range(0, cert.get_ext_count()):
ext = cert.get_ext_at(ext_index)

View file

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
Decrypt pillar data through the builtin NACL renderer
@ -20,10 +18,17 @@ Set ``nacl.config`` in your config.
"""
from __future__ import absolute_import, print_function, unicode_literals
import salt
__virtualname__ = "nacl"
def __virtual__():
if __opts__["fips_mode"] is True:
return False, "nacl pillar data not available in FIPS mode"
return __virtualname__
def ext_pillar(minion_id, pillar, *args, **kwargs):
render_function = salt.loader.render(__opts__, __salt__).get("nacl")

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
This module helps include encrypted passwords in pillars, grains and salt state files.
@ -112,16 +111,15 @@ Larger files like certificates can be encrypted with:
"""
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals
# Import Salt libs
import salt.utils.nacl
__virtualname__ = "nacl"
def __virtual__():
if __opts__["fips_mode"] is True:
return False, "nacl runner not available in FIPS mode"
return salt.utils.nacl.check_requirements()

View file

@ -321,7 +321,7 @@ def private_key_managed(
name, bits=bits, passphrase=passphrase, new=new, overwrite=overwrite
):
file_args["contents"] = __salt__["x509.get_pem_entry"](
name, pem_type="RSA PRIVATE KEY"
name, pem_type="(?:RSA )?PRIVATE KEY"
)
else:
new_key = True
@ -399,12 +399,13 @@ def _certificate_info_matches(cert_info, required_cert_info, check_serial=False)
ignored_keys = [
"Not Before",
"Not After",
"MD5 Finger Print",
"SHA1 Finger Print",
"SHA-256 Finger Print",
# The integrity of the issuer is checked elsewhere
"Issuer Public Key",
]
if __opts__["fips_mode"] is False:
ignored_keys.append("MD5 Finger Print")
for key in ignored_keys:
cert_info.pop(key, None)
required_cert_info.pop(key, None)

View file

@ -1,10 +1,7 @@
# -*- coding: utf-8 -*-
"""
Common code shared between the nacl module and runner.
"""
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals
import base64
import logging
@ -18,9 +15,6 @@ import salt.utils.versions
import salt.utils.win_dacl
import salt.utils.win_functions
# Import Salt libs
from salt.ext import six
log = logging.getLogger(__name__)
REQ_ERROR = None
@ -36,6 +30,8 @@ __virtualname__ = "nacl"
def __virtual__():
if __opts__["fips_mode"] is True:
return False, "nacl utils not available in FIPS mode"
return check_requirements()
@ -66,7 +62,7 @@ def _get_config(**kwargs):
"pk_file": pk_file,
}
config_key = "{0}.config".format(__virtualname__)
config_key = "{}.config".format(__virtualname__)
try:
config.update(__salt__["config.get"](config_key, {}))
except (NameError, KeyError) as e:
@ -91,7 +87,7 @@ def _get_sk(**kwargs):
try:
with salt.utils.files.fopen(sk_file, "rb") as keyf:
key = salt.utils.stringutils.to_unicode(keyf.read()).rstrip("\n")
except (IOError, OSError):
except OSError:
raise Exception("no key or sk_file found")
return base64.b64decode(key)
@ -109,9 +105,9 @@ def _get_pk(**kwargs):
try:
with salt.utils.files.fopen(pk_file, "rb") as keyf:
pubkey = salt.utils.stringutils.to_unicode(keyf.read()).rstrip("\n")
except (IOError, OSError):
except OSError:
raise Exception("no pubkey or pk_file found")
pubkey = six.text_type(pubkey)
pubkey = str(pubkey)
return base64.b64decode(pubkey)
@ -151,7 +147,7 @@ def keygen(sk_file=None, pk_file=None, **kwargs):
return {"sk": base64.b64encode(kp.sk), "pk": base64.b64encode(kp.pk)}
if pk_file is None:
pk_file = "{0}.pub".format(sk_file)
pk_file = "{}.pub".format(sk_file)
if sk_file and pk_file is None:
if not os.path.isfile(sk_file):
@ -172,16 +168,16 @@ def keygen(sk_file=None, pk_file=None, **kwargs):
else:
# chmod 0600 file
os.chmod(sk_file, 1536)
return "saved sk_file: {0}".format(sk_file)
return "saved sk_file: {}".format(sk_file)
else:
raise Exception("sk_file:{0} already exist.".format(sk_file))
raise Exception("sk_file:{} already exist.".format(sk_file))
if sk_file is None and pk_file:
raise Exception("sk_file: Must be set inorder to generate a public key.")
if os.path.isfile(sk_file) and os.path.isfile(pk_file):
raise Exception(
"sk_file:{0} and pk_file:{1} already exist.".format(sk_file, pk_file)
"sk_file:{} and pk_file:{} already exist.".format(sk_file, pk_file)
)
if os.path.isfile(sk_file) and not os.path.isfile(pk_file):
@ -192,7 +188,7 @@ def keygen(sk_file=None, pk_file=None, **kwargs):
kp = libnacl.public.SecretKey(sk)
with salt.utils.files.fopen(pk_file, "wb") as keyf:
keyf.write(base64.b64encode(kp.pk))
return "saved pk_file: {0}".format(pk_file)
return "saved pk_file: {}".format(pk_file)
kp = libnacl.public.SecretKey()
with salt.utils.files.fopen(sk_file, "wb") as keyf:
@ -208,7 +204,7 @@ def keygen(sk_file=None, pk_file=None, **kwargs):
os.chmod(sk_file, 1536)
with salt.utils.files.fopen(pk_file, "wb") as keyf:
keyf.write(base64.b64encode(kp.pk))
return "saved sk_file:{0} pk_file: {1}".format(sk_file, pk_file)
return "saved sk_file:{} pk_file: {}".format(sk_file, pk_file)
def enc(data, **kwargs):
@ -275,10 +271,10 @@ def enc_file(name, out=None, **kwargs):
d = enc(data, **kwargs)
if out:
if os.path.isfile(out):
raise Exception("file:{0} already exist.".format(out))
raise Exception("file:{} already exist.".format(out))
with salt.utils.files.fopen(out, "wb") as f:
f.write(salt.utils.stringutils.to_bytes(d))
return "Wrote: {0}".format(out)
return "Wrote: {}".format(out)
return d
@ -346,10 +342,10 @@ def dec_file(name, out=None, **kwargs):
d = dec(data, **kwargs)
if out:
if os.path.isfile(out):
raise Exception("file:{0} already exist.".format(out))
raise Exception("file:{} already exist.".format(out))
with salt.utils.files.fopen(out, "wb") as f:
f.write(salt.utils.stringutils.to_bytes(d))
return "Wrote: {0}".format(out)
return "Wrote: {}".format(out)
return d

View file

@ -1,22 +1,13 @@
# -*- coding: utf-8 -*-
"""
Neutron class
"""
# Import python libs
from __future__ import absolute_import, print_function, unicode_literals, with_statement
import logging
import salt.utils.versions
# Import salt libs
from salt import exceptions
# Import third party libs
from salt.ext import six
# pylint: disable=import-error
HAS_NEUTRON = False
try:
@ -73,7 +64,7 @@ def sanitize_neutronclient(kwargs):
"auth",
)
ret = {}
for var in six.iterkeys(kwargs):
for var in kwargs.keys():
if var in variables:
ret[var] = kwargs[var]
@ -103,7 +94,7 @@ class SaltNeutron(NeutronShell):
Set up neutron credentials
"""
salt.utils.versions.warn_until(
"Aluminium",
"Sulfur",
(
"The neutron module has been deprecated and will be removed in {version}. "
"Please update to using the neutronng module"

View file

@ -32,17 +32,23 @@ def _find_libcrypto():
# look in salts pkg install location.
lib = glob.glob("/opt/salt/lib/libcrypto.dylib")
# Find library symlinks in Homebrew locations.
lib = lib or glob.glob("/usr/local/opt/openssl/lib/libcrypto.dylib")
lib = lib or glob.glob("/usr/local/opt/openssl@*/lib/libcrypto.dylib")
brew_prefix = os.getenv("HOMEBREW_PREFIX", "/usr/local")
lib = lib or glob.glob(
os.path.join(brew_prefix, "opt/openssl/lib/libcrypto.dylib")
)
lib = lib or glob.glob(
os.path.join(brew_prefix, "opt/openssl@*/lib/libcrypto.dylib")
)
# look in macports.
lib = lib or glob.glob("/opt/local/lib/libcrypto.dylib")
# check if 10.15, regular libcrypto.dylib is just a false pointer.
if platform.mac_ver()[0].split(".")[:2] == ["10", "15"]:
lib = lib or glob.glob("/usr/lib/libcrypto.*.dylib")
lib = list(reversed(sorted(lib)))
# last but not least all the other macOS versions should work here.
# including Big Sur.
lib = lib[0] if lib else "/usr/lib/libcrypto.dylib"
elif int(platform.mac_ver()[0].split(".")[0]) < 11:
# Fall back on system libcrypto (only works before Big Sur)
lib = lib or ["/usr/lib/libcrypto.dylib"]
lib = lib[0] if lib else None
elif getattr(sys, "frozen", False) and salt.utils.platform.is_smartos():
lib = glob.glob(os.path.join(os.path.dirname(sys.executable), "libcrypto.so*"))
lib = lib[0] if lib else None

View file

@ -96,8 +96,8 @@ class SaltStackVersion:
"Aluminium": (3003,),
"Silicon": (MAX_SIZE - 95, 0),
"Phosphorus": (MAX_SIZE - 94, 0),
"Sulfur": (MAX_SIZE - 93, 0),
# pylint: disable=E8265
#'Sulfur' : (MAX_SIZE - 93, 0),
#'Chlorine' : (MAX_SIZE - 92, 0),
#'Argon' : (MAX_SIZE - 91, 0),
#'Potassium' : (MAX_SIZE - 90, 0),

View file

@ -1,8 +1,11 @@
import pytest
import salt.client.ssh.client
import salt.utils.msgpack
from salt.client import ssh
from tests.support.mock import MagicMock, patch
pytestmark = [pytest.mark.skip_if_binaries_missing("ssh", "ssh-keygen", check_all=True)]
@pytest.fixture
def ssh_target(tmpdir):
@ -57,3 +60,76 @@ def test_cmd_block_python_version_error(ssh_target):
with patch_shim:
ret = single.cmd_block()
assert "ERROR: Python version error. Recommendation(s) follow:" in ret[0]
@pytest.mark.parametrize(
"test_opts",
[
("extra_filerefs", "salt://foobar", True),
("host", "testhost", False),
("ssh_user", "testuser", True),
("ssh_passwd", "testpasswd", True),
("ssh_port", 23, False),
("ssh_sudo", True, True),
("ssh_sudo_user", "sudouser", False),
("ssh_priv", "test_priv", True),
("ssh_priv_passwd", "sshpasswd", True),
("ssh_identities_only", True, True),
("ssh_remote_port_forwards", "test", True),
("ssh_options", ["test1", "test2"], True),
("ssh_max_procs", 2, True),
("ssh_askpass", True, True),
("ssh_key_deploy", True, True),
("ssh_update_roster", True, True),
("ssh_scan_ports", "test", True),
("ssh_scan_timeout", 1.0, True),
("ssh_timeout", 1, False),
("ssh_log_file", "/tmp/test", True),
("raw_shell", True, True),
("refresh_cache", True, True),
("roster", "/test", True),
("roster_file", "/test1", True),
("rosters", ["test1"], False),
("ignore_host_keys", True, True),
("min_extra_mods", "test", True),
("thin_extra_mods", "test1", True),
("verbose", True, True),
("static", True, True),
("ssh_wipe", True, True),
("rand_thin_dir", True, True),
("regen_thin", True, True),
("python2_bin", "python2", True),
("python3_bin", "python3", True),
("ssh_run_pre_flight", True, True),
("no_host_keys", True, True),
("saltfile", "/tmp/test", True),
("doesnotexist", None, False),
],
)
def test_ssh_kwargs(test_opts):
"""
test all ssh kwargs are not excluded from kwargs
when preparing the SSH opts
"""
opt_key = test_opts[0]
opt_value = test_opts[1]
# Is the kwarg in salt.utils.parsers?
in_parser = test_opts[2]
opts = {
"eauth": "auto",
"username": "test",
"password": "test",
"client": "ssh",
"tgt": "localhost",
"fun": "test.ping",
opt_key: opt_value,
}
client = salt.client.ssh.client.SSHClient(disable_custom_roster=True)
if in_parser:
ssh_kwargs = salt.utils.parsers.SaltSSHOptionParser().defaults
assert opt_key in ssh_kwargs
with patch("salt.roster.get_roster_file", MagicMock(return_value="")):
ssh_obj = client._prep_ssh(**opts)
assert ssh_obj.opts.get(opt_key, None) == opt_value

View file

@ -0,0 +1,16 @@
"""
Unit tests for the salt.modules.nacl module
"""
import salt.modules.nacl
from tests.support.mock import patch
def test_fips_mode():
"""
Nacl module does not load when fips_mode is True
"""
opts = {"fips_mode": True}
with patch("salt.modules.nacl.__opts__", opts, create=True):
ret = salt.modules.nacl.__virtual__()
assert ret == (False, "nacl module not available in FIPS mode")

View file

@ -0,0 +1,21 @@
"""
Unit tests for the salt.modules.state module
"""
import salt.loader_context
import salt.modules.state
from tests.support.mock import patch
def test_get_initial_pillar():
"""
_get_initial_pillar returns pillar data not named context
"""
ctx = salt.loader_context.LoaderContext()
pillar_data = {"foo": "bar"}
named_ctx = ctx.named_context("__pillar__", pillar_data)
opts = {"__cli": "salt-call", "pillarenv": "base"}
with patch("salt.modules.state.__pillar__", named_ctx, create=True):
with patch("salt.modules.state.__opts__", opts, create=True):
pillar = salt.modules.state._get_initial_pillar(opts)
assert pillar == pillar_data

View file

View file

@ -0,0 +1,16 @@
"""
Unit tests for the salt.pillar.nacl module
"""
import salt.pillar.nacl
from tests.support.mock import patch
def test_fips_mode():
"""
Nacl pillar doesn't load when fips_mode is True
"""
opts = {"fips_mode": True}
with patch("salt.pillar.nacl.__opts__", opts, create=True):
ret = salt.pillar.nacl.__virtual__()
assert ret == (False, "nacl pillar data not available in FIPS mode")

View file

View file

@ -0,0 +1,16 @@
"""
Unit tests for the salt.runners.nacl module
"""
import salt.runners.nacl
from tests.support.mock import patch
def test_fips_mode():
"""
Nacl runner doesn't load when fips_mode is True
"""
opts = {"fips_mode": True}
with patch("salt.runners.nacl.__opts__", opts, create=True):
ret = salt.runners.nacl.__virtual__()
assert ret == (False, "nacl runner not available in FIPS mode")

View file

@ -93,3 +93,24 @@ def test_loaders_create_named_loader_contexts(loader_dir):
module_name = func.func.__module__
module = sys.modules[module_name]
assert isinstance(module.__context__, salt.loader_context.NamedLoaderContext)
def test_loaders_convert_context_to_values(loader_dir):
"""
LazyLoaders convert NamedLoaderContexts to values when instantiated.
"""
loader_context = salt.loader_context.LoaderContext()
grains_default = {
"os": "linux",
}
grains = salt.loader_context.NamedLoaderContext(
"grains", loader_context, grains_default
)
opts = {
"optimization_order": [0, 1, 2],
"grains": grains,
}
loader_1 = salt.loader.LazyLoader([loader_dir], opts,)
assert loader_1.opts["grains"] == grains_default
# The loader's opts is a copy
assert opts["grains"] == grains

View file

@ -1,6 +1,8 @@
"""
Tests for salt.loader_context
"""
import copy
import salt.loader
import salt.loader_context
@ -31,3 +33,15 @@ def test_named_loader_default():
# The loader's value is the same object as default
assert named_context.value() is default
assert named_context["foo"] == "bar"
def test_named_loader_context_deepcopy():
loader_context = salt.loader_context.LoaderContext()
default_data = {"foo": "bar"}
named_context = salt.loader_context.NamedLoaderContext(
"__test__", loader_context, default_data
)
coppied = copy.deepcopy(named_context)
assert coppied.name == named_context.name
assert id(coppied.loader_context) == id(named_context.loader_context)
assert id(coppied.default) != id(named_context.default)

View file

@ -0,0 +1,16 @@
"""
Unit tests for the salt.utils.nacl module
"""
import salt.utils.nacl
from tests.support.mock import patch
def test_fips_mode():
"""
Nacl pillar doesn't load when fips_mode is True
"""
opts = {"fips_mode": True}
with patch("salt.utils.nacl.__opts__", opts, create=True):
ret = salt.utils.nacl.__virtual__()
assert ret == (False, "nacl utils not available in FIPS mode")

View file

@ -381,3 +381,50 @@ class RestartcheckTestCase(TestCase, LoaderModuleMockMixin):
"Found 1 processes using old versions of upgraded files", ret
)
self.assertFalse(os.path.exists(create_file))
def test_valid_command_b(self):
"""
test for CVE-2020-28243
"""
create_file = os.path.join(RUNTIME_VARS.TMP, "created_file")
patch_kernel = patch(
"salt.modules.restartcheck._kernel_versions_redhat",
return_value=["3.10.0-1127.el7.x86_64"],
)
services = {
"NetworkManager": {"ExecMainPID": 123},
"auditd": {"ExecMainPID": 456},
"crond": {"ExecMainPID": 789},
}
patch_salt = patch.dict(
restartcheck.__salt__,
{
"cmd.run": MagicMock(
return_value="Linux localhost.localdomain 3.10.0-1127.el7.x86_64"
),
"service.get_running": MagicMock(return_value=list(services.keys())),
"service.show": MagicMock(side_effect=list(services.values())),
"pkg.owner": MagicMock(return_value=""),
"service.available": MagicMock(return_value=True),
},
)
patch_deleted = patch(
"salt.modules.restartcheck._deleted_files",
MagicMock(return_value=[("--admindir tmp dpkg", 123, "/root/ (deleted)")]),
)
patch_readlink = patch("os.readlink", return_value="--admindir tmp dpkg")
popen_mock = MagicMock()
popen_mock.return_value.stdout.readline.side_effect = ["/usr/bin\n", ""]
patch_popen = patch("subprocess.Popen", popen_mock)
patch_grains = patch.dict(restartcheck.__grains__, {"os_family": "RedHat"})
with patch_kernel, patch_salt, patch_deleted, patch_readlink, patch_grains, patch_popen:
ret = restartcheck.restartcheck()
self.assertIn("Found 1 processes using old versions of upgraded files", ret)
args, kwargs = popen_mock.call_args
assert args[0] == ["repoquery", "-l", "--admindir tmp dpkg"]

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
#
# Author: Bo Maryniuk <bo@suse.de>
#
@ -15,8 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# Import Salt Testing Libs
from __future__ import absolute_import, print_function, unicode_literals
import datetime
import os
@ -25,16 +22,11 @@ import tempfile
import salt.utils.files
import salt.utils.stringutils
from salt.modules import x509
from tests.support.helpers import dedent
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.mock import MagicMock, patch
from tests.support.unit import TestCase, skipIf
try:
import pytest
except ImportError as import_error:
pytest = None
try:
import M2Crypto # pylint: disable=unused-import
@ -99,10 +91,9 @@ c9bcgp7D7xD+TxWWNj4CSXEccJgGr91StV+gFg4ARQ==
}
@skipIf(not bool(pytest), False)
class X509TestCase(TestCase, LoaderModuleMockMixin):
def setup_loader_modules(self):
return {x509: {}}
return {x509: {"__opts__": {"fips_mode": False}}}
@patch("salt.modules.x509.log", MagicMock())
def test_private_func__parse_subject(self):
@ -111,7 +102,7 @@ class X509TestCase(TestCase, LoaderModuleMockMixin):
:return:
"""
class FakeSubject(object):
class FakeSubject:
"""
Class for faking x509'th subject.
"""
@ -436,3 +427,64 @@ class X509TestCase(TestCase, LoaderModuleMockMixin):
# Ensure that the correct server cert serial is amongst
# the revoked certificates
self.assertIn(serial_number, crl)
@skipIf(not HAS_M2CRYPTO, "Skipping, M2Crypto is unavailable")
def test_read_certificate(self):
"""
:return:
"""
cet = dedent(
"""
-----BEGIN CERTIFICATE-----
MIICdDCCAd2gAwIBAgIUH6g+PC0bGKSY4LMq7PISP09M5B4wDQYJKoZIhvcNAQEL
BQAwTDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB0FyaXpvbmExEzARBgNVBAcMClNj
b3R0c2RhbGUxFjAUBgNVBAoMDVN1cGVyIFdpZGdpdHMwHhcNMjEwMzIzMDExNDE2
WhcNMjIwMzIzMDExNDE2WjBMMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHQXJpem9u
YTETMBEGA1UEBwwKU2NvdHRzZGFsZTEWMBQGA1UECgwNU3VwZXIgV2lkZ2l0czCB
nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvtFFZP47UkzyAmVWtBnVHuXwe7iK
yu19c3qx59KPVAMHkMKgCew4S2KBMDHySBVnspiEz1peP1ywozcP1tIeWHG6aY/7
j2ewzl5bJ4HZPDBnEOYzGsC/NM8YY3qFlrteda/awvwoF99MkpVlrcLBMJzjt/c8
HjuBb0zTlnm4r7ECAwEAAaNTMFEwHQYDVR0OBBYEFJwdb0PKsvu3dU0j3kx3uP4B
NGpfMB8GA1UdIwQYMBaAFJwdb0PKsvu3dU0j3kx3uP4BNGpfMA8GA1UdEwEB/wQF
MAMBAf8wDQYJKoZIhvcNAQELBQADgYEAZblVv70rSk6+7ti3mYxVo48VLf3hG5R/
rMd434WYTeDOWlvl5GSklrBc4ToBW5GsJe/+JaFbUFo9YB+a0K0xjyNZ5CWWiaxg
3lwqTx6vwK1ucS18B+nt2qqyq9hL0UvpSB7gH4KeCwCMDIfRMsrPi32jg1RyKftD
B+O0S5LeuJw=
-----END CERTIFICATE-----
"""
)
ret = x509.read_certificate(cet)
assert "MD5 Finger Print" in ret
class X509FipsTestCase(TestCase, LoaderModuleMockMixin):
def setup_loader_modules(self):
return {x509: {"__opts__": {"fips_mode": True}}}
@skipIf(not HAS_M2CRYPTO, "Skipping, M2Crypto is unavailable")
def test_read_certificate(self):
"""
:return:
"""
cet = dedent(
"""
-----BEGIN CERTIFICATE-----
MIICdDCCAd2gAwIBAgIUH6g+PC0bGKSY4LMq7PISP09M5B4wDQYJKoZIhvcNAQEL
BQAwTDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB0FyaXpvbmExEzARBgNVBAcMClNj
b3R0c2RhbGUxFjAUBgNVBAoMDVN1cGVyIFdpZGdpdHMwHhcNMjEwMzIzMDExNDE2
WhcNMjIwMzIzMDExNDE2WjBMMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHQXJpem9u
YTETMBEGA1UEBwwKU2NvdHRzZGFsZTEWMBQGA1UECgwNU3VwZXIgV2lkZ2l0czCB
nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvtFFZP47UkzyAmVWtBnVHuXwe7iK
yu19c3qx59KPVAMHkMKgCew4S2KBMDHySBVnspiEz1peP1ywozcP1tIeWHG6aY/7
j2ewzl5bJ4HZPDBnEOYzGsC/NM8YY3qFlrteda/awvwoF99MkpVlrcLBMJzjt/c8
HjuBb0zTlnm4r7ECAwEAAaNTMFEwHQYDVR0OBBYEFJwdb0PKsvu3dU0j3kx3uP4B
NGpfMB8GA1UdIwQYMBaAFJwdb0PKsvu3dU0j3kx3uP4BNGpfMA8GA1UdEwEB/wQF
MAMBAf8wDQYJKoZIhvcNAQELBQADgYEAZblVv70rSk6+7ti3mYxVo48VLf3hG5R/
rMd434WYTeDOWlvl5GSklrBc4ToBW5GsJe/+JaFbUFo9YB+a0K0xjyNZ5CWWiaxg
3lwqTx6vwK1ucS18B+nt2qqyq9hL0UvpSB7gH4KeCwCMDIfRMsrPi32jg1RyKftD
B+O0S5LeuJw=
-----END CERTIFICATE-----
"""
)
ret = x509.read_certificate(cet)
assert "MD5 Finger Print" not in ret

View file

@ -0,0 +1,122 @@
import tempfile
import salt.utils.files
from salt.modules import x509 as x509_mod
from salt.states import x509
from tests.support.helpers import dedent
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.mock import MagicMock
from tests.support.unit import TestCase, skipIf
try:
import M2Crypto # pylint: disable=unused-import
HAS_M2CRYPTO = True
except ImportError:
HAS_M2CRYPTO = False
class X509TestCase(TestCase, LoaderModuleMockMixin):
def setup_loader_modules(self):
return {x509: {"__opts__": {"fips_mode": False}}}
def test_certificate_info_matches(self):
cert_info = {"MD5 Finger Print": ""}
required_info = {"MD5 Finger Print": ""}
ret = x509._certificate_info_matches(cert_info, required_info)
assert ret == (True, [])
class X509FipsTestCase(TestCase, LoaderModuleMockMixin):
def setup_loader_modules(self):
self.file_managed_mock = MagicMock()
self.file_managed_mock.return_value = {"changes": True}
return {
x509: {
"__opts__": {"fips_mode": True},
"__salt__": {
"x509.get_pem_entry": x509_mod.get_pem_entry,
"x509.get_private_key_size": x509_mod.get_private_key_size,
},
"__states__": {"file.managed": self.file_managed_mock},
}
}
@skipIf(not HAS_M2CRYPTO, "Skipping, M2Crypto is unavailable")
def test_private_key_fips_mode(self):
"""
:return:
"""
test_key = dedent(
"""
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDx7UUt0cPi5G51
FmRBhAZtZb5x6P0PFn7GwnLmSvLNhCsOcD/vq/yBUU62pknzmOjM5pgWTACZj66O
GOFmWBg06v8+sqUbaF9PZ/CxQD5MogmQhYNgfyuopHWWgLXMub2hlP+15qGohkzg
Tr/mXp2ohVAb6ihjqb7XV9MiZaLNVX+XWauM8SlhqXMiJyDUopEGbg2pLsHhIMcX
1twLlyDja+uDbCMZ4jDNB+wsWxTaPRH8KizfEabB1Cl+fdyD10pSAYcodOAnlkW+
G/DX2hwb/ZAM9B1SXTfZ3gzaIIbqXBEHcZQNXxHL7szBTVcOmfx/RPfOeRncytb9
Mit7RIBxAgMBAAECggEAD4Pi+uRIBsYVm2a7OURpURzEUPPbPtt3d/HCgqht1+ZR
CJUEVK+X+wcm4Cnb9kZpL7LeMBfhtfdz/2LzGagurT4g7nlwg0h3TFVjJ0ryc+G0
cVNOsKKXPzKE5AkPH7kNw04V9Cl9Vpx+U6hZQEHzJHqgP5oNyw540cCtJriT700b
fG1q3PYKWSkDwTiUnJTnVLybFIKQC6urxTeT2UWeiBadfDY7DjI4USfrQsqCfGMO
uWPpOOJk5RIvw5r0Of2xvxV76xCgzVTkgtWjBRMTEkfeYx3019xKlQtAKoGbZd1T
tF8DH0cDlnri4nG7YT8yYvx/LWVDg12E6IZij1X60QKBgQD7062JuQGEmTd99a7o
5TcgWYqDrmE9AEgJZjN+gnEPcsxc50HJaTQgrkV0oKrS8CMbStIymbzMKWifOj7o
gvQBVecydq1AaXePt3gRe8vBFiP4cHjFcSegs9FDvdfJR36iHOBIgEp4DWvV1vgs
+z82LT6Qy5kxUQvnlQ4dEaGdrQKBgQD175f0H4enRJ3BoWTrqt2mTAwtJcPsKmGD
9YfFB3H4+O2rEKP4FpBO5PFXZ0dqm54hDtxqyC/lSXorFCUjVUBero1ECGt6Gnn2
TSnhgk0VMxvhnc0GReIt4K9WrXGd0CMUDwIhFHj8kbb1X1yqt2hwyw7b10xFVStl
sGv8CQB+VQKBgAF9q1VZZwzl61Ivli2CzeS/IvbMnX7C9ao4lK13EDxLLbKPG/CZ
UtmurnKWUOyWx15t/viVuGxtAlWO/rhZriAj5g6CbVwoQ7DyIR/ZX8dw3h2mbNCe
buGgruh7wz9J0RIcoadMOySiz7SgZS++/QzRD8HDstB77loco8zAQfixAoGBALDO
FbTocfKbjrpkmBQg24YxR9OxQb/n3AEtI/VO2+38r4h6xxaUyhwd1S9bzWjkBXOI
poeR8XTqNQ0BR422PTeUT3SohPPcUu/yG3jG3zmta47wjjPDS85lqEgtGvA0cPN7
srErcatJ6nlOnGUSw9/K65y6lFeH2lIZ2hfwNM2dAoGBAMVCc7i3AIhLp6UrGzjP
0ioCHCakpxfl8s1VQp55lhHlP6Y4RfqT72Zq7ScteTrisIAQyI9ot0gsuct2miQM
nyDdyKGki/MPduGTzzWlBA7GZEHnxbAILH8kWJ7eE/Nh7zdF1CRts8utEO9L9S+0
lVz1j/xGOseQk4cVos681Wpw
-----END PRIVATE KEY-----"""
)
test_cert = dedent(
"""
-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIUAfATs1aodKw11Varh55msmU0LoowDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTAzMjMwMTM4MzdaFw0yMjAz
MjMwMTM4MzdaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQDx7UUt0cPi5G51FmRBhAZtZb5x6P0PFn7GwnLmSvLN
hCsOcD/vq/yBUU62pknzmOjM5pgWTACZj66OGOFmWBg06v8+sqUbaF9PZ/CxQD5M
ogmQhYNgfyuopHWWgLXMub2hlP+15qGohkzgTr/mXp2ohVAb6ihjqb7XV9MiZaLN
VX+XWauM8SlhqXMiJyDUopEGbg2pLsHhIMcX1twLlyDja+uDbCMZ4jDNB+wsWxTa
PRH8KizfEabB1Cl+fdyD10pSAYcodOAnlkW+G/DX2hwb/ZAM9B1SXTfZ3gzaIIbq
XBEHcZQNXxHL7szBTVcOmfx/RPfOeRncytb9Mit7RIBxAgMBAAGjUzBRMB0GA1Ud
DgQWBBT0qx4KLhozvuWAI9peT/utYV9FITAfBgNVHSMEGDAWgBT0qx4KLhozvuWA
I9peT/utYV9FITAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQDx
tWvUyGfEwJJg1ViBa10nVhg5sEc6KfqcPzc2GvatIGJlAbc3b1AYu6677X04SQNA
dYRA2jcZcKudy6eolPJow6SDpkt66IqciZYdbQE5h9elnwpZxmXlJTQTB9cEwyIk
2em5DKpdIwa9rRDlbAjAVJb3015MtpKRu2gsQ7gl5X2U3K+DFsWtBPf+0xiJqUiq
rd7tiHF/zylubSyH/LVONJZ6+/oT/qzJfxfpvygtQWcu4b2zzME/FPenMA8W6Rau
ZYycQfpMVc7KwqF5/wfjnkmfxoFKnkD7WQ3qFCJ/xULk/Yn1hrvNeIr+khX3qKQi
Y3BMA5m+J+PZrNy7EQSa
-----END CERTIFICATE-----
"""
)
fp, name = tempfile.mkstemp()
with salt.utils.files.fopen(name, "w") as fd:
fd.write(test_key)
fd.write(test_cert)
ret = x509.private_key_managed(name)
self.file_managed_mock.assert_called_once()
assert (
self.file_managed_mock.call_args.kwargs["contents"].strip()
== test_key.strip()
)
def test_certificate_info_matches(self):
cert_info = {"MD5 Finger Print": ""}
required_info = {"MD5 Finger Print": ""}
ret = x509._certificate_info_matches(cert_info, required_info)
assert ret == (False, ["MD5 Finger Print"])

View file

@ -200,6 +200,7 @@ class BadTestModuleNamesTestCase(TestCase):
"unit.utils.scheduler.test_run_job",
"unit.utils.scheduler.test_schedule",
"unit.utils.scheduler.test_skip",
"unit.auth.test_auth",
)
errors = []

View file

@ -1,11 +1,7 @@
# coding: utf-8
"""
Test the RSA ANSI X9.31 signer and verifier
"""
# python libs
from __future__ import absolute_import, print_function, unicode_literals
import ctypes
import ctypes.util
import fnmatch
@ -174,49 +170,89 @@ class RSAX931Test(TestCase):
fnmatch.fnmatch(lib_path, "/opt/freeware/lib/libcrypto.so*")
)
@skipIf(not salt.utils.platform.is_darwin(), "Host OS is not Darwin-like or macOS.")
@patch.object(salt.utils.platform, "is_darwin", lambda: True)
@patch.object(platform, "mac_ver", lambda: ("10.14.2", (), ""))
@patch.object(glob, "glob", lambda _: [])
def test_find_libcrypto_with_system_and_not_catalina(self):
@patch.object(sys, "platform", "macosx")
def test_find_libcrypto_with_system_before_catalina(self):
"""
Test _find_libcrypto on a Catalina-like macOS host, simulate
not finding any other libcryptos and just defaulting to system.
Test _find_libcrypto on a pre-Catalina macOS host by simulating not
finding any other libcryptos and verifying that it defaults to system.
"""
lib_path = _find_libcrypto()
passed = False
for i in (
"/opt/salt/lib/libcrypto.dylib",
"/usr/local/opt/openssl/lib/libcrypto.dylib",
"/usr/local/opt/openssl@*/lib/libcrypto.dylib",
"/opt/local/lib/libcrypto.dylib",
"/usr/lib/libcrypto.*.dylib",
):
if fnmatch.fnmatch(lib_path, i):
passed = True
break
self.assertFalse(passed)
self.assertEqual(lib_path, "/usr/lib/libcrypto.dylib")
@skipIf(not salt.utils.platform.is_darwin(), "Host OS is not Darwin-like or macOS.")
@patch.object(salt.utils.platform, "is_darwin", lambda: True)
@patch.object(platform, "mac_ver", lambda: ("10.15.2", (), ""))
@patch.object(sys, "platform", "macosx")
def test_find_libcrypto_darwin_catalina(self):
"""
Test _find_libcrypto on a Darwin-like macOS host where there isn't a
lacation returned by ctypes.util.find_library()
Test _find_libcrypto on a macOS Catalina host where there are no custom
libcryptos and defaulting to the versioned system libraries.
"""
lib_path = _find_libcrypto()
passed = False
for i in (
"/opt/salt/lib/libcrypto.dylib",
"/usr/local/opt/openssl/lib/libcrypto.dylib",
"/usr/local/opt/openssl@*/lib/libcrypto.dylib",
"/opt/local/lib/libcrypto.dylib",
"/usr/lib/libcrypto.*.dylib",
):
if fnmatch.fnmatch(lib_path, i):
passed = True
break
self.assertTrue(passed)
available = [
"/usr/lib/libcrypto.0.9.7.dylib",
"/usr/lib/libcrypto.0.9.8.dylib",
"/usr/lib/libcrypto.35.dylib",
"/usr/lib/libcrypto.41.dylib",
"/usr/lib/libcrypto.42.dylib",
"/usr/lib/libcrypto.44.dylib",
"/usr/lib/libcrypto.dylib",
]
def test_glob(pattern):
return [lib for lib in available if fnmatch.fnmatch(lib, pattern)]
with patch.object(glob, "glob", test_glob):
lib_path = _find_libcrypto()
self.assertEqual("/usr/lib/libcrypto.44.dylib", lib_path)
@patch.object(salt.utils.platform, "is_darwin", lambda: True)
@patch.object(platform, "mac_ver", lambda: ("11.2.2", (), ""))
@patch.object(sys, "platform", "macosx")
def test_find_libcrypto_darwin_bigsur_packaged(self):
"""
Test _find_libcrypto on a Darwin-like macOS host where there isn't a
lacation returned by ctypes.util.find_library() and the libcrypto
installation comes from a package manager (ports, brew, salt).
"""
managed_paths = {
"salt": "/opt/salt/lib/libcrypto.dylib",
"brew": "/test/homebrew/prefix/opt/openssl/lib/libcrypto.dylib",
"port": "/opt/local/lib/libcrypto.dylib",
}
saved_getenv = os.getenv
def mock_getenv(env):
def test_getenv(var, default=None):
return env.get(var, saved_getenv(var, default))
return test_getenv
def mock_glob(expected_lib):
def test_glob(pattern):
if fnmatch.fnmatch(expected_lib, pattern):
return [expected_lib]
return []
return test_glob
for package_manager, expected_lib in managed_paths.items():
if package_manager == "brew":
env = {"HOMEBREW_PREFIX": "/test/homebrew/prefix"}
else:
env = {"HOMEBREW_PREFIX": ""}
with patch.object(os, "getenv", mock_getenv(env)):
with patch.object(glob, "glob", mock_glob(expected_lib)):
lib_path = _find_libcrypto()
self.assertEqual(expected_lib, lib_path)
# On Big Sur, there's nothing else to fall back on.
with patch.object(glob, "glob", lambda _: []):
with self.assertRaises(OSError):
lib_path = _find_libcrypto()
@patch.object(ctypes.util, "find_library", lambda a: None)
@patch.object(glob, "glob", lambda a: [])