From 714d59479c528f62514ea97cbf2f278be4021d46 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Mon, 14 Dec 2020 10:53:04 -0500 Subject: [PATCH 01/69] Default zenoss module to verify SSL --- salt/modules/zenoss.py | 17 +++++++++++------ salt/utils/http.py | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/salt/modules/zenoss.py b/salt/modules/zenoss.py index 9c6b7de7b5f..9d3b8b074a0 100644 --- a/salt/modules/zenoss.py +++ b/salt/modules/zenoss.py @@ -16,6 +16,8 @@ Module for working with the Zenoss API hostname: https://zenoss.example.com username: admin password: admin123 + verify_ssl: True + ca_bundle: /etc/ssl/certs/ca-certificates.crt """ @@ -25,9 +27,10 @@ import logging import re import salt.utils.json +import salt.utils.http try: - import requests + import requests # pylint: disable=unused-import HAS_LIBS = True except ImportError: @@ -79,11 +82,13 @@ def _session(): """ config = __salt__["config.option"]("zenoss") - session = requests.session() - session.auth = (config.get("username"), config.get("password")) - session.verify = False - session.headers.update({"Content-type": "application/json; charset=utf-8"}) - return session + return salt.utils.http.session( + user=config.get("username"), + password=config.get("password"), + verify_ssl=config.get("verify_ssl", True), + ca_bundle=config.get("ca_bundle"), + headers={"Content-type": "application/json; charset=utf-8"}, + ) def _router_request(router, method, data=None): diff --git a/salt/utils/http.py b/salt/utils/http.py index 5ab4503f619..3ea17f65b19 100644 --- a/salt/utils/http.py +++ b/salt/utils/http.py @@ -1057,3 +1057,22 @@ def _sanitize_url_components(comp_list, field): ret = "{}&".format(comp_list[0]) comp_list.remove(comp_list[0]) return ret + _sanitize_url_components(comp_list, field) + + +def session(user=None, password=None, verify_ssl=True, ca_bundle=None, headers=None): + """ + create a requests session + """ + session = requests.session() + if user and password: + session.auth = (user, password) + if ca_bundle and not verify_ssl: + log.error("You cannot use both ca_bundle and verify_ssl False together") + return False + if ca_bundle: + session.verify = get_ca_bundle({"ca_bundle": ca_bundle}) + if not verify_ssl: + session.verify = False + if headers: + session.headers.update = headers + return session From bee8307aa83ec938d3c4d757c5d20e3ce4eed83d Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Mon, 14 Dec 2020 10:54:29 -0500 Subject: [PATCH 02/69] run pre-commit salt/modules/zenoss.py --- salt/modules/zenoss.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/salt/modules/zenoss.py b/salt/modules/zenoss.py index 9d3b8b074a0..5cb64bed180 100644 --- a/salt/modules/zenoss.py +++ b/salt/modules/zenoss.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Module for working with the Zenoss API @@ -21,13 +20,11 @@ Module for working with the Zenoss API """ -from __future__ import absolute_import, print_function, unicode_literals - import logging import re -import salt.utils.json import salt.utils.http +import salt.utils.json try: import requests # pylint: disable=unused-import @@ -56,7 +53,7 @@ def __virtual__(): else: return ( False, - "The '{0}' module could not be loaded: " + "The '{}' module could not be loaded: " "'requests' is not installed.".format(__virtualname__), ) @@ -104,7 +101,7 @@ def _router_request(router, method, data=None): config = __salt__["config.option"]("zenoss") log.debug("Making request to router %s with method %s", router, method) - url = "{0}/zport/dmd/{1}_router".format(config.get("hostname"), ROUTERS[router]) + url = "{}/zport/dmd/{}_router".format(config.get("hostname"), ROUTERS[router]) response = _session().post(url, data=req_data) # The API returns a 200 response code even whe auth is bad. @@ -217,7 +214,7 @@ def set_prod_state(prod_state, device=None): device_object = find_device(device) if not device_object: - return "Unable to find a device in Zenoss for {0}".format(device) + return "Unable to find a device in Zenoss for {}".format(device) log.info("Setting prodState to %d on %s device", prod_state, device) data = dict( From 8f7c002b029e152abaf1d2f11ca795ec91a67433 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Mon, 14 Dec 2020 10:58:47 -0500 Subject: [PATCH 03/69] Validate the zenoss module defaults to verifying SSL --- tests/unit/modules/test_zenoss.py | 54 +++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tests/unit/modules/test_zenoss.py diff --git a/tests/unit/modules/test_zenoss.py b/tests/unit/modules/test_zenoss.py new file mode 100644 index 00000000000..f8900cf6033 --- /dev/null +++ b/tests/unit/modules/test_zenoss.py @@ -0,0 +1,54 @@ +import salt.modules.config as config +import salt.modules.zenoss as zenoss +from tests.support.mixins import LoaderModuleMockMixin +from tests.support.mock import MagicMock, call, patch +from tests.support.unit import TestCase + + +class ZenossTestCase(TestCase, LoaderModuleMockMixin): + """ + Test cases for salt.modules.keystone + """ + + def setup_loader_modules(self): + return { + zenoss: {"__salt__": {"config.option": config.option}}, + config: {"__opts__": {}}, + } + + def test_zenoss_session(self): + """ + test zenoss._session when using verify_ssl + """ + zenoss_conf = { + "zenoss": { + "hostname": "https://test.zenoss.com", + "username": "admin", + "password": "test123", + } + } + + for verify in [True, False, None]: + zenoss_conf["zenoss"]["verify_ssl"] = verify + if verify is None: + zenoss_conf["zenoss"].pop("verify_ssl") + verify = True + + patch_opts = patch.dict(config.__opts__, zenoss_conf) + mock_http = MagicMock(return_value=None) + patch_http = patch("salt.utils.http.session", mock_http) + + with patch_http, patch_opts: + zenoss._session() + self.assertEqual( + mock_http.call_args_list, + [ + call( + ca_bundle=None, + headers={"Content-type": "application/json; charset=utf-8"}, + password="test123", + user="admin", + verify_ssl=verify, + ) + ], + ) From e745b2884f84b7f17e2e18a669f54d33b1a7eee5 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Mon, 21 Dec 2020 14:37:37 -0500 Subject: [PATCH 04/69] fix salt.utils.http.session --- salt/utils/http.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/salt/utils/http.py b/salt/utils/http.py index 3ea17f65b19..2d609a59396 100644 --- a/salt/utils/http.py +++ b/salt/utils/http.py @@ -1070,9 +1070,10 @@ def session(user=None, password=None, verify_ssl=True, ca_bundle=None, headers=N log.error("You cannot use both ca_bundle and verify_ssl False together") return False if ca_bundle: - session.verify = get_ca_bundle({"ca_bundle": ca_bundle}) + opts = {"ca_bundle": ca_bundle} + session.verify = get_ca_bundle(opts) if not verify_ssl: session.verify = False if headers: - session.headers.update = headers + session.headers.update(headers) return session From 3a92ebdd373e354552cbcce7e70b1626ae7df529 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Sat, 12 Dec 2020 07:42:31 +0000 Subject: [PATCH 05/69] Default the splunk returner to verify SSL --- salt/returners/splunk.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/salt/returners/splunk.py b/salt/returners/splunk.py index 509eab3cf77..9bed588796c 100644 --- a/salt/returners/splunk.py +++ b/salt/returners/splunk.py @@ -11,6 +11,7 @@ Requires the following config values to be specified in config or pillar: indexer: sourcetype: index: + verify_ssl: true Run a test by using ``salt-call test.ping --return splunk`` @@ -33,7 +34,6 @@ import salt.utils.json from salt.ext import six _max_content_bytes = 100000 -http_event_collector_SSL_verify = False http_event_collector_debug = False log = logging.getLogger(__name__) @@ -62,6 +62,9 @@ def _get_options(): indexer = __salt__["config.get"]("splunk_http_forwarder:indexer") sourcetype = __salt__["config.get"]("splunk_http_forwarder:sourcetype") index = __salt__["config.get"]("splunk_http_forwarder:index") + verify_ssl = __salt__["config.get"]( + "splunk_http_forwarder:verify_ssl", default=True + ) except Exception: # pylint: disable=broad-except log.error("Splunk HTTP Forwarder parameters not present in config.") return None @@ -70,6 +73,7 @@ def _get_options(): "indexer": indexer, "sourcetype": sourcetype, "index": index, + "verify_ssl": verify_ssl, } return splunk_opts @@ -89,9 +93,12 @@ def _send_splunk(event, index_override=None, sourcetype_override=None): ) http_event_collector_key = opts["token"] http_event_collector_host = opts["indexer"] + http_event_collector_verify_ssl = opts["verify_ssl"] # Set up the collector splunk_event = http_event_collector( - http_event_collector_key, http_event_collector_host + http_event_collector_key, + http_event_collector_host, + verify_ssl=http_event_collector_verify_ssl, ) # init the payload payload = {} @@ -129,11 +136,13 @@ class http_event_collector(object): http_event_port="8088", http_event_server_ssl=True, max_bytes=_max_content_bytes, + verify_ssl=True, ): self.token = token self.batchEvents = [] self.maxByteLength = max_bytes self.currentByteLength = 0 + self.verify_ssl = verify_ssl # Set host to specified value or default to localhostname if no value provided if host: @@ -179,7 +188,7 @@ class http_event_collector(object): self.server_uri, data=salt.utils.json.dumps(data), headers=headers, - verify=http_event_collector_SSL_verify, + verify=self.verify_ssl, ) # Print debug info if flag set @@ -224,7 +233,7 @@ class http_event_collector(object): self.server_uri, data=" ".join(self.batchEvents), headers=headers, - verify=http_event_collector_SSL_verify, + verify=self.verify_ssl, ) self.batchEvents = [] self.currentByteLength = 0 From 641048b4222e84663acbd413076ae8e6e90d4681 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Sat, 12 Dec 2020 07:18:40 +0000 Subject: [PATCH 06/69] Add tests for the splunk returner to verify SSL behavior --- tests/unit/returners/test_splunk.py | 95 +++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 tests/unit/returners/test_splunk.py diff --git a/tests/unit/returners/test_splunk.py b/tests/unit/returners/test_splunk.py new file mode 100644 index 00000000000..d48b26294b6 --- /dev/null +++ b/tests/unit/returners/test_splunk.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +""" +tests.unit.returners.test_splunk +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Unit tests for the splunk returner +""" +from __future__ import absolute_import, print_function, unicode_literals + +import json +import logging + +import salt.modules.config as config +import salt.returners.splunk as splunk +from tests.support.mixins import LoaderModuleMockMixin +from tests.support.mock import MagicMock, patch +from tests.support.unit import TestCase + +log = logging.getLogger(__name__) + + +class SplunkReturnerTest(TestCase, LoaderModuleMockMixin): + + def setup_loader_modules(self): + opts = { + "splunk_http_forwarder": { + "token": "TheToken", + "indexer": "the.splunk.domain", + "index": "TheIndex", + "sourcetype": "TheSourceType", + } + } + return { + splunk: {"__opts__": opts, "__salt__": {"config.get": config.get}}, + config: {"__opts__": opts}, + } + + def test_verify_ssl_defaults_to_true(self): + payload = {"some": "payload"} + requests_post = MagicMock() + ts = 1234565789 + host = "TheHostName" + data = { + "time": str(ts), + "index": "TheIndex", + "sourcetype": "TheSourceType", + "event": payload, + "host": host, + } + with patch( + "salt.returners.splunk.time.time", MagicMock(return_value=ts) + ), patch( + "salt.returners.splunk.socket.gethostname", MagicMock(return_value=host) + ), patch( + "requests.post", requests_post + ): + splunk.returner(payload.copy()) + requests_post.assert_called_with( + "https://the.splunk.domain:8088/services/collector/event", + data=json.dumps(data), + headers={"Authorization": "Splunk TheToken"}, + verify=True, + ) + + def test_verify_ssl(self): + payload = {"some": "payload"} + verify_ssl_values = [True, False, None] + payload = {"some": "payload"} + requests_post = MagicMock() + ts = 1234565789 + host = "TheHostName" + data = { + "time": str(ts), + "index": "TheIndex", + "sourcetype": "TheSourceType", + "event": payload, + "host": host, + } + for verify_ssl in verify_ssl_values: + with patch( + "salt.returners.splunk.time.time", MagicMock(return_value=ts) + ), patch( + "salt.returners.splunk.socket.gethostname", MagicMock(return_value=host) + ), patch( + "requests.post", requests_post + ), patch.dict( + splunk.__opts__["splunk_http_forwarder"], verify_ssl=verify_ssl + ): + splunk.returner(payload.copy()) + requests_post.assert_called_with( + "https://the.splunk.domain:8088/services/collector/event", + data=json.dumps(data), + headers={"Authorization": "Splunk TheToken"}, + verify=verify_ssl, + ) From 071feaf1dc3c11d588f84cc555e06361abb78c03 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Mon, 14 Dec 2020 01:39:57 +0000 Subject: [PATCH 07/69] Default the bigip requests session to verify SSL --- salt/modules/bigip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/modules/bigip.py b/salt/modules/bigip.py index 2b54e4d27c5..f7430db3015 100644 --- a/salt/modules/bigip.py +++ b/salt/modules/bigip.py @@ -52,7 +52,7 @@ def _build_session(username, password, trans_label=None): bigip = requests.session() bigip.auth = (username, password) - bigip.verify = False + bigip.verify = True bigip.headers.update({"Content-Type": "application/json"}) if trans_label: From 5314e142827016eed55c2a1c94faae853d2331e5 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Mon, 14 Dec 2020 01:35:05 +0000 Subject: [PATCH 08/69] Add tests to validate that bigip module requests session verifies SSL --- tests/unit/modules/test_bigip.py | 37 ++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/unit/modules/test_bigip.py diff --git a/tests/unit/modules/test_bigip.py b/tests/unit/modules/test_bigip.py new file mode 100644 index 00000000000..8944a7bd210 --- /dev/null +++ b/tests/unit/modules/test_bigip.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +""" +tests.unit.modules.test_bigip +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Unit tests for the bigip module +""" +from __future__ import absolute_import, print_function, unicode_literals +import logging + +import salt.modules.bigip as bigip +from tests.support.mixins import LoaderModuleMockMixin +from tests.support.mock import MagicMock, patch +from tests.support.unit import TestCase + +log = logging.getLogger(__name__) + + +class RequestsSession: + def __init__(self): + self.auth = None + self.verify = None + self.headers = {} + + +class BigipModuleTest(TestCase, LoaderModuleMockMixin): + + def setup_loader_modules(self): + return {bigip: {}} + + def test__build_session_verify_ssl(self): + requests_session = RequestsSession() + with patch("salt.modules.bigip.requests.sessions.Session", MagicMock(return_value=requests_session)): + bigip._build_session("username", "password") + + self.assertEqual(requests_session.auth, ("username", "password")) + assert requests_session.verify is True From f78776c755d58577d07309e59e885438655a9f7e Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Mon, 14 Dec 2020 10:18:10 -0500 Subject: [PATCH 09/69] Default panos proxy to verify SSL --- salt/proxy/panos.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/salt/proxy/panos.py b/salt/proxy/panos.py index 5c298b4f7d7..bdcac926cf8 100644 --- a/salt/proxy/panos.py +++ b/salt/proxy/panos.py @@ -53,6 +53,7 @@ the device with username and password. host: username: password: + verify_ssl: True proxytype ^^^^^^^^^ @@ -274,6 +275,7 @@ def init(opts): # Set configuration details DETAILS["host"] = opts["proxy"]["host"] + DETAILS["verify_ssl"] = opts["proxy"].get("verify_ssl", True) if "serial" in opts["proxy"]: DETAILS["serial"] = opts["proxy"].get("serial") if "apikey" in opts["proxy"]: @@ -321,7 +323,7 @@ def call(payload=None): method="POST", decode_type="plain", decode=True, - verify_ssl=False, + verify_ssl=DETAILS["verify_ssl"], status=True, raise_error=True, ) @@ -335,7 +337,7 @@ def call(payload=None): method="POST", decode_type="plain", decode=True, - verify_ssl=False, + verify_ssl=DETAILS["verify_ssl"], status=True, raise_error=True, ) @@ -352,7 +354,7 @@ def call(payload=None): method="POST", decode_type="plain", decode=True, - verify_ssl=False, + verify_ssl=DETAILS["verify_ssl"], status=True, raise_error=True, ) @@ -368,7 +370,7 @@ def call(payload=None): method="POST", decode_type="plain", decode=True, - verify_ssl=False, + verify_ssl=DETAILS["verify_ssl"], status=True, raise_error=True, ) From 9e056c73bff34ddee0e0c33bca23be8872bbf93c Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Mon, 14 Dec 2020 10:19:03 -0500 Subject: [PATCH 10/69] pre-commit salt/proxy/panos.py --- salt/proxy/panos.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/salt/proxy/panos.py b/salt/proxy/panos.py index bdcac926cf8..50a4639911a 100644 --- a/salt/proxy/panos.py +++ b/salt/proxy/panos.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Proxy Minion interface module for managing Palo Alto firewall devices ===================================================================== @@ -204,17 +203,12 @@ apikey The generated XML API key for the Panorama server. Required. """ -from __future__ import absolute_import, print_function, unicode_literals -# Import Python Libs import logging import salt.exceptions import salt.utils.xmlutil as xml - -# Import Salt Libs from salt._compat import ElementTree as ET -from salt.ext import six # This must be present or the Salt loader won't load this module. __proxyenabled__ = ["panos"] @@ -271,7 +265,7 @@ def init(opts): log.critical("No 'passwords' key found in pillar for this proxy.") return False - DETAILS["url"] = "https://{0}/api/".format(opts["proxy"]["host"]) + DETAILS["url"] = "https://{}/api/".format(opts["proxy"]["host"]) # Set configuration details DETAILS["host"] = opts["proxy"]["host"] @@ -384,21 +378,21 @@ def call(payload=None): "Did not receive a valid response from host." ) - if six.text_type(r["status"]) not in ["200", "201", "204"]: - if six.text_type(r["status"]) == "400": + if str(r["status"]) not in ["200", "201", "204"]: + if str(r["status"]) == "400": raise salt.exceptions.CommandExecutionError( "The server cannot process the request due to a client error." ) - elif six.text_type(r["status"]) == "401": + elif str(r["status"]) == "401": raise salt.exceptions.CommandExecutionError( "The server cannot process the request because it lacks valid authentication " "credentials for the target resource." ) - elif six.text_type(r["status"]) == "403": + elif str(r["status"]) == "403": raise salt.exceptions.CommandExecutionError( "The server refused to authorize the request." ) - elif six.text_type(r["status"]) == "404": + elif str(r["status"]) == "404": raise salt.exceptions.CommandExecutionError( "The requested resource could not be found." ) From beeef574740359e5b2f70b61f17f9f8b7e83c920 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Mon, 14 Dec 2020 10:21:05 -0500 Subject: [PATCH 11/69] Validate the panos proxy defaults to verifying SSL --- tests/unit/proxy/test_panos.py | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/unit/proxy/test_panos.py diff --git a/tests/unit/proxy/test_panos.py b/tests/unit/proxy/test_panos.py new file mode 100644 index 00000000000..ecfbe2a9bfa --- /dev/null +++ b/tests/unit/proxy/test_panos.py @@ -0,0 +1,46 @@ +import salt.proxy.panos as panos +from tests.support.mixins import LoaderModuleMockMixin +from tests.support.mock import MagicMock, call, patch +from tests.support.unit import TestCase + + +class PanosProxyTestCase(TestCase, LoaderModuleMockMixin): + def setup_loader_modules(self): + return {panos: {"DETAILS": {}, "__pillar__": {}}} + + def setUp(self): + self.opts = { + "proxy": {"proxytype": "panos", "host": "hosturl.com", "apikey": "api_key"} + } + + def test_init(self): + for verify in [True, False, None]: + self.opts["proxy"]["verify_ssl"] = verify + if verify is None: + self.opts["proxy"].pop("verify_ssl") + verify = True + mock_http = MagicMock( + return_value={"status": 200, "text": "some_test_data"} + ) + patch_http = patch.dict(panos.__utils__, {"http.query": mock_http}) + with patch_http: + panos.init(self.opts) + self.assertEqual( + mock_http.call_args_list, + [ + call( + "https://hosturl.com/api/", + data={ + "type": "op", + "cmd": "", + "key": "api_key", + }, + decode=True, + decode_type="plain", + method="POST", + raise_error=True, + status=True, + verify_ssl=verify, + ) + ], + ) From 8e5ec3ac3c1be5fbeec09189b55b1ee63b0f30ad Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Mon, 14 Dec 2020 13:09:10 -0500 Subject: [PATCH 12/69] Default keystone module to verify SSL --- salt/modules/keystone.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/salt/modules/keystone.py b/salt/modules/keystone.py index 52cb461339a..cc3119efc19 100644 --- a/salt/modules/keystone.py +++ b/salt/modules/keystone.py @@ -13,6 +13,7 @@ Module for handling openstack keystone calls. keystone.tenant: admin keystone.tenant_id: f80919baedab48ec8931f200c65a50df keystone.auth_url: 'http://127.0.0.1:5000/v2.0/' + keystone.verify_ssl: True OR (for token based authentication) @@ -32,6 +33,7 @@ Module for handling openstack keystone calls. keystone.tenant: admin keystone.tenant_id: f80919baedab48ec8931f200c65a50df keystone.auth_url: 'http://127.0.0.1:5000/v2.0/' + keystone.verify_ssl: True openstack2: keystone.user: admin @@ -39,6 +41,7 @@ Module for handling openstack keystone calls. keystone.tenant: admin keystone.tenant_id: f80919baedab48ec8931f200c65a50df keystone.auth_url: 'http://127.0.0.2:5000/v2.0/' + keystone.verify_ssl: True With this configuration in place, any of the keystone functions can make use of a configuration profile by declaring it explicitly. @@ -125,6 +128,7 @@ def _get_kwargs(profile=None, **connection_args): endpoint = get("endpoint", "http://127.0.0.1:35357/v2.0") user_domain_name = get("user_domain_name", "Default") project_domain_name = get("project_domain_name", "Default") + verify_ssl = get("verify_ssl", True) if token: kwargs = {"token": token, "endpoint": endpoint} else: @@ -141,6 +145,7 @@ def _get_kwargs(profile=None, **connection_args): # this ensures it's only passed in when defined if insecure: kwargs["insecure"] = True + kwargs["verify_ssl"] = verify_ssl return kwargs @@ -158,7 +163,8 @@ def api_version(profile=None, **connection_args): auth_url = kwargs.get("auth_url", kwargs.get("endpoint", None)) try: return salt.utils.http.query( - auth_url, decode=True, decode_type="json", verify_ssl=False + auth_url, decode=True, decode_type="json", + verify_ssl=kwargs["verify_ssl"] )["dict"]["version"]["id"] except KeyError: return None From 36a81044b71f6d62e1dda568e83a15a753bd963a Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Mon, 14 Dec 2020 13:25:12 -0500 Subject: [PATCH 13/69] Validate the keystone module defaults to verifying SSL --- tests/unit/modules/test_keystone.py | 47 +++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/tests/unit/modules/test_keystone.py b/tests/unit/modules/test_keystone.py index 018c21bfc68..4e9fa529d15 100644 --- a/tests/unit/modules/test_keystone.py +++ b/tests/unit/modules/test_keystone.py @@ -8,10 +8,11 @@ from __future__ import absolute_import, print_function, unicode_literals # Import Salt Libs import salt.modules.keystone as keystone +import salt.modules.config as config # Import Salt Testing Libs from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch +from tests.support.mock import MagicMock, patch, call from tests.support.unit import TestCase @@ -444,7 +445,10 @@ class KeystoneTestCase(TestCase, LoaderModuleMockMixin): "auth": MockClient, "client": MockClient(), "keystoneclient": MockKeystoneClient(), - } + "__salt__": {"config.get": config.get}, + "__opts__": {}, + }, + config: {"__opts__": {}}, } # 'ec2_credentials_create' function tests: 1 @@ -1053,3 +1057,42 @@ class KeystoneTestCase(TestCase, LoaderModuleMockMixin): } }, ) + + + def test_api_version_verify_ssl(self): + """ + test api_version when using verify_ssl + """ + test_verify = [True, False, None] + conn_args = { + "keystone.user": "admin", + "connection_password": "password", + "connection_tenant": "admin", + "connection_tenant_id": "id", + "connection_auth_url": "https://127.0.0.1/v2.0/", + "connection_verify_ssl": True, + } + + http_ret = {"dict": {"version": {"id": "id_test"}}} + for verify in test_verify: + mock_http = MagicMock(return_value=http_ret) + patch_http = patch("salt.utils.http.query", mock_http) + conn_args["connection_verify_ssl"] = verify + if verify is None: + conn_args.pop("connection_verify_ssl") + verify = True + + with patch_http: + ret = keystone.api_version(**conn_args) + + self.assertEqual( + mock_http.call_args_list, + [ + call( + "https://127.0.0.1/v2.0/", + decode=True, + decode_type="json", + verify_ssl=verify, + ) + ], + ) From bf5205bcf2322c795c9f9b92f0b8494cc39163e7 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Mon, 14 Dec 2020 13:25:32 -0500 Subject: [PATCH 14/69] run pre-commit on tests/unit/modules/test_keystone.py --- tests/unit/modules/test_keystone.py | 35 ++++++++++++----------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/tests/unit/modules/test_keystone.py b/tests/unit/modules/test_keystone.py index 4e9fa529d15..f395ec0271e 100644 --- a/tests/unit/modules/test_keystone.py +++ b/tests/unit/modules/test_keystone.py @@ -1,22 +1,16 @@ -# -*- coding: utf-8 -*- """ :codeauthor: Jayesh Kariya """ -# Import Python Libs -from __future__ import absolute_import, print_function, unicode_literals -# Import Salt Libs -import salt.modules.keystone as keystone import salt.modules.config as config - -# Import Salt Testing Libs +import salt.modules.keystone as keystone from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch, call +from tests.support.mock import MagicMock, call, patch from tests.support.unit import TestCase -class MockEC2(object): +class MockEC2: """ Mock of EC2 class """ @@ -69,7 +63,7 @@ class MockEC2(object): return [cr_ec2] -class MockEndpoints(object): +class MockEndpoints: """ Mock of Endpoints class """ @@ -104,7 +98,7 @@ class MockEndpoints(object): return id -class MockServices(object): +class MockServices: """ Mock of Services class """ @@ -160,7 +154,7 @@ class MockServices(object): return service_id -class MockRoles(object): +class MockRoles: """ Mock of Roles class """ @@ -230,7 +224,7 @@ class MockRoles(object): return [role] -class MockTenants(object): +class MockTenants: """ Mock of Tenants class """ @@ -280,7 +274,7 @@ class MockTenants(object): return tenant_id -class MockServiceCatalog(object): +class MockServiceCatalog: """ Mock of ServiceCatalog class """ @@ -303,7 +297,7 @@ class MockServiceCatalog(object): } -class MockUsers(object): +class MockUsers: """ Mock of Users class """ @@ -376,7 +370,7 @@ class Unauthorized(Exception): """ def __init__(self, message="Test"): - super(Unauthorized, self).__init__(message) + super().__init__(message) self.msg = message @@ -386,11 +380,11 @@ class AuthorizationFailure(Exception): """ def __init__(self, message="Test"): - super(AuthorizationFailure, self).__init__(message) + super().__init__(message) self.msg = message -class MockExceptions(object): +class MockExceptions: """ Mock of exceptions class """ @@ -400,7 +394,7 @@ class MockExceptions(object): self.AuthorizationFailure = AuthorizationFailure -class MockKeystoneClient(object): +class MockKeystoneClient: """ Mock of keystoneclient module """ @@ -409,7 +403,7 @@ class MockKeystoneClient(object): self.exceptions = MockExceptions() -class MockClient(object): +class MockClient: """ Mock of Client class """ @@ -1058,7 +1052,6 @@ class KeystoneTestCase(TestCase, LoaderModuleMockMixin): }, ) - def test_api_version_verify_ssl(self): """ test api_version when using verify_ssl From acbae526c6df66381d9772e502d71dbc9b246ac6 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Mon, 14 Dec 2020 13:38:31 -0500 Subject: [PATCH 15/69] run pre-commit salt/modules/keystone.py --- salt/modules/keystone.py | 144 ++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 76 deletions(-) diff --git a/salt/modules/keystone.py b/salt/modules/keystone.py index cc3119efc19..e8dd2fd99d3 100644 --- a/salt/modules/keystone.py +++ b/salt/modules/keystone.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Module for handling openstack keystone calls. @@ -52,17 +51,11 @@ Module for handling openstack keystone calls. salt '*' keystone.tenant_list profile=openstack1 """ -# Import Python libs -from __future__ import absolute_import, print_function, unicode_literals import logging -# Import Salt Libs import salt.utils.http -# Import 3rd-party libs -from salt.ext import six - HAS_KEYSTONE = False try: # pylint: disable=import-error @@ -163,8 +156,7 @@ def api_version(profile=None, **connection_args): auth_url = kwargs.get("auth_url", kwargs.get("endpoint", None)) try: return salt.utils.http.query( - auth_url, decode=True, decode_type="json", - verify_ssl=kwargs["verify_ssl"] + auth_url, decode=True, decode_type="json", verify_ssl=kwargs["verify_ssl"] )["dict"]["version"]["id"] except KeyError: return None @@ -275,7 +267,7 @@ def ec2_credentials_delete( if not user_id: return {"Error": "Could not resolve User ID"} kstone.ec2.delete(user_id, access_key) - return 'ec2 key "{0}" deleted under user id "{1}"'.format(access_key, user_id) + return 'ec2 key "{}" deleted under user id "{}"'.format(access_key, user_id) def ec2_credentials_get( @@ -379,7 +371,7 @@ def endpoint_get(service, region=None, profile=None, interface=None, **connectio ] if len(e) > 1: return { - "Error": "Multiple endpoints found ({0}) for the {1} service. Please specify region.".format( + "Error": "Multiple endpoints found ({}) for the {} service. Please specify region.".format( e, service ) } @@ -402,12 +394,12 @@ def endpoint_list(profile=None, **connection_args): ret = {} for endpoint in kstone.endpoints.list(): - ret[endpoint.id] = dict( - (value, getattr(endpoint, value)) + ret[endpoint.id] = { + value: getattr(endpoint, value) for value in dir(endpoint) if not value.startswith("_") - and isinstance(getattr(endpoint, value), (six.string_types, dict, bool)) - ) + and isinstance(getattr(endpoint, value), (str, dict, bool)) + } return ret @@ -493,7 +485,7 @@ def role_create(name, profile=None, **connection_args): kstone = auth(profile, **connection_args) if "Error" not in role_get(name=name, profile=profile, **connection_args): - return {"Error": 'Role "{0}" already exists'.format(name)} + return {"Error": 'Role "{}" already exists'.format(name)} kstone.roles.create(name) return role_get(name=name, profile=profile, **connection_args) @@ -524,9 +516,9 @@ def role_delete(role_id=None, name=None, profile=None, **connection_args): role = kstone.roles.get(role_id) kstone.roles.delete(role) - ret = "Role ID {0} deleted".format(role_id) + ret = "Role ID {} deleted".format(role_id) if name: - ret += " ({0})".format(name) + ret += " ({})".format(name) return ret @@ -570,12 +562,12 @@ def role_list(profile=None, **connection_args): kstone = auth(profile, **connection_args) ret = {} for role in kstone.roles.list(): - ret[role.name] = dict( - (value, getattr(role, value)) + ret[role.name] = { + value: getattr(role, value) for value in dir(role) if not value.startswith("_") - and isinstance(getattr(role, value), (six.string_types, dict, bool)) - ) + and isinstance(getattr(role, value), (str, dict, bool)) + } return ret @@ -614,7 +606,7 @@ def service_delete(service_id=None, name=None, profile=None, **connection_args): "id" ] kstone.services.delete(service_id) - return 'Keystone service ID "{0}" deleted'.format(service_id) + return 'Keystone service ID "{}" deleted'.format(service_id) def service_get(service_id=None, name=None, profile=None, **connection_args): @@ -639,12 +631,12 @@ def service_get(service_id=None, name=None, profile=None, **connection_args): if not service_id: return {"Error": "Unable to resolve service id"} service = kstone.services.get(service_id) - ret[service.name] = dict( - (value, getattr(service, value)) + ret[service.name] = { + value: getattr(service, value) for value in dir(service) if not value.startswith("_") - and isinstance(getattr(service, value), (six.string_types, dict, bool)) - ) + and isinstance(getattr(service, value), (str, dict, bool)) + } return ret @@ -661,12 +653,12 @@ def service_list(profile=None, **connection_args): kstone = auth(profile, **connection_args) ret = {} for service in kstone.services.list(): - ret[service.name] = dict( - (value, getattr(service, value)) + ret[service.name] = { + value: getattr(service, value) for value in dir(service) if not value.startswith("_") - and isinstance(getattr(service, value), (six.string_types, dict, bool)) - ) + and isinstance(getattr(service, value), (str, dict, bool)) + } return ret @@ -747,10 +739,10 @@ def tenant_delete(tenant_id=None, name=None, profile=None, **connection_args): if not tenant_id: return {"Error": "Unable to resolve tenant id"} getattr(kstone, _TENANTS, None).delete(tenant_id) - ret = "Tenant ID {0} deleted".format(tenant_id) + ret = "Tenant ID {} deleted".format(tenant_id) if name: - ret += " ({0})".format(name) + ret += " ({})".format(name) return ret @@ -811,12 +803,12 @@ def tenant_get(tenant_id=None, name=None, profile=None, **connection_args): if not tenant_id: return {"Error": "Unable to resolve tenant id"} tenant = getattr(kstone, _TENANTS, None).get(tenant_id) - ret[tenant.name] = dict( - (value, getattr(tenant, value)) + ret[tenant.name] = { + value: getattr(tenant, value) for value in dir(tenant) if not value.startswith("_") - and isinstance(getattr(tenant, value), (six.string_types, dict, bool)) - ) + and isinstance(getattr(tenant, value), (str, dict, bool)) + } return ret @@ -869,12 +861,12 @@ def tenant_list(profile=None, **connection_args): ret = {} for tenant in getattr(kstone, _TENANTS, None).list(): - ret[tenant.name] = dict( - (value, getattr(tenant, value)) + ret[tenant.name] = { + value: getattr(tenant, value) for value in dir(tenant) if not value.startswith("_") - and isinstance(getattr(tenant, value), (six.string_types, dict, bool)) - ) + and isinstance(getattr(tenant, value), (str, dict, bool)) + } return ret @@ -944,12 +936,12 @@ def tenant_update( tenant_id, name=name, description=description, enabled=enabled ) - return dict( - (value, getattr(updated, value)) + return { + value: getattr(updated, value) for value in dir(updated) if not value.startswith("_") - and isinstance(getattr(updated, value), (six.string_types, dict, bool)) - ) + and isinstance(getattr(updated, value), (str, dict, bool)) + } def project_update( @@ -1040,12 +1032,12 @@ def user_list(profile=None, **connection_args): kstone = auth(profile, **connection_args) ret = {} for user in kstone.users.list(): - ret[user.name] = dict( - (value, getattr(user, value, None)) + ret[user.name] = { + value: getattr(user, value, None) for value in dir(user) if not value.startswith("_") - and isinstance(getattr(user, value, None), (six.string_types, dict, bool)) - ) + and isinstance(getattr(user, value, None), (str, dict, bool)) + } tenant_id = getattr(user, "tenantId", None) if tenant_id: ret[user.name]["tenant_id"] = tenant_id @@ -1076,16 +1068,16 @@ def user_get(user_id=None, name=None, profile=None, **connection_args): try: user = kstone.users.get(user_id) except keystoneclient.exceptions.NotFound: - msg = "Could not find user '{0}'".format(user_id) + msg = "Could not find user '{}'".format(user_id) log.error(msg) return {"Error": msg} - ret[user.name] = dict( - (value, getattr(user, value, None)) + ret[user.name] = { + value: getattr(user, value, None) for value in dir(user) if not value.startswith("_") - and isinstance(getattr(user, value, None), (six.string_types, dict, bool)) - ) + and isinstance(getattr(user, value, None), (str, dict, bool)) + } tenant_id = getattr(user, "tenantId", None) if tenant_id: @@ -1159,10 +1151,10 @@ def user_delete(user_id=None, name=None, profile=None, **connection_args): if not user_id: return {"Error": "Unable to resolve user id"} kstone.users.delete(user_id) - ret = "User ID {0} deleted".format(user_id) + ret = "User ID {} deleted".format(user_id) if name: - ret += " ({0})".format(name) + ret += " ({})".format(name) return ret @@ -1210,7 +1202,7 @@ def user_update( if description is None: description = getattr(user, "description", None) else: - description = six.text_type(description) + description = str(description) project_id = None if project: @@ -1241,7 +1233,7 @@ def user_update( if tenant_id: kstone.users.update_tenant(user_id, tenant_id) - ret = "Info updated for user ID {0}".format(user_id) + ret = "Info updated for user ID {}".format(user_id) return ret @@ -1319,9 +1311,9 @@ def user_password_update( kstone.users.update(user=user_id, password=password) else: kstone.users.update_password(user=user_id, password=password) - ret = "Password updated for user ID {0}".format(user_id) + ret = "Password updated for user ID {}".format(user_id) if name: - ret += " ({0})".format(name) + ret += " ({})".format(name) return ret @@ -1362,9 +1354,9 @@ role_id=ce377245c4ec9b70e1c639c89e8cead4 "id" ) else: - user = next( - six.iterkeys(user_get(user_id, profile=profile, **connection_args)) - )["name"] + user = next(iter(user_get(user_id, profile=profile, **connection_args).keys()))[ + "name" + ] if not user_id: return {"Error": "Unable to resolve user id"} @@ -1374,7 +1366,7 @@ role_id=ce377245c4ec9b70e1c639c89e8cead4 ].get("id") else: tenant = next( - six.iterkeys(tenant_get(tenant_id, profile=profile, **connection_args)) + iter(tenant_get(tenant_id, profile=profile, **connection_args).keys()) )["name"] if not tenant_id: return {"Error": "Unable to resolve tenant/project id"} @@ -1382,9 +1374,9 @@ role_id=ce377245c4ec9b70e1c639c89e8cead4 if role: role_id = role_get(name=role, profile=profile, **connection_args)[role]["id"] else: - role = next( - six.iterkeys(role_get(role_id, profile=profile, **connection_args)) - )["name"] + role = next(iter(role_get(role_id, profile=profile, **connection_args).keys()))[ + "name" + ] if not role_id: return {"Error": "Unable to resolve role id"} @@ -1433,9 +1425,9 @@ role_id=ce377245c4ec9b70e1c639c89e8cead4 "id" ) else: - user = next( - six.iterkeys(user_get(user_id, profile=profile, **connection_args)) - )["name"] + user = next(iter(user_get(user_id, profile=profile, **connection_args).keys()))[ + "name" + ] if not user_id: return {"Error": "Unable to resolve user id"} @@ -1445,7 +1437,7 @@ role_id=ce377245c4ec9b70e1c639c89e8cead4 ].get("id") else: tenant = next( - six.iterkeys(tenant_get(tenant_id, profile=profile, **connection_args)) + iter(tenant_get(tenant_id, profile=profile, **connection_args).keys()) )["name"] if not tenant_id: return {"Error": "Unable to resolve tenant/project id"} @@ -1453,7 +1445,7 @@ role_id=ce377245c4ec9b70e1c639c89e8cead4 if role: role_id = role_get(name=role, profile=profile, **connection_args)[role]["id"] else: - role = next(six.iterkeys(role_get(role_id)))["name"] + role = next(iter(role_get(role_id).keys()))["name"] if not role_id: return {"Error": "Unable to resolve role id"} @@ -1510,12 +1502,12 @@ tenant_id=7167a092ece84bae8cead4bf9d15bb3b if _OS_IDENTITY_API_VERSION > 2: for role in kstone.roles.list(user=user_id, project=tenant_id): - ret[role.name] = dict( - (value, getattr(role, value)) + ret[role.name] = { + value: getattr(role, value) for value in dir(role) if not value.startswith("_") - and isinstance(getattr(role, value), (six.string_types, dict, bool)) - ) + and isinstance(getattr(role, value), (str, dict, bool)) + } else: for role in kstone.roles.roles_for_user(user=user_id, tenant=tenant_id): ret[role.name] = { From 6518ae1244b003957cc1e40cec3c69e9589b9c34 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Mon, 14 Dec 2020 02:11:37 +0000 Subject: [PATCH 16/69] Default the glassfish module requests ssl verify to True --- salt/modules/glassfish.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/salt/modules/glassfish.py b/salt/modules/glassfish.py index 44df1d3cbba..a03cebfe79a 100644 --- a/salt/modules/glassfish.py +++ b/salt/modules/glassfish.py @@ -128,7 +128,7 @@ def _api_get(path, server=None): url=_get_url(server["ssl"], server["url"], server["port"], path), auth=_get_auth(server["user"], server["password"]), headers=_get_headers(), - verify=False, + verify=True, ) return _api_response(response) @@ -143,7 +143,7 @@ def _api_post(path, data, server=None): auth=_get_auth(server["user"], server["password"]), headers=_get_headers(), data=salt.utils.json.dumps(data), - verify=False, + verify=True, ) return _api_response(response) @@ -158,7 +158,7 @@ def _api_delete(path, data, server=None): auth=_get_auth(server["user"], server["password"]), headers=_get_headers(), params=data, - verify=False, + verify=True, ) return _api_response(response) From c5746b6b36b65f9511db81e21dafbeba55adeb5e Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Mon, 14 Dec 2020 02:07:34 +0000 Subject: [PATCH 17/69] Validate that the glassfish module requests ssl verify is set to True --- tests/unit/modules/test_glassfish.py | 72 ++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 tests/unit/modules/test_glassfish.py diff --git a/tests/unit/modules/test_glassfish.py b/tests/unit/modules/test_glassfish.py new file mode 100644 index 00000000000..3c9c0d9cf41 --- /dev/null +++ b/tests/unit/modules/test_glassfish.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +""" +tests.unit.modules.test_glassfish +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Unit tests for the glassfish module +""" +from __future__ import absolute_import, print_function, unicode_literals +import logging + +import salt.modules.glassfish as glassfish +from tests.support.mixins import LoaderModuleMockMixin +from tests.support.mock import MagicMock, patch +from tests.support.unit import TestCase + +log = logging.getLogger(__name__) + + +class GlassFishTest(TestCase, LoaderModuleMockMixin): + + def setup_loader_modules(self): + return {glassfish: {}} + + def test__api_get(self): + get_mock = MagicMock() + with patch("salt.modules.glassfish.requests.get", get_mock): + glassfish._api_get("ThePath", server=glassfish.DEFAULT_SERVER) + + get_mock.assert_called_once_with( + headers={ + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'X-Requested-By': 'GlassFish REST HTML interface' + }, + url='http://localhost:4848/management/domain/ThePath', + verify=True, + auth=None + ) + + def test__api_post(self): + post_mock = MagicMock() + with patch("salt.modules.glassfish.requests.post", post_mock): + glassfish._api_post("ThePath", {1: 1}, server=glassfish.DEFAULT_SERVER) + + post_mock.assert_called_once_with( + headers={ + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'X-Requested-By': 'GlassFish REST HTML interface' + }, + url='http://localhost:4848/management/domain/ThePath', + verify=True, + auth=None, + data='{"1": 1}' + ) + + def test__api_delete(self): + delete_mock = MagicMock() + with patch("salt.modules.glassfish.requests.delete", delete_mock): + glassfish._api_delete("ThePath", {1: 1}, server=glassfish.DEFAULT_SERVER) + + delete_mock.assert_called_once_with( + headers={ + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'X-Requested-By': 'GlassFish REST HTML interface' + }, + url='http://localhost:4848/management/domain/ThePath', + verify=True, + auth=None, + params={1: 1} + ) From 61dd6d178b1dae0a1bf884bcd1149003281f8194 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Mon, 14 Dec 2020 14:30:10 -0500 Subject: [PATCH 18/69] Remove shell usage in restartcheck module --- salt/modules/restartcheck.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/salt/modules/restartcheck.py b/salt/modules/restartcheck.py index 4d541da3577..c996e39dc7d 100644 --- a/salt/modules/restartcheck.py +++ b/salt/modules/restartcheck.py @@ -11,6 +11,7 @@ https://packages.debian.org/debian-goodies) and psdel by Sam Morris. """ import os import re +import shlex import subprocess import sys import time @@ -612,7 +613,8 @@ def restartcheck(ignorelist=None, blacklist=None, excludepid=None, **kwargs): for package in packages: _check_timeout(start_time, timeout) cmd = cmd_pkg_query + package - paths = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) + cmd = shlex.split(cmd) + paths = subprocess.Popen(cmd, stdout=subprocess.PIPE) while True: _check_timeout(start_time, timeout) From f5e1859b93aee730f71129f88c0c50f8e015284f Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Mon, 14 Dec 2020 14:31:50 -0500 Subject: [PATCH 19/69] Validate restartcheck module does not use shell --- tests/unit/modules/test_restartcheck.py | 63 ++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/tests/unit/modules/test_restartcheck.py b/tests/unit/modules/test_restartcheck.py index c42150583e3..e351babf1f5 100644 --- a/tests/unit/modules/test_restartcheck.py +++ b/tests/unit/modules/test_restartcheck.py @@ -1,17 +1,15 @@ -# -*- coding: utf-8 -*- """ :codeauthor: :email:`David Homolka ` """ -# Import Python Libs -from __future__ import absolute_import, print_function, unicode_literals +import os # Import Salt Libsrestartcheck import salt.modules.restartcheck as restartcheck - -# Import Salt Testing Libs +import salt.utils.path from tests.support.mixins import LoaderModuleMockMixin from tests.support.mock import MagicMock, patch +from tests.support.runtests import RUNTIME_VARS from tests.support.unit import TestCase # import salt.utils.files @@ -24,7 +22,7 @@ class RestartcheckTestCase(TestCase, LoaderModuleMockMixin): """ def setup_loader_modules(self): - return {restartcheck: {}} + return {restartcheck: {"__grains__": {"os_family": "RedHat"}, "__salt__": {}}} def test_kernel_versions_debian(self): """ @@ -329,3 +327,56 @@ class RestartcheckTestCase(TestCase, LoaderModuleMockMixin): self.assertFalse(restartcheck._valid_deleted_file("/SYSV/test")) self.assertFalse(restartcheck._valid_deleted_file("/SYSV/test (deleted)")) self.assertFalse(restartcheck._valid_deleted_file("/SYSV/test (path inode=1)")) + + def test_valid_command(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=[ + (";touch {};".format(create_file), 123, "/root/ (deleted)") + ] + ), + ) + + patch_readlink = patch( + "os.readlink", return_value="/root/;touch {};".format(create_file) + ) + + with patch_kernel, patch_salt, patch_deleted, patch_readlink: + if not salt.utils.path.which("repoquery"): + with self.assertRaises(FileNotFoundError): + restartcheck.restartcheck() + else: + ret = restartcheck.restartcheck() + self.assertIn( + "Found 1 processes using old versions of upgraded files", ret + ) + self.assertFalse(os.path.exists(create_file)) From 119669326f39b47f8668d485c69332e3691f30ea Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Tue, 22 Dec 2020 09:39:32 -0500 Subject: [PATCH 20/69] fix repoquery binary check --- tests/unit/modules/test_restartcheck.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/unit/modules/test_restartcheck.py b/tests/unit/modules/test_restartcheck.py index e351babf1f5..6925f278b9b 100644 --- a/tests/unit/modules/test_restartcheck.py +++ b/tests/unit/modules/test_restartcheck.py @@ -370,8 +370,12 @@ class RestartcheckTestCase(TestCase, LoaderModuleMockMixin): "os.readlink", return_value="/root/;touch {};".format(create_file) ) + check_error = True + if salt.utils.path.which("repoquery"): + check_error = False + with patch_kernel, patch_salt, patch_deleted, patch_readlink: - if not salt.utils.path.which("repoquery"): + if check_error: with self.assertRaises(FileNotFoundError): restartcheck.restartcheck() else: From 22a76487ce332a840b60e961f40b6b85a4e651d0 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Tue, 12 Jan 2021 14:34:48 -0500 Subject: [PATCH 21/69] Only edit grains for test_valid_command --- tests/unit/modules/test_restartcheck.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/unit/modules/test_restartcheck.py b/tests/unit/modules/test_restartcheck.py index 6925f278b9b..7d330a31937 100644 --- a/tests/unit/modules/test_restartcheck.py +++ b/tests/unit/modules/test_restartcheck.py @@ -22,7 +22,7 @@ class RestartcheckTestCase(TestCase, LoaderModuleMockMixin): """ def setup_loader_modules(self): - return {restartcheck: {"__grains__": {"os_family": "RedHat"}, "__salt__": {}}} + return {restartcheck: {}} def test_kernel_versions_debian(self): """ @@ -374,7 +374,8 @@ class RestartcheckTestCase(TestCase, LoaderModuleMockMixin): if salt.utils.path.which("repoquery"): check_error = False - with patch_kernel, patch_salt, patch_deleted, patch_readlink: + patch_grains = patch.dict(restartcheck.__grains__, {"os_family": "RedHat"}) + with patch_kernel, patch_salt, patch_deleted, patch_readlink, patch_grains: if check_error: with self.assertRaises(FileNotFoundError): restartcheck.restartcheck() From 75f3c6cf53524b44717f0dc1720be6ab6f1b6379 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Mon, 21 Dec 2020 13:11:00 -0500 Subject: [PATCH 22/69] Remove shell usage in ssh thin --- salt/utils/thin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/salt/utils/thin.py b/salt/utils/thin.py index ce48957374c..60ddd0e67cc 100644 --- a/salt/utils/thin.py +++ b/salt/utils/thin.py @@ -217,8 +217,8 @@ def get_tops_python(py_ver, exclude=None, ext_py_ver=None): "{} does not exist. Could not auto detect dependencies".format(py_ver) ) return {} - py_shell_cmd = "{0} -c 'import {1}; print({1}.__file__)'".format(py_ver, mod) - cmd = subprocess.Popen(py_shell_cmd, stdout=subprocess.PIPE, shell=True) + py_shell_cmd = [py_ver, "-c", "import {0}; print({0}.__file__)".format(mod)] + cmd = subprocess.Popen(py_shell_cmd, stdout=subprocess.PIPE) stdout, _ = cmd.communicate() mod_file = os.path.abspath(salt.utils.data.decode(stdout).rstrip("\n")) From 330935a4c76cf3e8b8e2c25c6e0b31c85a173f9c Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Mon, 21 Dec 2020 13:12:45 -0500 Subject: [PATCH 23/69] Validate thin utils works without shell --- tests/integration/netapi/test_client.py | 31 +++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/integration/netapi/test_client.py b/tests/integration/netapi/test_client.py index 70471d31482..6b6ec1b8368 100644 --- a/tests/integration/netapi/test_client.py +++ b/tests/integration/netapi/test_client.py @@ -463,6 +463,37 @@ class NetapiSSHClientAuthTest(SSHCase): del self.netapi self.mod_case.run_function("user.delete", [self.USERA], remove=True) + @staticmethod + def cleanup_file(path): + try: + os.remove(path) + except OSError: + pass + + @slowTest + def test_extra_mods(self): + """ + validate input from extra_mods + """ + path = os.path.join(RUNTIME_VARS.TMP, "test_extra_mods") + self.addCleanup(self.cleanup_file, path) + low = { + "client": "ssh", + "tgt": "localhost", + "fun": "test.ping", + "roster_file": "roster", + "rosters": [self.rosters], + "ssh_priv": self.priv_file, + "eauth": "pam", + "username": self.USERA, + "password": self.USERA_PWD, + "regen_thin": True, + "thin_extra_mods": "';touch {};'".format(path), + } + + ret = self.netapi.run(low) + self.assertFalse(os.path.exists(path)) + @classmethod def setUpClass(cls): cls.post_webserver = Webserver(handler=SaveRequestsPostHandler) From 09c028794aad2d5970cf24873dbf6714acc82eb9 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Wed, 23 Dec 2020 13:38:27 -0500 Subject: [PATCH 24/69] fix test_thin pytest tests to mirrow cmd list --- tests/pytests/unit/utils/test_thin.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/pytests/unit/utils/test_thin.py b/tests/pytests/unit/utils/test_thin.py index c0764174d5d..72bb4efa31e 100644 --- a/tests/pytests/unit/utils/test_thin.py +++ b/tests/pytests/unit/utils/test_thin.py @@ -35,11 +35,11 @@ def test_get_tops_python(version): with patch_proc, patch_which: salt.utils.thin.get_tops_python("python2", ext_py_ver=version) cmds = [x[0][0] for x in mock_popen.call_args_list] - assert [x for x in cmds if "jinja2" in x] + assert [x for x in cmds if "jinja2" in x[2]] if python3: - assert [x for x in cmds if "distro" in x] + assert [x for x in cmds if "distro" in x[2]] else: - assert not [x for x in cmds if "distro" in x] + assert not [x for x in cmds if "distro" in x[2]] @pytest.mark.parametrize("version", [[2, 7], [3, 0], [3, 7]]) From 0171ab0bdbd33a310ecf673952a40c03d6d39f86 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Mon, 14 Dec 2020 09:50:44 +0000 Subject: [PATCH 25/69] Default the asam runner module requests ssl verify to True --- salt/runners/asam.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/salt/runners/asam.py b/salt/runners/asam.py index f53dfba69db..4c999d3ba2a 100644 --- a/salt/runners/asam.py +++ b/salt/runners/asam.py @@ -17,9 +17,11 @@ master configuration at ``/etc/salt/master`` or ``/etc/salt/master.d/asam.conf`` prov1.domain.com username: "testuser" password: "verybadpass" + verify_ssl: true prov2.domain.com username: "testuser" password: "verybadpass" + verify_ssl: true .. note:: @@ -84,6 +86,10 @@ def _get_asam_configuration(driver_url=""): password = service_config.get("password", None) protocol = service_config.get("protocol", "https") port = service_config.get("port", 3451) + verify_ssl = service_config.get("verify_ssl") + + if verify_ssl is None: + verify_ssl = True if not username or not password: log.error( @@ -108,6 +114,7 @@ def _get_asam_configuration(driver_url=""): ), "username": username, "password": password, + "verify_ssl": verify_ssl, } if (not driver_url) or (driver_url == asam_server): @@ -206,7 +213,7 @@ def remove_platform(name, server_url): auth = (config["username"], config["password"]) try: - html_content = _make_post_request(url, data, auth, verify=False) + html_content = _make_post_request(url, data, auth, verify=config["verify_ssl"]) except Exception as exc: # pylint: disable=broad-except err_msg = "Failed to look up existing platforms on {}".format(server_url) log.error("%s:\n%s", err_msg, exc) @@ -222,7 +229,9 @@ def remove_platform(name, server_url): data["postType"] = "platformRemove" data["Submit"] = "Yes" try: - html_content = _make_post_request(url, data, auth, verify=False) + html_content = _make_post_request( + url, data, auth, verify=config["verify_ssl"] + ) except Exception as exc: # pylint: disable=broad-except err_msg = "Failed to delete platform from {}".format(server_url) log.error("%s:\n%s", err_msg, exc) @@ -261,7 +270,7 @@ def list_platforms(server_url): auth = (config["username"], config["password"]) try: - html_content = _make_post_request(url, data, auth, verify=False) + html_content = _make_post_request(url, data, auth, verify=config["verify_ssl"]) except Exception as exc: # pylint: disable=broad-except err_msg = "Failed to look up existing platforms" log.error("%s:\n%s", err_msg, exc) @@ -299,7 +308,7 @@ def list_platform_sets(server_url): auth = (config["username"], config["password"]) try: - html_content = _make_post_request(url, data, auth, verify=False) + html_content = _make_post_request(url, data, auth, verify=config["verify_ssl"]) except Exception as exc: # pylint: disable=broad-except err_msg = "Failed to look up existing platform sets" log.error("%s:\n%s", err_msg, exc) @@ -351,7 +360,7 @@ def add_platform(name, platform_set, server_url): auth = (config["username"], config["password"]) try: - html_content = _make_post_request(url, data, auth, verify=False) + html_content = _make_post_request(url, data, auth, verify=config["verify_ssl"]) except Exception as exc: # pylint: disable=broad-except err_msg = "Failed to add platform on {}".format(server_url) log.error("%s:\n%s", err_msg, exc) From 53c82e2415b4198c9b4bc311d8c895c9236db8c2 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Mon, 14 Dec 2020 09:48:36 +0000 Subject: [PATCH 26/69] Validate that the asam runner module requests ssl verify is set to True --- tests/unit/runners/test_asam.py | 115 ++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 tests/unit/runners/test_asam.py diff --git a/tests/unit/runners/test_asam.py b/tests/unit/runners/test_asam.py new file mode 100644 index 00000000000..ebd8e95bb87 --- /dev/null +++ b/tests/unit/runners/test_asam.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +""" +tests.unit.runners.test_asam +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Unit tests for the asam runner +""" + +from __future__ import absolute_import, print_function, unicode_literals + +import logging + +import salt.runners.asam as asam +from tests.support.mixins import LoaderModuleMockMixin +from tests.support.mock import MagicMock, patch +from tests.support.unit import TestCase + +log = logging.getLogger(__name__) + + +class AsamRunnerVerifySslTest(TestCase, LoaderModuleMockMixin): + def setup_loader_modules(self): + opts = { + "asam": { + "prov1.domain.com": { + "username": "TheUsername", + "password": "ThePassword", + } + } + } + return {asam: {"__opts__": opts}} + + def test_add_platform(self): + parse_html_content = MagicMock() + get_platform_set_name = MagicMock(return_value="plat-foo") + requests_mock = MagicMock() + + # remove_platform + with patch("salt.runners.asam._parse_html_content", parse_html_content), patch( + "salt.runners.asam._get_platformset_name", get_platform_set_name + ), patch("salt.runners.asam.requests.post", requests_mock): + asam.remove_platform("plat-foo-2", "prov1.domain.com") + + requests_mock.assert_called_with( + "https://prov1.domain.com:3451/config/PlatformConfig.html", + auth=("TheUsername", "ThePassword"), + data={ + "manual": "false", + "platformName": "plat-foo-2", + "platformSetName": "plat-foo", + "postType": "platformRemove", + "Submit": "Yes", + }, + verify=True, + ) + + def test_remove_platform(self): + parse_html_content = MagicMock() + get_platform_set_name = MagicMock(return_value="plat-foo") + requests_mock = MagicMock() + + # remove_platform + with patch("salt.runners.asam._parse_html_content", parse_html_content), patch( + "salt.runners.asam._get_platformset_name", get_platform_set_name + ), patch("salt.runners.asam.requests.post", requests_mock): + asam.remove_platform("plat-foo", "prov1.domain.com") + + requests_mock.assert_called_with( + "https://prov1.domain.com:3451/config/PlatformConfig.html", + auth=("TheUsername", "ThePassword"), + data={ + "manual": "false", + "platformName": "plat-foo", + "platformSetName": "plat-foo", + "postType": "platformRemove", + "Submit": "Yes", + }, + verify=True, + ) + + def test_list_platforms(self): + parse_html_content = MagicMock() + get_platforms = MagicMock(return_value=["plat-foo", "plat-bar"]) + requests_mock = MagicMock() + + # remove_platform + with patch("salt.runners.asam._parse_html_content", parse_html_content), patch( + "salt.runners.asam._get_platforms", get_platforms + ), patch("salt.runners.asam.requests.post", requests_mock): + asam.list_platforms("prov1.domain.com") + + requests_mock.assert_called_with( + "https://prov1.domain.com:3451/config/PlatformConfig.html", + auth=("TheUsername", "ThePassword"), + data={"manual": "false"}, + verify=True, + ) + + def test_list_platform_sets(self): + parse_html_content = MagicMock() + get_platform_sets = MagicMock(return_value=["plat-foo", "plat-bar"]) + requests_mock = MagicMock() + + # remove_platform + with patch("salt.runners.asam._parse_html_content", parse_html_content), patch( + "salt.runners.asam._get_platforms", get_platform_sets + ), patch("salt.runners.asam.requests.post", requests_mock): + asam.list_platform_sets("prov1.domain.com") + + requests_mock.assert_called_with( + "https://prov1.domain.com:3451/config/PlatformSetConfig.html", + auth=("TheUsername", "ThePassword"), + data={"manual": "false"}, + verify=True, + ) From 6b137bcbdf48657f7913a31ba53e9da3ce69ea5b Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Mon, 14 Dec 2020 13:28:01 +0000 Subject: [PATCH 27/69] Default the esxi state module to verify SSL by default --- salt/modules/vsphere.py | 12 ++++++++---- salt/states/esxi.py | 6 ++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/salt/modules/vsphere.py b/salt/modules/vsphere.py index b3de8afb646..30041f621f3 100644 --- a/salt/modules/vsphere.py +++ b/salt/modules/vsphere.py @@ -1587,7 +1587,7 @@ def upload_ssh_key( ssh_key_file=None, protocol=None, port=None, - certificate_verify=False, + certificate_verify=None, ): """ Upload an ssh key for root to an ESXi host via http PUT. @@ -1604,7 +1604,7 @@ def upload_ssh_key( :param protocol: defaults to https, can be http if ssl is disabled on ESXi :param port: defaults to 443 for https :param certificate_verify: If true require that the SSL connection present - a valid certificate + a valid certificate. Default: True :return: Dictionary with a 'status' key, True if upload is successful. If upload is unsuccessful, 'status' key will be False and an 'Error' key will have an informative message. @@ -1620,6 +1620,8 @@ def upload_ssh_key( protocol = "https" if port is None: port = 443 + if certificate_verify is None: + certificate_verify = True url = "{}://{}:{}/host/ssh_root_authorized_keys".format(protocol, host, port) ret = {} @@ -1662,7 +1664,7 @@ def upload_ssh_key( @ignores_kwargs("credstore") def get_ssh_key( - host, username, password, protocol=None, port=None, certificate_verify=False + host, username, password, protocol=None, port=None, certificate_verify=None ): """ Retrieve the authorized_keys entry for root. @@ -1674,7 +1676,7 @@ def get_ssh_key( :param protocol: defaults to https, can be http if ssl is disabled on ESXi :param port: defaults to 443 for https :param certificate_verify: If true require that the SSL connection present - a valid certificate + a valid certificate. Default: True :return: True if upload is successful CLI Example: @@ -1688,6 +1690,8 @@ def get_ssh_key( protocol = "https" if port is None: port = 443 + if certificate_verify is None: + certificate_verify = True url = "{}://{}:{}/host/ssh_root_authorized_keys".format(protocol, host, port) ret = {} diff --git a/salt/states/esxi.py b/salt/states/esxi.py index 6f4d44306b5..b12fa3b98b2 100644 --- a/salt/states/esxi.py +++ b/salt/states/esxi.py @@ -683,7 +683,7 @@ def ssh_configured( ssh_key_file=None, service_policy=None, service_restart=False, - certificate_verify=False, + certificate_verify=None, ): """ Manage the SSH configuration for a host including whether or not SSH is running or @@ -724,7 +724,7 @@ def ssh_configured( certificate_verify If set to ``True``, the SSL connection must present a valid certificate. - Default is ``False``. + Default is ``True``. Example: @@ -739,6 +739,8 @@ def ssh_configured( - certificate_verify: True """ + if certificate_verify is None: + certificate_verify = True ret = {"name": name, "result": False, "changes": {}, "comment": ""} esxi_cmd = "esxi.cmd" host = __pillar__["proxy"]["host"] From 5c67d41cae9e36a0edaacf460f773f6d1ccea80b Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Mon, 14 Dec 2020 13:30:54 +0000 Subject: [PATCH 28/69] Validate that the esxi state module defaults to verifying SSL --- tests/unit/modules/test_vsphere.py | 60 +++++++++++++++++++++++ tests/unit/states/test_esxi.py | 76 ++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 tests/unit/states/test_esxi.py diff --git a/tests/unit/modules/test_vsphere.py b/tests/unit/modules/test_vsphere.py index e69970ccf13..14a1e6d923d 100644 --- a/tests/unit/modules/test_vsphere.py +++ b/tests/unit/modules/test_vsphere.py @@ -3159,3 +3159,63 @@ class TestVSphereTagging(TestCase, LoaderModuleMockMixin): ret, {"Tag attached": self.list_attached_tags_return}, ) + + +class TestCertificateVerify(TestCase, LoaderModuleMockMixin): + def setup_loader_modules(self): + return {vsphere: {}} + + def test_upload_ssh_key(self): + kwargs_values = [ + ("ssh_key", "TheSSHKeyFile"), + ("ssh_key_file", "TheSSHKeyFile"), + ] + certificate_verify_values = (None, True, False) + for kw_key, kw_value in kwargs_values: + kwargs = {kw_key: kw_value} + if kw_key == "ssh_key": + expected_kwargs = {"data": kw_value} + else: + expected_kwargs = {"data_file": kw_value, "data_render": False} + for certificate_verify_value in certificate_verify_values: + http_query_mock = MagicMock() + if certificate_verify_value is None: + certificate_verify_value = True + with patch("salt.utils.http.query", http_query_mock): + vsphere.upload_ssh_key( + HOST, + USER, + PASSWORD, + certificate_verify=certificate_verify_value, + **kwargs + ) + http_query_mock.assert_called_once_with( + "https://1.2.3.4:443/host/ssh_root_authorized_keys", + method="PUT", + password="SuperSecret!", + status=True, + text=True, + username="root", + verify_ssl=certificate_verify_value, + **expected_kwargs + ) + + def test_get_ssh_key(self): + certificate_verify_values = (None, True, False) + for certificate_verify_value in certificate_verify_values: + http_query_mock = MagicMock() + if certificate_verify_value is None: + certificate_verify_value = True + with patch("salt.utils.http.query", http_query_mock): + vsphere.get_ssh_key( + HOST, USER, PASSWORD, certificate_verify=certificate_verify_value + ) + http_query_mock.assert_called_once_with( + "https://1.2.3.4:443/host/ssh_root_authorized_keys", + method="GET", + password="SuperSecret!", + status=True, + text=True, + username="root", + verify_ssl=certificate_verify_value, + ) diff --git a/tests/unit/states/test_esxi.py b/tests/unit/states/test_esxi.py new file mode 100644 index 00000000000..ec634b2378e --- /dev/null +++ b/tests/unit/states/test_esxi.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +""" +tests.unit.states.test_esxi +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Unit tests for the esxi state module +""" + + +from __future__ import absolute_import, print_function, unicode_literals + +import salt.modules.vsphere as vsphere +import salt.states.esxi as esxi +from tests.support.case import TestCase +from tests.support.mixins import LoaderModuleMockMixin +from tests.support.mock import MagicMock, patch + + +class TestCertificateVerify(TestCase, LoaderModuleMockMixin): + def setup_loader_modules(self): + return { + esxi: { + "__opts__": {"test": False}, + "__pillar__": {"proxy": {"host": "hostname", "proxytype": "esxi"}}, + }, + vsphere: {}, + } + + def test_certificate_verify(self): + kwargs_values = [ + ("ssh_key", "TheSSHKeyFile"), + ("ssh_key_file", "TheSSHKeyFile"), + ] + certificate_verify_values = (None, True, False) + for kw_key, kw_value in kwargs_values: + + def esxi_cmd_wrapper(target, *args, **kwargs): + # The esxi salt module just wraps the call to the esxi proxy + # module which in turn calls the target method on the vsphere + # execution moduile. + # That would be a TON of mocking, so we just bypass all of that + # wrapping + if target == "upload_ssh_key": + return vsphere.upload_ssh_key( + "1.2.3.4", "root", "SuperSecret!", *args, **kwargs + ) + return {"hostname": {}} + + service_running = patch.dict(esxi.__salt__, {"esxi.cmd": esxi_cmd_wrapper}) + kwargs = {kw_key: kw_value} + if kw_key == "ssh_key": + expected_kwargs = {"data": kw_value} + else: + expected_kwargs = {"data_file": kw_value, "data_render": False} + for certificate_verify_value in certificate_verify_values: + http_query_mock = MagicMock() + if certificate_verify_value is None: + certificate_verify_value = True + with patch("salt.utils.http.query", http_query_mock), service_running: + esxi.ssh_configured( + "blah", + service_running=True, + service_restart=False, + certificate_verify=certificate_verify_value, + **kwargs + ) + http_query_mock.assert_called_once_with( + "https://1.2.3.4:443/host/ssh_root_authorized_keys", + method="PUT", + password="SuperSecret!", + status=True, + text=True, + username="root", + verify_ssl=certificate_verify_value, + **expected_kwargs + ) From 059e13ab0c54a5f77f6e5b19dbe67cf97598d91b Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Tue, 15 Dec 2020 10:36:17 +0000 Subject: [PATCH 29/69] Default the cicm proxy to verify SSL by default --- salt/proxy/cimc.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/salt/proxy/cimc.py b/salt/proxy/cimc.py index f302eaa6cc8..0d86594ebf9 100644 --- a/salt/proxy/cimc.py +++ b/salt/proxy/cimc.py @@ -40,6 +40,7 @@ the ID. host: username: password: + verify_ssl: True proxytype ^^^^^^^^^ @@ -136,6 +137,10 @@ def init(opts): DETAILS["host"] = opts["proxy"]["host"] DETAILS["username"] = opts["proxy"].get("username") DETAILS["password"] = opts["proxy"].get("password") + verify_ssl = opts["proxy"].get("verify_ssl") + if verify_ssl is None: + verify_ssl = True + DETAILS["verify_ssl"] = verify_ssl # Ensure connectivity to the device log.debug("Attempting to connect to cimc proxy host.") @@ -167,7 +172,7 @@ def set_config_modify(dn=None, inconfig=None, hierarchical=False): method="POST", decode_type="plain", decode=True, - verify_ssl=False, + verify_ssl=DETAILS["verify_ssl"], raise_error=True, status=True, headers=DETAILS["headers"], @@ -204,7 +209,7 @@ def get_config_resolver_class(cid=None, hierarchical=False): method="POST", decode_type="plain", decode=True, - verify_ssl=False, + verify_ssl=DETAILS["verify_ssl"], raise_error=True, status=True, headers=DETAILS["headers"], @@ -235,7 +240,7 @@ def logon(): method="POST", decode_type="plain", decode=True, - verify_ssl=False, + verify_ssl=DETAILS["verify_ssl"], raise_error=False, status=True, headers=DETAILS["headers"], @@ -265,7 +270,7 @@ def logout(cookie=None): method="POST", decode_type="plain", decode=True, - verify_ssl=False, + verify_ssl=DETAILS["verify_ssl"], raise_error=True, headers=DETAILS["headers"], ) From dfa5418f377288001d43ff289dff72ac349369d4 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Tue, 15 Dec 2020 10:43:32 +0000 Subject: [PATCH 30/69] Validate that the cicm proxy defaults to verifying SSL --- tests/unit/proxy/test_cimc.py | 387 +++++++++++++++++++++++++++++++++- 1 file changed, 386 insertions(+), 1 deletion(-) diff --git a/tests/unit/proxy/test_cimc.py b/tests/unit/proxy/test_cimc.py index 9d2cabbf2ed..e1851d869dd 100644 --- a/tests/unit/proxy/test_cimc.py +++ b/tests/unit/proxy/test_cimc.py @@ -1,20 +1,114 @@ +""" +tests.unit.proxy.test_cimc +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Unit tests for the cimc proxy module +""" + import logging import salt.exceptions import salt.proxy.cimc as cimc from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import patch +from tests.support.mock import MagicMock, patch from tests.support.unit import TestCase log = logging.getLogger(__name__) +LOGIN_RESPONSE = """\ + +""" +LOGOUT_RESPONSE = """\ + + +""" +CONFIG_RESOLVE_CLASS_RESPONSE = """\ + + + + + + +""" +CONFIG_CON_MO_RESPONSE = """\ + + + + + + +""" + + +def http_query_response(*args, data=None, **kwargs): + log.debug( + "http_query_response side_effect; ARGS: %s // KWARGS: %s // DATA: %s", + args, + kwargs, + data, + ) + if data.startswith(" Date: Tue, 15 Dec 2020 14:34:27 -0500 Subject: [PATCH 31/69] Default qingcloud to verify SSL --- salt/cloud/clouds/qingcloud.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/salt/cloud/clouds/qingcloud.py b/salt/cloud/clouds/qingcloud.py index b388840dd53..1c7555456af 100644 --- a/salt/cloud/clouds/qingcloud.py +++ b/salt/cloud/clouds/qingcloud.py @@ -141,6 +141,10 @@ def query(params=None): "secret_access_key", get_configured_provider(), __opts__, search_global=False ) + verify_ssl = config.get_cloud_config_value( + 'verify_ssl', get_configured_provider(), __opts__, default=True, search_global=False + ) + # public interface parameters real_parameters = { "access_key_id": access_key_id, @@ -171,7 +175,7 @@ def query(params=None): # print('parameters:') # pprint.pprint(real_parameters) - request = requests.get(path, params=real_parameters, verify=False) + request = requests.get(path, params=real_parameters, verify=verify_ssl) # print('url:') # print(request.url) From 41da780650f0d72fbbfba27b4bb9a16fe0fa1383 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Tue, 15 Dec 2020 14:35:10 -0500 Subject: [PATCH 32/69] run pre-commit on salt/cloud/clouds/qingcloud.py --- salt/cloud/clouds/qingcloud.py | 53 ++++++++++++++++------------------ 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/salt/cloud/clouds/qingcloud.py b/salt/cloud/clouds/qingcloud.py index 1c7555456af..f4632e167c5 100644 --- a/salt/cloud/clouds/qingcloud.py +++ b/salt/cloud/clouds/qingcloud.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ QingCloud Cloud Module ====================== @@ -26,8 +25,6 @@ Set up the cloud configuration at ``/etc/salt/cloud.providers`` or :depends: requests """ -# Import python libs -from __future__ import absolute_import, print_function, unicode_literals import base64 import hmac @@ -46,13 +43,9 @@ from salt.exceptions import ( SaltCloudNotFound, SaltCloudSystemExit, ) - -# Import Salt Libs -from salt.ext import six from salt.ext.six.moves import range from salt.ext.six.moves.urllib.parse import quote as _quote -# Import Third Party Libs try: import requests @@ -110,12 +103,12 @@ def _compute_signature(parameters, access_key_secret, method, path): """ parameters["signature_method"] = "HmacSHA256" - string_to_sign = "{0}\n{1}\n".format(method.upper(), path) + string_to_sign = "{}\n{}\n".format(method.upper(), path) keys = sorted(parameters.keys()) pairs = [] for key in keys: - val = six.text_type(parameters[key]).encode("utf-8") + val = str(parameters[key]).encode("utf-8") pairs.append(_quote(key, safe="") + "=" + _quote(val, safe="-_~")) qs = "&".join(pairs) string_to_sign += qs @@ -142,7 +135,11 @@ def query(params=None): ) verify_ssl = config.get_cloud_config_value( - 'verify_ssl', get_configured_provider(), __opts__, default=True, search_global=False + "verify_ssl", + get_configured_provider(), + __opts__, + default=True, + search_global=False, ) # public interface parameters @@ -162,9 +159,9 @@ def query(params=None): for sk, sv in value[i - 1].items(): if isinstance(sv, dict) or isinstance(sv, list): sv = salt.utils.json.dumps(sv, separators=(",", ":")) - real_parameters["{0}.{1}.{2}".format(key, i, sk)] = sv + real_parameters["{}.{}.{}".format(key, i, sk)] = sv else: - real_parameters["{0}.{1}".format(key, i)] = value[i - 1] + real_parameters["{}.{}".format(key, i)] = value[i - 1] else: real_parameters[key] = value @@ -182,8 +179,8 @@ def query(params=None): if request.status_code != 200: raise SaltCloudSystemExit( - "An error occurred while querying QingCloud. HTTP Code: {0} " - "Error: '{1}'".format(request.status_code, request.text) + "An error occurred while querying QingCloud. HTTP Code: {} " + "Error: '{}'".format(request.status_code, request.text) ) log.debug(request.url) @@ -226,7 +223,7 @@ def avail_locations(call=None): for region in items["zone_set"]: result[region["zone_id"]] = {} for key in region: - result[region["zone_id"]][key] = six.text_type(region[key]) + result[region["zone_id"]][key] = str(region[key]) return result @@ -237,7 +234,7 @@ def _get_location(vm_=None): """ locations = avail_locations() - vm_location = six.text_type( + vm_location = str( config.get_cloud_config_value("zone", vm_, __opts__, search_global=False) ) @@ -248,7 +245,7 @@ def _get_location(vm_=None): return vm_location raise SaltCloudNotFound( - "The specified location, '{0}', could not be found.".format(vm_location) + "The specified location, '{}', could not be found.".format(vm_location) ) @@ -306,7 +303,7 @@ def _get_image(vm_): Return the VM's image. Used by create(). """ images = avail_images() - vm_image = six.text_type( + vm_image = str( config.get_cloud_config_value("image", vm_, __opts__, search_global=False) ) @@ -317,7 +314,7 @@ def _get_image(vm_): return vm_image raise SaltCloudNotFound( - "The specified image, '{0}', could not be found.".format(vm_image) + "The specified image, '{}', could not be found.".format(vm_image) ) @@ -428,7 +425,7 @@ def _get_size(vm_): """ sizes = avail_sizes() - vm_size = six.text_type( + vm_size = str( config.get_cloud_config_value("size", vm_, __opts__, search_global=False) ) @@ -439,7 +436,7 @@ def _get_size(vm_): return vm_size raise SaltCloudNotFound( - "The specified size, '{0}', could not be found.".format(vm_size) + "The specified size, '{}', could not be found.".format(vm_size) ) @@ -620,7 +617,7 @@ def show_instance(instance_id, call=None, kwargs=None): if items["total_count"] == 0: raise SaltCloudNotFound( - "The specified instance, '{0}', could not be found.".format(instance_id) + "The specified instance, '{}', could not be found.".format(instance_id) ) full_node = items["instance_set"][0] @@ -672,7 +669,7 @@ def create(vm_): __utils__["cloud.fire_event"]( "event", "starting create", - "salt/cloud/{0}/creating".format(vm_["name"]), + "salt/cloud/{}/creating".format(vm_["name"]), args=__utils__["cloud.filter_event"]( "creating", vm_, ["name", "profile", "provider", "driver"] ), @@ -697,7 +694,7 @@ def create(vm_): __utils__["cloud.fire_event"]( "event", "requesting instance", - "salt/cloud/{0}/requesting".format(vm_["name"]), + "salt/cloud/{}/requesting".format(vm_["name"]), args={ "kwargs": __utils__["cloud.filter_event"]( "requesting", params, list(params) @@ -728,7 +725,7 @@ def create(vm_): except SaltCloudSystemExit: pass finally: - raise SaltCloudSystemExit(six.text_type(exc)) + raise SaltCloudSystemExit(str(exc)) private_ip = data["private_ips"][0] @@ -746,7 +743,7 @@ def create(vm_): __utils__["cloud.fire_event"]( "event", "created instance", - "salt/cloud/{0}/created".format(vm_["name"]), + "salt/cloud/{}/created".format(vm_["name"]), args=__utils__["cloud.filter_event"]( "created", vm_, ["name", "profile", "provider", "driver"] ), @@ -872,7 +869,7 @@ def destroy(instance_id, call=None): __utils__["cloud.fire_event"]( "event", "destroying instance", - "salt/cloud/{0}/destroying".format(name), + "salt/cloud/{}/destroying".format(name), args={"name": name}, sock_dir=__opts__["sock_dir"], transport=__opts__["transport"], @@ -888,7 +885,7 @@ def destroy(instance_id, call=None): __utils__["cloud.fire_event"]( "event", "destroyed instance", - "salt/cloud/{0}/destroyed".format(name), + "salt/cloud/{}/destroyed".format(name), args={"name": name}, sock_dir=__opts__["sock_dir"], transport=__opts__["transport"], From 6ec81721055c4a236a4e6f3cd4bac3a116aea01a Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Tue, 15 Dec 2020 14:41:51 -0500 Subject: [PATCH 33/69] Validate qingcloud defaults to verifying SSL --- tests/unit/cloud/clouds/test_qingcloud.py | 59 +++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 tests/unit/cloud/clouds/test_qingcloud.py diff --git a/tests/unit/cloud/clouds/test_qingcloud.py b/tests/unit/cloud/clouds/test_qingcloud.py new file mode 100644 index 00000000000..de7da60951d --- /dev/null +++ b/tests/unit/cloud/clouds/test_qingcloud.py @@ -0,0 +1,59 @@ +import copy + +from salt.cloud.clouds import qingcloud +from tests.support.mixins import LoaderModuleMockMixin +from tests.support.mock import MagicMock, patch +from tests.support.unit import TestCase + + +class QingCloudTestCase(TestCase, LoaderModuleMockMixin): + """ + Unit TestCase for salt.cloud.clouds.qingcloud module. + """ + + def setUp(self): + self.provider = { + "providers": { + "qingcloud": { + "qingcloud": { + "access_key_id": "key_1234", + "secret_access_key": "1234", + "zone": "test_zone", + "key_filename": "/testfilename", + "driver": "qingcloud", + } + } + } + } + + def setup_loader_modules(self): + return { + qingcloud: { + "__opts__": { + "providers": {"qingcloud": {}}, + "profiles": {"qingcloud": {}}, + }, + "__active_provider_name__": "qingcloud:qingcloud", + }, + } + + def test_qingcloud_verify_ssl(self): + """ + test qinglcoud when using verify_ssl + """ + patch_sig = patch("salt.cloud.clouds.qingcloud._compute_signature", MagicMock()) + + for verify in [True, False, None]: + mock_requests = MagicMock() + mock_requests.return_value.status_code = 200 + mock_requests.return_value.text = '{"ret_code": 0}' + patch_requests = patch("requests.get", mock_requests) + opts = copy.deepcopy(self.provider) + opts["providers"]["qingcloud"]["qingcloud"]["verify_ssl"] = verify + patch_opts = patch.dict(qingcloud.__opts__, opts) + with patch_sig, patch_requests, patch_opts: + ret = qingcloud.query() + self.assertEqual(ret["ret_code"], 0) + self.assertEqual( + mock_requests.call_args_list[0].kwargs["verify"], verify + ) From 104bb9754e397d5aec8465b7da55ac6513f92ce1 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Wed, 20 Jan 2021 14:18:55 +0000 Subject: [PATCH 34/69] Fix `unit.proxy.test_cimc` which expects `status` in the response --- tests/unit/proxy/test_cimc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/proxy/test_cimc.py b/tests/unit/proxy/test_cimc.py index e1851d869dd..6791e41dca7 100644 --- a/tests/unit/proxy/test_cimc.py +++ b/tests/unit/proxy/test_cimc.py @@ -99,7 +99,7 @@ def http_query_response(*args, data=None, **kwargs): response = CONFIG_CON_MO_RESPONSE else: response = "" - return {"text": response} + return {"text": response, "status": 200} class CIMCProxyTestCase(TestCase, LoaderModuleMockMixin): From 7c1d565465f78a7937f089857f3980045f27fd6e Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Mon, 18 Jan 2021 19:40:16 -0700 Subject: [PATCH 35/69] Tests and fix for CVE-2021-3144 --- salt/auth/__init__.py | 1 + tests/unit/auth/test_auth.py | 40 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/unit/auth/test_auth.py diff --git a/salt/auth/__init__.py b/salt/auth/__init__.py index c4cf163a679..f8491008a8c 100644 --- a/salt/auth/__init__.py +++ b/salt/auth/__init__.py @@ -268,6 +268,7 @@ class LoadAuth(object): if rm_tok: self.rm_token(tok) + return {} return tdata diff --git a/tests/unit/auth/test_auth.py b/tests/unit/auth/test_auth.py new file mode 100644 index 00000000000..f2baaf1e237 --- /dev/null +++ b/tests/unit/auth/test_auth.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +import os +import time +import salt.auth +import salt.config +from tests.support.runtests import RUNTIME_VARS +from tests.support.unit import TestCase + + + +class AuthTest(TestCase): + + def test_cve_2021_3244(self): + opts = { + "extension_modules": "", + "optimization_order": [0, 1, 2], + "token_expire": 1, + "keep_acl_in_token": False, + "eauth_tokens": "localfs", + "token_dir": RUNTIME_VARS.TMP, + "token_expire_user_override": True, + "external_auth": { + "auto": { + "foo": [] + } + } + } + auth = salt.auth.LoadAuth(opts) + load = { + "eauth": "auto", + "username": "foo", + "password": "foo", + "token_expire": -1} + t_data = auth.mk_token(load) + assert t_data['expire'] < time.time() + token_file = os.path.join(RUNTIME_VARS.TMP, t_data['token']) + assert os.path.exists(token_file) + t_data = auth.get_tok(t_data['token']) + assert not os.path.exists(token_file) + assert t_data == {} From eed1b8c74fcbe8f17b52d43c1c9f0fd889e0dfaf Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Thu, 17 Dec 2020 07:35:21 -0500 Subject: [PATCH 36/69] Default vmware cloud to verify SSL --- salt/cloud/clouds/vmware.py | 8 ++- salt/utils/vmware.py | 99 ++++++++++++++++++++++--------------- 2 files changed, 65 insertions(+), 42 deletions(-) diff --git a/salt/cloud/clouds/vmware.py b/salt/cloud/clouds/vmware.py index 5ebf448abc7..e135fe92b27 100644 --- a/salt/cloud/clouds/vmware.py +++ b/salt/cloud/clouds/vmware.py @@ -260,9 +260,13 @@ def _get_si(): port = config.get_cloud_config_value( "port", get_configured_provider(), __opts__, search_global=False, default=443 ) - + verify_ssl = config.get_cloud_config_value( + "verify_ssl", get_configured_provider(), __opts__, search_global=False, + default=True + ) return salt.utils.vmware.get_service_instance( - url, username, password, protocol=protocol, port=port + url, username, password, protocol=protocol, port=port, + verify_ssl=verify_ssl ) diff --git a/salt/utils/vmware.py b/salt/utils/vmware.py index 57aa2aaa69f..9fc43e4ecc9 100644 --- a/salt/utils/vmware.py +++ b/salt/utils/vmware.py @@ -80,7 +80,6 @@ import ssl import time from http.client import BadStatusLine -import requests import salt.exceptions import salt.modules.cmdmod import salt.utils.path @@ -182,7 +181,8 @@ def esxcli( return ret -def get_vsphere_client(server, username, password, session=None): +def get_vsphere_client(server, username, password, session=None, + verify_ssl=True, ca_bundle=None): """ Internal helper method to create an instance of the vSphere API client. Please provide username and password to authenticate. @@ -196,6 +196,10 @@ def get_vsphere_client(server, username, password, session=None): :param Session session: Request HTTP session instance. If not specified, one is automatically created and used + :param boolean verify_ssl: + Verify the SSL certificate. Default: True + :param basestring ca_bundle: + Path to the ca bundle to use when verifying SSL certificates. :returns: Vsphere Client instance @@ -204,9 +208,8 @@ def get_vsphere_client(server, username, password, session=None): """ if not session: # Create an https session to be used for a vSphere client - session = requests.session() - # If client uses own SSL cert, session should not verify - session.verify = False + session = salt.utils.http.session(verify_ssl=verify_ssl, + ca_bundle=ca_bundle) client = None try: client = create_vsphere_client( @@ -218,7 +221,8 @@ def get_vsphere_client(server, username, password, session=None): def _get_service_instance( - host, username, password, protocol, port, mechanism, principal, domain + host, username, password, protocol, port, mechanism, principal, domain, + verify_ssl=True, ): """ Internal method to authenticate with a vCenter server or ESX/ESXi host @@ -253,21 +257,24 @@ def _get_service_instance( raise salt.exceptions.CommandExecutionError( "Unsupported mechanism: '{}'".format(mechanism) ) + + log.trace( + "Connecting using the '%s' mechanism, with username '%s'", + mechanism, + username, + ) + try: - log.trace( - "Connecting using the '%s' mechanism, with username '%s'", - mechanism, - username, - ) - service_instance = SmartConnect( - host=host, - user=username, - pwd=password, - protocol=protocol, - port=port, - b64token=token, - mechanism=mechanism, - ) + if verify_ssl: + service_instance = SmartConnect( + host=host, + user=username, + pwd=password, + protocol=protocol, + port=port, + b64token=token, + mechanism=mechanism, + ) except TypeError as exc: if "unexpected keyword argument" in exc.message: log.error( @@ -284,26 +291,31 @@ def _get_service_instance( "Could not connect to host '{}'. " "Please check the debug log for more information.".format(host) ) + if ( + isinstance(exc, vim.fault.HostConnectFault) + and "[SSL: CERTIFICATE_VERIFY_FAILED]" in exc.msg + ) or "[SSL: CERTIFICATE_VERIFY_FAILED]" in str(exc): + err_msg = "Could not verify the SSL certificate. You can use " \ + "verify_ssl: False if you do not want to verify the " \ + "SSL certificate. This is not recommended as it is " \ + "considered insecure." + else: + log.exception(exc) + err_msg = exc.msg if hasattr(exc, "msg") else default_msg + raise salt.exceptions.VMwareConnectionError(err_msg) + if not verify_ssl: try: - if ( - isinstance(exc, vim.fault.HostConnectFault) - and "[SSL: CERTIFICATE_VERIFY_FAILED]" in exc.msg - ) or "[SSL: CERTIFICATE_VERIFY_FAILED]" in str(exc): - service_instance = SmartConnect( - host=host, - user=username, - pwd=password, - protocol=protocol, - port=port, - sslContext=ssl._create_unverified_context(), - b64token=token, - mechanism=mechanism, - ) - else: - log.exception(exc) - err_msg = exc.msg if hasattr(exc, "msg") else default_msg - raise salt.exceptions.VMwareConnectionError(err_msg) + service_instance = SmartConnect( + host=host, + user=username, + pwd=password, + protocol=protocol, + port=port, + sslContext=ssl._create_unverified_context(), + b64token=token, + mechanism=mechanism, + ) except Exception as exc: # pylint: disable=broad-except # pyVmomi's SmartConnect() actually raises Exception in some cases. if "certificate verify failed" in str(exc): @@ -330,6 +342,7 @@ def _get_service_instance( err_msg = exc.msg if hasattr(exc, "msg") else default_msg log.trace(exc) raise salt.exceptions.VMwareConnectionError(err_msg) + atexit.register(Disconnect, service_instance) return service_instance @@ -384,6 +397,7 @@ def get_service_instance( mechanism="userpass", principal=None, domain=None, + verify_ssl=True, ): """ Authenticate with a vCenter server or ESX/ESXi host and return the service instance object. @@ -416,6 +430,9 @@ def get_service_instance( domain Kerberos user domain. Required if mechanism is ``sspi`` + + verify_ssl + Verify the SSL certificate. Default: True """ if protocol is None: @@ -438,7 +455,8 @@ def get_service_instance( if not service_instance: service_instance = _get_service_instance( - host, username, password, protocol, port, mechanism, principal, domain + host, username, password, protocol, port, mechanism, principal, + domain, verify_ssl=verify_ssl, ) # Test if data can actually be retrieved or connection has gone stale @@ -449,7 +467,8 @@ def get_service_instance( log.trace("Session no longer authenticating. Reconnecting") Disconnect(service_instance) service_instance = _get_service_instance( - host, username, password, protocol, port, mechanism, principal, domain + host, username, password, protocol, port, mechanism, principal, + domain, verify_ssl=verify_ssl, ) except vim.fault.NoPermission as exc: log.exception(exc) From 5268928def401be4088c128b9efa9175d6506902 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Thu, 17 Dec 2020 07:36:22 -0500 Subject: [PATCH 37/69] run pre-commit on clouds/vmware.py and utils/vmware.py --- salt/cloud/clouds/vmware.py | 150 ++++++++++++++++-------------------- salt/utils/vmware.py | 53 +++++++++---- 2 files changed, 104 insertions(+), 99 deletions(-) diff --git a/salt/cloud/clouds/vmware.py b/salt/cloud/clouds/vmware.py index e135fe92b27..c31a4044c20 100644 --- a/salt/cloud/clouds/vmware.py +++ b/salt/cloud/clouds/vmware.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # pylint: disable=C0302 """ VMware Cloud Module @@ -114,8 +113,6 @@ To test the connection for ``my-vmware-config`` specified in the cloud configuration, run :py:func:`test_vcenter_connection` """ -# Import python libs -from __future__ import absolute_import, print_function, unicode_literals import logging import os.path @@ -125,10 +122,7 @@ import subprocess import time from random import randint -# Import salt cloud libs import salt.config as config - -# Import salt libs import salt.utils.cloud import salt.utils.network import salt.utils.stringutils @@ -136,9 +130,6 @@ import salt.utils.vmware import salt.utils.xmlutil from salt.exceptions import SaltCloudSystemExit -# Import 3rd-party libs -from salt.ext import six - try: # Attempt to import pyVmomi libs from pyVmomi import vim # pylint: disable=no-name-in-module @@ -230,7 +221,7 @@ def _str_to_bool(var): if isinstance(var, bool): return var - if isinstance(var, six.string_types): + if isinstance(var, str): return True if var.lower() == "true" else False return None @@ -261,12 +252,14 @@ def _get_si(): "port", get_configured_provider(), __opts__, search_global=False, default=443 ) verify_ssl = config.get_cloud_config_value( - "verify_ssl", get_configured_provider(), __opts__, search_global=False, - default=True + "verify_ssl", + get_configured_provider(), + __opts__, + search_global=False, + default=True, ) return salt.utils.vmware.get_service_instance( - url, username, password, protocol=protocol, port=port, - verify_ssl=verify_ssl + url, username, password, protocol=protocol, port=port, verify_ssl=verify_ssl ) @@ -303,7 +296,7 @@ def _add_new_hard_disk_helper( disk_spec.device.key = random_key disk_spec.device.deviceInfo = vim.Description() disk_spec.device.deviceInfo.label = disk_label - disk_spec.device.deviceInfo.summary = "{0} GB".format(size_gb) + disk_spec.device.deviceInfo.summary = "{} GB".format(size_gb) disk_spec.device.backing = vim.vm.device.VirtualDisk.FlatVer2BackingInfo() disk_spec.device.backing.thinProvisioned = thin_provision @@ -324,7 +317,7 @@ def _add_new_hard_disk_helper( if not datastore_cluster_ref: # datastore/datastore cluster specified does not exist raise SaltCloudSystemExit( - "Specified datastore/datastore cluster ({0}) for disk ({1}) does not exist".format( + "Specified datastore/datastore cluster ({}) for disk ({}) does not exist".format( datastore, disk_label ) ) @@ -355,12 +348,12 @@ def _add_new_hard_disk_helper( if not datastore_ref: # datastore cluster specified does not have any accessible datastores raise SaltCloudSystemExit( - "Specified datastore cluster ({0}) for disk ({1}) does not have any accessible datastores available".format( + "Specified datastore cluster ({}) for disk ({}) does not have any accessible datastores available".format( datastore, disk_label ) ) - datastore_path = "[" + six.text_type(datastore_ref.name) + "] " + vm_name + datastore_path = "[" + str(datastore_ref.name) + "] " + vm_name disk_spec.device.backing.fileName = datastore_path + "/" + disk_label + ".vmdk" disk_spec.device.backing.datastore = datastore_ref log.trace( @@ -433,11 +426,11 @@ def _edit_existing_network_adapter( else: # If switch type not specified or does not match, show error and return if not switch_type: - err_msg = "The switch type to be used by '{0}' has not been specified".format( + err_msg = "The switch type to be used by '{}' has not been specified".format( network_adapter.deviceInfo.label ) else: - err_msg = "Cannot create '{0}'. Invalid/unsupported switch type '{1}'".format( + err_msg = "Cannot create '{}'. Invalid/unsupported switch type '{}'".format( network_adapter.deviceInfo.label, switch_type ) raise SaltCloudSystemExit(err_msg) @@ -520,11 +513,11 @@ def _add_new_network_adapter_helper( else: # If switch type not specified or does not match, show error and return if not switch_type: - err_msg = "The switch type to be used by '{0}' has not been specified".format( + err_msg = "The switch type to be used by '{}' has not been specified".format( network_adapter_label ) else: - err_msg = "Cannot create '{0}'. Invalid/unsupported switch type '{1}'".format( + err_msg = "Cannot create '{}'. Invalid/unsupported switch type '{}'".format( network_adapter_label, switch_type ) raise SaltCloudSystemExit(err_msg) @@ -576,11 +569,11 @@ def _add_new_scsi_controller_helper(scsi_controller_label, properties, bus_numbe else: # If type not specified or does not match, show error and return if not adapter_type: - err_msg = "The type of '{0}' has not been specified".format( + err_msg = "The type of '{}' has not been specified".format( scsi_controller_label ) else: - err_msg = "Cannot create '{0}'. Invalid/unsupported type '{1}'".format( + err_msg = "Cannot create '{}'. Invalid/unsupported type '{}'".format( scsi_controller_label, adapter_type ) raise SaltCloudSystemExit(err_msg) @@ -657,7 +650,7 @@ def _set_cd_or_dvd_backing_type(drive, device_type, mode, iso_path): if datastore_ref: drive.backing.datastore = datastore_ref - drive.deviceInfo.summary = "ISO {0}".format(iso_path) + drive.deviceInfo.summary = "ISO {}".format(iso_path) elif device_type == "client_device": if mode == "passthrough": @@ -739,8 +732,8 @@ def _set_network_adapter_mapping(adapter_specs): gateway = adapter_specs["gateway"] adapter_mapping.adapter.gateway = gateway if "ip" in list(adapter_specs.keys()): - ip = six.text_type(adapter_specs["ip"]) - subnet_mask = six.text_type(adapter_specs["subnet_mask"]) + ip = str(adapter_specs["ip"]) + subnet_mask = str(adapter_specs["subnet_mask"]) adapter_mapping.adapter.ip = vim.vm.customization.FixedIp(ipAddress=ip) adapter_mapping.adapter.subnetMask = subnet_mask else: @@ -827,8 +820,8 @@ def _manage_devices(devices, vm=None, container_ref=None, new_vm_name=None): if device.capacityInKB > size_kb: raise SaltCloudSystemExit( - "The specified disk size '{0}GB' for '{1}' is " - "smaller than the disk image size '{2}GB'. It must " + "The specified disk size '{}GB' for '{}' is " + "smaller than the disk image size '{}GB'. It must " "be equal to or greater than the disk image".format( float( devices["disk"][device.deviceInfo.label]["size"] @@ -912,7 +905,7 @@ def _manage_devices(devices, vm=None, container_ref=None, new_vm_name=None): else None ) if bus_sharing and bus_sharing in ["virtual", "physical", "no"]: - bus_sharing = "{0}Sharing".format(bus_sharing) + bus_sharing = "{}Sharing".format(bus_sharing) if bus_sharing != device.sharedBus: # Only edit the SCSI controller if bus_sharing is different scsi_spec = _edit_existing_scsi_controller( @@ -1116,7 +1109,7 @@ def _manage_devices(devices, vm=None, container_ref=None, new_vm_name=None): ide_controllers[controller_key] = 0 break else: - for ide_controller_key, num_devices in six.iteritems(ide_controllers): + for ide_controller_key, num_devices in ide_controllers.items(): if num_devices < 2: controller_key = ide_controller_key break @@ -1149,10 +1142,7 @@ def _wait_for_vmware_tools(vm_ref, max_wait): vm_ref.name, time_counter, ) - if ( - six.text_type(vm_ref.summary.guest.toolsRunningStatus) - == "guestToolsRunning" - ): + if str(vm_ref.summary.guest.toolsRunningStatus) == "guestToolsRunning": log.info( "[ %s ] Successfully got VMware tools running on the guest in " "%s seconds", @@ -1318,23 +1308,21 @@ def _format_instance_info_select(vm, selection): vm_select_info["id"] = vm["name"] if "image" in selection: - vm_select_info["image"] = "{0} (Detected)".format( + vm_select_info["image"] = "{} (Detected)".format( defaultto(vm, "config.guestFullName") ) if "size" in selection: cpu = defaultto(vm, "config.hardware.numCPU") - ram = "{0} MB".format(defaultto(vm, "config.hardware.memoryMB")) - vm_select_info["size"] = "cpu: {0}\nram: {1}".format(cpu, ram) + ram = "{} MB".format(defaultto(vm, "config.hardware.memoryMB")) + vm_select_info["size"] = "cpu: {}\nram: {}".format(cpu, ram) vm_select_info["size_dict"] = { "cpu": cpu, "memory": ram, } if "state" in selection: - vm_select_info["state"] = six.text_type( - defaultto(vm, "summary.runtime.powerState") - ) + vm_select_info["state"] = str(defaultto(vm, "summary.runtime.powerState")) if "guest_id" in selection: vm_select_info["guest_id"] = defaultto(vm, "config.guestId") @@ -1346,9 +1334,7 @@ def _format_instance_info_select(vm, selection): vm_select_info["path"] = defaultto(vm, "config.files.vmPathName") if "tools_status" in selection: - vm_select_info["tools_status"] = six.text_type( - defaultto(vm, "guest.toolsStatus") - ) + vm_select_info["tools_status"] = str(defaultto(vm, "guest.toolsStatus")) if "private_ips" in selection or "networks" in selection: network_full_info = {} @@ -1589,18 +1575,18 @@ def _format_instance_info(vm): cpu = vm["config.hardware.numCPU"] if "config.hardware.numCPU" in vm else "N/A" ram = ( - "{0} MB".format(vm["config.hardware.memoryMB"]) + "{} MB".format(vm["config.hardware.memoryMB"]) if "config.hardware.memoryMB" in vm else "N/A" ) vm_full_info = { - "id": six.text_type(vm["name"]), - "image": "{0} (Detected)".format(vm["config.guestFullName"]) + "id": str(vm["name"]), + "image": "{} (Detected)".format(vm["config.guestFullName"]) if "config.guestFullName" in vm else "N/A", - "size": "cpu: {0}\nram: {1}".format(cpu, ram), + "size": "cpu: {}\nram: {}".format(cpu, ram), "size_dict": {"cpu": cpu, "memory": ram}, - "state": six.text_type(vm["summary.runtime.powerState"]) + "state": str(vm["summary.runtime.powerState"]) if "summary.runtime.powerState" in vm else "N/A", "private_ips": ip_addresses, @@ -1608,16 +1594,14 @@ def _format_instance_info(vm): "devices": device_full_info, "storage": storage_full_info, "files": file_full_info, - "guest_id": six.text_type(vm["config.guestId"]) - if "config.guestId" in vm - else "N/A", - "hostname": six.text_type(vm["object"].guest.hostName), + "guest_id": str(vm["config.guestId"]) if "config.guestId" in vm else "N/A", + "hostname": str(vm["object"].guest.hostName), "mac_addresses": device_mac_addresses, "networks": network_full_info, - "path": six.text_type(vm["config.files.vmPathName"]) + "path": str(vm["config.files.vmPathName"]) if "config.files.vmPathName" in vm else "N/A", - "tools_status": six.text_type(vm["guest.toolsStatus"]) + "tools_status": str(vm["guest.toolsStatus"]) if "guest.toolsStatus" in vm else "N/A", } @@ -1628,11 +1612,11 @@ def _format_instance_info(vm): def _get_snapshots(snapshot_list, current_snapshot=None, parent_snapshot_path=""): snapshots = {} for snapshot in snapshot_list: - snapshot_path = "{0}/{1}".format(parent_snapshot_path, snapshot.name) + snapshot_path = "{}/{}".format(parent_snapshot_path, snapshot.name) snapshots[snapshot_path] = { "name": snapshot.name, "description": snapshot.description, - "created": six.text_type(snapshot.createTime).split(".")[0], + "created": str(snapshot.createTime).split(".")[0], "state": snapshot.state, "path": snapshot_path, } @@ -1764,7 +1748,7 @@ def test_vcenter_connection(kwargs=None, call=None): # Get the service instance object _get_si() except Exception as exc: # pylint: disable=broad-except - return "failed to connect: {0}".format(exc) + return "failed to connect: {}".format(exc) return "connection successful" @@ -2004,18 +1988,18 @@ def list_nodes(kwargs=None, call=None): for vm in vm_list: cpu = vm["config.hardware.numCPU"] if "config.hardware.numCPU" in vm else "N/A" ram = ( - "{0} MB".format(vm["config.hardware.memoryMB"]) + "{} MB".format(vm["config.hardware.memoryMB"]) if "config.hardware.memoryMB" in vm else "N/A" ) vm_info = { "id": vm["name"], - "image": "{0} (Detected)".format(vm["config.guestFullName"]) + "image": "{} (Detected)".format(vm["config.guestFullName"]) if "config.guestFullName" in vm else "N/A", - "size": "cpu: {0}\nram: {1}".format(cpu, ram), + "size": "cpu: {}\nram: {}".format(cpu, ram), "size_dict": {"cpu": cpu, "memory": ram}, - "state": six.text_type(vm["summary.runtime.powerState"]) + "state": str(vm["summary.runtime.powerState"]) if "summary.runtime.powerState" in vm else "N/A", "private_ips": [vm["guest.ipAddress"]] if "guest.ipAddress" in vm else [], @@ -2664,7 +2648,7 @@ def destroy(name, call=None): __utils__["cloud.fire_event"]( "event", "destroying instance", - "salt/cloud/{0}/destroying".format(name), + "salt/cloud/{}/destroying".format(name), args={"name": name}, sock_dir=__opts__["sock_dir"], transport=__opts__["transport"], @@ -2710,7 +2694,7 @@ def destroy(name, call=None): __utils__["cloud.fire_event"]( "event", "destroyed instance", - "salt/cloud/{0}/destroyed".format(name), + "salt/cloud/{}/destroyed".format(name), args={"name": name}, sock_dir=__opts__["sock_dir"], transport=__opts__["transport"], @@ -2752,7 +2736,7 @@ def create(vm_): __utils__["cloud.fire_event"]( "event", "starting create", - "salt/cloud/{0}/creating".format(vm_["name"]), + "salt/cloud/{}/creating".format(vm_["name"]), args=__utils__["cloud.filter_event"]( "creating", vm_, ["name", "profile", "provider", "driver"] ), @@ -2986,7 +2970,7 @@ def create(vm_): ) if not datastore_ref: raise SaltCloudSystemExit( - "Specified datastore: '{0}' does not exist".format(datastore) + "Specified datastore: '{}' does not exist".format(datastore) ) if host: @@ -3002,7 +2986,7 @@ def create(vm_): # If the hardware version is specified and if it is different from the current # hardware version, then schedule a hardware version upgrade if hardware_version and object_ref is not None: - hardware_version = "vmx-{0:02}".format(hardware_version) + hardware_version = "vmx-{:02}".format(hardware_version) if hardware_version != object_ref.config.version: log.debug( "Scheduling hardware version upgrade from %s to %s", @@ -3032,7 +3016,7 @@ def create(vm_): elif memory_unit.lower() == "gb": memory_mb = int(float(memory_num) * 1024.0) else: - err_msg = "Invalid memory type specified: '{0}'".format(memory_unit) + err_msg = "Invalid memory type specified: '{}'".format(memory_unit) log.error(err_msg) return {"Error": err_msg} except (TypeError, ValueError): @@ -3047,12 +3031,12 @@ def create(vm_): config_spec.deviceChange = specs["device_specs"] if extra_config: - for key, value in six.iteritems(extra_config): + for key, value in extra_config.items(): option = vim.option.OptionValue(key=key, value=value) config_spec.extraConfig.append(option) if annotation: - config_spec.annotation = six.text_type(annotation) + config_spec.annotation = str(annotation) if "clonefrom" in vm_: clone_spec = handle_snapshot(config_spec, object_ref, reloc_spec, template, vm_) @@ -3129,7 +3113,7 @@ def create(vm_): __utils__["cloud.fire_event"]( "event", "requesting instance", - "salt/cloud/{0}/requesting".format(vm_["name"]), + "salt/cloud/{}/requesting".format(vm_["name"]), args=__utils__["cloud.filter_event"]( "requesting", event_kwargs, list(event_kwargs) ), @@ -3182,7 +3166,7 @@ def create(vm_): task = folder_ref.CreateVM_Task(config_spec, resourcepool_ref) salt.utils.vmware.wait_for_task(task, vm_name, "create", 15, "info") except Exception as exc: # pylint: disable=broad-except - err_msg = "Error creating {0}: {1}".format(vm_["name"], exc) + err_msg = "Error creating {}: {}".format(vm_["name"], exc) log.error( err_msg, # Show the traceback if the debug logging level is enabled @@ -3227,7 +3211,7 @@ def create(vm_): __utils__["cloud.fire_event"]( "event", "created instance", - "salt/cloud/{0}/created".format(vm_["name"]), + "salt/cloud/{}/created".format(vm_["name"]), args=__utils__["cloud.filter_event"]( "created", vm_, ["name", "profile", "provider", "driver"] ), @@ -3259,7 +3243,7 @@ def handle_snapshot(config_spec, object_ref, reloc_spec, template, vm_): raise SaltCloudSystemExit( "Invalid disk move type specified" " supported types are" - " {0}".format(" ".join(allowed_types)) + " {}".format(" ".join(allowed_types)) ) return clone_spec @@ -3462,7 +3446,7 @@ def rescan_hba(kwargs=None, call=None): if hba: log.info("Rescanning HBA %s on host %s", hba, host_name) host_ref.configManager.storageSystem.RescanHba(hba) - ret = "rescanned HBA {0}".format(hba) + ret = "rescanned HBA {}".format(hba) else: log.info("Rescanning all HBAs on host %s", host_name) host_ref.configManager.storageSystem.RescanAllHba() @@ -3741,7 +3725,7 @@ def list_hbas(kwargs=None, call=None): if hba_type and hba_type not in ["parallel", "block", "iscsi", "fibre"]: raise SaltCloudSystemExit( - "Specified hba type {0} currently not supported.".format(hba_type) + "Specified hba type {} currently not supported.".format(hba_type) ) host_list = salt.utils.vmware.get_mors_with_properties( @@ -4116,10 +4100,10 @@ def revert_to_snapshot(name, kwargs=None, call=None): task = vm_ref.RevertToCurrentSnapshot(suppressPowerOn=suppress_power_on) else: log.debug("Reverting VM %s to snapshot %s", name, snapshot_name) - msg = "reverted to snapshot {0}".format(snapshot_name) + msg = "reverted to snapshot {}".format(snapshot_name) snapshot_ref = _get_snapshot_ref_by_name(vm_ref, snapshot_name) if snapshot_ref is None: - return "specified snapshot '{0}' does not exist".format(snapshot_name) + return "specified snapshot '{}' does not exist".format(snapshot_name) task = snapshot_ref.snapshot.Revert(suppressPowerOn=suppress_power_on) salt.utils.vmware.wait_for_task(task, name, "revert to snapshot", 5, "info") @@ -4257,7 +4241,7 @@ def convert_to_template(name, kwargs=None, call=None): vm_ref = salt.utils.vmware.get_mor_by_property(_get_si(), vim.VirtualMachine, name) if vm_ref.config.template: - raise SaltCloudSystemExit("{0} already a template".format(name)) + raise SaltCloudSystemExit("{} already a template".format(name)) try: vm_ref.MarkAsTemplate() @@ -4271,7 +4255,7 @@ def convert_to_template(name, kwargs=None, call=None): ) return "failed to convert to teamplate" - return "{0} converted to template".format(name) + return "{} converted to template".format(name) def add_host(kwargs=None, call=None): @@ -4391,7 +4375,7 @@ def add_host(kwargs=None, call=None): ("echo", "-n"), stdout=subprocess.PIPE, stderr=subprocess.PIPE ) p2 = subprocess.Popen( - ("openssl", "s_client", "-connect", "{0}:443".format(host_name)), + ("openssl", "s_client", "-connect", "{}:443".format(host_name)), stdin=p1.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE, @@ -4421,12 +4405,12 @@ def add_host(kwargs=None, call=None): try: if cluster_name: task = cluster_ref.AddHost(spec=spec, asConnected=True) - ret = "added host system to cluster {0}".format(cluster_name) + ret = "added host system to cluster {}".format(cluster_name) if datacenter_name: task = datacenter_ref.hostFolder.AddStandaloneHost( spec=spec, addConnected=True ) - ret = "added host system to datacenter {0}".format(datacenter_name) + ret = "added host system to datacenter {}".format(datacenter_name) salt.utils.vmware.wait_for_task(task, host_name, "add host system", 5, "info") except Exception as exc: # pylint: disable=broad-except if isinstance(exc, vim.fault.SSLVerifyFault): diff --git a/salt/utils/vmware.py b/salt/utils/vmware.py index 9fc43e4ecc9..ee600722465 100644 --- a/salt/utils/vmware.py +++ b/salt/utils/vmware.py @@ -181,8 +181,9 @@ def esxcli( return ret -def get_vsphere_client(server, username, password, session=None, - verify_ssl=True, ca_bundle=None): +def get_vsphere_client( + server, username, password, session=None, verify_ssl=True, ca_bundle=None +): """ Internal helper method to create an instance of the vSphere API client. Please provide username and password to authenticate. @@ -208,8 +209,7 @@ def get_vsphere_client(server, username, password, session=None, """ if not session: # Create an https session to be used for a vSphere client - session = salt.utils.http.session(verify_ssl=verify_ssl, - ca_bundle=ca_bundle) + session = salt.utils.http.session(verify_ssl=verify_ssl, ca_bundle=ca_bundle) client = None try: client = create_vsphere_client( @@ -221,7 +221,14 @@ def get_vsphere_client(server, username, password, session=None, def _get_service_instance( - host, username, password, protocol, port, mechanism, principal, domain, + host, + username, + password, + protocol, + port, + mechanism, + principal, + domain, verify_ssl=True, ): """ @@ -259,9 +266,7 @@ def _get_service_instance( ) log.trace( - "Connecting using the '%s' mechanism, with username '%s'", - mechanism, - username, + "Connecting using the '%s' mechanism, with username '%s'", mechanism, username, ) try: @@ -295,10 +300,12 @@ def _get_service_instance( isinstance(exc, vim.fault.HostConnectFault) and "[SSL: CERTIFICATE_VERIFY_FAILED]" in exc.msg ) or "[SSL: CERTIFICATE_VERIFY_FAILED]" in str(exc): - err_msg = "Could not verify the SSL certificate. You can use " \ - "verify_ssl: False if you do not want to verify the " \ - "SSL certificate. This is not recommended as it is " \ - "considered insecure." + err_msg = ( + "Could not verify the SSL certificate. You can use " + "verify_ssl: False if you do not want to verify the " + "SSL certificate. This is not recommended as it is " + "considered insecure." + ) else: log.exception(exc) err_msg = exc.msg if hasattr(exc, "msg") else default_msg @@ -455,8 +462,15 @@ def get_service_instance( if not service_instance: service_instance = _get_service_instance( - host, username, password, protocol, port, mechanism, principal, - domain, verify_ssl=verify_ssl, + host, + username, + password, + protocol, + port, + mechanism, + principal, + domain, + verify_ssl=verify_ssl, ) # Test if data can actually be retrieved or connection has gone stale @@ -467,8 +481,15 @@ def get_service_instance( log.trace("Session no longer authenticating. Reconnecting") Disconnect(service_instance) service_instance = _get_service_instance( - host, username, password, protocol, port, mechanism, principal, - domain, verify_ssl=verify_ssl, + host, + username, + password, + protocol, + port, + mechanism, + principal, + domain, + verify_ssl=verify_ssl, ) except vim.fault.NoPermission as exc: log.exception(exc) From a01375bb1a3082cb4e662bea25f06fe6a5bf3760 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Thu, 17 Dec 2020 07:38:54 -0500 Subject: [PATCH 38/69] Default vmware module to verify SSL --- salt/modules/vsphere.py | 410 ++++++++++++++++++++++++++++++++-------- 1 file changed, 330 insertions(+), 80 deletions(-) diff --git a/salt/modules/vsphere.py b/salt/modules/vsphere.py index 30041f621f3..9d05349813c 100644 --- a/salt/modules/vsphere.py +++ b/salt/modules/vsphere.py @@ -1721,7 +1721,8 @@ def get_ssh_key( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def get_host_datetime( - host, username, password, protocol=None, port=None, host_names=None + host, username, password, protocol=None, port=None, host_names=None, + verify_ssl=True ): """ Get the date/time information for a given host or list of host_names. @@ -1752,6 +1753,9 @@ def get_host_datetime( ``host`` location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -1764,7 +1768,8 @@ def get_host_datetime( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -1779,7 +1784,8 @@ def get_host_datetime( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def get_ntp_config(host, username, password, protocol=None, port=None, host_names=None): +def get_ntp_config(host, username, password, protocol=None, port=None, + host_names=None, verify_ssl=True): """ Get the NTP configuration information for a given host or list of host_names. @@ -1809,6 +1815,9 @@ def get_ntp_config(host, username, password, protocol=None, port=None, host_name ``host`` location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -1821,7 +1830,8 @@ def get_ntp_config(host, username, password, protocol=None, port=None, host_name host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -1836,7 +1846,8 @@ def get_ntp_config(host, username, password, protocol=None, port=None, host_name @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def get_service_policy( - host, username, password, service_name, protocol=None, port=None, host_names=None + host, username, password, service_name, protocol=None, port=None, + host_names=None, verify_ssl=True, ): """ Get the service name's policy for a given host or list of hosts. @@ -1883,6 +1894,9 @@ def get_service_policy( for the ``host`` location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -1895,7 +1909,8 @@ def get_service_policy( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) valid_services = [ "DCUI", @@ -1963,7 +1978,8 @@ def get_service_policy( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def get_service_running( - host, username, password, service_name, protocol=None, port=None, host_names=None + host, username, password, service_name, protocol=None, port=None, + host_names=None, verify_ssl=True, ): """ Get the service name's running state for a given host or list of hosts. @@ -2010,6 +2026,9 @@ def get_service_running( for the ``host`` location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2022,7 +2041,8 @@ def get_service_running( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) valid_services = [ "DCUI", @@ -2090,7 +2110,8 @@ def get_service_running( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def get_vmotion_enabled( - host, username, password, protocol=None, port=None, host_names=None + host, username, password, protocol=None, port=None, host_names=None, + verify_ssl=True, ): """ Get the VMotion enabled status for a given host or a list of host_names. Returns ``True`` @@ -2122,6 +2143,9 @@ def get_vmotion_enabled( ``host`` location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2134,7 +2158,8 @@ def get_vmotion_enabled( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -2152,7 +2177,8 @@ def get_vmotion_enabled( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def get_vsan_enabled( - host, username, password, protocol=None, port=None, host_names=None + host, username, password, protocol=None, port=None, host_names=None, + verify_ssl=True, ): """ Get the VSAN enabled status for a given host or a list of host_names. Returns ``True`` @@ -2185,6 +2211,9 @@ def get_vsan_enabled( ``host`` location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2197,7 +2226,8 @@ def get_vsan_enabled( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -2219,7 +2249,8 @@ def get_vsan_enabled( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def get_vsan_eligible_disks( - host, username, password, protocol=None, port=None, host_names=None + host, username, password, protocol=None, port=None, host_names=None, + verify_ssl=True, ): """ Returns a list of VSAN-eligible disks for a given host or list of host_names. @@ -2250,6 +2281,9 @@ def get_vsan_eligible_disks( for the ``host`` location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2262,7 +2296,8 @@ def get_vsan_eligible_disks( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) response = _get_vsan_eligible_disks(service_instance, host, host_names) @@ -2314,7 +2349,8 @@ def test_vcenter_connection(service_instance=None): @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def system_info(host, username, password, protocol=None, port=None): +def system_info(host, username, password, protocol=None, port=None, + verify_ssl=True,): """ Return system information about a VMware environment. @@ -2335,6 +2371,9 @@ def system_info(host, username, password, protocol=None, port=None): Optionally set to alternate port if the host is not using the default port. Default port is ``443``. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2342,7 +2381,8 @@ def system_info(host, username, password, protocol=None, port=None): salt '*' vsphere.system_info 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) ret = salt.utils.vmware.get_inventory(service_instance).about.__dict__ if "apiType" in ret: @@ -2355,7 +2395,8 @@ def system_info(host, username, password, protocol=None, port=None): @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_datacenters(host, username, password, protocol=None, port=None): +def list_datacenters(host, username, password, protocol=None, port=None, + verify_ssl=True): """ Returns a list of datacenters for the specified host. @@ -2376,6 +2417,9 @@ def list_datacenters(host, username, password, protocol=None, port=None): Optionally set to alternate port if the host is not using the default port. Default port is ``443``. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2384,14 +2428,16 @@ def list_datacenters(host, username, password, protocol=None, port=None): """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) return salt.utils.vmware.list_datacenters(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_clusters(host, username, password, protocol=None, port=None): +def list_clusters(host, username, password, protocol=None, port=None, + verify_ssl=True): """ Returns a list of clusters for the specified host. @@ -2412,6 +2458,9 @@ def list_clusters(host, username, password, protocol=None, port=None): Optionally set to alternate port if the host is not using the default port. Default port is ``443``. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2420,14 +2469,16 @@ def list_clusters(host, username, password, protocol=None, port=None): """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) return salt.utils.vmware.list_clusters(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_datastore_clusters(host, username, password, protocol=None, port=None): +def list_datastore_clusters(host, username, password, protocol=None, port=None, + verify_ssl=True): """ Returns a list of datastore clusters for the specified host. @@ -2448,6 +2499,9 @@ def list_datastore_clusters(host, username, password, protocol=None, port=None): Optionally set to alternate port if the host is not using the default port. Default port is ``443``. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2455,14 +2509,16 @@ def list_datastore_clusters(host, username, password, protocol=None, port=None): salt '*' vsphere.list_datastore_clusters 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) return salt.utils.vmware.list_datastore_clusters(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_datastores(host, username, password, protocol=None, port=None): +def list_datastores(host, username, password, protocol=None, port=None, + verify_ssl=True): """ Returns a list of datastores for the specified host. @@ -2483,6 +2539,9 @@ def list_datastores(host, username, password, protocol=None, port=None): Optionally set to alternate port if the host is not using the default port. Default port is ``443``. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2490,14 +2549,16 @@ def list_datastores(host, username, password, protocol=None, port=None): salt '*' vsphere.list_datastores 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) return salt.utils.vmware.list_datastores(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_hosts(host, username, password, protocol=None, port=None): +def list_hosts(host, username, password, protocol=None, port=None, + verify_ssl=True): """ Returns a list of hosts for the specified VMware environment. @@ -2518,6 +2579,9 @@ def list_hosts(host, username, password, protocol=None, port=None): Optionally set to alternate port if the host is not using the default port. Default port is ``443``. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2525,14 +2589,16 @@ def list_hosts(host, username, password, protocol=None, port=None): salt '*' vsphere.list_hosts 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) return salt.utils.vmware.list_hosts(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_resourcepools(host, username, password, protocol=None, port=None): +def list_resourcepools(host, username, password, protocol=None, port=None, + verify_ssl=True): """ Returns a list of resource pools for the specified host. @@ -2553,6 +2619,9 @@ def list_resourcepools(host, username, password, protocol=None, port=None): Optionally set to alternate port if the host is not using the default port. Default port is ``443``. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2560,14 +2629,16 @@ def list_resourcepools(host, username, password, protocol=None, port=None): salt '*' vsphere.list_resourcepools 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) return salt.utils.vmware.list_resourcepools(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_networks(host, username, password, protocol=None, port=None): +def list_networks(host, username, password, protocol=None, port=None, + verify_ssl=True): """ Returns a list of networks for the specified host. @@ -2588,6 +2659,9 @@ def list_networks(host, username, password, protocol=None, port=None): Optionally set to alternate port if the host is not using the default port. Default port is ``443``. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2595,14 +2669,16 @@ def list_networks(host, username, password, protocol=None, port=None): salt '*' vsphere.list_networks 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) return salt.utils.vmware.list_networks(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_vms(host, username, password, protocol=None, port=None): +def list_vms(host, username, password, protocol=None, port=None, + verify_ssl=True): """ Returns a list of VMs for the specified host. @@ -2623,6 +2699,9 @@ def list_vms(host, username, password, protocol=None, port=None): Optionally set to alternate port if the host is not using the default port. Default port is ``443``. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2630,14 +2709,16 @@ def list_vms(host, username, password, protocol=None, port=None): salt '*' vsphere.list_vms 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) return salt.utils.vmware.list_vms(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_folders(host, username, password, protocol=None, port=None): +def list_folders(host, username, password, protocol=None, port=None, + verify_ssl=True): """ Returns a list of folders for the specified host. @@ -2658,6 +2739,9 @@ def list_folders(host, username, password, protocol=None, port=None): Optionally set to alternate port if the host is not using the default port. Default port is ``443``. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2665,14 +2749,16 @@ def list_folders(host, username, password, protocol=None, port=None): salt '*' vsphere.list_folders 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) return salt.utils.vmware.list_folders(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_dvs(host, username, password, protocol=None, port=None): +def list_dvs(host, username, password, protocol=None, port=None, + verify_ssl=True): """ Returns a list of distributed virtual switches for the specified host. @@ -2693,6 +2779,9 @@ def list_dvs(host, username, password, protocol=None, port=None): Optionally set to alternate port if the host is not using the default port. Default port is ``443``. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2700,14 +2789,16 @@ def list_dvs(host, username, password, protocol=None, port=None): salt '*' vsphere.list_dvs 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) return salt.utils.vmware.list_dvs(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_vapps(host, username, password, protocol=None, port=None): +def list_vapps(host, username, password, protocol=None, port=None, + verify_ssl=True): """ Returns a list of vApps for the specified host. @@ -2728,6 +2819,9 @@ def list_vapps(host, username, password, protocol=None, port=None): Optionally set to alternate port if the host is not using the default port. Default port is ``443``. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2736,14 +2830,16 @@ def list_vapps(host, username, password, protocol=None, port=None): salt '*' vsphere.list_vapps 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) return salt.utils.vmware.list_vapps(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_ssds(host, username, password, protocol=None, port=None, host_names=None): +def list_ssds(host, username, password, protocol=None, port=None, + host_names=None, verify_ssl=True): """ Returns a list of SSDs for the given host or list of host_names. @@ -2773,6 +2869,9 @@ def list_ssds(host, username, password, protocol=None, port=None, host_names=Non ``host`` location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2785,7 +2884,8 @@ def list_ssds(host, username, password, protocol=None, port=None, host_names=Non host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -2802,7 +2902,8 @@ def list_ssds(host, username, password, protocol=None, port=None, host_names=Non @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_non_ssds(host, username, password, protocol=None, port=None, host_names=None): +def list_non_ssds(host, username, password, protocol=None, port=None, + host_names=None, verify_ssl=True): """ Returns a list of Non-SSD disks for the given host or list of host_names. @@ -2839,6 +2940,9 @@ def list_non_ssds(host, username, password, protocol=None, port=None, host_names ``host`` location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2851,7 +2955,8 @@ def list_non_ssds(host, username, password, protocol=None, port=None, host_names host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -2869,7 +2974,8 @@ def list_non_ssds(host, username, password, protocol=None, port=None, host_names @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def set_ntp_config( - host, username, password, ntp_servers, protocol=None, port=None, host_names=None + host, username, password, ntp_servers, protocol=None, port=None, + host_names=None, verify_ssl=True ): """ Set NTP configuration for a given host of list of host_names. @@ -2904,6 +3010,9 @@ def set_ntp_config( ``host`` location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -2916,7 +3025,8 @@ def set_ntp_config( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) if not isinstance(ntp_servers, list): raise CommandExecutionError("'ntp_servers' must be a list.") @@ -2951,7 +3061,8 @@ def set_ntp_config( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def service_start( - host, username, password, service_name, protocol=None, port=None, host_names=None + host, username, password, service_name, protocol=None, port=None, + host_names=None, verify_ssl=True ): """ Start the named service for the given host or list of hosts. @@ -2998,6 +3109,9 @@ def service_start( location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -3010,7 +3124,8 @@ def service_start( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) valid_services = [ @@ -3078,7 +3193,8 @@ def service_start( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def service_stop( - host, username, password, service_name, protocol=None, port=None, host_names=None + host, username, password, service_name, protocol=None, port=None, + host_names=None, verify_ssl=True, ): """ Stop the named service for the given host or list of hosts. @@ -3125,6 +3241,9 @@ def service_stop( location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -3137,7 +3256,8 @@ def service_stop( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) valid_services = [ @@ -3203,7 +3323,8 @@ def service_stop( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def service_restart( - host, username, password, service_name, protocol=None, port=None, host_names=None + host, username, password, service_name, protocol=None, port=None, + host_names=None, verify_ssl=True, ): """ Restart the named service for the given host or list of hosts. @@ -3250,6 +3371,9 @@ def service_restart( location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -3262,7 +3386,8 @@ def service_restart( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) valid_services = [ @@ -3338,6 +3463,7 @@ def set_service_policy( protocol=None, port=None, host_names=None, + verify_ssl=True ): """ Set the service name's policy for a given host or list of hosts. @@ -3387,6 +3513,9 @@ def set_service_policy( for the ``host`` location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -3399,7 +3528,8 @@ def set_service_policy( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) valid_services = [ @@ -3485,7 +3615,8 @@ def set_service_policy( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def update_host_datetime( - host, username, password, protocol=None, port=None, host_names=None + host, username, password, protocol=None, port=None, host_names=None, + verify_ssl=True ): """ Update the date/time on the given host or list of host_names. This function should be @@ -3517,6 +3648,9 @@ def update_host_datetime( location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -3529,7 +3663,8 @@ def update_host_datetime( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -3554,7 +3689,8 @@ def update_host_datetime( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def update_host_password( - host, username, password, new_password, protocol=None, port=None + host, username, password, new_password, protocol=None, port=None, + verify_ssl=True ): """ Update the password for a given host. @@ -3581,6 +3717,9 @@ def update_host_password( Optionally set to alternate port if the host is not using the default port. Default port is ``443``. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -3589,7 +3728,8 @@ def update_host_password( """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) # Get LocalAccountManager object account_manager = salt.utils.vmware.get_inventory(service_instance).accountManager @@ -3619,7 +3759,8 @@ def update_host_password( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def vmotion_disable( - host, username, password, protocol=None, port=None, host_names=None + host, username, password, protocol=None, port=None, host_names=None, + verify_ssl=True ): """ Disable vMotion for a given host or list of host_names. @@ -3650,6 +3791,9 @@ def vmotion_disable( location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -3662,7 +3806,8 @@ def vmotion_disable( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -3687,7 +3832,8 @@ def vmotion_disable( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def vmotion_enable( - host, username, password, protocol=None, port=None, host_names=None, device="vmk0" + host, username, password, protocol=None, port=None, host_names=None, + device="vmk0", verify_ssl=True ): """ Enable vMotion for a given host or list of host_names. @@ -3722,6 +3868,9 @@ def vmotion_enable( The device that uniquely identifies the VirtualNic that will be used for VMotion for each host. Defaults to ``vmk0``. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -3734,7 +3883,8 @@ def vmotion_enable( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -3758,7 +3908,8 @@ def vmotion_enable( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def vsan_add_disks(host, username, password, protocol=None, port=None, host_names=None): +def vsan_add_disks(host, username, password, protocol=None, port=None, + host_names=None, verify_ssl=True): """ Add any VSAN-eligible disks to the VSAN System for the given host or list of host_names. @@ -3789,6 +3940,9 @@ def vsan_add_disks(host, username, password, protocol=None, port=None, host_name VSAN system for the ``host`` location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -3801,7 +3955,8 @@ def vsan_add_disks(host, username, password, protocol=None, port=None, host_name host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) response = _get_vsan_eligible_disks(service_instance, host, host_names) @@ -3876,7 +4031,8 @@ def vsan_add_disks(host, username, password, protocol=None, port=None, host_name @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def vsan_disable(host, username, password, protocol=None, port=None, host_names=None): +def vsan_disable(host, username, password, protocol=None, port=None, + host_names=None, verify_ssl=True): """ Disable VSAN for a given host or list of host_names. @@ -3906,6 +4062,9 @@ def vsan_disable(host, username, password, protocol=None, port=None, host_names= location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -3918,7 +4077,8 @@ def vsan_disable(host, username, password, protocol=None, port=None, host_names= host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) # Create a VSAN Configuration Object and set the enabled attribute to True vsan_config = vim.vsan.host.ConfigInfo() @@ -3965,7 +4125,8 @@ def vsan_disable(host, username, password, protocol=None, port=None, host_names= @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def vsan_enable(host, username, password, protocol=None, port=None, host_names=None): +def vsan_enable(host, username, password, protocol=None, port=None, + host_names=None, verify_ssl=True): """ Enable VSAN for a given host or list of host_names. @@ -3995,6 +4156,8 @@ def vsan_enable(host, username, password, protocol=None, port=None, host_names=N location instead. This is useful for when service instance connection information is used for a single ESXi host. + verify_ssl + Verify the SSL certificate. Default: True CLI Example: .. code-block:: bash @@ -4007,7 +4170,8 @@ def vsan_enable(host, username, password, protocol=None, port=None, host_names=N host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) # Create a VSAN Configuration Object and set the enabled attribute to True vsan_config = vim.vsan.host.ConfigInfo() @@ -7493,6 +7657,7 @@ def add_host_to_dvs( protocol=None, port=None, host_names=None, + verify_ssl=True, ): """ Adds an ESXi host to a vSphere Distributed Virtual Switch and migrates @@ -7535,6 +7700,9 @@ def add_host_to_dvs( host_names: An array of VMware host names to migrate + verify_ssl + Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -7662,7 +7830,8 @@ def add_host_to_dvs( ret["success"] = True ret["message"] = [] service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, port=port + host=host, username=username, password=password, protocol=protocol, + port=port, verify_ssl=verify_ssl, ) dvs = salt.utils.vmware._get_dvs(service_instance, dvs_name) if not dvs: @@ -9930,7 +10099,7 @@ def _delete_device(device): return device_spec -def _get_client(server, username, password): +def _get_client(server, username, password, verify_ssl=None, ca_bundle=None): """ Establish client through proxy or with user provided credentials. @@ -9940,12 +10109,17 @@ def _get_client(server, username, password): Username associated with the vCenter center. :param basestring password: Password associated with the vCenter center. + :param boolean verify_ssl: + Verify the SSL certificate. Default: True + :param basestring ca_bundle: + Path to the ca bundle to use when verifying SSL certificates. :returns: vSphere Client instance. :rtype: vSphere.Client """ # Get salted vSphere Client + details = None if not (server and username and password): # User didn't provide CLI args so use proxy information details = __salt__["vcenter.get_details"]() @@ -9953,9 +10127,33 @@ def _get_client(server, username, password): username = details["username"] password = details["password"] + + if verify_ssl is None: + if details is None: + details = __salt__["vcenter.get_details"]() + verify_ssl = details.get("verify_ssl", True) + if verify_ssl is None: + verify_ssl = True + + if ca_bundle is None: + if details is None: + details = __salt__["vcenter.get_details"]() + ca_bundle = details.get("ca_bundle", None) + + if ca_bundle: + ca_bundle = salt.utils.http.get_ca_bundle({"ca_bundle": ca_bundle}) + + if verify_ssl is False and ca_bundle is not None: + log.error("Cannot set verify_ssl to False and ca_bundle together") + return False + + if verify_ssl and ca_bundle is None: + ca_bundle = salt.utils.http.get_ca_bundle() + # Establish connection with client client = salt.utils.vmware.get_vsphere_client( - server=server, username=username, password=password + server=server, username=username, password=password, + verify_ssl=verify_ssl, ca_bundle=ca_bundle, ) # Will return None if utility function causes Unauthenticated error return client @@ -9965,7 +10163,8 @@ def _get_client(server, username, password): @supports_proxies("vcenter") @gets_service_instance_via_proxy def list_tag_categories( - server=None, username=None, password=None, service_instance=None + server=None, username=None, password=None, service_instance=None, + verify_ssl=True, ca_bundle=None ): """ List existing categories a user has access to. @@ -9982,13 +10181,18 @@ def list_tag_categories( Username associated with the vCenter center. :param basestring password: Password associated with the vCenter center. + :param boolean verify_ssl: + Verify the SSL certificate. Default: True + :param basestring ca_bundle: + Path to the ca bundle to use when verifying SSL certificates. :returns: Value(s) of category_id. :rtype: list of str """ categories = None - client = _get_client(server, username, password) + client = _get_client(server, username, password, verify_ssl=verify_ssl, + ca_bundle=ca_bundle) if client: categories = client.tagging.Category.list() @@ -9998,7 +10202,8 @@ def list_tag_categories( @depends(HAS_PYVMOMI, HAS_VSPHERE_SDK) @supports_proxies("vcenter") @gets_service_instance_via_proxy -def list_tags(server=None, username=None, password=None, service_instance=None): +def list_tags(server=None, username=None, password=None, service_instance=None, + verify_ssl=True, ca_bundle=None): """ List existing tags a user has access to. @@ -10014,13 +10219,18 @@ def list_tags(server=None, username=None, password=None, service_instance=None): Username associated with the vCenter center. :param basestring password: Password associated with the vCenter center. + :param boolean verify_ssl: + Verify the SSL certificate. Default: True + :param basestring ca_bundle: + Path to the ca bundle to use when verifying SSL certificates. :return: Value(s) of tag_id. :rtype: list of str """ tags = None - client = _get_client(server, username, password) + client = _get_client(server, username, password, verify_ssl=verify_ssl, + ca_bundle=ca_bundle) if client: tags = client.tagging.Tag.list() @@ -10038,6 +10248,8 @@ def attach_tag( username=None, password=None, service_instance=None, + verify_ssl=True, + ca_bundle=None, ): """ Attach an existing tag to an input object. @@ -10070,6 +10282,10 @@ def attach_tag( Username associated with the vCenter center. :param basestring password: Password associated with the vCenter center. + :param boolean verify_ssl: + Verify the SSL certificate. Default: True + :param basestring ca_bundle: + Path to the ca bundle to use when verifying SSL certificates. :return: The list of all tag identifiers that correspond to the tags attached to the given object. @@ -10081,7 +10297,8 @@ def attach_tag( if the user can not be authenticated. """ tag_attached = None - client = _get_client(server, username, password) + client = _get_client(server, username, password, verify_ssl=verify_ssl, + ca_bundle=ca_bundle) if client: # Create dynamic id object associated with a type and an id. @@ -10114,6 +10331,8 @@ def list_attached_tags( username=None, password=None, service_instance=None, + verify_ssl=True, + ca_bundle=None, ): """ List existing tags a user has access to. @@ -10136,6 +10355,10 @@ def list_attached_tags( Username associated with the vCenter center. :param basestring password: Password associated with the vCenter center. + :param boolean verify_ssl: + Verify the SSL certificate. Default: True + :param basestring ca_bundle: + Path to the ca bundle to use when verifying SSL certificates. :return: The list of all tag identifiers that correspond to the tags attached to the given object. @@ -10147,7 +10370,8 @@ def list_attached_tags( if the user can not be authenticated. """ attached_tags = None - client = _get_client(server, username, password) + client = _get_client(server, username, password, verify_ssl=verify_ssl, + ca_bundle=ca_bundle) if client: # Create dynamic id object associated with a type and an id. @@ -10179,6 +10403,8 @@ def create_tag_category( username=None, password=None, service_instance=None, + verify_ssl=True, + ca_bundle=None, ): """ Create a category with given cardinality. @@ -10201,6 +10427,10 @@ def create_tag_category( Username associated with the vCenter center. :param basestring password: Password associated with the vCenter center. + :param boolean verify_ssl: + Verify the SSL certificate. Default: True + :param basestring ca_bundle: + Path to the ca bundle to use when verifying SSL certificates. :return: Identifier of the created category. :rtype: @@ -10214,7 +10444,8 @@ def create_tag_category( if you do not have the privilege to create a category. """ category_created = None - client = _get_client(server, username, password) + client = _get_client(server, username, password, verify_ssl=verify_ssl, + ca_bundle=ca_bundle) if client: if cardinality == "SINGLE": @@ -10245,7 +10476,8 @@ def create_tag_category( @supports_proxies("vcenter") @gets_service_instance_via_proxy def delete_tag_category( - category_id, server=None, username=None, password=None, service_instance=None + category_id, server=None, username=None, password=None, + service_instance=None, verify_ssl=True, ca_bundle=None ): """ Delete a category. @@ -10266,6 +10498,10 @@ def delete_tag_category( Username associated with the vCenter center. :param basestring password: Password associated with the vCenter center. + :param boolean verify_ssl: + Verify the SSL certificate. Default: True + :param basestring ca_bundle: + Path to the ca bundle to use when verifying SSL certificates. :raise: NotFound if the tag for the given tag_id does not exist in the system. :raise: Unauthorized @@ -10274,7 +10510,8 @@ def delete_tag_category( if the user can not be authenticated. """ category_deleted = None - client = _get_client(server, username, password) + client = _get_client(server, username, password, verify_ssl=verify_ssl, + ca_bundle=ca_bundle) if client: try: @@ -10298,6 +10535,8 @@ def create_tag( username=None, password=None, service_instance=None, + verify_ssl=True, + ca_bundle=None, ): """ Create a tag under a category with given description. @@ -10320,6 +10559,10 @@ def create_tag( Given description of tag category. :param str category_id: Value of category_id representative of the category created previously. + :param boolean verify_ssl: + Verify the SSL certificate. Default: True + :param basestring ca_bundle: + Path to the ca bundle to use when verifying SSL certificates. :return: The identifier of the created tag. :rtype: @@ -10336,7 +10579,8 @@ def create_tag( if you do not have the privilege to create tag. """ tag_created = None - client = _get_client(server, username, password) + client = _get_client(server, username, password, verify_ssl=verify_ssl, + ca_bundle=ca_bundle) if client: create_spec = client.tagging.Tag.CreateSpec() @@ -10357,7 +10601,8 @@ def create_tag( @supports_proxies("vcenter") @gets_service_instance_via_proxy def delete_tag( - tag_id, server=None, username=None, password=None, service_instance=None + tag_id, server=None, username=None, password=None, service_instance=None, + verify_ssl=True, ca_bundle=None ): """ Delete a tag. @@ -10378,6 +10623,10 @@ def delete_tag( Username associated with the vCenter center. :param basestring password: Password associated with the vCenter center. + :param boolean verify_ssl: + Verify the SSL certificate. Default: True + :param basestring ca_bundle: + Path to the ca bundle to use when verifying SSL certificates. :raise: AlreadyExists if the name provided in the create_spec is the name of an already existing category. @@ -10387,7 +10636,8 @@ def delete_tag( if you do not have the privilege to create a category. """ tag_deleted = None - client = _get_client(server, username, password) + client = _get_client(server, username, password, verify_ssl=verify_ssl, + ca_bundle=ca_bundle) if client: try: From 510141d9687b84778fa733495057940d787feaa0 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Thu, 17 Dec 2020 07:39:12 -0500 Subject: [PATCH 39/69] run pre-commit on modules/vsphere.py --- salt/modules/vsphere.py | 537 ++++++++++++++++++++++++++++------------ 1 file changed, 380 insertions(+), 157 deletions(-) diff --git a/salt/modules/vsphere.py b/salt/modules/vsphere.py index 9d05349813c..ec9d0995dc3 100644 --- a/salt/modules/vsphere.py +++ b/salt/modules/vsphere.py @@ -1721,8 +1721,7 @@ def get_ssh_key( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def get_host_datetime( - host, username, password, protocol=None, port=None, host_names=None, - verify_ssl=True + host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True ): """ Get the date/time information for a given host or list of host_names. @@ -1768,8 +1767,12 @@ def get_host_datetime( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -1784,8 +1787,9 @@ def get_host_datetime( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def get_ntp_config(host, username, password, protocol=None, port=None, - host_names=None, verify_ssl=True): +def get_ntp_config( + host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True +): """ Get the NTP configuration information for a given host or list of host_names. @@ -1830,8 +1834,12 @@ def get_ntp_config(host, username, password, protocol=None, port=None, host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -1846,8 +1854,14 @@ def get_ntp_config(host, username, password, protocol=None, port=None, @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def get_service_policy( - host, username, password, service_name, protocol=None, port=None, - host_names=None, verify_ssl=True, + host, + username, + password, + service_name, + protocol=None, + port=None, + host_names=None, + verify_ssl=True, ): """ Get the service name's policy for a given host or list of hosts. @@ -1909,8 +1923,12 @@ def get_service_policy( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) valid_services = [ "DCUI", @@ -1978,8 +1996,14 @@ def get_service_policy( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def get_service_running( - host, username, password, service_name, protocol=None, port=None, - host_names=None, verify_ssl=True, + host, + username, + password, + service_name, + protocol=None, + port=None, + host_names=None, + verify_ssl=True, ): """ Get the service name's running state for a given host or list of hosts. @@ -2041,8 +2065,12 @@ def get_service_running( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) valid_services = [ "DCUI", @@ -2110,7 +2138,12 @@ def get_service_running( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def get_vmotion_enabled( - host, username, password, protocol=None, port=None, host_names=None, + host, + username, + password, + protocol=None, + port=None, + host_names=None, verify_ssl=True, ): """ @@ -2158,8 +2191,12 @@ def get_vmotion_enabled( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -2177,7 +2214,12 @@ def get_vmotion_enabled( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def get_vsan_enabled( - host, username, password, protocol=None, port=None, host_names=None, + host, + username, + password, + protocol=None, + port=None, + host_names=None, verify_ssl=True, ): """ @@ -2226,8 +2268,12 @@ def get_vsan_enabled( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -2249,7 +2295,12 @@ def get_vsan_enabled( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def get_vsan_eligible_disks( - host, username, password, protocol=None, port=None, host_names=None, + host, + username, + password, + protocol=None, + port=None, + host_names=None, verify_ssl=True, ): """ @@ -2296,8 +2347,12 @@ def get_vsan_eligible_disks( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) response = _get_vsan_eligible_disks(service_instance, host, host_names) @@ -2349,8 +2404,9 @@ def test_vcenter_connection(service_instance=None): @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def system_info(host, username, password, protocol=None, port=None, - verify_ssl=True,): +def system_info( + host, username, password, protocol=None, port=None, verify_ssl=True, +): """ Return system information about a VMware environment. @@ -2381,8 +2437,12 @@ def system_info(host, username, password, protocol=None, port=None, salt '*' vsphere.system_info 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) ret = salt.utils.vmware.get_inventory(service_instance).about.__dict__ if "apiType" in ret: @@ -2395,8 +2455,9 @@ def system_info(host, username, password, protocol=None, port=None, @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_datacenters(host, username, password, protocol=None, port=None, - verify_ssl=True): +def list_datacenters( + host, username, password, protocol=None, port=None, verify_ssl=True +): """ Returns a list of datacenters for the specified host. @@ -2428,16 +2489,19 @@ def list_datacenters(host, username, password, protocol=None, port=None, """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) return salt.utils.vmware.list_datacenters(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_clusters(host, username, password, protocol=None, port=None, - verify_ssl=True): +def list_clusters(host, username, password, protocol=None, port=None, verify_ssl=True): """ Returns a list of clusters for the specified host. @@ -2469,16 +2533,21 @@ def list_clusters(host, username, password, protocol=None, port=None, """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) return salt.utils.vmware.list_clusters(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_datastore_clusters(host, username, password, protocol=None, port=None, - verify_ssl=True): +def list_datastore_clusters( + host, username, password, protocol=None, port=None, verify_ssl=True +): """ Returns a list of datastore clusters for the specified host. @@ -2509,16 +2578,21 @@ def list_datastore_clusters(host, username, password, protocol=None, port=None, salt '*' vsphere.list_datastore_clusters 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) return salt.utils.vmware.list_datastore_clusters(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_datastores(host, username, password, protocol=None, port=None, - verify_ssl=True): +def list_datastores( + host, username, password, protocol=None, port=None, verify_ssl=True +): """ Returns a list of datastores for the specified host. @@ -2549,16 +2623,19 @@ def list_datastores(host, username, password, protocol=None, port=None, salt '*' vsphere.list_datastores 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) return salt.utils.vmware.list_datastores(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_hosts(host, username, password, protocol=None, port=None, - verify_ssl=True): +def list_hosts(host, username, password, protocol=None, port=None, verify_ssl=True): """ Returns a list of hosts for the specified VMware environment. @@ -2589,16 +2666,21 @@ def list_hosts(host, username, password, protocol=None, port=None, salt '*' vsphere.list_hosts 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) return salt.utils.vmware.list_hosts(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_resourcepools(host, username, password, protocol=None, port=None, - verify_ssl=True): +def list_resourcepools( + host, username, password, protocol=None, port=None, verify_ssl=True +): """ Returns a list of resource pools for the specified host. @@ -2629,16 +2711,19 @@ def list_resourcepools(host, username, password, protocol=None, port=None, salt '*' vsphere.list_resourcepools 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) return salt.utils.vmware.list_resourcepools(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_networks(host, username, password, protocol=None, port=None, - verify_ssl=True): +def list_networks(host, username, password, protocol=None, port=None, verify_ssl=True): """ Returns a list of networks for the specified host. @@ -2669,16 +2754,19 @@ def list_networks(host, username, password, protocol=None, port=None, salt '*' vsphere.list_networks 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) return salt.utils.vmware.list_networks(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_vms(host, username, password, protocol=None, port=None, - verify_ssl=True): +def list_vms(host, username, password, protocol=None, port=None, verify_ssl=True): """ Returns a list of VMs for the specified host. @@ -2709,16 +2797,19 @@ def list_vms(host, username, password, protocol=None, port=None, salt '*' vsphere.list_vms 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) return salt.utils.vmware.list_vms(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_folders(host, username, password, protocol=None, port=None, - verify_ssl=True): +def list_folders(host, username, password, protocol=None, port=None, verify_ssl=True): """ Returns a list of folders for the specified host. @@ -2749,16 +2840,19 @@ def list_folders(host, username, password, protocol=None, port=None, salt '*' vsphere.list_folders 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) return salt.utils.vmware.list_folders(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_dvs(host, username, password, protocol=None, port=None, - verify_ssl=True): +def list_dvs(host, username, password, protocol=None, port=None, verify_ssl=True): """ Returns a list of distributed virtual switches for the specified host. @@ -2789,16 +2883,19 @@ def list_dvs(host, username, password, protocol=None, port=None, salt '*' vsphere.list_dvs 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) return salt.utils.vmware.list_dvs(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_vapps(host, username, password, protocol=None, port=None, - verify_ssl=True): +def list_vapps(host, username, password, protocol=None, port=None, verify_ssl=True): """ Returns a list of vApps for the specified host. @@ -2830,16 +2927,21 @@ def list_vapps(host, username, password, protocol=None, port=None, salt '*' vsphere.list_vapps 1.2.3.4 root bad-password """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) return salt.utils.vmware.list_vapps(service_instance) @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_ssds(host, username, password, protocol=None, port=None, - host_names=None, verify_ssl=True): +def list_ssds( + host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True +): """ Returns a list of SSDs for the given host or list of host_names. @@ -2884,8 +2986,12 @@ def list_ssds(host, username, password, protocol=None, port=None, host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -2902,8 +3008,9 @@ def list_ssds(host, username, password, protocol=None, port=None, @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def list_non_ssds(host, username, password, protocol=None, port=None, - host_names=None, verify_ssl=True): +def list_non_ssds( + host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True +): """ Returns a list of Non-SSD disks for the given host or list of host_names. @@ -2955,8 +3062,12 @@ def list_non_ssds(host, username, password, protocol=None, port=None, host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -2974,8 +3085,14 @@ def list_non_ssds(host, username, password, protocol=None, port=None, @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def set_ntp_config( - host, username, password, ntp_servers, protocol=None, port=None, - host_names=None, verify_ssl=True + host, + username, + password, + ntp_servers, + protocol=None, + port=None, + host_names=None, + verify_ssl=True, ): """ Set NTP configuration for a given host of list of host_names. @@ -3025,8 +3142,12 @@ def set_ntp_config( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) if not isinstance(ntp_servers, list): raise CommandExecutionError("'ntp_servers' must be a list.") @@ -3061,8 +3182,14 @@ def set_ntp_config( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def service_start( - host, username, password, service_name, protocol=None, port=None, - host_names=None, verify_ssl=True + host, + username, + password, + service_name, + protocol=None, + port=None, + host_names=None, + verify_ssl=True, ): """ Start the named service for the given host or list of hosts. @@ -3124,8 +3251,12 @@ def service_start( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) valid_services = [ @@ -3193,8 +3324,14 @@ def service_start( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def service_stop( - host, username, password, service_name, protocol=None, port=None, - host_names=None, verify_ssl=True, + host, + username, + password, + service_name, + protocol=None, + port=None, + host_names=None, + verify_ssl=True, ): """ Stop the named service for the given host or list of hosts. @@ -3256,8 +3393,12 @@ def service_stop( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) valid_services = [ @@ -3323,8 +3464,14 @@ def service_stop( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def service_restart( - host, username, password, service_name, protocol=None, port=None, - host_names=None, verify_ssl=True, + host, + username, + password, + service_name, + protocol=None, + port=None, + host_names=None, + verify_ssl=True, ): """ Restart the named service for the given host or list of hosts. @@ -3386,8 +3533,12 @@ def service_restart( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) valid_services = [ @@ -3463,7 +3614,7 @@ def set_service_policy( protocol=None, port=None, host_names=None, - verify_ssl=True + verify_ssl=True, ): """ Set the service name's policy for a given host or list of hosts. @@ -3528,8 +3679,12 @@ def set_service_policy( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) valid_services = [ @@ -3615,8 +3770,7 @@ def set_service_policy( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def update_host_datetime( - host, username, password, protocol=None, port=None, host_names=None, - verify_ssl=True + host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True ): """ Update the date/time on the given host or list of host_names. This function should be @@ -3663,8 +3817,12 @@ def update_host_datetime( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -3689,8 +3847,7 @@ def update_host_datetime( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def update_host_password( - host, username, password, new_password, protocol=None, port=None, - verify_ssl=True + host, username, password, new_password, protocol=None, port=None, verify_ssl=True ): """ Update the password for a given host. @@ -3728,8 +3885,12 @@ def update_host_password( """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) # Get LocalAccountManager object account_manager = salt.utils.vmware.get_inventory(service_instance).accountManager @@ -3759,8 +3920,7 @@ def update_host_password( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def vmotion_disable( - host, username, password, protocol=None, port=None, host_names=None, - verify_ssl=True + host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True ): """ Disable vMotion for a given host or list of host_names. @@ -3806,8 +3966,12 @@ def vmotion_disable( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -3832,8 +3996,14 @@ def vmotion_disable( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") def vmotion_enable( - host, username, password, protocol=None, port=None, host_names=None, - device="vmk0", verify_ssl=True + host, + username, + password, + protocol=None, + port=None, + host_names=None, + device="vmk0", + verify_ssl=True, ): """ Enable vMotion for a given host or list of host_names. @@ -3883,8 +4053,12 @@ def vmotion_enable( host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) ret = {} @@ -3908,8 +4082,9 @@ def vmotion_enable( @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def vsan_add_disks(host, username, password, protocol=None, port=None, - host_names=None, verify_ssl=True): +def vsan_add_disks( + host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True +): """ Add any VSAN-eligible disks to the VSAN System for the given host or list of host_names. @@ -3955,8 +4130,12 @@ def vsan_add_disks(host, username, password, protocol=None, port=None, host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) host_names = _check_hosts(service_instance, host, host_names) response = _get_vsan_eligible_disks(service_instance, host, host_names) @@ -4031,8 +4210,9 @@ def vsan_add_disks(host, username, password, protocol=None, port=None, @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def vsan_disable(host, username, password, protocol=None, port=None, - host_names=None, verify_ssl=True): +def vsan_disable( + host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True +): """ Disable VSAN for a given host or list of host_names. @@ -4077,8 +4257,12 @@ def vsan_disable(host, username, password, protocol=None, port=None, host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) # Create a VSAN Configuration Object and set the enabled attribute to True vsan_config = vim.vsan.host.ConfigInfo() @@ -4125,8 +4309,9 @@ def vsan_disable(host, username, password, protocol=None, port=None, @depends(HAS_PYVMOMI) @ignores_kwargs("credstore") -def vsan_enable(host, username, password, protocol=None, port=None, - host_names=None, verify_ssl=True): +def vsan_enable( + host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True +): """ Enable VSAN for a given host or list of host_names. @@ -4170,8 +4355,12 @@ def vsan_enable(host, username, password, protocol=None, port=None, host_names='[esxi-1.host.com, esxi-2.host.com]' """ service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) # Create a VSAN Configuration Object and set the enabled attribute to True vsan_config = vim.vsan.host.ConfigInfo() @@ -7830,8 +8019,12 @@ def add_host_to_dvs( ret["success"] = True ret["message"] = [] service_instance = salt.utils.vmware.get_service_instance( - host=host, username=username, password=password, protocol=protocol, - port=port, verify_ssl=verify_ssl, + host=host, + username=username, + password=password, + protocol=protocol, + port=port, + verify_ssl=verify_ssl, ) dvs = salt.utils.vmware._get_dvs(service_instance, dvs_name) if not dvs: @@ -10127,7 +10320,6 @@ def _get_client(server, username, password, verify_ssl=None, ca_bundle=None): username = details["username"] password = details["password"] - if verify_ssl is None: if details is None: details = __salt__["vcenter.get_details"]() @@ -10152,8 +10344,11 @@ def _get_client(server, username, password, verify_ssl=None, ca_bundle=None): # Establish connection with client client = salt.utils.vmware.get_vsphere_client( - server=server, username=username, password=password, - verify_ssl=verify_ssl, ca_bundle=ca_bundle, + server=server, + username=username, + password=password, + verify_ssl=verify_ssl, + ca_bundle=ca_bundle, ) # Will return None if utility function causes Unauthenticated error return client @@ -10163,8 +10358,12 @@ def _get_client(server, username, password, verify_ssl=None, ca_bundle=None): @supports_proxies("vcenter") @gets_service_instance_via_proxy def list_tag_categories( - server=None, username=None, password=None, service_instance=None, - verify_ssl=True, ca_bundle=None + server=None, + username=None, + password=None, + service_instance=None, + verify_ssl=True, + ca_bundle=None, ): """ List existing categories a user has access to. @@ -10191,8 +10390,9 @@ def list_tag_categories( list of str """ categories = None - client = _get_client(server, username, password, verify_ssl=verify_ssl, - ca_bundle=ca_bundle) + client = _get_client( + server, username, password, verify_ssl=verify_ssl, ca_bundle=ca_bundle + ) if client: categories = client.tagging.Category.list() @@ -10202,8 +10402,14 @@ def list_tag_categories( @depends(HAS_PYVMOMI, HAS_VSPHERE_SDK) @supports_proxies("vcenter") @gets_service_instance_via_proxy -def list_tags(server=None, username=None, password=None, service_instance=None, - verify_ssl=True, ca_bundle=None): +def list_tags( + server=None, + username=None, + password=None, + service_instance=None, + verify_ssl=True, + ca_bundle=None, +): """ List existing tags a user has access to. @@ -10229,8 +10435,9 @@ def list_tags(server=None, username=None, password=None, service_instance=None, list of str """ tags = None - client = _get_client(server, username, password, verify_ssl=verify_ssl, - ca_bundle=ca_bundle) + client = _get_client( + server, username, password, verify_ssl=verify_ssl, ca_bundle=ca_bundle + ) if client: tags = client.tagging.Tag.list() @@ -10297,8 +10504,9 @@ def attach_tag( if the user can not be authenticated. """ tag_attached = None - client = _get_client(server, username, password, verify_ssl=verify_ssl, - ca_bundle=ca_bundle) + client = _get_client( + server, username, password, verify_ssl=verify_ssl, ca_bundle=ca_bundle + ) if client: # Create dynamic id object associated with a type and an id. @@ -10370,8 +10578,9 @@ def list_attached_tags( if the user can not be authenticated. """ attached_tags = None - client = _get_client(server, username, password, verify_ssl=verify_ssl, - ca_bundle=ca_bundle) + client = _get_client( + server, username, password, verify_ssl=verify_ssl, ca_bundle=ca_bundle + ) if client: # Create dynamic id object associated with a type and an id. @@ -10444,8 +10653,9 @@ def create_tag_category( if you do not have the privilege to create a category. """ category_created = None - client = _get_client(server, username, password, verify_ssl=verify_ssl, - ca_bundle=ca_bundle) + client = _get_client( + server, username, password, verify_ssl=verify_ssl, ca_bundle=ca_bundle + ) if client: if cardinality == "SINGLE": @@ -10476,8 +10686,13 @@ def create_tag_category( @supports_proxies("vcenter") @gets_service_instance_via_proxy def delete_tag_category( - category_id, server=None, username=None, password=None, - service_instance=None, verify_ssl=True, ca_bundle=None + category_id, + server=None, + username=None, + password=None, + service_instance=None, + verify_ssl=True, + ca_bundle=None, ): """ Delete a category. @@ -10510,8 +10725,9 @@ def delete_tag_category( if the user can not be authenticated. """ category_deleted = None - client = _get_client(server, username, password, verify_ssl=verify_ssl, - ca_bundle=ca_bundle) + client = _get_client( + server, username, password, verify_ssl=verify_ssl, ca_bundle=ca_bundle + ) if client: try: @@ -10579,8 +10795,9 @@ def create_tag( if you do not have the privilege to create tag. """ tag_created = None - client = _get_client(server, username, password, verify_ssl=verify_ssl, - ca_bundle=ca_bundle) + client = _get_client( + server, username, password, verify_ssl=verify_ssl, ca_bundle=ca_bundle + ) if client: create_spec = client.tagging.Tag.CreateSpec() @@ -10601,8 +10818,13 @@ def create_tag( @supports_proxies("vcenter") @gets_service_instance_via_proxy def delete_tag( - tag_id, server=None, username=None, password=None, service_instance=None, - verify_ssl=True, ca_bundle=None + tag_id, + server=None, + username=None, + password=None, + service_instance=None, + verify_ssl=True, + ca_bundle=None, ): """ Delete a tag. @@ -10636,8 +10858,9 @@ def delete_tag( if you do not have the privilege to create a category. """ tag_deleted = None - client = _get_client(server, username, password, verify_ssl=verify_ssl, - ca_bundle=ca_bundle) + client = _get_client( + server, username, password, verify_ssl=verify_ssl, ca_bundle=ca_bundle + ) if client: try: From 08d8ff148f7c0e61054cb93dfaf6ce482f40f41a Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Thu, 17 Dec 2020 07:47:03 -0500 Subject: [PATCH 40/69] Default vmware pillar to verify SSL --- salt/pillar/vmware_pillar.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/salt/pillar/vmware_pillar.py b/salt/pillar/vmware_pillar.py index a33b3945005..7cfda8940b4 100644 --- a/salt/pillar/vmware_pillar.py +++ b/salt/pillar/vmware_pillar.py @@ -370,7 +370,8 @@ def ext_pillar(minion_id, pillar, **kwargs): # pylint: disable=W0613 vmware_pillar[pillar_key] = {} try: _conn = salt.utils.vmware.get_service_instance( - host, username, password, protocol, port + host, username, password, protocol, port, + verify_ssl=kwargs.get("verify_ssl", True) ) if _conn: data = None From 37cce5830de4803d14da335c5ce6b15ebd00f8a5 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Thu, 17 Dec 2020 07:47:25 -0500 Subject: [PATCH 41/69] run pre-commit on pillar/vmware_pillar.py --- salt/pillar/vmware_pillar.py | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/salt/pillar/vmware_pillar.py b/salt/pillar/vmware_pillar.py index 7cfda8940b4..08bdb18e568 100644 --- a/salt/pillar/vmware_pillar.py +++ b/salt/pillar/vmware_pillar.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Pillar data from vCenter or an ESXi host @@ -142,18 +141,12 @@ Optionally, the following keyword arguments can be passed to the ext_pillar for part of the pillar regardless of this setting. """ -from __future__ import absolute_import, print_function, unicode_literals -# Import python libs import logging -# Import salt libs import salt.utils.dictupdate as dictupdate import salt.utils.vmware -# Import 3rd-party libs -from salt.ext import six - try: # pylint: disable=no-name-in-module from pyVmomi import vim @@ -370,8 +363,12 @@ def ext_pillar(minion_id, pillar, **kwargs): # pylint: disable=W0613 vmware_pillar[pillar_key] = {} try: _conn = salt.utils.vmware.get_service_instance( - host, username, password, protocol, port, - verify_ssl=kwargs.get("verify_ssl", True) + host, + username, + password, + protocol, + port, + verify_ssl=kwargs.get("verify_ssl", True), ) if _conn: data = None @@ -411,12 +408,10 @@ def ext_pillar(minion_id, pillar, **kwargs): # pylint: disable=W0613 ) except RuntimeError: log.error( - ( - "A runtime error occurred in the vmware_pillar, " - "this is likely caused by an infinite recursion in " - "a requested attribute. Verify your requested attributes " - "and reconfigure the pillar." - ) + "A runtime error occurred in the vmware_pillar, " + "this is likely caused by an infinite recursion in " + "a requested attribute. Verify your requested attributes " + "and reconfigure the pillar." ) return vmware_pillar @@ -436,7 +431,7 @@ def _recurse_config_to_dict(t_data): return t_list elif isinstance(t_data, dict): t_dict = {} - for k, v in six.iteritems(t_data): + for k, v in t_data.items(): t_dict[k] = _recurse_config_to_dict(v) return t_dict else: From 2da4b0fc86d4b9f040612fc6ed5455a5ca0b284c Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Thu, 17 Dec 2020 09:07:21 -0500 Subject: [PATCH 42/69] Default vmware proxy to verify SSL --- salt/config/schemas/vcenter.py | 4 +++- salt/proxy/vcenter.py | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/salt/config/schemas/vcenter.py b/salt/config/schemas/vcenter.py index 7db8b67c417..a19e59ee5ed 100644 --- a/salt/config/schemas/vcenter.py +++ b/salt/config/schemas/vcenter.py @@ -13,7 +13,7 @@ from __future__ import absolute_import, print_function, unicode_literals # Import Salt libs -from salt.utils.schema import ArrayItem, IntegerItem, Schema, StringItem +from salt.utils.schema import ArrayItem, IntegerItem, Schema, StringItem, BooleanItem class VCenterEntitySchema(Schema): @@ -48,6 +48,8 @@ class VCenterProxySchema(Schema): mechanism = StringItem(required=True, enum=["userpass", "sspi"]) username = StringItem() passwords = ArrayItem(min_items=1, items=StringItem(), unique_items=True) + verify_ssl = BooleanItem() + ca_bundle = StringItem() domain = StringItem() principal = StringItem(default="host") diff --git a/salt/proxy/vcenter.py b/salt/proxy/vcenter.py index fa1d090bd21..6794a307aaa 100644 --- a/salt/proxy/vcenter.py +++ b/salt/proxy/vcenter.py @@ -277,6 +277,8 @@ def init(opts): # Save optional DETAILS["protocol"] = proxy_conf.get("protocol") DETAILS["port"] = proxy_conf.get("port") + DETAILS["verify_ssl"] = proxy_conf.get("verify_ssl") + DETAILS["ca_bundle"] = proxy_conf.get("ca_bundle") # Test connection if DETAILS["mechanism"] == "userpass": From 2a3ebba8051f4a21343b18541dd6a98fc01638f2 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Thu, 17 Dec 2020 09:07:53 -0500 Subject: [PATCH 43/69] run pre-commit on config/schemas/vcenter.py and proxy/vcenter.py --- salt/config/schemas/vcenter.py | 6 +----- salt/proxy/vcenter.py | 4 ---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/salt/config/schemas/vcenter.py b/salt/config/schemas/vcenter.py index a19e59ee5ed..bd82bd17615 100644 --- a/salt/config/schemas/vcenter.py +++ b/salt/config/schemas/vcenter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ :codeauthor: :email:`Rod McKenzie (roderick.mckenzie@morganstanley.com)` :codeauthor: :email:`Alexandru Bleotu (alexandru.bleotu@morganstanley.com)` @@ -9,11 +8,8 @@ VCenter configuration schemas """ -# Import Python libs -from __future__ import absolute_import, print_function, unicode_literals -# Import Salt libs -from salt.utils.schema import ArrayItem, IntegerItem, Schema, StringItem, BooleanItem +from salt.utils.schema import ArrayItem, BooleanItem, IntegerItem, Schema, StringItem class VCenterEntitySchema(Schema): diff --git a/salt/proxy/vcenter.py b/salt/proxy/vcenter.py index 6794a307aaa..4bbdb0ee669 100644 --- a/salt/proxy/vcenter.py +++ b/salt/proxy/vcenter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Proxy Minion interface module for managing VMWare vCenters. @@ -182,13 +181,10 @@ and that host would reach out over the network and communicate with the ESXi host. """ -# Import Python Libs -from __future__ import absolute_import, print_function, unicode_literals import logging import os -# Import Salt Libs import salt.exceptions from salt.config.schemas.vcenter import VCenterProxySchema from salt.utils.dictupdate import merge From 1777d58935e729c000a9f30f3643c4ebfbec25bb Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Thu, 17 Dec 2020 09:11:00 -0500 Subject: [PATCH 44/69] Validate vmware cloud defaults to verifying SSL --- tests/integration/cloud/clouds/test_vmware.py | 16 ++++++++++++++++ .../integration/cloud/helpers/cloud_test_base.py | 15 +++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/tests/integration/cloud/clouds/test_vmware.py b/tests/integration/cloud/clouds/test_vmware.py index a22c79950ca..29edbcf1139 100644 --- a/tests/integration/cloud/clouds/test_vmware.py +++ b/tests/integration/cloud/clouds/test_vmware.py @@ -72,3 +72,19 @@ class VMWareTest(CloudTest): self.assertIn(s_ret_str, six.text_type(create_snapshot)) self.assertDestroyInstance() + + def test_verify_ssl_false(self): + """ + Tests creating and deleting an instance on vmware when using + verify_ssl: False + """ + profile_name = "vmware_verify_ssl" + self.add_profile_config("vmware-test", {"verify_ssl": False,}, + "vmware.conf", profile_name) + # create the instance + ret_val = self.run_cloud( + "-p {} {}".format(profile_name, self.instance_name), timeout=TIMEOUT + ) + # check if instance returned with salt installed + self.assertInstanceExists(ret_val) + self.assertDestroyInstance() diff --git a/tests/integration/cloud/helpers/cloud_test_base.py b/tests/integration/cloud/helpers/cloud_test_base.py index b8b154f5740..9210e04571d 100644 --- a/tests/integration/cloud/helpers/cloud_test_base.py +++ b/tests/integration/cloud/helpers/cloud_test_base.py @@ -11,6 +11,7 @@ from time import sleep from salt.config import cloud_config, cloud_providers_config from salt.ext.six.moves import range from salt.utils.yaml import safe_load +import salt.utils.verify from tests.support.case import ShellCase from tests.support.helpers import expensiveTest, random_string from tests.support.paths import FILES @@ -195,6 +196,20 @@ class CloudTest(ShellCase): def profile_str(self): return self.PROVIDER + "-config" + def add_profile_config(self, name, data, conf, new_profile): + """ + copy the current profile and add a new profile in the same file + """ + conf_path = os.path.join( + RUNTIME_VARS.TMP_CONF_DIR, "cloud.profiles.d", conf + ) + with salt.utils.files.fopen(conf_path, "r") as fp: + conf = safe_load(fp) + conf[new_profile] = conf[name].copy() + conf[new_profile].update(data) + with salt.utils.files.fopen(conf_path, "w") as fp: + salt.utils.yaml.safe_dump(conf, fp) + def setUp(self): """ Sets up the test requirements. In child classes, define PROVIDER and REQUIRED_PROVIDER_CONFIG_ITEMS or this will fail From 605761d0ed6830c0c2d3a5f5e0205f41c7401337 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Thu, 17 Dec 2020 09:12:04 -0500 Subject: [PATCH 45/69] run pre-commit on test_vmware.py and cloud_test_base.py --- tests/integration/cloud/clouds/test_vmware.py | 25 +++++++------------ .../cloud/helpers/cloud_test_base.py | 6 ++--- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/tests/integration/cloud/clouds/test_vmware.py b/tests/integration/cloud/clouds/test_vmware.py index 29edbcf1139..9119ac5905f 100644 --- a/tests/integration/cloud/clouds/test_vmware.py +++ b/tests/integration/cloud/clouds/test_vmware.py @@ -1,14 +1,6 @@ -# -*- coding: utf-8 -*- """ :codeauthor: Megan Wilhite """ - -# Import Python Libs -from __future__ import absolute_import, print_function, unicode_literals - -# Import Salt Libs -from salt.ext import six - # Create the cloud instance name to be used throughout the tests from tests.integration.cloud.helpers.cloud_test_base import TIMEOUT, CloudTest @@ -31,9 +23,9 @@ class VMWareTest(CloudTest): ] ret_val = self.run_cloud( - "-p vmware-test {0}".format(self.instance_name), timeout=TIMEOUT + "-p vmware-test {}".format(self.instance_name), timeout=TIMEOUT ) - disk_datastore_str = " [{0}] {1}/Hard disk 2-flat.vmdk".format( + disk_datastore_str = " [{}] {}/Hard disk 2-flat.vmdk".format( disk_datastore, self.instance_name ) @@ -42,7 +34,7 @@ class VMWareTest(CloudTest): self.assertIn( disk_datastore_str, ret_val, - msg="Hard Disk 2 did not use the Datastore {0} ".format(disk_datastore), + msg="Hard Disk 2 did not use the Datastore {} ".format(disk_datastore), ) self.assertDestroyInstance() @@ -53,14 +45,14 @@ class VMWareTest(CloudTest): """ # create the instance ret_val = self.run_cloud( - "-p vmware-test {0} --no-deploy".format(self.instance_name), timeout=TIMEOUT + "-p vmware-test {} --no-deploy".format(self.instance_name), timeout=TIMEOUT ) # check if instance returned with salt installed self.assertInstanceExists(ret_val) create_snapshot = self.run_cloud( - "-a create_snapshot {0} \ + "-a create_snapshot {} \ snapshot_name='Test Cloud' \ memdump=True -y".format( self.instance_name @@ -69,7 +61,7 @@ class VMWareTest(CloudTest): ) s_ret_str = "Snapshot created successfully" - self.assertIn(s_ret_str, six.text_type(create_snapshot)) + self.assertIn(s_ret_str, str(create_snapshot)) self.assertDestroyInstance() @@ -79,8 +71,9 @@ class VMWareTest(CloudTest): verify_ssl: False """ profile_name = "vmware_verify_ssl" - self.add_profile_config("vmware-test", {"verify_ssl": False,}, - "vmware.conf", profile_name) + self.add_profile_config( + "vmware-test", {"verify_ssl": False}, "vmware.conf", profile_name + ) # create the instance ret_val = self.run_cloud( "-p {} {}".format(profile_name, self.instance_name), timeout=TIMEOUT diff --git a/tests/integration/cloud/helpers/cloud_test_base.py b/tests/integration/cloud/helpers/cloud_test_base.py index 9210e04571d..f73152526fd 100644 --- a/tests/integration/cloud/helpers/cloud_test_base.py +++ b/tests/integration/cloud/helpers/cloud_test_base.py @@ -8,10 +8,10 @@ import os import shutil from time import sleep +import salt.utils.verify from salt.config import cloud_config, cloud_providers_config from salt.ext.six.moves import range from salt.utils.yaml import safe_load -import salt.utils.verify from tests.support.case import ShellCase from tests.support.helpers import expensiveTest, random_string from tests.support.paths import FILES @@ -200,9 +200,7 @@ class CloudTest(ShellCase): """ copy the current profile and add a new profile in the same file """ - conf_path = os.path.join( - RUNTIME_VARS.TMP_CONF_DIR, "cloud.profiles.d", conf - ) + conf_path = os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "cloud.profiles.d", conf) with salt.utils.files.fopen(conf_path, "r") as fp: conf = safe_load(fp) conf[new_profile] = conf[name].copy() From 46cd3263f967ea5b09b881caf56cf525091d35f1 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Thu, 17 Dec 2020 10:59:06 -0500 Subject: [PATCH 46/69] Validate vmware module defaults to verifying SSL --- .pre-commit-config.yaml | 20 +++- requirements/static/ci/git-sources.txt | 1 + requirements/static/ci/py3.5/linux.txt | 4 +- requirements/static/ci/py3.6/linux.txt | 4 +- requirements/static/ci/py3.7/linux.txt | 4 +- requirements/static/ci/py3.8/linux.txt | 4 +- requirements/static/ci/py3.9/linux.txt | 4 +- tests/pytests/unit/utils/test_http.py | 52 +++++++++ tests/unit/modules/test_vsphere.py | 111 ++++++++++++++++++ tests/unit/utils/test_vmware.py | 150 +++++++++++-------------- 10 files changed, 261 insertions(+), 93 deletions(-) create mode 100644 requirements/static/ci/git-sources.txt create mode 100644 tests/pytests/unit/utils/test_http.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 65b4fff1ff0..4c561092be0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -277,7 +277,7 @@ repos: - id: pip-tools-compile alias: compile-ci-linux-py3.5-zmq-requirements name: Linux CI Py3.5 ZeroMQ Requirements - files: ^requirements/((base|zeromq|pytest)\.txt|static/((ci|pkg)/linux\.in|pkg/py3\.5/linux\.txt))$ + files: ^requirements/((base|zeromq|pytest)\.txt|static/((ci|pkg)/(linux\.in|git-sources\.txt)|pkg/py3\.5/linux\.txt))$ pass_filenames: false args: - -v @@ -285,12 +285,14 @@ repos: - --platform=linux - --include=requirements/static/pkg/py{py_version}/linux.txt - --include=requirements/pytest.txt + - --include=requirements/static/ci/git-sources.txt + - --passthrough-line-from-input=^git\+https(.*)$ - requirements/static/ci/linux.in - id: pip-tools-compile alias: compile-ci-linux-py3.6-zmq-requirements name: Linux CI Py3.6 ZeroMQ Requirements - files: ^requirements/((base|zeromq|pytest)\.txt|static/((ci|pkg)/linux\.in|pkg/py3\.6/linux\.txt))$ + files: ^requirements/((base|zeromq|pytest)\.txt|static/((ci|pkg)/(linux\.in|git-sources\.txt)|pkg/py3\.6/linux\.txt))$ pass_filenames: false args: - -v @@ -298,12 +300,14 @@ repos: - --platform=linux - --include=requirements/static/pkg/py{py_version}/linux.txt - --include=requirements/pytest.txt + - --include=requirements/static/ci/git-sources.txt + - --passthrough-line-from-input=^git\+https(.*)$ - requirements/static/ci/linux.in - id: pip-tools-compile alias: compile-ci-linux-py3.7-zmq-requirements name: Linux CI Py3.7 ZeroMQ Requirements - files: ^requirements/((base|zeromq|pytest)\.txt|static/((ci|pkg)/linux\.in|pkg/py3\.7/linux\.txt))$ + files: ^requirements/((base|zeromq|pytest)\.txt|static/((ci|pkg)/(linux\.in|git-sources\.txt)|pkg/py3\.7/linux\.txt))$ pass_filenames: false args: - -v @@ -311,12 +315,14 @@ repos: - --platform=linux - --include=requirements/static/pkg/py{py_version}/linux.txt - --include=requirements/pytest.txt + - --include=requirements/static/ci/git-sources.txt + - --passthrough-line-from-input=^git\+https(.*)$ - requirements/static/ci/linux.in - id: pip-tools-compile alias: compile-ci-linux-py3.8-zmq-requirements name: Linux CI Py3.8 ZeroMQ Requirements - files: ^requirements/((base|zeromq|pytest)\.txt|static/((ci|pkg)/linux\.in|pkg/py3\.8/linux\.txt))$ + files: ^requirements/((base|zeromq|pytest)\.txt|static/((ci|pkg)/(linux\.in|git-sources\.txt)|pkg/py3\.8/linux\.txt))$ pass_filenames: false args: - -v @@ -324,12 +330,14 @@ repos: - --platform=linux - --include=requirements/static/pkg/py{py_version}/linux.txt - --include=requirements/pytest.txt + - --include=requirements/static/ci/git-sources.txt + - --passthrough-line-from-input=^git\+https(.*)$ - requirements/static/ci/linux.in - id: pip-tools-compile alias: compile-ci-linux-py3.9-zmq-requirements name: Linux CI Py3.9 ZeroMQ Requirements - files: ^requirements/((base|zeromq|pytest)\.txt|static/((ci|pkg)/linux\.in|pkg/py3\.9/linux\.txt))$ + files: ^requirements/((base|zeromq|pytest)\.txt|static/((ci|pkg)/(linux\.in|git-sources\.txt)|pkg/py3\.9/linux\.txt))$ pass_filenames: false args: - -v @@ -337,6 +345,8 @@ repos: - --platform=linux - --include=requirements/static/pkg/py{py_version}/linux.txt - --include=requirements/pytest.txt + - --include=requirements/static/ci/git-sources.txt + - --passthrough-line-from-input=^git\+https(.*)$ - requirements/static/ci/linux.in - id: pip-tools-compile diff --git a/requirements/static/ci/git-sources.txt b/requirements/static/ci/git-sources.txt new file mode 100644 index 00000000000..7ef76a47d08 --- /dev/null +++ b/requirements/static/ci/git-sources.txt @@ -0,0 +1 @@ +git+https://github.com/vmware/vsphere-automation-sdk-python.git diff --git a/requirements/static/ci/py3.5/linux.txt b/requirements/static/ci/py3.5/linux.txt index c6b57bf491e..9439fd12cb6 100644 --- a/requirements/static/ci/py3.5/linux.txt +++ b/requirements/static/ci/py3.5/linux.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile # To update, run: # -# pip-compile -o requirements/static/ci/py3.5/linux.txt -v requirements/static/pkg/py3.5/linux.txt requirements/pytest.txt requirements/static/ci/linux.in +# pip-compile -o requirements/static/ci/py3.5/linux.txt -v requirements/static/pkg/py3.5/linux.txt requirements/pytest.txt requirements/static/ci/git-sources.txt requirements/static/ci/linux.in # adal==1.2.3 # via azure-datalake-store, msrestazure apache-libcloud==2.0.0 @@ -225,3 +225,5 @@ xmltodict==0.12.0 # via moto yamlordereddictloader==0.4.0 # via junos-eznc zc.lockfile==1.4 zipp==0.6.0 # via importlib-metadata, importlib-resources +# Passthrough dependencies from requirements/static/ci/git-sources.txt +git+https://github.com/vmware/vsphere-automation-sdk-python.git diff --git a/requirements/static/ci/py3.6/linux.txt b/requirements/static/ci/py3.6/linux.txt index 3317837a35a..c67a25cc11e 100644 --- a/requirements/static/ci/py3.6/linux.txt +++ b/requirements/static/ci/py3.6/linux.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile # To update, run: # -# pip-compile -o requirements/static/ci/py3.6/linux.txt -v requirements/static/pkg/py3.6/linux.txt requirements/pytest.txt requirements/static/ci/linux.in +# pip-compile -o requirements/static/ci/py3.6/linux.txt -v requirements/static/pkg/py3.6/linux.txt requirements/pytest.txt requirements/static/ci/git-sources.txt requirements/static/ci/linux.in # adal==1.2.3 # via azure-datalake-store, msrestazure apache-libcloud==2.0.0 @@ -229,3 +229,5 @@ xmltodict==0.12.0 # via moto yamlordereddictloader==0.4.0 # via junos-eznc zc.lockfile==1.4 zipp==0.6.0 # via importlib-metadata, importlib-resources +# Passthrough dependencies from requirements/static/ci/git-sources.txt +git+https://github.com/vmware/vsphere-automation-sdk-python.git diff --git a/requirements/static/ci/py3.7/linux.txt b/requirements/static/ci/py3.7/linux.txt index 9c6a5139b2f..87131756346 100644 --- a/requirements/static/ci/py3.7/linux.txt +++ b/requirements/static/ci/py3.7/linux.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile # To update, run: # -# pip-compile -o requirements/static/ci/py3.7/linux.txt -v requirements/static/pkg/py3.7/linux.txt requirements/pytest.txt requirements/static/ci/linux.in +# pip-compile -o requirements/static/ci/py3.7/linux.txt -v requirements/static/pkg/py3.7/linux.txt requirements/pytest.txt requirements/static/ci/git-sources.txt requirements/static/ci/linux.in # adal==1.2.3 # via azure-datalake-store, msrestazure apache-libcloud==2.0.0 @@ -227,3 +227,5 @@ xmltodict==0.12.0 # via moto yamlordereddictloader==0.4.0 # via junos-eznc zc.lockfile==1.4 zipp==0.6.0 # via importlib-metadata +# Passthrough dependencies from requirements/static/ci/git-sources.txt +git+https://github.com/vmware/vsphere-automation-sdk-python.git diff --git a/requirements/static/ci/py3.8/linux.txt b/requirements/static/ci/py3.8/linux.txt index 9ae7e8957e6..6229a118575 100644 --- a/requirements/static/ci/py3.8/linux.txt +++ b/requirements/static/ci/py3.8/linux.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile # To update, run: # -# pip-compile -o requirements/static/ci/py3.8/linux.txt -v requirements/static/pkg/py3.8/linux.txt requirements/pytest.txt requirements/static/ci/linux.in +# pip-compile -o requirements/static/ci/py3.8/linux.txt -v requirements/static/pkg/py3.8/linux.txt requirements/pytest.txt requirements/static/ci/git-sources.txt requirements/static/ci/linux.in # adal==1.2.3 # via azure-datalake-store, msrestazure apache-libcloud==2.0.0 @@ -226,3 +226,5 @@ wrapt==1.11.1 # via aws-xray-sdk xmltodict==0.12.0 # via moto yamlordereddictloader==0.4.0 # via junos-eznc zc.lockfile==1.4 +# Passthrough dependencies from requirements/static/ci/git-sources.txt +git+https://github.com/vmware/vsphere-automation-sdk-python.git diff --git a/requirements/static/ci/py3.9/linux.txt b/requirements/static/ci/py3.9/linux.txt index ae6683ea037..f85ebe7fe67 100644 --- a/requirements/static/ci/py3.9/linux.txt +++ b/requirements/static/ci/py3.9/linux.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile # To update, run: # -# pip-compile -o requirements/static/ci/py3.9/linux.txt -v requirements/static/pkg/py3.9/linux.txt requirements/pytest.txt requirements/static/ci/linux.in +# pip-compile -o requirements/static/ci/py3.9/linux.txt -v requirements/static/pkg/py3.9/linux.txt requirements/pytest.txt requirements/static/ci/git-sources.txt requirements/static/ci/linux.in # adal==1.2.3 # via azure-datalake-store, msrestazure apache-libcloud==2.0.0 @@ -226,3 +226,5 @@ wrapt==1.11.1 # via aws-xray-sdk xmltodict==0.12.0 # via moto yamlordereddictloader==0.4.0 # via junos-eznc zc.lockfile==1.4 +# Passthrough dependencies from requirements/static/ci/git-sources.txt +git+https://github.com/vmware/vsphere-automation-sdk-python.git diff --git a/tests/pytests/unit/utils/test_http.py b/tests/pytests/unit/utils/test_http.py new file mode 100644 index 00000000000..246416d92fc --- /dev/null +++ b/tests/pytests/unit/utils/test_http.py @@ -0,0 +1,52 @@ +import pytest +import requests +import salt.utils.http +from tests.support.mock import MagicMock, patch + + +def test_requests_session_verify_ssl_false(ssl_webserver, integration_files_dir): + """ + test salt.utils.http.session when using verify_ssl + """ + for verify in [True, False, None]: + kwargs = {"verify_ssl": verify} + if verify is None: + kwargs.pop("verify_ssl") + + if verify is True or verify is None: + with pytest.raises(requests.exceptions.SSLError) as excinfo: + session = salt.utils.http.session(**kwargs) + ret = session.get(ssl_webserver.url("this.txt")) + else: + session = salt.utils.http.session(**kwargs) + ret = session.get(ssl_webserver.url("this.txt")) + assert ret.status_code == 200 + + +def test_session_ca_bundle_verify_false(): + """ + test salt.utils.http.session when using + both ca_bunlde and verify_ssl false + """ + ret = salt.utils.http.session(ca_bundle="/tmp/test_bundle", verify_ssl=False) + assert ret is False + + +def test_session_headers(): + """ + test salt.utils.http.session when setting + headers + """ + ret = salt.utils.http.session(headers={"Content-Type": "application/json"}) + assert ret.headers["Content-Type"] == "application/json" + + +def test_session_ca_bundle(): + """ + test salt.utils.https.session when setting ca_bundle + """ + fpath = "/tmp/test_bundle" + patch_os = patch("os.path.exists", MagicMock(return_value=True)) + with patch_os: + ret = salt.utils.http.session(ca_bundle=fpath) + assert ret.verify == fpath diff --git a/tests/unit/modules/test_vsphere.py b/tests/unit/modules/test_vsphere.py index 14a1e6d923d..394f05f507f 100644 --- a/tests/unit/modules/test_vsphere.py +++ b/tests/unit/modules/test_vsphere.py @@ -3160,6 +3160,116 @@ class TestVSphereTagging(TestCase, LoaderModuleMockMixin): {"Tag attached": self.list_attached_tags_return}, ) + def test_get_client(self): + """ + test get_client when verify_ssl and ca_bundle are not passed + """ + mock_client = MagicMock(return_value=None) + patch_client = patch("salt.utils.vmware.get_vsphere_client", + mock_client) + + cert_path="/test/ca-certificates.crt" + mock_ca = MagicMock(return_value=cert_path) + patch_ca = patch("salt.utils.http.get_ca_bundle", mock_ca) + + mock_details = MagicMock(return_value=self.details) + patch_details = patch.dict(vsphere.__salt__, {"vcenter.get_details": + mock_details}) + + with patch_client, patch_ca, patch_details: + vsphere._get_client(server='localhost', username='testuser', + password='testpassword') + self.assertEqual(mock_client.call_args_list, + [call(ca_bundle=cert_path, + password='testpassword', server='localhost', + username='testuser', verify_ssl=True)]) + self.assertEqual(mock_details.assert_called_once(), None) + self.assertEqual(mock_ca.assert_called_once(), None) + + def test_get_client_verify_ssl_false(self): + """ + test get_client when verify_ssl=False is set + """ + details = self.details.copy() + details["verify_ssl"] = False + mock_client = MagicMock(return_value=None) + patch_client = patch("salt.utils.vmware.get_vsphere_client", + mock_client) + + cert_path="/test/ca-certificates.crt" + mock_ca = MagicMock(return_value=cert_path) + patch_ca = patch("salt.utils.http.get_ca_bundle", mock_ca) + + mock_details = MagicMock(return_value=details) + patch_details = patch.dict(vsphere.__salt__, {"vcenter.get_details": + mock_details}) + + with patch_client, patch_ca, patch_details: + vsphere._get_client(server='localhost', username='testuser', + password='testpassword') + self.assertEqual(mock_client.call_args_list, + [call(ca_bundle=None, + password='testpassword', server='localhost', + username='testuser', verify_ssl=False)]) + self.assertEqual(mock_details.assert_called_once(), None) + self.assertEqual(mock_ca.assert_not_called(), None) + + def test_get_client_verify_ssl_false_ca_bundle(self): + """ + test get_client when verify_ssl=False and ca_bundle set + """ + details = self.details.copy() + details["verify_ssl"] = False + details["ca_bundle"] = '/tmp/test' + mock_client = MagicMock(return_value=None) + patch_client = patch("salt.utils.vmware.get_vsphere_client", + mock_client) + + cert_path="/test/ca-certificates.crt" + mock_ca = MagicMock(return_value=cert_path) + patch_ca = patch("salt.utils.http.get_ca_bundle", mock_ca) + + mock_details = MagicMock(return_value=details) + patch_details = patch.dict(vsphere.__salt__, {"vcenter.get_details": + mock_details}) + + with patch_client, patch_ca, patch_details: + self.assertFalse(vsphere._get_client(server='localhost', username='testuser', + password='testpassword')) + self.assertEqual(mock_details.assert_called_once(), None) + self.assertEqual(mock_ca.assert_not_called(), None) + + + def test_get_client_ca_bundle(self): + """ + test get_client when verify_ssl=False and ca_bundle set + """ + cert_path="/test/ca-certificates.crt" + details = self.details.copy() + details["ca_bundle"] = cert_path + mock_client = MagicMock(return_value=None) + patch_client = patch("salt.utils.vmware.get_vsphere_client", + mock_client) + + mock_ca = MagicMock(return_value=cert_path) + patch_ca = patch("salt.utils.http.get_ca_bundle", mock_ca) + + mock_details = MagicMock(return_value=details) + patch_details = patch.dict(vsphere.__salt__, {"vcenter.get_details": + mock_details}) + + with patch_client, patch_ca, patch_details: + vsphere._get_client(server='localhost', username='testuser', + password='testpassword') + self.assertEqual(mock_client.call_args_list, + [call(ca_bundle=cert_path, + password='testpassword', server='localhost', + username='testuser', verify_ssl=True)]) + self.assertEqual(mock_details.assert_called_once(), None) + self.assertEqual(mock_ca.assert_called_once(), None) + self.assertEqual(mock_ca.call_args_list, [call({'ca_bundle': + cert_path})]) + class TestCertificateVerify(TestCase, LoaderModuleMockMixin): def setup_loader_modules(self): @@ -3219,3 +3329,4 @@ class TestCertificateVerify(TestCase, LoaderModuleMockMixin): username="root", verify_ssl=certificate_verify_value, ) + diff --git a/tests/unit/utils/test_vmware.py b/tests/unit/utils/test_vmware.py index 33e35dc92e7..4721a38fbea 100644 --- a/tests/unit/utils/test_vmware.py +++ b/tests/unit/utils/test_vmware.py @@ -1691,13 +1691,13 @@ class PrivateGetServiceInstanceTestCase(TestCase): mechanism="sspi", ) - def test_second_attempt_successful_connection(self): + def test_first_attempt_successful_connection_verify_ssl_false(self): with patch("ssl.SSLContext", MagicMock()), patch( "ssl._create_unverified_context", MagicMock() ): exc = vim.fault.HostConnectFault() exc.msg = "[SSL: CERTIFICATE_VERIFY_FAILED]" - mock_sc = MagicMock(side_effect=[exc, None]) + mock_sc = MagicMock(side_effect=[None]) mock_ssl = MagicMock() with patch("salt.utils.vmware.SmartConnect", mock_sc): @@ -1712,19 +1712,11 @@ class PrivateGetServiceInstanceTestCase(TestCase): mechanism="sspi", principal="fake_principal", domain="fake_domain", + verify_ssl=False, ) mock_ssl.assert_called_once_with() calls = [ - call( - host="fake_host.fqdn", - user="fake_username", - pwd="fake_password", - protocol="fake_protocol", - port=1, - b64token="fake_token", - mechanism="sspi", - ), call( host="fake_host.fqdn", user="fake_username", @@ -1738,21 +1730,18 @@ class PrivateGetServiceInstanceTestCase(TestCase): ] mock_sc.assert_has_calls(calls) - def test_third_attempt_successful_connection(self): + def test_second_attempt_successful_connection_verify_ssl_false(self): with patch("ssl.SSLContext", MagicMock()), patch( "ssl._create_unverified_context", MagicMock() ): - exc = vim.fault.HostConnectFault() - exc.msg = "[SSL: CERTIFICATE_VERIFY_FAILED]" - exc2 = Exception("certificate verify failed") - mock_sc = MagicMock(side_effect=[exc, exc2, None]) + exc = Exception("certificate verify failed") + mock_sc = MagicMock(side_effect=[exc, None]) mock_ssl_unverif = MagicMock() mock_ssl_context = MagicMock() with patch("salt.utils.vmware.SmartConnect", mock_sc): with patch("ssl._create_unverified_context", mock_ssl_unverif): with patch("ssl.SSLContext", mock_ssl_context): - salt.utils.vmware._get_service_instance( host="fake_host.fqdn", username="fake_username", @@ -1762,20 +1751,12 @@ class PrivateGetServiceInstanceTestCase(TestCase): mechanism="sspi", principal="fake_principal", domain="fake_domain", + verify_ssl=False ) mock_ssl_context.assert_called_once_with(ssl.PROTOCOL_TLSv1) mock_ssl_unverif.assert_called_once_with() calls = [ - call( - host="fake_host.fqdn", - user="fake_username", - pwd="fake_password", - protocol="fake_protocol", - port=1, - b64token="fake_token", - mechanism="sspi", - ), call( host="fake_host.fqdn", user="fake_username", @@ -1799,7 +1780,7 @@ class PrivateGetServiceInstanceTestCase(TestCase): ] mock_sc.assert_has_calls(calls) - def test_first_attempt_unsuccessful_connection_default_error(self): + def test_attempt_unsuccessful_connection_default_error(self): exc = Exception("Exception") mock_sc = MagicMock(side_effect=exc) @@ -1816,13 +1797,13 @@ class PrivateGetServiceInstanceTestCase(TestCase): domain="fake_domain", ) - self.assertEqual(mock_sc.call_count, 1) - self.assertIn( - "Could not connect to host 'fake_host.fqdn'", - excinfo.Exception.message, - ) + self.assertEqual(mock_sc.call_count, 1) + self.assertIn( + "Could not connect to host 'fake_host.fqdn'", + excinfo.exception.message, + ) - def test_first_attempt_unsuccessful_connection_vim_fault(self): + def test_attempt_unsuccessful_connection_vim_fault(self): exc = vim.fault.VimFault() exc.msg = "VimFault" mock_sc = MagicMock(side_effect=exc) @@ -1840,15 +1821,15 @@ class PrivateGetServiceInstanceTestCase(TestCase): domain="fake_domain", ) - self.assertEqual(mock_sc.call_count, 1) - self.assertEqual("VimFault", excinfo.Exception.message) + self.assertEqual(mock_sc.call_count, 1) + self.assertEqual("VimFault", excinfo.exception.message) - def test_second_attempt_unsuccsessful_connection_default_error(self): + def test_first_attempt_unsuccsessful_connection_default_error(self): with patch("ssl.SSLContext", MagicMock()), patch( "ssl._create_unverified_context", MagicMock() ): exc = vim.fault.HostConnectFault() - exc.msg = "[SSL: CERTIFICATE_VERIFY_FAILED]" + exc.msg = "certificate verify failed" exc2 = Exception("Exception") mock_sc = MagicMock(side_effect=[exc, exc2]) @@ -1863,22 +1844,48 @@ class PrivateGetServiceInstanceTestCase(TestCase): mechanism="sspi", principal="fake_principal", domain="fake_domain", + verify_ssl=False, ) - self.assertEqual(mock_sc.call_count, 2) - self.assertIn( - "Could not connect to host 'fake_host.fqdn'", - excinfo.Exception.message, + self.assertEqual(mock_sc.call_count, 2) + self.assertIn( + "Could not connect to host 'fake_host.fqdn'", + excinfo.exception.message + ) + + def test_first_attempt_unsuccsessful_cannot_vim_fault_verify_ssl(self): + with patch("ssl.SSLContext", MagicMock()), patch( + "ssl._create_unverified_context", MagicMock() + ): + exc = vim.fault.VimFault() + exc.msg = "VimFault" + + mock_sc = MagicMock(side_effect=[exc]) + + with patch("salt.utils.vmware.SmartConnect", mock_sc): + with self.assertRaises(VMwareConnectionError) as excinfo: + salt.utils.vmware._get_service_instance( + host="fake_host.fqdn", + username="fake_username", + password="fake_password", + protocol="fake_protocol", + port=1, + mechanism="sspi", + principal="fake_principal", + domain="fake_domain", + verify_ssl=False, ) - def test_second_attempt_unsuccsessful_connection_vim_fault(self): + self.assertEqual(mock_sc.call_count, 1) + self.assertIn("VimFault", excinfo.exception.message) + + def test_third_attempt_unsuccessful_connection_detault_error(self): with patch("ssl.SSLContext", MagicMock()), patch( "ssl._create_unverified_context", MagicMock() ): exc = vim.fault.HostConnectFault() - exc.msg = "[SSL: CERTIFICATE_VERIFY_FAILED]" - exc2 = vim.fault.VimFault() - exc2.msg = "VimFault" + exc.msg = "certificate verify failed" + exc2 = Exception("Exception") mock_sc = MagicMock(side_effect=[exc, exc2]) with patch("salt.utils.vmware.SmartConnect", mock_sc): @@ -1892,20 +1899,19 @@ class PrivateGetServiceInstanceTestCase(TestCase): mechanism="sspi", principal="fake_principal", domain="fake_domain", + verify_ssl=False ) - self.assertEqual(mock_sc.call_count, 2) - self.assertIn("VimFault", excinfo.Exception.message) + self.assertEqual(mock_sc.call_count, 2) + self.assertIn("Could not connect to host 'fake_host.fqdn", excinfo.exception.message) - def test_third_attempt_unsuccessful_connection_detault_error(self): + def test_second_attempt_unsuccessful_connection_vim_fault(self): with patch("ssl.SSLContext", MagicMock()), patch( "ssl._create_unverified_context", MagicMock() ): - exc = vim.fault.HostConnectFault() - exc.msg = "[SSL: CERTIFICATE_VERIFY_FAILED]" - exc2 = Exception("certificate verify failed") - exc3 = Exception("Exception") - mock_sc = MagicMock(side_effect=[exc, exc2, exc3]) + exc = vim.fault.VimFault() + exc.msg = "VimFault" + mock_sc = MagicMock(side_effect=[exc]) with patch("salt.utils.vmware.SmartConnect", mock_sc): with self.assertRaises(VMwareConnectionError) as excinfo: @@ -1918,37 +1924,11 @@ class PrivateGetServiceInstanceTestCase(TestCase): mechanism="sspi", principal="fake_principal", domain="fake_domain", + verify_ssl=False ) - self.assertEqual(mock_sc.call_count, 3) - self.assertIn("Exception", excinfo.Exception.message) - - def test_third_attempt_unsuccessful_connection_vim_fault(self): - with patch("ssl.SSLContext", MagicMock()), patch( - "ssl._create_unverified_context", MagicMock() - ): - exc = vim.fault.HostConnectFault() - exc.msg = "[SSL: CERTIFICATE_VERIFY_FAILED]" - exc2 = Exception("certificate verify failed") - exc3 = vim.fault.VimFault() - exc3.msg = "VimFault" - mock_sc = MagicMock(side_effect=[exc, exc2, exc3]) - - with patch("salt.utils.vmware.SmartConnect", mock_sc): - with self.assertRaises(VMwareConnectionError) as excinfo: - salt.utils.vmware._get_service_instance( - host="fake_host.fqdn", - username="fake_username", - password="fake_password", - protocol="fake_protocol", - port=1, - mechanism="sspi", - principal="fake_principal", - domain="fake_domain", - ) - - self.assertEqual(mock_sc.call_count, 3) - self.assertIn("VimFault", excinfo.Exception.message) + self.assertEqual(mock_sc.call_count, 1) + self.assertIn("VimFault", excinfo.exception.message) @skipIf(not HAS_PYVMOMI, "The 'pyvmomi' library is missing") @@ -1975,7 +1955,8 @@ class GetServiceInstanceTestCase(TestCase): with patch("salt.utils.vmware._get_service_instance", mock_get_si): salt.utils.vmware.get_service_instance(host="fake_host") mock_get_si.assert_called_once_with( - "fake_host", None, None, "https", 443, "userpass", None, None + "fake_host", None, None, "https", 443, "userpass", None, None, + verify_ssl=True ) def test_no_cached_service_instance_same_host_on_proxy(self): @@ -2002,6 +1983,7 @@ class GetServiceInstanceTestCase(TestCase): "fake_mechanism", "fake_principal", "fake_domain", + verify_ssl=True, ) def test_cached_service_instance_different_host(self): @@ -2039,6 +2021,7 @@ class GetServiceInstanceTestCase(TestCase): mechanism="fake_mechanism", principal="fake_principal", domain="fake_domain", + verify_ssl=True ) mock_get_si.assert_called_once_with( "fake_host", @@ -2049,6 +2032,7 @@ class GetServiceInstanceTestCase(TestCase): "fake_mechanism", "fake_principal", "fake_domain", + verify_ssl=True, ) def test_unauthenticated_service_instance(self): From a87eaf26a6a5c960eac107bb18c2a2d963a309ae Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Thu, 17 Dec 2020 10:59:35 -0500 Subject: [PATCH 47/69] run pre-commit on test_vsphere.py and test_vmware.py --- tests/unit/modules/test_vsphere.py | 114 ++++++++++++++++++----------- tests/unit/utils/test_vmware.py | 29 +++++--- 2 files changed, 89 insertions(+), 54 deletions(-) diff --git a/tests/unit/modules/test_vsphere.py b/tests/unit/modules/test_vsphere.py index 394f05f507f..a5270b6cf9a 100644 --- a/tests/unit/modules/test_vsphere.py +++ b/tests/unit/modules/test_vsphere.py @@ -3165,24 +3165,33 @@ class TestVSphereTagging(TestCase, LoaderModuleMockMixin): test get_client when verify_ssl and ca_bundle are not passed """ mock_client = MagicMock(return_value=None) - patch_client = patch("salt.utils.vmware.get_vsphere_client", - mock_client) + patch_client = patch("salt.utils.vmware.get_vsphere_client", mock_client) - cert_path="/test/ca-certificates.crt" + cert_path = "/test/ca-certificates.crt" mock_ca = MagicMock(return_value=cert_path) patch_ca = patch("salt.utils.http.get_ca_bundle", mock_ca) mock_details = MagicMock(return_value=self.details) - patch_details = patch.dict(vsphere.__salt__, {"vcenter.get_details": - mock_details}) + patch_details = patch.dict( + vsphere.__salt__, {"vcenter.get_details": mock_details} + ) with patch_client, patch_ca, patch_details: - vsphere._get_client(server='localhost', username='testuser', - password='testpassword') - self.assertEqual(mock_client.call_args_list, - [call(ca_bundle=cert_path, - password='testpassword', server='localhost', - username='testuser', verify_ssl=True)]) + vsphere._get_client( + server="localhost", username="testuser", password="testpassword" + ) + self.assertEqual( + mock_client.call_args_list, + [ + call( + ca_bundle=cert_path, + password="testpassword", + server="localhost", + username="testuser", + verify_ssl=True, + ) + ], + ) self.assertEqual(mock_details.assert_called_once(), None) self.assertEqual(mock_ca.assert_called_once(), None) @@ -3193,24 +3202,33 @@ class TestVSphereTagging(TestCase, LoaderModuleMockMixin): details = self.details.copy() details["verify_ssl"] = False mock_client = MagicMock(return_value=None) - patch_client = patch("salt.utils.vmware.get_vsphere_client", - mock_client) + patch_client = patch("salt.utils.vmware.get_vsphere_client", mock_client) - cert_path="/test/ca-certificates.crt" + cert_path = "/test/ca-certificates.crt" mock_ca = MagicMock(return_value=cert_path) patch_ca = patch("salt.utils.http.get_ca_bundle", mock_ca) mock_details = MagicMock(return_value=details) - patch_details = patch.dict(vsphere.__salt__, {"vcenter.get_details": - mock_details}) + patch_details = patch.dict( + vsphere.__salt__, {"vcenter.get_details": mock_details} + ) with patch_client, patch_ca, patch_details: - vsphere._get_client(server='localhost', username='testuser', - password='testpassword') - self.assertEqual(mock_client.call_args_list, - [call(ca_bundle=None, - password='testpassword', server='localhost', - username='testuser', verify_ssl=False)]) + vsphere._get_client( + server="localhost", username="testuser", password="testpassword" + ) + self.assertEqual( + mock_client.call_args_list, + [ + call( + ca_bundle=None, + password="testpassword", + server="localhost", + username="testuser", + verify_ssl=False, + ) + ], + ) self.assertEqual(mock_details.assert_called_once(), None) self.assertEqual(mock_ca.assert_not_called(), None) @@ -3220,51 +3238,62 @@ class TestVSphereTagging(TestCase, LoaderModuleMockMixin): """ details = self.details.copy() details["verify_ssl"] = False - details["ca_bundle"] = '/tmp/test' + details["ca_bundle"] = "/tmp/test" mock_client = MagicMock(return_value=None) - patch_client = patch("salt.utils.vmware.get_vsphere_client", - mock_client) + patch_client = patch("salt.utils.vmware.get_vsphere_client", mock_client) - cert_path="/test/ca-certificates.crt" + cert_path = "/test/ca-certificates.crt" mock_ca = MagicMock(return_value=cert_path) patch_ca = patch("salt.utils.http.get_ca_bundle", mock_ca) mock_details = MagicMock(return_value=details) - patch_details = patch.dict(vsphere.__salt__, {"vcenter.get_details": - mock_details}) + patch_details = patch.dict( + vsphere.__salt__, {"vcenter.get_details": mock_details} + ) with patch_client, patch_ca, patch_details: - self.assertFalse(vsphere._get_client(server='localhost', username='testuser', - password='testpassword')) + self.assertFalse( + vsphere._get_client( + server="localhost", username="testuser", password="testpassword" + ) + ) self.assertEqual(mock_details.assert_called_once(), None) self.assertEqual(mock_ca.assert_not_called(), None) - def test_get_client_ca_bundle(self): """ test get_client when verify_ssl=False and ca_bundle set """ - cert_path="/test/ca-certificates.crt" + cert_path = "/test/ca-certificates.crt" details = self.details.copy() details["ca_bundle"] = cert_path mock_client = MagicMock(return_value=None) - patch_client = patch("salt.utils.vmware.get_vsphere_client", - mock_client) + patch_client = patch("salt.utils.vmware.get_vsphere_client", mock_client) mock_ca = MagicMock(return_value=cert_path) patch_ca = patch("salt.utils.http.get_ca_bundle", mock_ca) mock_details = MagicMock(return_value=details) - patch_details = patch.dict(vsphere.__salt__, {"vcenter.get_details": - mock_details}) + patch_details = patch.dict( + vsphere.__salt__, {"vcenter.get_details": mock_details} + ) with patch_client, patch_ca, patch_details: - vsphere._get_client(server='localhost', username='testuser', - password='testpassword') - self.assertEqual(mock_client.call_args_list, - [call(ca_bundle=cert_path, - password='testpassword', server='localhost', - username='testuser', verify_ssl=True)]) + vsphere._get_client( + server="localhost", username="testuser", password="testpassword" + ) + self.assertEqual( + mock_client.call_args_list, + [ + call( + ca_bundle=cert_path, + password="testpassword", + server="localhost", + username="testuser", + verify_ssl=True, + ) + ], + ) self.assertEqual(mock_details.assert_called_once(), None) self.assertEqual(mock_ca.assert_called_once(), None) self.assertEqual(mock_ca.call_args_list, [call({'ca_bundle': @@ -3329,4 +3358,3 @@ class TestCertificateVerify(TestCase, LoaderModuleMockMixin): username="root", verify_ssl=certificate_verify_value, ) - diff --git a/tests/unit/utils/test_vmware.py b/tests/unit/utils/test_vmware.py index 4721a38fbea..e3fac373814 100644 --- a/tests/unit/utils/test_vmware.py +++ b/tests/unit/utils/test_vmware.py @@ -1751,7 +1751,7 @@ class PrivateGetServiceInstanceTestCase(TestCase): mechanism="sspi", principal="fake_principal", domain="fake_domain", - verify_ssl=False + verify_ssl=False, ) mock_ssl_context.assert_called_once_with(ssl.PROTOCOL_TLSv1) @@ -1799,8 +1799,7 @@ class PrivateGetServiceInstanceTestCase(TestCase): self.assertEqual(mock_sc.call_count, 1) self.assertIn( - "Could not connect to host 'fake_host.fqdn'", - excinfo.exception.message, + "Could not connect to host 'fake_host.fqdn'", excinfo.exception.message, ) def test_attempt_unsuccessful_connection_vim_fault(self): @@ -1849,8 +1848,7 @@ class PrivateGetServiceInstanceTestCase(TestCase): self.assertEqual(mock_sc.call_count, 2) self.assertIn( - "Could not connect to host 'fake_host.fqdn'", - excinfo.exception.message + "Could not connect to host 'fake_host.fqdn'", excinfo.exception.message ) def test_first_attempt_unsuccsessful_cannot_vim_fault_verify_ssl(self): @@ -1899,11 +1897,13 @@ class PrivateGetServiceInstanceTestCase(TestCase): mechanism="sspi", principal="fake_principal", domain="fake_domain", - verify_ssl=False + verify_ssl=False, ) self.assertEqual(mock_sc.call_count, 2) - self.assertIn("Could not connect to host 'fake_host.fqdn", excinfo.exception.message) + self.assertIn( + "Could not connect to host 'fake_host.fqdn", excinfo.exception.message + ) def test_second_attempt_unsuccessful_connection_vim_fault(self): with patch("ssl.SSLContext", MagicMock()), patch( @@ -1924,7 +1924,7 @@ class PrivateGetServiceInstanceTestCase(TestCase): mechanism="sspi", principal="fake_principal", domain="fake_domain", - verify_ssl=False + verify_ssl=False, ) self.assertEqual(mock_sc.call_count, 1) @@ -1955,8 +1955,15 @@ class GetServiceInstanceTestCase(TestCase): with patch("salt.utils.vmware._get_service_instance", mock_get_si): salt.utils.vmware.get_service_instance(host="fake_host") mock_get_si.assert_called_once_with( - "fake_host", None, None, "https", 443, "userpass", None, None, - verify_ssl=True + "fake_host", + None, + None, + "https", + 443, + "userpass", + None, + None, + verify_ssl=True, ) def test_no_cached_service_instance_same_host_on_proxy(self): @@ -2021,7 +2028,7 @@ class GetServiceInstanceTestCase(TestCase): mechanism="fake_mechanism", principal="fake_principal", domain="fake_domain", - verify_ssl=True + verify_ssl=True, ) mock_get_si.assert_called_once_with( "fake_host", From bfb5cd9f6a42f2c877bf8fbc9212241678fb9314 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Tue, 22 Dec 2020 13:19:21 -0500 Subject: [PATCH 48/69] fix test_get_client_verify_ssl_false_ca_bundle test and docs --- salt/modules/vsphere.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/salt/modules/vsphere.py b/salt/modules/vsphere.py index ec9d0995dc3..c7ff9c1db19 100644 --- a/salt/modules/vsphere.py +++ b/salt/modules/vsphere.py @@ -4343,6 +4343,7 @@ def vsan_enable( verify_ssl Verify the SSL certificate. Default: True + CLI Example: .. code-block:: bash @@ -10332,13 +10333,13 @@ def _get_client(server, username, password, verify_ssl=None, ca_bundle=None): details = __salt__["vcenter.get_details"]() ca_bundle = details.get("ca_bundle", None) - if ca_bundle: - ca_bundle = salt.utils.http.get_ca_bundle({"ca_bundle": ca_bundle}) - if verify_ssl is False and ca_bundle is not None: log.error("Cannot set verify_ssl to False and ca_bundle together") return False + if ca_bundle: + ca_bundle = salt.utils.http.get_ca_bundle({"ca_bundle": ca_bundle}) + if verify_ssl and ca_bundle is None: ca_bundle = salt.utils.http.get_ca_bundle() From 4fdaff22983bc8123002f5df36a5fba3126328a4 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Fri, 15 Jan 2021 13:05:02 -0500 Subject: [PATCH 49/69] run full cloud tests --- cicd/jenkins/kitchen-centos7-py3-cloud | 1 + cicd/jenkins/kitchen-centos7-py3-cloud-pytest | 1 + 2 files changed, 2 insertions(+) diff --git a/cicd/jenkins/kitchen-centos7-py3-cloud b/cicd/jenkins/kitchen-centos7-py3-cloud index e84cdbbf095..e3371848682 100644 --- a/cicd/jenkins/kitchen-centos7-py3-cloud +++ b/cicd/jenkins/kitchen-centos7-py3-cloud @@ -13,6 +13,7 @@ runTestSuite( nox_passthrough_opts: '', python_version: 'py3', testrun_timeout: 6, + force_run_full: true, use_spot_instances: true) // vim: ft=groovy diff --git a/cicd/jenkins/kitchen-centos7-py3-cloud-pytest b/cicd/jenkins/kitchen-centos7-py3-cloud-pytest index 9312dbc9639..073169e83e0 100644 --- a/cicd/jenkins/kitchen-centos7-py3-cloud-pytest +++ b/cicd/jenkins/kitchen-centos7-py3-cloud-pytest @@ -13,6 +13,7 @@ runTestSuite( nox_passthrough_opts: '', python_version: 'py3', testrun_timeout: 6, + force_run_full: true, use_spot_instances: true) // vim: ft=groovy From 7080ab1d11c2c69d495a5f5b84cb682ee3a2978f Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Tue, 19 Jan 2021 08:58:59 -0500 Subject: [PATCH 50/69] Fix pre-commit --- requirements/static/ci/git-sources.txt | 3 ++- requirements/static/ci/py3.5/linux.txt | 15 +++++++++++++-- requirements/static/ci/py3.6/linux.txt | 15 +++++++++++++-- requirements/static/ci/py3.7/linux.txt | 15 +++++++++++++-- requirements/static/ci/py3.8/linux.txt | 15 +++++++++++++-- requirements/static/ci/py3.9/linux.txt | 15 +++++++++++++-- tests/unit/modules/test_vsphere.py | 3 +-- 7 files changed, 68 insertions(+), 13 deletions(-) diff --git a/requirements/static/ci/git-sources.txt b/requirements/static/ci/git-sources.txt index 7ef76a47d08..e6afbd10e60 100644 --- a/requirements/static/ci/git-sources.txt +++ b/requirements/static/ci/git-sources.txt @@ -1 +1,2 @@ -git+https://github.com/vmware/vsphere-automation-sdk-python.git +--extra-index-url=https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/master/lib/ +-e git+https://github.com/vmware/vsphere-automation-sdk-python.git#egg=vSphere-Automation-SDK diff --git a/requirements/static/ci/py3.5/linux.txt b/requirements/static/ci/py3.5/linux.txt index 9439fd12cb6..b30592b74fc 100644 --- a/requirements/static/ci/py3.5/linux.txt +++ b/requirements/static/ci/py3.5/linux.txt @@ -4,6 +4,9 @@ # # pip-compile -o requirements/static/ci/py3.5/linux.txt -v requirements/static/pkg/py3.5/linux.txt requirements/pytest.txt requirements/static/ci/git-sources.txt requirements/static/ci/linux.in # +--extra-index-url https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/master/lib/ + +-e git+https://github.com/vmware/vsphere-automation-sdk-python.git#egg=vSphere-Automation-SDK adal==1.2.3 # via azure-datalake-store, msrestazure apache-libcloud==2.0.0 appdirs==1.4.4 # via virtualenv @@ -156,6 +159,10 @@ msrest==0.6.14 # via azure-applicationinsights, azure-eventgrid, azur msrestazure==0.6.3 # via azure-batch, azure-eventgrid, azure-graphrbac, azure-keyvault, azure-mgmt-advisor, azure-mgmt-applicationinsights, azure-mgmt-authorization, azure-mgmt-batch, azure-mgmt-batchai, azure-mgmt-billing, azure-mgmt-cdn, azure-mgmt-cognitiveservices, azure-mgmt-commerce, azure-mgmt-compute, azure-mgmt-consumption, azure-mgmt-containerinstance, azure-mgmt-containerregistry, azure-mgmt-containerservice, azure-mgmt-cosmosdb, azure-mgmt-datafactory, azure-mgmt-datalake-analytics, azure-mgmt-datalake-store, azure-mgmt-datamigration, azure-mgmt-devspaces, azure-mgmt-devtestlabs, azure-mgmt-dns, azure-mgmt-eventgrid, azure-mgmt-eventhub, azure-mgmt-hanaonazure, azure-mgmt-iotcentral, azure-mgmt-iothub, azure-mgmt-iothubprovisioningservices, azure-mgmt-keyvault, azure-mgmt-loganalytics, azure-mgmt-logic, azure-mgmt-machinelearningcompute, azure-mgmt-managementgroups, azure-mgmt-managementpartner, azure-mgmt-maps, azure-mgmt-marketplaceordering, azure-mgmt-media, azure-mgmt-monitor, azure-mgmt-msi, azure-mgmt-network, azure-mgmt-notificationhubs, azure-mgmt-policyinsights, azure-mgmt-powerbiembedded, azure-mgmt-rdbms, azure-mgmt-recoveryservices, azure-mgmt-recoveryservicesbackup, azure-mgmt-redis, azure-mgmt-relay, azure-mgmt-reservations, azure-mgmt-resource, azure-mgmt-scheduler, azure-mgmt-search, azure-mgmt-servicebus, azure-mgmt-servicefabric, azure-mgmt-signalr, azure-mgmt-sql, azure-mgmt-storage, azure-mgmt-subscription, azure-mgmt-trafficmanager, azure-mgmt-web ncclient==0.6.4 # via junos-eznc netaddr==0.7.19 # via junos-eznc +nsx-policy-python-sdk==3.0.2.0.0.16837625 +nsx-python-sdk==3.0.2.0.0.16837625 +nsx-vmc-aws-integration-python-sdk==3.0.2.0.0.16837625 +nsx-vmc-policy-python-sdk==3.0.2.0.0.16837625 ntc-templates==1.4.0 # via junos-eznc oauthlib==3.1.0 # via requests-oauthlib oscrypto==1.2.0 # via certvalidator @@ -208,6 +215,7 @@ setuptools-scm==3.2.0 six==1.15.0 smmap2==2.0.5 # via gitdb2 strict-rfc3339==0.7 +suds-jurko==0.6 tempora==1.14.1 terminal==0.4.0 # via ntc-templates textfsm==1.1.0 # via ntc-templates @@ -215,8 +223,13 @@ timelib==0.2.5 toml==0.10.0 transitions==0.8.1 # via junos-eznc urllib3==1.24.2 +vapi-client-bindings==3.5.0 +vapi-common-client==2.19.0 # via nsx-policy-python-sdk, nsx-python-sdk, nsx-vmc-aws-integration-python-sdk, nsx-vmc-policy-python-sdk, vmc-client-bindings, vmc-draas-client-bindings +vapi-runtime==2.19.0 # via nsx-policy-python-sdk, nsx-python-sdk, nsx-vmc-aws-integration-python-sdk, nsx-vmc-policy-python-sdk, vapi-client-bindings, vapi-common-client, vmc-client-bindings, vmc-draas-client-bindings vcert==0.7.3 virtualenv==20.0.20 +vmc-client-bindings==1.31.0 +vmc-draas-client-bindings==1.17.0 watchdog==0.9.0 websocket-client==0.40.0 # via docker, kubernetes werkzeug==0.15.6 # via moto @@ -225,5 +238,3 @@ xmltodict==0.12.0 # via moto yamlordereddictloader==0.4.0 # via junos-eznc zc.lockfile==1.4 zipp==0.6.0 # via importlib-metadata, importlib-resources -# Passthrough dependencies from requirements/static/ci/git-sources.txt -git+https://github.com/vmware/vsphere-automation-sdk-python.git diff --git a/requirements/static/ci/py3.6/linux.txt b/requirements/static/ci/py3.6/linux.txt index c67a25cc11e..404316cab78 100644 --- a/requirements/static/ci/py3.6/linux.txt +++ b/requirements/static/ci/py3.6/linux.txt @@ -4,6 +4,9 @@ # # pip-compile -o requirements/static/ci/py3.6/linux.txt -v requirements/static/pkg/py3.6/linux.txt requirements/pytest.txt requirements/static/ci/git-sources.txt requirements/static/ci/linux.in # +--extra-index-url https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/master/lib/ + +-e git+https://github.com/vmware/vsphere-automation-sdk-python.git#egg=vSphere-Automation-SDK adal==1.2.3 # via azure-datalake-store, msrestazure apache-libcloud==2.0.0 appdirs==1.4.4 # via virtualenv @@ -160,6 +163,10 @@ napalm==3.1.0 ; python_version >= "3.6" ncclient==0.6.4 # via junos-eznc netaddr==0.7.19 # via junos-eznc, napalm, pyeapi netmiko==3.2.0 # via napalm +nsx-policy-python-sdk==3.0.2.0.0.16837625 +nsx-python-sdk==3.0.2.0.0.16837625 +nsx-vmc-aws-integration-python-sdk==3.0.2.0.0.16837625 +nsx-vmc-policy-python-sdk==3.0.2.0.0.16837625 ntc-templates==1.4.0 # via junos-eznc oauthlib==3.1.0 # via requests-oauthlib oscrypto==1.2.0 # via certvalidator @@ -212,6 +219,7 @@ setuptools-scm==3.2.0 six==1.15.0 smmap2==2.0.5 # via gitdb2 strict-rfc3339==0.7 +suds-jurko==0.6 tempora==1.14.1 terminal==0.4.0 # via ntc-templates textfsm==1.1.0 # via napalm, netmiko, ntc-templates @@ -219,8 +227,13 @@ timelib==0.2.5 toml==0.10.0 transitions==0.8.1 # via junos-eznc urllib3==1.24.2 +vapi-client-bindings==3.5.0 +vapi-common-client==2.19.0 # via nsx-policy-python-sdk, nsx-python-sdk, nsx-vmc-aws-integration-python-sdk, nsx-vmc-policy-python-sdk, vmc-client-bindings, vmc-draas-client-bindings +vapi-runtime==2.19.0 # via nsx-policy-python-sdk, nsx-python-sdk, nsx-vmc-aws-integration-python-sdk, nsx-vmc-policy-python-sdk, vapi-client-bindings, vapi-common-client, vmc-client-bindings, vmc-draas-client-bindings vcert==0.7.3 virtualenv==20.0.20 +vmc-client-bindings==1.31.0 +vmc-draas-client-bindings==1.17.0 watchdog==0.9.0 websocket-client==0.40.0 # via docker, kubernetes werkzeug==0.15.6 # via moto @@ -229,5 +242,3 @@ xmltodict==0.12.0 # via moto yamlordereddictloader==0.4.0 # via junos-eznc zc.lockfile==1.4 zipp==0.6.0 # via importlib-metadata, importlib-resources -# Passthrough dependencies from requirements/static/ci/git-sources.txt -git+https://github.com/vmware/vsphere-automation-sdk-python.git diff --git a/requirements/static/ci/py3.7/linux.txt b/requirements/static/ci/py3.7/linux.txt index 87131756346..ab552ac8f08 100644 --- a/requirements/static/ci/py3.7/linux.txt +++ b/requirements/static/ci/py3.7/linux.txt @@ -4,6 +4,9 @@ # # pip-compile -o requirements/static/ci/py3.7/linux.txt -v requirements/static/pkg/py3.7/linux.txt requirements/pytest.txt requirements/static/ci/git-sources.txt requirements/static/ci/linux.in # +--extra-index-url https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/master/lib/ + +-e git+https://github.com/vmware/vsphere-automation-sdk-python.git#egg=vSphere-Automation-SDK adal==1.2.3 # via azure-datalake-store, msrestazure apache-libcloud==2.0.0 appdirs==1.4.4 # via virtualenv @@ -158,6 +161,10 @@ napalm==3.1.0 ; python_version >= "3.6" ncclient==0.6.4 # via junos-eznc netaddr==0.7.19 # via junos-eznc, napalm, pyeapi netmiko==3.2.0 # via napalm +nsx-policy-python-sdk==3.0.2.0.0.16837625 +nsx-python-sdk==3.0.2.0.0.16837625 +nsx-vmc-aws-integration-python-sdk==3.0.2.0.0.16837625 +nsx-vmc-policy-python-sdk==3.0.2.0.0.16837625 ntc-templates==1.4.0 # via junos-eznc oauthlib==3.1.0 # via requests-oauthlib oscrypto==1.2.0 # via certvalidator @@ -210,6 +217,7 @@ setuptools-scm==3.2.0 six==1.15.0 smmap2==2.0.5 # via gitdb2 strict-rfc3339==0.7 +suds-jurko==0.6 tempora==1.14.1 terminal==0.4.0 # via ntc-templates textfsm==1.1.0 # via napalm, netmiko, ntc-templates @@ -217,8 +225,13 @@ timelib==0.2.5 toml==0.10.0 transitions==0.8.1 # via junos-eznc urllib3==1.24.2 +vapi-client-bindings==3.5.0 +vapi-common-client==2.19.0 # via nsx-policy-python-sdk, nsx-python-sdk, nsx-vmc-aws-integration-python-sdk, nsx-vmc-policy-python-sdk, vmc-client-bindings, vmc-draas-client-bindings +vapi-runtime==2.19.0 # via nsx-policy-python-sdk, nsx-python-sdk, nsx-vmc-aws-integration-python-sdk, nsx-vmc-policy-python-sdk, vapi-client-bindings, vapi-common-client, vmc-client-bindings, vmc-draas-client-bindings vcert==0.7.3 virtualenv==20.0.20 +vmc-client-bindings==1.31.0 +vmc-draas-client-bindings==1.17.0 watchdog==0.9.0 websocket-client==0.40.0 # via docker, kubernetes werkzeug==0.15.6 # via moto @@ -227,5 +240,3 @@ xmltodict==0.12.0 # via moto yamlordereddictloader==0.4.0 # via junos-eznc zc.lockfile==1.4 zipp==0.6.0 # via importlib-metadata -# Passthrough dependencies from requirements/static/ci/git-sources.txt -git+https://github.com/vmware/vsphere-automation-sdk-python.git diff --git a/requirements/static/ci/py3.8/linux.txt b/requirements/static/ci/py3.8/linux.txt index 6229a118575..c7d6935a843 100644 --- a/requirements/static/ci/py3.8/linux.txt +++ b/requirements/static/ci/py3.8/linux.txt @@ -4,6 +4,9 @@ # # pip-compile -o requirements/static/ci/py3.8/linux.txt -v requirements/static/pkg/py3.8/linux.txt requirements/pytest.txt requirements/static/ci/git-sources.txt requirements/static/ci/linux.in # +--extra-index-url https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/master/lib/ + +-e git+https://github.com/vmware/vsphere-automation-sdk-python.git#egg=vSphere-Automation-SDK adal==1.2.3 # via azure-datalake-store, msrestazure apache-libcloud==2.0.0 appdirs==1.4.4 # via virtualenv @@ -158,6 +161,10 @@ napalm==3.1.0 ; python_version >= "3.6" ncclient==0.6.4 # via junos-eznc netaddr==0.7.19 # via junos-eznc, napalm, pyeapi netmiko==3.2.0 # via napalm +nsx-policy-python-sdk==3.0.2.0.0.16837625 +nsx-python-sdk==3.0.2.0.0.16837625 +nsx-vmc-aws-integration-python-sdk==3.0.2.0.0.16837625 +nsx-vmc-policy-python-sdk==3.0.2.0.0.16837625 ntc-templates==1.4.1 # via junos-eznc oauthlib==3.1.0 # via requests-oauthlib oscrypto==1.2.0 # via certvalidator @@ -210,6 +217,7 @@ setuptools-scm==3.2.0 six==1.15.0 smmap2==2.0.5 # via gitdb2 strict-rfc3339==0.7 +suds-jurko==0.6 tempora==1.14.1 terminal==0.4.0 # via ntc-templates textfsm==1.1.0 # via napalm, netmiko, ntc-templates @@ -217,8 +225,13 @@ timelib==0.2.5 toml==0.10.0 transitions==0.8.1 # via junos-eznc urllib3==1.24.2 +vapi-client-bindings==3.5.0 +vapi-common-client==2.19.0 # via nsx-policy-python-sdk, nsx-python-sdk, nsx-vmc-aws-integration-python-sdk, nsx-vmc-policy-python-sdk, vmc-client-bindings, vmc-draas-client-bindings +vapi-runtime==2.19.0 # via nsx-policy-python-sdk, nsx-python-sdk, nsx-vmc-aws-integration-python-sdk, nsx-vmc-policy-python-sdk, vapi-client-bindings, vapi-common-client, vmc-client-bindings, vmc-draas-client-bindings vcert==0.7.3 virtualenv==20.0.20 +vmc-client-bindings==1.31.0 +vmc-draas-client-bindings==1.17.0 watchdog==0.9.0 websocket-client==0.40.0 # via docker, kubernetes werkzeug==0.15.6 # via moto @@ -226,5 +239,3 @@ wrapt==1.11.1 # via aws-xray-sdk xmltodict==0.12.0 # via moto yamlordereddictloader==0.4.0 # via junos-eznc zc.lockfile==1.4 -# Passthrough dependencies from requirements/static/ci/git-sources.txt -git+https://github.com/vmware/vsphere-automation-sdk-python.git diff --git a/requirements/static/ci/py3.9/linux.txt b/requirements/static/ci/py3.9/linux.txt index f85ebe7fe67..859c63d13c3 100644 --- a/requirements/static/ci/py3.9/linux.txt +++ b/requirements/static/ci/py3.9/linux.txt @@ -4,6 +4,9 @@ # # pip-compile -o requirements/static/ci/py3.9/linux.txt -v requirements/static/pkg/py3.9/linux.txt requirements/pytest.txt requirements/static/ci/git-sources.txt requirements/static/ci/linux.in # +--extra-index-url https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/master/lib/ + +-e git+https://github.com/vmware/vsphere-automation-sdk-python.git#egg=vSphere-Automation-SDK adal==1.2.3 # via azure-datalake-store, msrestazure apache-libcloud==2.0.0 appdirs==1.4.4 # via virtualenv @@ -158,6 +161,10 @@ napalm==3.1.0 ; python_version >= "3.6" ncclient==0.6.4 # via junos-eznc netaddr==0.7.19 # via junos-eznc, napalm, pyeapi netmiko==3.2.0 # via napalm +nsx-policy-python-sdk==3.0.2.0.0.16837625 +nsx-python-sdk==3.0.2.0.0.16837625 +nsx-vmc-aws-integration-python-sdk==3.0.2.0.0.16837625 +nsx-vmc-policy-python-sdk==3.0.2.0.0.16837625 ntc-templates==1.4.1 # via junos-eznc oauthlib==3.1.0 # via requests-oauthlib oscrypto==1.2.0 # via certvalidator @@ -210,6 +217,7 @@ setuptools-scm==3.2.0 six==1.15.0 smmap2==2.0.5 # via gitdb2 strict-rfc3339==0.7 +suds-jurko==0.6 tempora==1.14.1 terminal==0.4.0 # via ntc-templates textfsm==1.1.0 # via napalm, netmiko, ntc-templates @@ -217,8 +225,13 @@ timelib==0.2.5 toml==0.10.0 transitions==0.8.1 # via junos-eznc urllib3==1.24.2 +vapi-client-bindings==3.5.0 +vapi-common-client==2.19.0 # via nsx-policy-python-sdk, nsx-python-sdk, nsx-vmc-aws-integration-python-sdk, nsx-vmc-policy-python-sdk, vmc-client-bindings, vmc-draas-client-bindings +vapi-runtime==2.19.0 # via nsx-policy-python-sdk, nsx-python-sdk, nsx-vmc-aws-integration-python-sdk, nsx-vmc-policy-python-sdk, vapi-client-bindings, vapi-common-client, vmc-client-bindings, vmc-draas-client-bindings vcert==0.7.3 virtualenv==20.0.20 +vmc-client-bindings==1.31.0 +vmc-draas-client-bindings==1.17.0 watchdog==0.9.0 websocket-client==0.40.0 # via docker, kubernetes werkzeug==0.15.6 # via moto @@ -226,5 +239,3 @@ wrapt==1.11.1 # via aws-xray-sdk xmltodict==0.12.0 # via moto yamlordereddictloader==0.4.0 # via junos-eznc zc.lockfile==1.4 -# Passthrough dependencies from requirements/static/ci/git-sources.txt -git+https://github.com/vmware/vsphere-automation-sdk-python.git diff --git a/tests/unit/modules/test_vsphere.py b/tests/unit/modules/test_vsphere.py index a5270b6cf9a..8b2ca88ce04 100644 --- a/tests/unit/modules/test_vsphere.py +++ b/tests/unit/modules/test_vsphere.py @@ -3296,8 +3296,7 @@ class TestVSphereTagging(TestCase, LoaderModuleMockMixin): ) self.assertEqual(mock_details.assert_called_once(), None) self.assertEqual(mock_ca.assert_called_once(), None) - self.assertEqual(mock_ca.call_args_list, [call({'ca_bundle': - cert_path})]) + self.assertEqual(mock_ca.call_args_list, [call({"ca_bundle": cert_path})]) class TestCertificateVerify(TestCase, LoaderModuleMockMixin): From e1f6b829bd8123ebf9a8d434a08f2caa17588581 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Tue, 19 Jan 2021 18:00:33 -0500 Subject: [PATCH 51/69] Use requests CA bundle by default --- salt/modules/vsphere.py | 3 --- tests/unit/modules/test_vsphere.py | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/salt/modules/vsphere.py b/salt/modules/vsphere.py index c7ff9c1db19..666e850ef91 100644 --- a/salt/modules/vsphere.py +++ b/salt/modules/vsphere.py @@ -10340,9 +10340,6 @@ def _get_client(server, username, password, verify_ssl=None, ca_bundle=None): if ca_bundle: ca_bundle = salt.utils.http.get_ca_bundle({"ca_bundle": ca_bundle}) - if verify_ssl and ca_bundle is None: - ca_bundle = salt.utils.http.get_ca_bundle() - # Establish connection with client client = salt.utils.vmware.get_vsphere_client( server=server, diff --git a/tests/unit/modules/test_vsphere.py b/tests/unit/modules/test_vsphere.py index 8b2ca88ce04..5e5cf8c8465 100644 --- a/tests/unit/modules/test_vsphere.py +++ b/tests/unit/modules/test_vsphere.py @@ -3184,7 +3184,7 @@ class TestVSphereTagging(TestCase, LoaderModuleMockMixin): mock_client.call_args_list, [ call( - ca_bundle=cert_path, + ca_bundle=None, password="testpassword", server="localhost", username="testuser", @@ -3193,7 +3193,7 @@ class TestVSphereTagging(TestCase, LoaderModuleMockMixin): ], ) self.assertEqual(mock_details.assert_called_once(), None) - self.assertEqual(mock_ca.assert_called_once(), None) + self.assertEqual(mock_ca.assert_not_called(), None) def test_get_client_verify_ssl_false(self): """ From ac2ce3a3a000e428122bc120179e083de95c1de7 Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Mon, 18 Jan 2021 20:50:25 -0700 Subject: [PATCH 52/69] Tests and fix for CVE-2021-25284 --- salt/modules/cmdmod.py | 25 +++++++++++-------------- tests/unit/modules/test_cmdmod.py | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/salt/modules/cmdmod.py b/salt/modules/cmdmod.py index c8eb4d23059..feae915b91f 100644 --- a/salt/modules/cmdmod.py +++ b/salt/modules/cmdmod.py @@ -77,6 +77,12 @@ def __virtual__(): return __virtualname__ +def _log_cmd(cmd): + if not isinstance(cmd, list): + return cmd.split()[0].strip() + return cmd[0].strip() + + def _check_cb(cb_): """ If the callback is None or is not callable, return a lambda that returns @@ -386,22 +392,13 @@ def _run( ) env[bad_env_key] = "" - def _get_stripped(cmd): - # Return stripped command string copies to improve logging. - if isinstance(cmd, list): - return [x.strip() if isinstance(x, str) else x for x in cmd] - elif isinstance(cmd, str): - return cmd.strip() - else: - return cmd - if output_loglevel is not None: # Always log the shell commands at INFO unless quiet logging is # requested. The command output is what will be controlled by the # 'loglevel' parameter. msg = "Executing command {}{}{} {}{}in directory '{}'{}".format( "'" if not isinstance(cmd, list) else "", - _get_stripped(cmd), + _log_cmd(cmd), "'" if not isinstance(cmd, list) else "", "as user '{}' ".format(runas) if runas else "", "in group '{}' ".format(group) if group else "", @@ -723,7 +720,7 @@ def _run( log.error( "Failed to decode stdout from command %s, non-decodable " "characters have been replaced", - cmd, + _log_cmd(cmd), ) try: @@ -741,7 +738,7 @@ def _run( log.error( "Failed to decode stderr from command %s, non-decodable " "characters have been replaced", - cmd, + _log_cmd(cmd), ) if rstrip: @@ -841,7 +838,7 @@ def _run( if not ignore_retcode and ret["retcode"] != 0: if output_loglevel < LOG_LEVELS["error"]: output_loglevel = LOG_LEVELS["error"] - msg = "Command '{}' failed with return code: {}".format(cmd, ret["retcode"]) + msg = "Command '{}' failed with return code: {}".format(_log_cmd(cmd), ret["retcode"]) log.error(log_callback(msg)) if ret["stdout"]: log.log(output_loglevel, "stdout: %s", log_callback(ret["stdout"])) @@ -1211,7 +1208,7 @@ def run( if not ignore_retcode and ret["retcode"] != 0: if lvl < LOG_LEVELS["error"]: lvl = LOG_LEVELS["error"] - msg = "Command '{}' failed with return code: {}".format(cmd, ret["retcode"]) + msg = "Command '{}' failed with return code: {}".format(_log_cmd(cmd), ret["retcode"]) log.error(log_callback(msg)) if raise_err: raise CommandExecutionError( diff --git a/tests/unit/modules/test_cmdmod.py b/tests/unit/modules/test_cmdmod.py index 15b97f85688..29167e9ab66 100644 --- a/tests/unit/modules/test_cmdmod.py +++ b/tests/unit/modules/test_cmdmod.py @@ -640,3 +640,20 @@ class CMDMODTestCase(TestCase, LoaderModuleMockMixin): umask=None, use_vt=False, ) + + def test_cve_2021_25284(self): + proc = MagicMock( + return_value=MockTimedProc( + stdout=b"foo", + stderr=b"wtf", + returncode=2 + ) + ) + with patch("salt.utils.timed_subprocess.TimedProc", proc): + with TstSuiteLoggingHandler() as log_handler: + cmdmod.run("testcmd -p ImAPassword", output_loglevel="error") + for x in log_handler.messages: + if x.find("Executing command") > -1: + assert x.find("ImAPassword") == -1, x + if x.find("faild with return code") > -1: + assert x.find("ImAPassword") == -1, x From 38078de88ba457f2b78959b181f4b51254508630 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Thu, 21 Jan 2021 11:27:17 +0000 Subject: [PATCH 53/69] Fix the `AsamRunnerVerifySslTest.test_add_platform` test --- tests/unit/runners/test_asam.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/tests/unit/runners/test_asam.py b/tests/unit/runners/test_asam.py index ebd8e95bb87..8efd24e6ffd 100644 --- a/tests/unit/runners/test_asam.py +++ b/tests/unit/runners/test_asam.py @@ -39,19 +39,13 @@ class AsamRunnerVerifySslTest(TestCase, LoaderModuleMockMixin): with patch("salt.runners.asam._parse_html_content", parse_html_content), patch( "salt.runners.asam._get_platformset_name", get_platform_set_name ), patch("salt.runners.asam.requests.post", requests_mock): - asam.remove_platform("plat-foo-2", "prov1.domain.com") + asam.add_platform("plat-foo-2", "plat-foo", "prov1.domain.com") requests_mock.assert_called_with( - "https://prov1.domain.com:3451/config/PlatformConfig.html", - auth=("TheUsername", "ThePassword"), - data={ - "manual": "false", - "platformName": "plat-foo-2", - "platformSetName": "plat-foo", - "postType": "platformRemove", - "Submit": "Yes", - }, - verify=True, + 'https://prov1.domain.com:3451/config/PlatformSetConfig.html', + auth=('TheUsername', 'ThePassword'), + data={'manual': 'false'}, + verify=True ) def test_remove_platform(self): From aafc5ed6de60403c90201d85963299df351147ec Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Fri, 22 Jan 2021 14:25:39 -0700 Subject: [PATCH 54/69] Tests and fix for CVE-2021-25282 --- salt/wheel/pillar_roots.py | 8 +++-- tests/integration/wheel/test_pillar_roots.py | 37 ++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 tests/integration/wheel/test_pillar_roots.py diff --git a/salt/wheel/pillar_roots.py b/salt/wheel/pillar_roots.py index 2c242ef3a7e..5b164c31971 100644 --- a/salt/wheel/pillar_roots.py +++ b/salt/wheel/pillar_roots.py @@ -4,16 +4,14 @@ The `pillar_roots` wheel module is used to manage files under the pillar roots directories on the master server. """ -# Import python libs from __future__ import absolute_import, print_function, unicode_literals import os -# Import salt libs import salt.utils.files import salt.utils.path +import salt.utils.verify -# Import 3rd-party libs from salt.ext import six @@ -109,6 +107,10 @@ def write(data, path, saltenv="base", index=0): return ( "The path passed in {0} is not relative to the environment " "{1}" ).format(path, saltenv) + roots_dir = __opts__["pillar_roots"][saltenv][index] + dest = os.path.join(roots_dir, path) + if not salt.utils.verify.clean_path(roots_dir, dest): + return "Invalid path" dest = os.path.join(__opts__["pillar_roots"][saltenv][index], path) dest_dir = os.path.dirname(dest) if not os.path.isdir(dest_dir): diff --git a/tests/integration/wheel/test_pillar_roots.py b/tests/integration/wheel/test_pillar_roots.py new file mode 100644 index 00000000000..98512af95ef --- /dev/null +++ b/tests/integration/wheel/test_pillar_roots.py @@ -0,0 +1,37 @@ +import os + +import salt.wheel +from tests.support.mixins import AdaptedConfigurationTestCaseMixin +from tests.support.unit import TestCase + + +class WheelPillarRootsTest(TestCase, AdaptedConfigurationTestCaseMixin): + def setUp(self): + self.wheel = salt.wheel.Wheel(dict(self.get_config("client_config"))) + self.pillar_dir = self.wheel.opts["pillar_roots"]["base"][0] + self.traversed_dir = os.path.dirname(self.pillar_dir) + + def tearDown(self): + try: + os.remove(os.path.join(self.pillar_dir, "foo")) + except Exception: + pass + try: + os.remove(os.path.join(self.traversed_dir, "foo")) + except Exception: + pass + del self.wheel + + def test_write(self): + ret = self.wheel.cmd( + "pillar_roots.write", kwarg={"data": "foo: bar", "path": "foo"} + ) + assert os.path.exists(os.path.join(self.pillar_dir, "foo")) + assert ret.find("Wrote data to file") != -1 + + def test_cvr_2021_25282(self): + ret = self.wheel.cmd( + "pillar_roots.write", kwarg={"data": "foo", "path": "../foo"} + ) + assert not os.path.exists(os.path.join(self.traversed_dir, "foo")) + assert ret.find("Invalid path") != -1 From 14baae8b095df37f140ce50c00bffbbf621ee165 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Thu, 21 Jan 2021 16:35:17 -0500 Subject: [PATCH 55/69] compare mock object call_args_list in splunk returner --- tests/unit/returners/test_splunk.py | 33 ++++++++++++++++------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/tests/unit/returners/test_splunk.py b/tests/unit/returners/test_splunk.py index d48b26294b6..a1ed49c3dc2 100644 --- a/tests/unit/returners/test_splunk.py +++ b/tests/unit/returners/test_splunk.py @@ -1,11 +1,9 @@ -# -*- coding: utf-8 -*- """ tests.unit.returners.test_splunk ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Unit tests for the splunk returner """ -from __future__ import absolute_import, print_function, unicode_literals import json import logging @@ -20,7 +18,6 @@ log = logging.getLogger(__name__) class SplunkReturnerTest(TestCase, LoaderModuleMockMixin): - def setup_loader_modules(self): opts = { "splunk_http_forwarder": { @@ -55,18 +52,20 @@ class SplunkReturnerTest(TestCase, LoaderModuleMockMixin): "requests.post", requests_post ): splunk.returner(payload.copy()) - requests_post.assert_called_with( - "https://the.splunk.domain:8088/services/collector/event", - data=json.dumps(data), - headers={"Authorization": "Splunk TheToken"}, - verify=True, + assert json.loads(requests_post.call_args_list[0][1]["data"]) == data + assert requests_post.call_args_list[0][1]["verify"] + assert requests_post.call_args_list[0][1]["headers"] == { + "Authorization": "Splunk TheToken" + } + assert ( + requests_post.call_args_list[0][0][0] + == "https://the.splunk.domain:8088/services/collector/event" ) def test_verify_ssl(self): payload = {"some": "payload"} verify_ssl_values = [True, False, None] payload = {"some": "payload"} - requests_post = MagicMock() ts = 1234565789 host = "TheHostName" data = { @@ -77,6 +76,7 @@ class SplunkReturnerTest(TestCase, LoaderModuleMockMixin): "host": host, } for verify_ssl in verify_ssl_values: + requests_post = MagicMock() with patch( "salt.returners.splunk.time.time", MagicMock(return_value=ts) ), patch( @@ -87,9 +87,12 @@ class SplunkReturnerTest(TestCase, LoaderModuleMockMixin): splunk.__opts__["splunk_http_forwarder"], verify_ssl=verify_ssl ): splunk.returner(payload.copy()) - requests_post.assert_called_with( - "https://the.splunk.domain:8088/services/collector/event", - data=json.dumps(data), - headers={"Authorization": "Splunk TheToken"}, - verify=verify_ssl, - ) + assert json.loads(requests_post.call_args_list[0][1]["data"]) == data + assert requests_post.call_args_list[0][1]["verify"] == verify_ssl + assert requests_post.call_args_list[0][1]["headers"] == { + "Authorization": "Splunk TheToken" + } + assert ( + requests_post.call_args_list[0][0][0] + == "https://the.splunk.domain:8088/services/collector/event" + ) From 5273722c2180c394bc426f731450b95809ca952e Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Thu, 21 Jan 2021 17:40:25 -0700 Subject: [PATCH 56/69] Tests and fix for CVE-2021-3197 --- salt/client/ssh/client.py | 46 +++++++++++++++++++++++++ tests/integration/netapi/test_client.py | 37 ++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/salt/client/ssh/client.py b/salt/client/ssh/client.py index 55436366cf4..9ece7e8b37f 100644 --- a/salt/client/ssh/client.py +++ b/salt/client/ssh/client.py @@ -45,12 +45,58 @@ class SSHClient(object): # Salt API should never offer a custom roster! self.opts["__disable_custom_roster"] = disable_custom_roster + def sanitize_kwargs(self, kwargs): + roster_vals = [ + ("host", str), + ("ssh_user", str), + ("ssh_passwd", str), + ("ssh_port", int), + ("ssh_sudo", bool), + ("ssh_sudo_user", str), + ("ssh_priv", str), + ("ssh_priv_passwd", str), + ("ssh_identities_only", bool), + ("ssh_remote_port_forwards", bool), + ("ssh_options", list), + ("roster_file", str), + ("rosters", list), + ("ignore_host_keys", bool), + ("raw_shell", bool), + ] + sane_kwargs = {} + for name, kind in roster_vals: + if name not in kwargs: + continue + try: + val = kind(kwargs[name]) + except ValueError: + log.warn("Unable to cast kwarg %s", name) + continue + if kind is bool or kind is int: + sane_kwargs[name] = val + elif kind is str: + if val.find("ProxyCommand") != -1: + log.warn("Filter unsafe value for kwarg %s", name) + continue + sane_kwargs[name] = val + elif kind is list: + sane_val = [] + for item in val: + # This assumes the values are strings + if item.find("ProxyCommand") != -1: + log.warn("Filter unsafe value for kwarg %s", name) + continue + sane_val.append(item) + sane_kwargs[name] = sane_val + return sane_kwargs + def _prep_ssh( self, tgt, fun, arg=(), timeout=None, tgt_type="glob", kwarg=None, **kwargs ): """ Prepare the arguments """ + kwargs = self.sanitize_kwargs(kwargs) opts = copy.deepcopy(self.opts) opts.update(kwargs) if timeout: diff --git a/tests/integration/netapi/test_client.py b/tests/integration/netapi/test_client.py index 6b6ec1b8368..75161986eba 100644 --- a/tests/integration/netapi/test_client.py +++ b/tests/integration/netapi/test_client.py @@ -458,8 +458,14 @@ class NetapiSSHClientAuthTest(SSHCase): except AssertionError: self.mod_case.run_function("user.delete", [self.USERA], remove=True) self.skipTest("Could not add user or password, skipping test") + self.expfile = os.path.join(RUNTIME_VARS.TMP, "exploited") def tearDown(self): + try: + os.remove(self.expfile) + except OSError: + pass + del self.expfile del self.netapi self.mod_case.run_function("user.delete", [self.USERA], remove=True) @@ -608,3 +614,34 @@ class NetapiSSHClientAuthTest(SSHCase): ret = self.netapi.run(low) assert "localhost" in ret assert ret["localhost"]["return"] is True + + def test_ssh_cve_2021_3197_a(self): + assert not os.path.exists(self.expfile) + low = { + "eauth": "auto", + "username": self.USERA, + "password": self.USERA_PWD, + "client": "ssh", + "tgt": "localhost", + "fun": "test.ping", + "ssh_port": '22 -o ProxyCommand="touch {}"'.format(self.expfile), + "ssh_priv": self.priv_file, + } + ret = self.netapi.run(low) + assert not os.path.exists(self.expfile) + + def test_ssh_cve_2021_3197_b(self): + assert not os.path.exists(self.expfile) + low = { + "eauth": "auto", + "username": self.USERA, + "password": self.USERA_PWD, + "client": "ssh", + "tgt": "localhost", + "fun": "test.ping", + "ssh_port": 22, + "ssh_priv": self.priv_file, + "ssh_options": ['ProxyCommand="touch {}"'.format(self.expfile)], + } + ret = self.netapi.run(low) + assert not os.path.exists(self.expfile) From 386fd5fdc236e47219a437166c87118a854b9345 Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Fri, 22 Jan 2021 19:37:26 -0500 Subject: [PATCH 57/69] Set verify_ssl for vmware proxy --- salt/modules/vsphere.py | 17 +++++++++++------ salt/utils/vmware.py | 8 ++++---- tests/unit/modules/test_vsphere.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/salt/modules/vsphere.py b/salt/modules/vsphere.py index 666e850ef91..7100e3fde49 100644 --- a/salt/modules/vsphere.py +++ b/salt/modules/vsphere.py @@ -336,7 +336,7 @@ def _get_proxy_connection_details(): details = __salt__["esxvm.get_details"]() else: raise CommandExecutionError("'{}' proxy is not supported" "".format(proxytype)) - return ( + proxy_details = [ details.get("vcenter") if "vcenter" in details else details.get("host"), details.get("username"), details.get("password"), @@ -345,7 +345,10 @@ def _get_proxy_connection_details(): details.get("mechanism"), details.get("principal"), details.get("domain"), - ) + ] + if "verify_ssl" in details: + proxy_details.append(details.get("verify_ssl")) + return tuple(proxy_details) def supports_proxies(*proxy_types): @@ -429,7 +432,7 @@ def gets_service_instance_via_proxy(fn): # case 1: The call was made with enough positional # parameters to include 'service_instance' if not args[idx]: - local_service_instance = salt.utils.vmware.get_service_instance( + local_service_instance = salt.utils.vmware.get_service_instance( # pylint: disable=no-value-for-parameter *connection_details ) # Tuples are immutable, so if we want to change what @@ -440,7 +443,7 @@ def gets_service_instance_via_proxy(fn): # case 2: Not enough positional parameters so # 'service_instance' must be a named parameter if not kwargs.get("service_instance"): - local_service_instance = salt.utils.vmware.get_service_instance( + local_service_instance = salt.utils.vmware.get_service_instance( # pylint: disable=no-value-for-parameter *connection_details ) kwargs["service_instance"] = local_service_instance @@ -448,7 +451,7 @@ def gets_service_instance_via_proxy(fn): # 'service_instance' is not a paremter in the function definition # but it will be caught by the **kwargs parameter if not kwargs.get("service_instance"): - local_service_instance = salt.utils.vmware.get_service_instance( + local_service_instance = salt.utils.vmware.get_service_instance( # pylint: disable=no-value-for-parameter *connection_details ) kwargs["service_instance"] = local_service_instance @@ -485,7 +488,9 @@ def get_service_instance_via_proxy(service_instance=None): See note above """ connection_details = _get_proxy_connection_details() - return salt.utils.vmware.get_service_instance(*connection_details) + return salt.utils.vmware.get_service_instance( # pylint: disable=no-value-for-parameter + *connection_details + ) @depends(HAS_PYVMOMI) diff --git a/salt/utils/vmware.py b/salt/utils/vmware.py index ee600722465..f801ba2aab3 100644 --- a/salt/utils/vmware.py +++ b/salt/utils/vmware.py @@ -268,6 +268,10 @@ def _get_service_instance( log.trace( "Connecting using the '%s' mechanism, with username '%s'", mechanism, username, ) + default_msg = ( + "Could not connect to host '{}'. " + "Please check the debug log for more information.".format(host) + ) try: if verify_ssl: @@ -292,10 +296,6 @@ def _get_service_instance( raise except Exception as exc: # pylint: disable=broad-except # pyVmomi's SmartConnect() actually raises Exception in some cases. - default_msg = ( - "Could not connect to host '{}'. " - "Please check the debug log for more information.".format(host) - ) if ( isinstance(exc, vim.fault.HostConnectFault) and "[SSL: CERTIFICATE_VERIFY_FAILED]" in exc.msg diff --git a/tests/unit/modules/test_vsphere.py b/tests/unit/modules/test_vsphere.py index 5e5cf8c8465..3baf8fa57ab 100644 --- a/tests/unit/modules/test_vsphere.py +++ b/tests/unit/modules/test_vsphere.py @@ -5,6 +5,7 @@ Tests for functions in salt.modules.vsphere """ + import salt.modules.vsphere as vsphere import salt.utils.args import salt.utils.vmware @@ -1100,6 +1101,34 @@ class _GetProxyConnectionDetailsTestCase(TestCase, LoaderModuleMockMixin): "'unsupported' proxy is not supported", excinfo.exception.strerror ) + def test_vcenter_proxy_details_verify_ssl(self): + for verify_ssl in [True, False]: + details = self.vcenter_details.copy() + details["verify_ssl"] = verify_ssl + + with patch( + "salt.modules.vsphere.get_proxy_type", MagicMock(return_value="vcenter") + ): + with patch.dict( + vsphere.__salt__, + {"vcenter.get_details": MagicMock(return_value=details)}, + ): + ret = vsphere._get_proxy_connection_details() + self.assertEqual( + ( + "fake_vcenter", + "fake_username", + "fake_password", + "fake_protocol", + "fake_port", + "fake_mechanism", + "fake_principal", + "fake_domain", + verify_ssl, + ), + ret, + ) + class GetsServiceInstanceViaProxyTestCase(TestCase, LoaderModuleMockMixin): """ From d809689ae8a5465018d0aeb7baf9040766c298ac Mon Sep 17 00:00:00 2001 From: Megan Wilhite Date: Sat, 23 Jan 2021 13:01:48 -0500 Subject: [PATCH 58/69] query verify_ssl from proxy config --- salt/modules/vsphere.py | 16 +- tests/unit/modules/test_vsphere.py | 514 +++++++++++++++++++---------- 2 files changed, 339 insertions(+), 191 deletions(-) diff --git a/salt/modules/vsphere.py b/salt/modules/vsphere.py index 7100e3fde49..8fc2c410f2c 100644 --- a/salt/modules/vsphere.py +++ b/salt/modules/vsphere.py @@ -10365,7 +10365,7 @@ def list_tag_categories( username=None, password=None, service_instance=None, - verify_ssl=True, + verify_ssl=None, ca_bundle=None, ): """ @@ -10410,7 +10410,7 @@ def list_tags( username=None, password=None, service_instance=None, - verify_ssl=True, + verify_ssl=None, ca_bundle=None, ): """ @@ -10458,7 +10458,7 @@ def attach_tag( username=None, password=None, service_instance=None, - verify_ssl=True, + verify_ssl=None, ca_bundle=None, ): """ @@ -10542,7 +10542,7 @@ def list_attached_tags( username=None, password=None, service_instance=None, - verify_ssl=True, + verify_ssl=None, ca_bundle=None, ): """ @@ -10615,7 +10615,7 @@ def create_tag_category( username=None, password=None, service_instance=None, - verify_ssl=True, + verify_ssl=None, ca_bundle=None, ): """ @@ -10694,7 +10694,7 @@ def delete_tag_category( username=None, password=None, service_instance=None, - verify_ssl=True, + verify_ssl=None, ca_bundle=None, ): """ @@ -10754,7 +10754,7 @@ def create_tag( username=None, password=None, service_instance=None, - verify_ssl=True, + verify_ssl=None, ca_bundle=None, ): """ @@ -10826,7 +10826,7 @@ def delete_tag( username=None, password=None, service_instance=None, - verify_ssl=True, + verify_ssl=None, ca_bundle=None, ): """ diff --git a/tests/unit/modules/test_vsphere.py b/tests/unit/modules/test_vsphere.py index 3baf8fa57ab..37a310403ce 100644 --- a/tests/unit/modules/test_vsphere.py +++ b/tests/unit/modules/test_vsphere.py @@ -2631,52 +2631,70 @@ class TestVSphereTagging(TestCase, LoaderModuleMockMixin): self.assertEqual(ret, {"Category created": None}) def test_create_tag_category_client(self): - get_details = MagicMock(return_value=self.details) + for verify_ssl in [True, False, None]: + details = self.details.copy() + if verify_ssl is None: + verify_ssl = True + else: + details["verify_ssl"] = verify_ssl + get_details = MagicMock(return_value=details) - # Mock CreateSpec object and create objects - mock_client = Mock( - tagging=Mock( - Category=Mock( - CreateSpec=Mock(return_value=Mock()), - create=Mock( - return_value=self.create_tag_category["Category created"] - ), + # Mock CreateSpec object and create objects + mock_client = Mock( + tagging=Mock( + Category=Mock( + CreateSpec=Mock(return_value=Mock()), + create=Mock( + return_value=self.create_tag_category["Category created"] + ), + ) ) ) - ) - # Start patching each external API return with Mock Objects - with patch.object( - vsphere, "get_proxy_type", return_value="vcenter" - ) as get_proxy_type: + # Start patching each external API return with Mock Objects with patch.object( - vsphere, "_get_proxy_connection_details", return_value=[] - ) as get_proxy_connection: + vsphere, "get_proxy_type", return_value="vcenter" + ) as get_proxy_type: with patch.object( - salt.utils.vmware, "get_service_instance", return_value=None - ) as get_service_instance: - with patch.dict( - vsphere.__salt__, - {"vcenter.get_details": get_details}, - clear=True, - ) as get_vcenter_details: - with patch.object( - salt.utils.vmware, - "get_vsphere_client", - return_value=mock_client, - ) as get_vsphere_client: - ret = vsphere.create_tag_category( - self.func_attrs["name"], - self.func_attrs["description"], - self.func_attrs["cardinality"], - ) + vsphere, "_get_proxy_connection_details", return_value=[] + ) as get_proxy_connection: + with patch.object( + salt.utils.vmware, "get_service_instance", return_value=None + ) as get_service_instance: + with patch.dict( + vsphere.__salt__, + {"vcenter.get_details": get_details}, + clear=True, + ) as get_vcenter_details: + with patch.object( + salt.utils.vmware, + "get_vsphere_client", + return_value=mock_client, + ) as get_vsphere_client: + ret = vsphere.create_tag_category( + self.func_attrs["name"], + self.func_attrs["description"], + self.func_attrs["cardinality"], + ) - # Check function calls and return data - get_proxy_type.assert_called_once() - get_proxy_connection.assert_called_once() - get_service_instance.assert_called_once() - get_vsphere_client.assert_called_once() - self.assertEqual(ret, self.create_tag_category) + # Check function calls and return data + get_proxy_type.assert_called_once() + get_proxy_connection.assert_called_once() + get_service_instance.assert_called_once() + get_vsphere_client.assert_called_once() + self.assertEqual(ret, self.create_tag_category) + self.assertEqual( + get_vsphere_client.call_args_list, + [ + call( + ca_bundle=None, + password=None, + server=None, + username=None, + verify_ssl=verify_ssl, + ) + ], + ) def test_create_tag_client_none(self): get_details = MagicMock(return_value=self.details) @@ -2788,49 +2806,67 @@ class TestVSphereTagging(TestCase, LoaderModuleMockMixin): self.assertEqual(ret, {"Category deleted": None}) def test_delete_tag_category_client(self): - get_details = MagicMock(return_value=self.details) + for verify_ssl in [True, False, None]: + details = self.details.copy() + if verify_ssl is None: + verify_ssl = True + else: + details["verify_ssl"] = verify_ssl + get_details = MagicMock(return_value=details) - # Mock CreateSpec object and create objects - mock_client = Mock( - tagging=Mock( - Category=Mock( - delete=Mock( - return_value=self.delete_tag_category["Category deleted"] + # Mock CreateSpec object and create objects + mock_client = Mock( + tagging=Mock( + Category=Mock( + delete=Mock( + return_value=self.delete_tag_category["Category deleted"] + ) ) ) ) - ) - # Start patching each external API return with Mock Objects - with patch.object( - vsphere, "get_proxy_type", return_value="vcenter" - ) as get_proxy_type: + # Start patching each external API return with Mock Objects with patch.object( - vsphere, "_get_proxy_connection_details", return_value=[] - ) as get_proxy_connection: + vsphere, "get_proxy_type", return_value="vcenter" + ) as get_proxy_type: with patch.object( - salt.utils.vmware, "get_service_instance", return_value=None - ) as get_service_instance: - with patch.dict( - vsphere.__salt__, - {"vcenter.get_details": get_details}, - clear=True, - ) as get_vcenter_details: - with patch.object( - salt.utils.vmware, - "get_vsphere_client", - return_value=mock_client, - ) as get_vsphere_client: - ret = vsphere.delete_tag_category( - self.func_attrs["category_id"] - ) + vsphere, "_get_proxy_connection_details", return_value=[] + ) as get_proxy_connection: + with patch.object( + salt.utils.vmware, "get_service_instance", return_value=None + ) as get_service_instance: + with patch.dict( + vsphere.__salt__, + {"vcenter.get_details": get_details}, + clear=True, + ) as get_vcenter_details: + with patch.object( + salt.utils.vmware, + "get_vsphere_client", + return_value=mock_client, + ) as get_vsphere_client: + ret = vsphere.delete_tag_category( + self.func_attrs["category_id"] + ) - # Check function calls and return data - get_proxy_type.assert_called_once() - get_proxy_connection.assert_called_once() - get_service_instance.assert_called_once() - get_vsphere_client.assert_called_once() - self.assertEqual(ret, self.delete_tag_category) + # Check function calls and return data + get_proxy_type.assert_called_once() + get_proxy_connection.assert_called_once() + get_service_instance.assert_called_once() + get_vsphere_client.assert_called_once() + self.assertEqual(ret, self.delete_tag_category) + self.assertEqual( + get_vsphere_client.call_args_list, + [ + call( + ca_bundle=None, + password=None, + server=None, + username=None, + verify_ssl=verify_ssl, + ) + ], + ) def test_delete_tag_client_none(self): get_details = MagicMock(return_value=self.details) @@ -2930,44 +2966,64 @@ class TestVSphereTagging(TestCase, LoaderModuleMockMixin): self.assertEqual(ret, {"Categories": None}) def test_list_tag_categories_client(self): - get_details = MagicMock(return_value=self.details) + for verify_ssl in [True, False, None]: + details = self.details.copy() + if verify_ssl is not None: + details["verify_ssl"] = verify_ssl + else: + verify_ssl = True + get_details = MagicMock(return_value=details) - # Mock CreateSpec object and create objects - mock_client = Mock( - tagging=Mock( - Category=Mock(list=Mock(return_value=self.list_tag_categories_return)) + # Mock CreateSpec object and create objects + mock_client = Mock( + tagging=Mock( + Category=Mock( + list=Mock(return_value=self.list_tag_categories_return) + ) + ) ) - ) - # Start patching each external API return with Mock Objects - with patch.object( - vsphere, "get_proxy_type", return_value="vcenter" - ) as get_proxy_type: + # Start patching each external API return with Mock Objects with patch.object( - vsphere, "_get_proxy_connection_details", return_value=[] - ) as get_proxy_connection: + vsphere, "get_proxy_type", return_value="vcenter" + ) as get_proxy_type: with patch.object( - salt.utils.vmware, "get_service_instance", return_value=None - ) as get_service_instance: - with patch.dict( - vsphere.__salt__, - {"vcenter.get_details": get_details}, - clear=True, - ) as get_vcenter_details: - with patch.object( - salt.utils.vmware, - "get_vsphere_client", - return_value=mock_client, - ) as get_vsphere_client: - ret = vsphere.list_tag_categories() + vsphere, "_get_proxy_connection_details", return_value=[] + ) as get_proxy_connection: + with patch.object( + salt.utils.vmware, "get_service_instance", return_value=None + ) as get_service_instance: + with patch.dict( + vsphere.__salt__, + {"vcenter.get_details": get_details}, + clear=True, + ) as get_vcenter_details: + with patch.object( + salt.utils.vmware, + "get_vsphere_client", + return_value=mock_client, + ) as get_vsphere_client: + ret = vsphere.list_tag_categories() - get_proxy_type.assert_called_once() - get_proxy_connection.assert_called_once() - get_service_instance.assert_called_once() - get_vsphere_client.assert_called_once() - self.assertEqual( - ret, {"Categories": self.list_tag_categories_return} - ) + get_proxy_type.assert_called_once() + get_proxy_connection.assert_called_once() + get_service_instance.assert_called_once() + get_vsphere_client.assert_called_once() + self.assertEqual( + get_vsphere_client.call_args_list, + [ + call( + ca_bundle=None, + password=None, + server=None, + username=None, + verify_ssl=verify_ssl, + ) + ], + ) + self.assertEqual( + ret, {"Categories": self.list_tag_categories_return} + ) def test_list_tags_client_none(self): get_details = MagicMock(return_value=self.details) @@ -3034,6 +3090,56 @@ class TestVSphereTagging(TestCase, LoaderModuleMockMixin): get_vsphere_client.assert_called_once() self.assertEqual(ret, {"Tags": self.list_tags_return}) + def test_list_tags_client_verify_ssl(self): + for verify_ssl in [True, False]: + details = self.details.copy() + if verify_ssl is not None: + details["verify_ssl"] = verify_ssl + else: + verify_ssl = True + get_details = MagicMock(return_value=details) + + # Mock CreateSpec object and create objects + mock_client = Mock( + tagging=Mock(Tag=Mock(list=Mock(return_value=self.list_tags_return))) + ) + + # Start patching each external API return with Mock Objects + with patch.object( + vsphere, "get_proxy_type", return_value="vcenter" + ) as get_proxy_type: + with patch.object( + vsphere, "_get_proxy_connection_details", return_value=[] + ) as get_proxy_connection: + with patch.object( + salt.utils.vmware, "get_service_instance", return_value=None + ) as get_service_instance: + with patch.dict( + vsphere.__salt__, + {"vcenter.get_details": get_details}, + clear=True, + ) as get_vcenter_details: + with patch.object( + salt.utils.vmware, + "get_vsphere_client", + return_value=mock_client, + ) as get_vsphere_client: + # Check function calls and return + ret = vsphere.list_tags() + self.assertEqual(ret, {"Tags": self.list_tags_return}) + self.assertEqual( + get_vsphere_client.call_args_list, + [ + call( + ca_bundle=None, + password=None, + server=None, + username=None, + verify_ssl=verify_ssl, + ) + ], + ) + def test_list_attached_tags_client_none(self): get_details = MagicMock(return_value=self.details) @@ -3065,50 +3171,72 @@ class TestVSphereTagging(TestCase, LoaderModuleMockMixin): self.assertEqual(ret, {"Attached tags": None}) def test_list_attached_tags_client(self): - get_details = MagicMock(return_value=self.details) + for verify_ssl in [True, False, None]: + details = self.details.copy() + if verify_ssl is None: + verify_ssl = True + else: + details["verify_ssl"] = verify_ssl + get_details = MagicMock(return_value=details) - # Mock CreateSpec object and create objects - mock_client = Mock( - tagging=Mock( - TagAssociation=Mock( - list_attached_tags=Mock(return_value=self.list_attached_tags_return) + # Mock CreateSpec object and create objects + mock_client = Mock( + tagging=Mock( + TagAssociation=Mock( + list_attached_tags=Mock( + return_value=self.list_attached_tags_return + ) + ) ) ) - ) - # Start patching each external API return with Mock Objects - with patch.object( - vsphere, "get_proxy_type", return_value="vcenter" - ) as get_proxy_type: + # Start patching each external API return with Mock Objects with patch.object( - vsphere, "_get_proxy_connection_details", return_value=[] - ) as get_proxy_connection: + vsphere, "get_proxy_type", return_value="vcenter" + ) as get_proxy_type: with patch.object( - salt.utils.vmware, "get_service_instance", return_value=None - ) as get_service_instance: - with patch.dict( - vsphere.__salt__, - {"vcenter.get_details": get_details}, - clear=True, - ) as get_vcenter_details: - with patch.object( - salt.utils.vmware, - "get_vsphere_client", - return_value=mock_client, - ) as get_vsphere_client: - with patch.object(vsphere, "DynamicID") as dynamic_id: - # Check function calls and return - ret = vsphere.list_attached_tags( - self.func_attrs["object_id"] - ) - get_proxy_type.assert_called_once() - get_proxy_connection.assert_called_once() - get_service_instance.assert_called_once() - get_vsphere_client.assert_called_once() - self.assertEqual( - ret, - {"Attached tags": self.list_attached_tags_return}, - ) + vsphere, "_get_proxy_connection_details", return_value=[] + ) as get_proxy_connection: + with patch.object( + salt.utils.vmware, "get_service_instance", return_value=None + ) as get_service_instance: + with patch.dict( + vsphere.__salt__, + {"vcenter.get_details": get_details}, + clear=True, + ) as get_vcenter_details: + with patch.object( + salt.utils.vmware, + "get_vsphere_client", + return_value=mock_client, + ) as get_vsphere_client: + with patch.object(vsphere, "DynamicID") as dynamic_id: + # Check function calls and return + ret = vsphere.list_attached_tags( + self.func_attrs["object_id"] + ) + get_proxy_type.assert_called_once() + get_proxy_connection.assert_called_once() + get_service_instance.assert_called_once() + get_vsphere_client.assert_called_once() + self.assertEqual( + ret, + { + "Attached tags": self.list_attached_tags_return + }, + ) + self.assertEqual( + get_vsphere_client.call_args_list, + [ + call( + ca_bundle=None, + password=None, + server=None, + username=None, + verify_ssl=verify_ssl, + ) + ], + ) def test_attach_tags_client_none(self): get_details = MagicMock(return_value=self.details) @@ -3143,51 +3271,71 @@ class TestVSphereTagging(TestCase, LoaderModuleMockMixin): self.assertEqual(ret, {"Tag attached": None}) def test_attach_tags_client(self): - get_details = MagicMock(return_value=self.details) + for verify_ssl in [True, False, None]: + details = self.details.copy() + if verify_ssl is None: + verify_ssl = True + else: + details["verify_ssl"] = verify_ssl + get_details = MagicMock(return_value=details) - # Mock CreateSpec object and create objects - mock_client = Mock( - tagging=Mock( - TagAssociation=Mock( - attach=Mock(return_value=self.list_attached_tags_return) + # Mock CreateSpec object and create objects + mock_client = Mock( + tagging=Mock( + TagAssociation=Mock( + attach=Mock(return_value=self.list_attached_tags_return) + ) ) ) - ) - # Start patching each external API return with Mock Objects - with patch.object( - vsphere, "get_proxy_type", return_value="vcenter" - ) as get_proxy_type: + # Start patching each external API return with Mock Objects with patch.object( - vsphere, "_get_proxy_connection_details", return_value=[] - ) as get_proxy_connection: + vsphere, "get_proxy_type", return_value="vcenter" + ) as get_proxy_type: with patch.object( - salt.utils.vmware, "get_service_instance", return_value=None - ) as get_service_instance: - with patch.dict( - vsphere.__salt__, - {"vcenter.get_details": get_details}, - clear=True, - ) as get_vcenter_details: - with patch.object( - salt.utils.vmware, - "get_vsphere_client", - return_value=mock_client, - ) as get_vsphere_client: - with patch.object(vsphere, "DynamicID") as dynamic_id: - # Check function calls and return - ret = vsphere.attach_tag( - object_id=self.func_attrs["object_id"], - tag_id=self.func_attrs["tag_id"], - ) - get_proxy_type.assert_called_once() - get_proxy_connection.assert_called_once() - get_service_instance.assert_called_once() - get_vsphere_client.assert_called_once() - self.assertEqual( - ret, - {"Tag attached": self.list_attached_tags_return}, - ) + vsphere, "_get_proxy_connection_details", return_value=[] + ) as get_proxy_connection: + with patch.object( + salt.utils.vmware, "get_service_instance", return_value=None + ) as get_service_instance: + with patch.dict( + vsphere.__salt__, + {"vcenter.get_details": get_details}, + clear=True, + ) as get_vcenter_details: + with patch.object( + salt.utils.vmware, + "get_vsphere_client", + return_value=mock_client, + ) as get_vsphere_client: + with patch.object(vsphere, "DynamicID") as dynamic_id: + # Check function calls and return + ret = vsphere.attach_tag( + object_id=self.func_attrs["object_id"], + tag_id=self.func_attrs["tag_id"], + ) + get_proxy_type.assert_called_once() + get_proxy_connection.assert_called_once() + get_service_instance.assert_called_once() + get_vsphere_client.assert_called_once() + self.assertEqual( + get_vsphere_client.call_args_list, + [ + call( + ca_bundle=None, + password=None, + server=None, + username=None, + verify_ssl=verify_ssl, + ) + ], + ) + self.assertEqual( + ret, + { + "Tag attached": self.list_attached_tags_return + }, + ) def test_get_client(self): """ From 0a253e757336e79a4a8f4fe15ca0b51bb269a63f Mon Sep 17 00:00:00 2001 From: Frode Gundersen Date: Thu, 14 Jan 2021 11:38:43 -0700 Subject: [PATCH 59/69] Update man pages 3002.3 --- doc/man/salt-api.1 | 2 +- doc/man/salt-call.1 | 2 +- doc/man/salt-cloud.1 | 2 +- doc/man/salt-cp.1 | 2 +- doc/man/salt-key.1 | 2 +- doc/man/salt-master.1 | 2 +- doc/man/salt-minion.1 | 2 +- doc/man/salt-proxy.1 | 2 +- doc/man/salt-run.1 | 2 +- doc/man/salt-ssh.1 | 2 +- doc/man/salt-syndic.1 | 2 +- doc/man/salt-unity.1 | 2 +- doc/man/salt.1 | 2 +- doc/man/salt.7 | 221 +++++++++++++++++++++++++----------------- doc/man/spm.1 | 2 +- 15 files changed, 145 insertions(+), 104 deletions(-) diff --git a/doc/man/salt-api.1 b/doc/man/salt-api.1 index cbd17897d56..4b8efef98fa 100644 --- a/doc/man/salt-api.1 +++ b/doc/man/salt-api.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-API" "1" "Nov 14, 2020" "3002.2" "Salt" +.TH "SALT-API" "1" "Jan 14, 2021" "3002.3" "Salt" .SH NAME salt-api \- salt-api Command . diff --git a/doc/man/salt-call.1 b/doc/man/salt-call.1 index 550a3d01324..6b0d865cdfb 100644 --- a/doc/man/salt-call.1 +++ b/doc/man/salt-call.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-CALL" "1" "Nov 14, 2020" "3002.2" "Salt" +.TH "SALT-CALL" "1" "Jan 14, 2021" "3002.3" "Salt" .SH NAME salt-call \- salt-call Documentation . diff --git a/doc/man/salt-cloud.1 b/doc/man/salt-cloud.1 index cf0a632f48e..7fc5010e8e7 100644 --- a/doc/man/salt-cloud.1 +++ b/doc/man/salt-cloud.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-CLOUD" "1" "Nov 14, 2020" "3002.2" "Salt" +.TH "SALT-CLOUD" "1" "Jan 14, 2021" "3002.3" "Salt" .SH NAME salt-cloud \- Salt Cloud Command . diff --git a/doc/man/salt-cp.1 b/doc/man/salt-cp.1 index a5e0211e10f..cb3e5dfe059 100644 --- a/doc/man/salt-cp.1 +++ b/doc/man/salt-cp.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-CP" "1" "Nov 14, 2020" "3002.2" "Salt" +.TH "SALT-CP" "1" "Jan 14, 2021" "3002.3" "Salt" .SH NAME salt-cp \- salt-cp Documentation . diff --git a/doc/man/salt-key.1 b/doc/man/salt-key.1 index 07ed01fceff..505e06796a1 100644 --- a/doc/man/salt-key.1 +++ b/doc/man/salt-key.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-KEY" "1" "Nov 14, 2020" "3002.2" "Salt" +.TH "SALT-KEY" "1" "Jan 14, 2021" "3002.3" "Salt" .SH NAME salt-key \- salt-key Documentation . diff --git a/doc/man/salt-master.1 b/doc/man/salt-master.1 index e603ffbe659..c1433ac11dc 100644 --- a/doc/man/salt-master.1 +++ b/doc/man/salt-master.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-MASTER" "1" "Nov 14, 2020" "3002.2" "Salt" +.TH "SALT-MASTER" "1" "Jan 14, 2021" "3002.3" "Salt" .SH NAME salt-master \- salt-master Documentation . diff --git a/doc/man/salt-minion.1 b/doc/man/salt-minion.1 index 51f83015cd6..b47f0c7a863 100644 --- a/doc/man/salt-minion.1 +++ b/doc/man/salt-minion.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-MINION" "1" "Nov 14, 2020" "3002.2" "Salt" +.TH "SALT-MINION" "1" "Jan 14, 2021" "3002.3" "Salt" .SH NAME salt-minion \- salt-minion Documentation . diff --git a/doc/man/salt-proxy.1 b/doc/man/salt-proxy.1 index 1b796b229d2..defb449dd29 100644 --- a/doc/man/salt-proxy.1 +++ b/doc/man/salt-proxy.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-PROXY" "1" "Nov 14, 2020" "3002.2" "Salt" +.TH "SALT-PROXY" "1" "Jan 14, 2021" "3002.3" "Salt" .SH NAME salt-proxy \- salt-proxy Documentation . diff --git a/doc/man/salt-run.1 b/doc/man/salt-run.1 index e928daa636f..11d53fabb4e 100644 --- a/doc/man/salt-run.1 +++ b/doc/man/salt-run.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-RUN" "1" "Nov 14, 2020" "3002.2" "Salt" +.TH "SALT-RUN" "1" "Jan 14, 2021" "3002.3" "Salt" .SH NAME salt-run \- salt-run Documentation . diff --git a/doc/man/salt-ssh.1 b/doc/man/salt-ssh.1 index 18b3df7cd0c..fa558bf6183 100644 --- a/doc/man/salt-ssh.1 +++ b/doc/man/salt-ssh.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-SSH" "1" "Nov 14, 2020" "3002.2" "Salt" +.TH "SALT-SSH" "1" "Jan 14, 2021" "3002.3" "Salt" .SH NAME salt-ssh \- salt-ssh Documentation . diff --git a/doc/man/salt-syndic.1 b/doc/man/salt-syndic.1 index 4e8a9cdcab0..b1a25c79824 100644 --- a/doc/man/salt-syndic.1 +++ b/doc/man/salt-syndic.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-SYNDIC" "1" "Nov 14, 2020" "3002.2" "Salt" +.TH "SALT-SYNDIC" "1" "Jan 14, 2021" "3002.3" "Salt" .SH NAME salt-syndic \- salt-syndic Documentation . diff --git a/doc/man/salt-unity.1 b/doc/man/salt-unity.1 index c1ca49ed3cd..8a288461193 100644 --- a/doc/man/salt-unity.1 +++ b/doc/man/salt-unity.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-UNITY" "1" "Nov 14, 2020" "3002.2" "Salt" +.TH "SALT-UNITY" "1" "Jan 14, 2021" "3002.3" "Salt" .SH NAME salt-unity \- salt-unity Command . diff --git a/doc/man/salt.1 b/doc/man/salt.1 index f9973583ffb..64f5f05c546 100644 --- a/doc/man/salt.1 +++ b/doc/man/salt.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT" "1" "Nov 14, 2020" "3002.2" "Salt" +.TH "SALT" "1" "Jan 14, 2021" "3002.3" "Salt" .SH NAME salt \- salt . diff --git a/doc/man/salt.7 b/doc/man/salt.7 index 90fa8c6d33c..8c36ca002a8 100644 --- a/doc/man/salt.7 +++ b/doc/man/salt.7 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT" "7" "Nov 14, 2020" "3002.2" "Salt" +.TH "SALT" "7" "Jan 14, 2021" "3002.3" "Salt" .SH NAME salt \- Salt Documentation . @@ -41657,7 +41657,7 @@ Will insert the following message in the minion logs: .UNINDENT .SS Profiling .sp -New in version 3002.2. +New in version 3002. .sp When working with a very large codebase, it becomes increasingly imperative to @@ -58765,7 +58765,7 @@ twice, even though \fBqa1\fP appears twice. \fBWARNING:\fP .INDENT 0.0 .INDENT 3.5 -In the 3002.2 release \fBsls_path\fP, \fBtplfile\fP, and \fBtpldir\fP have had some significant +In the 3002 release \fBsls_path\fP, \fBtplfile\fP, and \fBtpldir\fP have had some significant improvements which have the potential to break states that rely on old and broken functionality. These fixes can be enabled by setting the \fBenable_slsvars_fixes\fP feature flag to \fBTrue\fP in your minion\(aqs config file. @@ -151139,7 +151139,7 @@ verify or set the code page before the command \fIcmd\fP is executed. Code page 65001 corresponds with UTF\-8 and allows international localization of Windows. .UNINDENT .sp -New in version 3002.2. +New in version 3002. .UNINDENT @@ -155632,7 +155632,7 @@ New in version 2018.3.0. If \fBFalse\fP, remote https file sources (\fBhttps://\fP) and source_hash will not attempt to validate the servers certificate. Default is True. .sp -New in version 3002.2. +New in version 3002. .UNINDENT .sp @@ -171382,7 +171382,7 @@ New in version 3001. If \fBFalse\fP, remote https file sources (\fBhttps://\fP) will not attempt to validate the servers certificate. Default is True. .sp -New in version 3002.2. +New in version 3002. .UNINDENT .UNINDENT @@ -171453,7 +171453,7 @@ Changed in version 3001: selinux attributes added If \fBFalse\fP, remote https file sources (\fBhttps://\fP) and source_hash will not attempt to validate the servers certificate. Default is True. .sp -New in version 3002.2. +New in version 3002. .UNINDENT .sp @@ -172343,7 +172343,7 @@ New in version 2016.3.0. If \fBFalse\fP, remote https file sources (\fBhttps://\fP) and source_hash will not attempt to validate the servers certificate. Default is True. .sp -New in version 3002.2. +New in version 3002. .UNINDENT .sp @@ -172444,7 +172444,7 @@ Salt fileserver (i.e. one beginning with \fBsalt://\fP). If \fBFalse\fP, remote https file sources (\fBhttps://\fP) and source_hash will not attempt to validate the servers certificate. Default is True. .sp -New in version 3002.2. +New in version 3002. .UNINDENT .sp @@ -173488,7 +173488,7 @@ New in version 3001. If \fBFalse\fP, remote https file sources (\fBhttps://\fP) will not attempt to validate the servers certificate. Default is True. .sp -New in version 3002.2. +New in version 3002. .UNINDENT .sp @@ -191333,7 +191333,7 @@ Passes through all the parameters described in the \fI\%utils.http.query function\fP: .INDENT 7.0 .TP -.B salt.utils.http.query(url, method=\(aqGET\(aq, params=None, data=None, data_file=None, header_dict=None, header_list=None, header_file=None, username=None, password=None, auth=None, decode=False, decode_type=\(aqauto\(aq, status=False, headers=False, text=False, cookies=None, cookie_jar=None, cookie_format=\(aqlwp\(aq, persist_session=False, session_cookie_jar=None, data_render=False, data_renderer=None, header_render=False, header_renderer=None, template_dict=None, test=False, test_url=None, node=\(aqminion\(aq, port=80, opts=None, backend=None, ca_bundle=None, verify_ssl=None, cert=None, text_out=None, headers_out=None, decode_out=None, stream=False, streaming_callback=None, header_callback=None, handle=False, agent=\(aqSalt/3002.2\-108\-g4f096201ea\(aq, hide_fields=None, raise_error=True, formdata=False, formdata_fieldname=None, formdata_filename=None, decode_body=True, **kwargs) +.B salt.utils.http.query(url, method=\(aqGET\(aq, params=None, data=None, data_file=None, header_dict=None, header_list=None, header_file=None, username=None, password=None, auth=None, decode=False, decode_type=\(aqauto\(aq, status=False, headers=False, text=False, cookies=None, cookie_jar=None, cookie_format=\(aqlwp\(aq, persist_session=False, session_cookie_jar=None, data_render=False, data_renderer=None, header_render=False, header_renderer=None, template_dict=None, test=False, test_url=None, node=\(aqminion\(aq, port=80, opts=None, backend=None, ca_bundle=None, verify_ssl=None, cert=None, text_out=None, headers_out=None, decode_out=None, stream=False, streaming_callback=None, header_callback=None, handle=False, agent=\(aqSalt/3002.2\(aq, hide_fields=None, raise_error=True, formdata=False, formdata_fieldname=None, formdata_filename=None, decode_body=True, **kwargs) Query a resource, and decode the return data .UNINDENT .INDENT 7.0 @@ -191551,7 +191551,7 @@ salt \(aq*\(aq icinga2.save_cert domain.tld master.domain.tld .sp This module provides access to idem execution modules .sp -New in version 3002.2. +New in version 3002. .INDENT 0.0 .TP @@ -216793,7 +216793,7 @@ be used to properly interact with the service. \fBNOTE:\fP .INDENT 0.0 .INDENT 3.5 -As of the 3002.2 release, if a service name of \fBsalt\-minion\fP is passed this +As of the 3002 release, if a service name of \fBsalt\-minion\fP is passed this module will convert it over to it\(aqs macOS equivalent name, in this case to \fBcom.saltstack.salt.minion\fP\&. This is true for \fBsalt\-master\fP \fBsalt\-api\fP, and \fBsalt\-syndic\fP as well. @@ -242998,7 +242998,7 @@ salt \(aq*\(aq nftables.flush filter input family=ipv6 .INDENT 0.0 .TP .B salt.modules.nftables.get_policy(table=\(aqfilter\(aq, chain=None, family=\(aqipv4\(aq) -New in version 3002.2. +New in version 3002. .sp Return the current policy for the specified table/chain @@ -243081,7 +243081,7 @@ salt \(aq*\(aq nftables.get_rules family=ipv6 .INDENT 0.0 .TP .B salt.modules.nftables.get_rules_json(family=\(aqipv4\(aq) -New in version 3002.2. +New in version 3002. .sp Return a list of dictionaries comprising the current, in\-memory rules @@ -243239,7 +243239,7 @@ salt \(aq*\(aq nftables.new_table filter family=ipv6 .INDENT 0.0 .TP .B salt.modules.nftables.save(filename=None, family=\(aqipv4\(aq) -Changed in version 3002.2. +Changed in version 3002. .sp Save the current in\-memory rules to disk. On systems where /etc/nftables is @@ -243261,7 +243261,7 @@ salt \(aq*\(aq nftables.save /etc/nftables .INDENT 0.0 .TP .B salt.modules.nftables.set_policy(table=\(aqfilter\(aq, chain=None, policy=None, family=\(aqipv4\(aq) -New in version 3002.2. +New in version 3002. .sp Set the current policy for the specified table/chain. This only works on @@ -277727,7 +277727,7 @@ minion, and it is using a different module (or gives an error similar to Returns \fBTrue\fP if the specified service is available, otherwise returns \fBFalse\fP\&. .sp -New in version 3002.2. +New in version 3002. .sp CLI Example: @@ -277747,7 +277747,7 @@ salt \(aq*\(aq service.available sshd .B salt.modules.slackware_service.disable(name, **kwargs) Disable the named service to start at boot .sp -New in version 3002.2. +New in version 3002. .sp CLI Example: @@ -277767,7 +277767,7 @@ salt \(aq*\(aq service.disable .B salt.modules.slackware_service.disabled(name) Return True if the named service is enabled, false otherwise .sp -New in version 3002.2. +New in version 3002. .sp CLI Example: @@ -277787,7 +277787,7 @@ salt \(aq*\(aq service.disabled .B salt.modules.slackware_service.enable(name, **kwargs) Enable the named service to start at boot .sp -New in version 3002.2. +New in version 3002. .sp CLI Example: @@ -277807,7 +277807,7 @@ salt \(aq*\(aq service.enable .B salt.modules.slackware_service.enabled(name, **kwargs) Return True if the named service is enabled, false otherwise .sp -New in version 3002.2. +New in version 3002. .sp CLI Example: @@ -277827,7 +277827,7 @@ salt \(aq*\(aq service.enabled .B salt.modules.slackware_service.force_reload(name) Force\-reload the named service .sp -New in version 3002.2. +New in version 3002. .sp CLI Example: @@ -277847,7 +277847,7 @@ salt \(aq*\(aq service.force_reload .B salt.modules.slackware_service.get_all() Return all available boot services .sp -New in version 3002.2. +New in version 3002. .sp CLI Example: @@ -277867,7 +277867,7 @@ salt \(aq*\(aq service.get_all .B salt.modules.slackware_service.get_disabled() Return a set of services that are installed but disabled .sp -New in version 3002.2. +New in version 3002. .sp CLI Example: @@ -277887,7 +277887,7 @@ salt \(aq*\(aq service.get_disabled .B salt.modules.slackware_service.get_enabled() Return a list of service that are enabled on boot .sp -New in version 3002.2. +New in version 3002. .sp CLI Example: @@ -277909,7 +277909,7 @@ The inverse of service.available. Returns \fBTrue\fP if the specified service is not available, otherwise returns \fBFalse\fP\&. .sp -New in version 3002.2. +New in version 3002. .sp CLI Example: @@ -277929,7 +277929,7 @@ salt \(aq*\(aq service.missing sshd .B salt.modules.slackware_service.reload_(name) Reload the named service .sp -New in version 3002.2. +New in version 3002. .sp CLI Example: @@ -277949,7 +277949,7 @@ salt \(aq*\(aq service.reload .B salt.modules.slackware_service.restart(name) Restart the named service .sp -New in version 3002.2. +New in version 3002. .sp CLI Example: @@ -277969,7 +277969,7 @@ salt \(aq*\(aq service.restart .B salt.modules.slackware_service.start(name) Start the specified service .sp -New in version 3002.2. +New in version 3002. .sp CLI Example: @@ -277991,7 +277991,7 @@ Return the status for a service. If the name contains globbing, a dict mapping service name to True/False values is returned. .sp -New in version 3002.2. +New in version 3002. .INDENT 7.0 .TP @@ -278028,7 +278028,7 @@ salt \(aq*\(aq service.status [service signature] .B salt.modules.slackware_service.stop(name) Stop the specified service .sp -New in version 3002.2. +New in version 3002. .sp CLI Example: @@ -298253,7 +298253,7 @@ all migration functions .SS Units Units specification .sp -New in version 3002.2. +New in version 3002. .sp The string should contain a number optionally followed @@ -299580,7 +299580,7 @@ Initialize a new vm .IP \(bu 2 \fBmem\fP \-\- .sp -Amount of memory to allocate to the virtual machine in MiB. Since 3002.2, a dictionary can be used to +Amount of memory to allocate to the virtual machine in MiB. Since 3002, a dictionary can be used to contain detailed configuration which support memory allocation or tuning. Supported parameters are \fBboot\fP, \fBcurrent\fP, \fBmax\fP, \fBslots\fP, \fBhard_limit\fP, \fBsoft_limit\fP, \fBswap_hard_limit\fP and \fBmin_guarantee\fP\&. The structure of the dictionary is documented in \fI\%Memory parameter definition\fP\&. Both decimal and binary base are supported. @@ -299606,7 +299606,7 @@ an integer. .UNINDENT .UNINDENT .sp -Changed in version 3002.2. +Changed in version 3002. .IP \(bu 2 @@ -300289,7 +300289,7 @@ Shared storage migration .sp True to connect over ssh .sp -Deprecated since version 3002.2. +Deprecated since version 3002. .IP \(bu 2 @@ -300367,7 +300367,7 @@ username: Username to connect with target host password: Password to connect with target host .UNINDENT .sp -New in version 3002.2. +New in version 3002. .UNINDENT @@ -300422,7 +300422,7 @@ Attempt to execute non\-shared storage "all" migration .sp True to connect over ssh .sp -Deprecated since version 3002.2. +Deprecated since version 3002. .IP \(bu 2 @@ -300494,7 +300494,7 @@ username: Username to connect with target host password: Password to connect with target host .UNINDENT .sp -New in version 3002.2. +New in version 3002. .UNINDENT @@ -300546,7 +300546,7 @@ Attempt to execute non\-shared storage "inc" migration .sp True to connect over ssh .sp -Deprecated since version 3002.2. +Deprecated since version 3002. .IP \(bu 2 @@ -300618,7 +300618,7 @@ username: Username to connect with target host password: Password to connect with target host .UNINDENT .sp -New in version 3002.2. +New in version 3002. .UNINDENT @@ -302509,7 +302509,7 @@ Update the definition of an existing domain. .IP \(bu 2 \fBmem\fP \-\- .sp -Amount of memory to allocate to the virtual machine in MiB. Since 3002.2, a dictionary can be used to +Amount of memory to allocate to the virtual machine in MiB. Since 3002, a dictionary can be used to contain detailed configuration which support memory allocation or tuning. Supported parameters are \fBboot\fP, \fBcurrent\fP, \fBmax\fP, \fBslots\fP, \fBhard_limit\fP, \fBsoft_limit\fP, \fBswap_hard_limit\fP and \fBmin_guarantee\fP\&. The structure of the dictionary is documented in \fI\%Memory parameter definition\fP\&. Both decimal and binary base are supported. @@ -302531,7 +302531,7 @@ is mapped to \fBnull\fP in sls file, pass \fBnull\fP in sls file instead. .UNINDENT .UNINDENT .sp -Changed in version 3002.2. +Changed in version 3002. .IP \(bu 2 @@ -302599,7 +302599,7 @@ Values can be \fBhd\fP, \fBfd\fP, \fBcdrom\fP or \fBnetwork\fP\&. .sp By default, the value will \fB"hd"\fP\&. .sp -New in version 3002.2. +New in version 3002. .IP \(bu 2 @@ -385572,7 +385572,7 @@ swap: mappedbyuuid: crypted.mapped: - \- device: UUID=066e0200\-2867\-4ebe\-b9e6\-f3002.26ca2314 + \- device: UUID=066e0200\-2867\-4ebe\-b9e6\-f30026ca2314 \- keyfile: /etc/keyfile.key \- config: /etc/alternate\-crypttab .ft P @@ -385593,7 +385593,7 @@ The name under which the device is to be mapped .TP .B device The device name, typically the device node, such as \fB/dev/sdb1\fP -or \fBUUID=066e0200\-2867\-4ebe\-b9e6\-f3002.26ca2314\fP\&. +or \fBUUID=066e0200\-2867\-4ebe\-b9e6\-f30026ca2314\fP\&. .TP .B keyfile Either \fBNone\fP if the password is to be entered manually on boot, or @@ -395598,7 +395598,7 @@ create_config_file: If \fBFalse\fP, remote https file sources (\fBhttps://\fP) and source_hash will not attempt to validate the servers certificate. Default is True. .sp -New in version 3002.2. +New in version 3002. .UNINDENT .UNINDENT @@ -396647,7 +396647,7 @@ New in version 2015.8.0. Write the data as this format. See the list of all\-salt.serializers for supported output formats. .sp -Changed in version 3002.2: \fBserializer\fP argument added as an alternative to \fBformatter\fP\&. +Changed in version 3002: \fBserializer\fP argument added as an alternative to \fBformatter\fP\&. Both are accepted, but using both will result in an error. .TP @@ -401400,7 +401400,7 @@ Icinga2 master node for which this certificate will be saved .sp This state provides access to idem states .sp -New in version 3002.2. +New in version 3002. .INDENT 0.0 .TP @@ -407271,7 +407271,7 @@ New in version 2018.3.0. Assume yes to all prompts .UNINDENT .sp -New in version 3002.2.0. +New in version 3002.0. .INDENT 7.0 .TP @@ -410204,7 +410204,7 @@ Mount any type of mountable filesystem with the mounted function: /srv/bigdata: mount.mounted: - \- device: UUID=066e0200\-2867\-4ebe\-b9e6\-f3002.26ca2314 + \- device: UUID=066e0200\-2867\-4ebe\-b9e6\-f30026ca2314 \- fstype: xfs \- opts: nobootwait,noatime,nodiratime,nobarrier,logbufs=8 \- dump: 0 @@ -410342,7 +410342,7 @@ The path to the location where the device is to be mounted .TP .B device The device name, typically the device node, such as \fB/dev/sdb1\fP -or \fBUUID=066e0200\-2867\-4ebe\-b9e6\-f3002.26ca2314\fP or \fBLABEL=DATA\fP +or \fBUUID=066e0200\-2867\-4ebe\-b9e6\-f30026ca2314\fP or \fBLABEL=DATA\fP .TP .B fstype The filesystem type, this will be \fBxfs\fP, \fBext2/3/4\fP in the case of classic @@ -414021,7 +414021,7 @@ argument. .UNINDENT .SS Network Teaming (RHEL/CentOS 7 and later) .sp -New in version 3002.2. +New in version 3002. .INDENT 0.0 .IP \(bu 2 @@ -414961,7 +414961,7 @@ Networking family, either ipv4 or ipv6 New in version 2014.7.0. .sp -Changed in version 3002.2. +Changed in version 3002. .sp Verify a chain exists in a table. @@ -415005,7 +415005,7 @@ specified as \fIconnstate\fP instead of \fIstate\fP (not to be confused with New in version 2014.7.0. .sp -Changed in version 3002.2. +Changed in version 3002. .sp Flush current nftables state @@ -415018,7 +415018,7 @@ Networking family, either ipv4 or ipv6 If set to True, attempts to flush a non\-existent table will not result in a failed state. .sp -New in version 3002.2. +New in version 3002. .UNINDENT .UNINDENT @@ -415047,7 +415047,7 @@ specified as \fIconnstate\fP instead of \fIstate\fP (not to be confused with .INDENT 0.0 .TP .B salt.states.nftables.set_policy(name, table=\(aqfilter\(aq, family=\(aqipv4\(aq, **kwargs) -New in version 3002.2. +New in version 3002. .sp Sets the default policy for nftables chains @@ -415073,7 +415073,7 @@ or /etc/nftables/salt\-all\-in\-one.nft if the former is a directory) .INDENT 0.0 .TP .B salt.states.nftables.table_absent(name, family=\(aqipv4\(aq, **kwargs) -New in version 3002.2. +New in version 3002. .sp Ensure an nftables table is absent @@ -415089,7 +415089,7 @@ Networking family, either ipv4 or ipv6 .INDENT 0.0 .TP .B salt.states.nftables.table_present(name, family=\(aqipv4\(aq, **kwargs) -New in version 3002.2. +New in version 3002. .sp Ensure an nftables table is present @@ -420498,7 +420498,7 @@ the regular package manager commands. .B copr Use community packages outside of the main package repository. .sp -New in version 3002.2. +New in version 3002. .INDENT 7.0 .INDENT 3.5 @@ -420612,7 +420612,7 @@ reverse will be passed as \fBenabled\fP\&. For example passing Fedora and RedHat based distributions only. Use community packages outside of the main package repository. .sp -New in version 3002.2. +New in version 3002. .TP .B humanname @@ -430116,7 +430116,7 @@ New in version 3001. .IP \(bu 2 \fBmem\fP \-\- .sp -Amount of memory to allocate to the virtual machine in MiB. Since 3002.2, a dictionary can be used to +Amount of memory to allocate to the virtual machine in MiB. Since 3002, a dictionary can be used to contain detailed configuration which support memory allocation or tuning. Supported parameters are \fBboot\fP, \fBcurrent\fP, \fBmax\fP, \fBslots\fP, \fBhard_limit\fP, \fBsoft_limit\fP, \fBswap_hard_limit\fP and \fBmin_guarantee\fP\&. The structure of the dictionary is documented in init\-mem\-def\&. Both decimal and binary base are supported. @@ -430142,7 +430142,7 @@ an integer. .UNINDENT .UNINDENT .sp -Changed in version 3002.2. +Changed in version 3002. .IP \(bu 2 @@ -430219,7 +430219,7 @@ Values can be \fBhd\fP, \fBfd\fP, \fBcdrom\fP or \fBnetwork\fP\&. .sp By default, the value will \fB"hd"\fP\&. .sp -New in version 3002.2. +New in version 3002. .UNINDENT @@ -430823,7 +430823,7 @@ New in version 2016.3.0. .IP \(bu 2 \fBmem\fP \-\- .sp -Amount of memory to allocate to the virtual machine in MiB. Since 3002.2, a dictionary can be used to +Amount of memory to allocate to the virtual machine in MiB. Since 3002, a dictionary can be used to contain detailed configuration which support memory allocation or tuning. Supported parameters are \fBboot\fP, \fBcurrent\fP, \fBmax\fP, \fBslots\fP, \fBhard_limit\fP, \fBsoft_limit\fP, \fBswap_hard_limit\fP and \fBmin_guarantee\fP\&. The structure of the dictionary is documented in init\-mem\-def\&. Both decimal and binary base are supported. @@ -430845,7 +430845,7 @@ is mapped to \fBnull\fP in sls file, pass \fBnull\fP in sls file instead. .UNINDENT .UNINDENT .sp -Changed in version 3002.2. +Changed in version 3002. .IP \(bu 2 @@ -431028,7 +431028,7 @@ Values can be \fBhd\fP, \fBfd\fP, \fBcdrom\fP or \fBnetwork\fP\&. .sp By default, the value will \fB"hd"\fP\&. .sp -New in version 3002.2. +New in version 3002. .UNINDENT @@ -445561,7 +445561,7 @@ def some_function(bar=False, foo=None): .UNINDENT .UNINDENT .sp -Development begins on the \fBAluminum\fP release when the \fB3002.2\fP branch is +Development begins on the \fBAluminum\fP release when the \fB3002\fP branch is forked from the develop branch. Once this occurs, all uses of the \fBwarn_until\fP function targeting \fBAluminum\fP, along with the code they are warning about should be removed from the code. @@ -454644,7 +454644,7 @@ information about the version numbering scheme. .sp Release Candidate .SS Previous Releases -.SS Salt 3002.2 Release Notes \- Codename Magnesium +.SS Salt 3002 Release Notes \- Codename Magnesium .SS New Features .SS Network Teaming Support Added (RHEL/CentOS) .sp @@ -454949,9 +454949,9 @@ Added features config option for feature flags. Added a feature flag This flag will be depricated in the Phosphorus release when this functionality becomes the default. (#58652) .UNINDENT -.SS Salt 3002.2.1 Release Notes +.SS Salt 3002.1 Release Notes .sp -Version 3002.2.1 is a CVE fix release for 3002.2\&. +Version 3002.1 is a CVE fix release for 3002\&. .SS Fixed .INDENT 0.0 .IP \(bu 2 @@ -454964,6 +454964,44 @@ Prior to this change eauth was not properly validated when calling Salt ssh via the salt\-api. Any value for \(aqeauth\(aq or \(aqtoken\(aq would allow a user to bypass authentication and make calls to Salt ssh. (CVE\-2020\-25592) .UNINDENT +.SS Salt 3002.2 Release Notes +.sp +Version 3002.2 is a bugfix release for 3002\&. +.SS Fixed +.INDENT 0.0 +.IP \(bu 2 +Change dict check to isinstance instead of type() for key_values in file.keyvalue. (#57758) +.IP \(bu 2 +Fail when func_ret is False when using the new module.run syntax. (#57768) +.IP \(bu 2 +Fix comparison of certificate values (#58296) +.IP \(bu 2 +When using ssh_pre_flight if there is a failure, fail on retcode not stderr. (#58439) +.IP \(bu 2 +Fix use of unauthd cached vmware service instance (#58691) +.IP \(bu 2 +Removing use of undefined varilable in utils/slack.py. (#58753) +.IP \(bu 2 +Restored the ability to specify the amount of extents for a Logical +Volume as a percentage. (#58759) +.IP \(bu 2 +Ensuring that the version check function is run a second time in all the user related functions incase the user being managed is the connection user and the password has been updated. (#58773) +.IP \(bu 2 +Allow bytes in gpg renderer (#58794) +.IP \(bu 2 +Fix issue where win_wua module fails to load when BITS is set to Manual (#58848) +.IP \(bu 2 +Ensure that elasticsearch.index_exists is available before loading the elasticsearch returner. (#58851) +.IP \(bu 2 +Log a different object when debugging if we\(aqre using disk cache vs memory cache. The disk cache pillar class has the dict object but the cache pillar object which is used with the memory cache does not include a _dict obeject because it is a dict already. (#58861) +.IP \(bu 2 +Do not generate grains for every job run on Windows minions. This makes Windows +conform more to the way posix OSes work today. (#58904) +.IP \(bu 2 +Fixes salt\-ssh authentication when using tty (#58922) +.IP \(bu 2 +Revert LazyLoader finalizer. Removed the weakref.finalizer code. On some occasions, the finalized would run when trying to load a new module, firing a race condition. (#58947) +.UNINDENT .SS Salt 3001 Release Notes \- Codename Sodium .SS Python 2 Dropped .sp @@ -489562,15 +489600,15 @@ ab1b099730 Merge pull request \fI\%#42948\fP from Ch3LL/2017.7.0_follow_up .UNINDENT .UNINDENT .IP \(bu 2 -\fBISSUE\fP \fI\%#42989\fP: (\fI\%blbradley\fP) GitFS GitPython performance regression in 2017.7.1 (refs: \fI\%#43002.2\fP) +\fBISSUE\fP \fI\%#42989\fP: (\fI\%blbradley\fP) GitFS GitPython performance regression in 2017.7.1 (refs: \fI\%#43002\fP) .IP \(bu 2 -\fBPR\fP \fI\%#43034\fP: (\fI\%rallytime\fP) Back\-port \fI\%#43002.2\fP to 2017.7 +\fBPR\fP \fI\%#43034\fP: (\fI\%rallytime\fP) Back\-port \fI\%#43002\fP to 2017.7 @ \fI2017\-08\-17 23:18:16 UTC\fP .INDENT 2.0 .IP \(bu 2 -\fBPR\fP \fI\%#43002.2\fP: (\fI\%the\-glu\fP) Try to fix \fI\%#42989\fP (refs: \fI\%#43034\fP) +\fBPR\fP \fI\%#43002\fP: (\fI\%the\-glu\fP) Try to fix \fI\%#42989\fP (refs: \fI\%#43034\fP) .IP \(bu 2 -bcbb973a71 Merge pull request \fI\%#43034\fP from rallytime/bp\-43002.2 +bcbb973a71 Merge pull request \fI\%#43034\fP from rallytime/bp\-43002 .IP \(bu 2 350c0767dc Try to fix \fI\%#42989\fP by doing sslVerify and refspecs for origin remote only if there is no remotes .UNINDENT @@ -490704,7 +490742,7 @@ ab21bd9b5b Sync cloud modules when saltutil.sync_all is run @ \fI2017\-07\-27 22:32:07 UTC\fP .INDENT 2.0 .IP \(bu 2 -e2dd443002.2 Merge pull request \fI\%#42601\fP from rallytime/merge\-2017.7 +e2dd443002 Merge pull request \fI\%#42601\fP from rallytime/merge\-2017.7 .IP \(bu 2 36a1bcf8c5 Merge branch \(aq2016.11\(aq into \(aq2017.7\(aq .INDENT 2.0 @@ -506448,7 +506486,7 @@ abe4eb3b98 fix encoding problem aws responses .IP \(bu 2 1001987f64 Catch possible exception from lsb_release (\fI\%#37962\fP) .IP \(bu 2 -33002.21cd8b Handle empty tokens safely (\fI\%#37961\fP) +330021cd8b Handle empty tokens safely (\fI\%#37961\fP) .IP \(bu 2 ea46639ce7 Merge pull request \fI\%#37272\fP from vutny/fix\-getting\-default\-logging\-opts .INDENT 2.0 @@ -534137,7 +534175,7 @@ a6c1d0b408 Fixed a bug where logging_command wasnt set as a key in a couple spot .IP \(bu 2 8bb7cb7ff4 Use correct indexes .IP \(bu 2 -c3483002.2b0 [2015.8] Fixup salt\-cloud logging +c3483002b0 [2015.8] Fixup salt\-cloud logging .UNINDENT .IP \(bu 2 \fBPR\fP \fI\%#27332\fP: (\fI\%terminalmage\fP) Adjust dockerng/dockerio docstrings @@ -545085,7 +545123,7 @@ f7e58a241c Merge branch \(aq2015.5\(aq into \(aq2015.8\(aq 1cb1c2da07 Fixes wrong function scope .UNINDENT .IP \(bu 2 -1c6c9b1a06 Merge pull request \fI\%#3002.25\fP from jtand/boto_tests +1c6c9b1a06 Merge pull request \fI\%#30025\fP from jtand/boto_tests .INDENT 2.0 .IP \(bu 2 e706642152 Skipping some Boto tests until resolved moto issue @@ -545257,11 +545295,11 @@ a257249789 Add versionadded to SSH Port docs 0bb83e51aa Updated Cloud msic section. .UNINDENT .IP \(bu 2 -\fBPR\fP \fI\%#3002.29\fP: (\fI\%terminalmage\fP) git.latest: Fix handling of nonexistant branches +\fBPR\fP \fI\%#30029\fP: (\fI\%terminalmage\fP) git.latest: Fix handling of nonexistant branches @ \fI2015\-12\-28 19:39:29 UTC\fP .INDENT 2.0 .IP \(bu 2 -a5f7d9c2fc Merge pull request \fI\%#3002.29\fP from terminalmage/git.latest\-nonexistant\-branch +a5f7d9c2fc Merge pull request \fI\%#30029\fP from terminalmage/git.latest\-nonexistant\-branch .IP \(bu 2 0b95894c9f git.latest: Fix handling of nonexistant branches .UNINDENT @@ -545284,11 +545322,11 @@ e7fe24dc64 Merge pull request \fI\%#30016\fP from alprs/fix\-gen_locale_normaliz 5799729aee locale module: don\(aqt escape the slash in n .UNINDENT .IP \(bu 2 -\fBPR\fP \fI\%#3002.22\fP: (\fI\%gqgunhed\fP) Two minor typos fixed +\fBPR\fP \fI\%#30022\fP: (\fI\%gqgunhed\fP) Two minor typos fixed @ \fI2015\-12\-28 15:22:24 UTC\fP .INDENT 2.0 .IP \(bu 2 -b871ce5310 Merge pull request \fI\%#3002.22\fP from gqgunhed/winrepo_typo +b871ce5310 Merge pull request \fI\%#30022\fP from gqgunhed/winrepo_typo .IP \(bu 2 a052ff016e fixed minor typos and a :ref: link .IP \(bu 2 @@ -545297,11 +545335,11 @@ e47db1a076 Merge remote\-tracking branch \(aqrefs/remotes/saltstack/2015.8\(aq i 0c4c8b9b5c Merge remote\-tracking branch \(aqrefs/remotes/saltstack/2015.8\(aq into 2015.8 .UNINDENT .IP \(bu 2 -\fBPR\fP \fI\%#3002.26\fP: (\fI\%anlutro\fP) states.at: fix wrong variable being used +\fBPR\fP \fI\%#30026\fP: (\fI\%anlutro\fP) states.at: fix wrong variable being used @ \fI2015\-12\-28 15:21:23 UTC\fP .INDENT 2.0 .IP \(bu 2 -4b8ac20d45 Merge pull request \fI\%#3002.26\fP from alprs/fix\-at_without_tag_job +4b8ac20d45 Merge pull request \fI\%#30026\fP from alprs/fix\-at_without_tag_job .IP \(bu 2 c0fe9c09bd states.at: fix wrong variable being used .UNINDENT @@ -551509,9 +551547,9 @@ b869a92eea Change Zypper calls to a single point .IP \(bu 2 \fBPR\fP \fI\%#33017\fP: (\fI\%rallytime\fP) Update the docs for saltutil.find_job to be more clear/accurate .IP \(bu 2 -\fBPR\fP \fI\%#33031\fP: (\fI\%rallytime\fP) Back\-port \fI\%#33002.2\fP to 2015.8 +\fBPR\fP \fI\%#33031\fP: (\fI\%rallytime\fP) Back\-port \fI\%#33002\fP to 2015.8 .IP \(bu 2 -\fBPR\fP \fI\%#33002.2\fP: (\fI\%whiteinge\fP) Add saltenv to the cmd.script state function (refs: \fI\%#33031\fP) +\fBPR\fP \fI\%#33002\fP: (\fI\%whiteinge\fP) Add saltenv to the cmd.script state function (refs: \fI\%#33031\fP) .IP \(bu 2 \fBPR\fP \fI\%#33021\fP: (\fI\%UtahDave\fP) Fix syndic regression (refs: \fI\%#33044\fP) .UNINDENT @@ -567064,13 +567102,13 @@ cfbfd58afe Noting that file_roots and "state tree" should both be avoided, becau 1cb1c2da07 Fixes wrong function scope .UNINDENT .IP \(bu 2 -\fBPR\fP \fI\%#3002.25\fP: (\fI\%justinta\fP) Skipping some Boto tests until resolved moto issue +\fBPR\fP \fI\%#30025\fP: (\fI\%justinta\fP) Skipping some Boto tests until resolved moto issue @ \fI2015\-12\-28 15:21:45 UTC\fP .INDENT 2.0 .IP \(bu 2 -\fBPR\fP \fI\%#29725\fP: (\fI\%cachedout\fP) Disable some boto tests per resolution of moto issue (refs: \fI\%#3002.25\fP) +\fBPR\fP \fI\%#29725\fP: (\fI\%cachedout\fP) Disable some boto tests per resolution of moto issue (refs: \fI\%#30025\fP) .IP \(bu 2 -1c6c9b1a06 Merge pull request \fI\%#3002.25\fP from jtand/boto_tests +1c6c9b1a06 Merge pull request \fI\%#30025\fP from jtand/boto_tests .IP \(bu 2 e706642152 Skipping some Boto tests until resolved moto issue .UNINDENT @@ -576689,6 +576727,9 @@ runners and commands like salt\-key. Tests have been added to test the aspects of the client APIs and ensure that the client calls work, and that they manage passed data, in a desirable way. .SS Upcoming Release +.SS Salt 3003 Release Notes \- Codename Aluminium +.sp +Salt 3003 is an \fIunreleased\fP upcoming feature release. .sp \fBSEE ALSO:\fP .INDENT 0.0 diff --git a/doc/man/spm.1 b/doc/man/spm.1 index 15029351ef4..7387624bf48 100644 --- a/doc/man/spm.1 +++ b/doc/man/spm.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SPM" "1" "Nov 14, 2020" "3002.2" "Salt" +.TH "SPM" "1" "Jan 14, 2021" "3002.3" "Salt" .SH NAME spm \- Salt Package Manager Command . From 039b7f3f5713170799363d96e6263c2809e4245c Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Sat, 23 Jan 2021 14:28:56 -0700 Subject: [PATCH 60/69] Fix ssh_remote_port_forwards wart causing test to fail --- salt/client/ssh/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/client/ssh/client.py b/salt/client/ssh/client.py index 9ece7e8b37f..c892ef2a61e 100644 --- a/salt/client/ssh/client.py +++ b/salt/client/ssh/client.py @@ -56,7 +56,7 @@ class SSHClient(object): ("ssh_priv", str), ("ssh_priv_passwd", str), ("ssh_identities_only", bool), - ("ssh_remote_port_forwards", bool), + ("ssh_remote_port_forwards", str), ("ssh_options", list), ("roster_file", str), ("rosters", list), From 58908b8f72a8a68b6a1571b7c4c8637c1c66909c Mon Sep 17 00:00:00 2001 From: Frode Gundersen Date: Mon, 25 Jan 2021 16:12:50 +0000 Subject: [PATCH 61/69] Update docs 3002.3 --- CHANGELOG.md | 6 +++++ doc/topics/releases/3000.7.rst | 41 ++++++++++++++++++++++++++++++++++ doc/topics/releases/3001.5.rst | 41 ++++++++++++++++++++++++++++++++++ doc/topics/releases/3002.3.rst | 41 ++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+) create mode 100644 doc/topics/releases/3000.7.rst create mode 100644 doc/topics/releases/3001.5.rst create mode 100644 doc/topics/releases/3002.3.rst diff --git a/CHANGELOG.md b/CHANGELOG.md index d8867b633e9..05c843ba08b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ Versions are `MAJOR.PATCH`. # Changelog +Salt 3002.3 (2021-01-25) +======================== + +No significant changes. + + Salt 3002.2 (2020-11-16) ======================== diff --git a/doc/topics/releases/3000.7.rst b/doc/topics/releases/3000.7.rst new file mode 100644 index 00000000000..58d0b2400d8 --- /dev/null +++ b/doc/topics/releases/3000.7.rst @@ -0,0 +1,41 @@ +.. _release-3000-7: + +========================= +Salt 3000.7 Release Notes +========================= + +Version 3000.7 is a CVE fix release for :ref:`3000 `. + +Fixed +----- + +- CVE-2020-28243 - Fix local privilege escalation in the restartcheck module. + +- CVE-2020-28972 - Ensure authentication to vcenter, vsphere, and esxi server + validates the SSL/TLS certificate by default. If you want to skip SSL verification + you can use `verify_ssl: False`. + +- CVE-2020-35662 - Ensure the asam runner, qingcloud, splunk returner, panos + proxy, cimc proxy, zenoss module, esxi module, vsphere module, glassfish + module, bigip module, and keystone module validate SSL by default. If you want + to skip SSL verification you can use `verify_ssl: False`. + +- CVE-2021-3148 - Fix a command injection in the Salt-API when using the + Salt-SSH client. + +- CVE-2021-3144 - Fix eauth tokens can be used once after expiration + +- CVE-2021-25281 - Fix salt-api so it honors eauth credentials for the + wheel_async client. + +- CVE-2021-25282 - Fix the salt.wheel.pillar_roots.write method so it is not + vulnerable to directory traversal. + +- CVE-2021-25283 - Fix the jinja render to protect against server side template + injection attacks. + +- CVE-2021-25284 - Fix cmdmod so it will not log credentials to log levels info + and error. + +- CVE-2021-3197 - Fix ssh client to remove ProxyCommand from arguments provided + by cli and netapi. diff --git a/doc/topics/releases/3001.5.rst b/doc/topics/releases/3001.5.rst new file mode 100644 index 00000000000..bca2151abdf --- /dev/null +++ b/doc/topics/releases/3001.5.rst @@ -0,0 +1,41 @@ +.. _release-3001-5: + +========================= +Salt 3001.5 Release Notes +========================= + +Version 3001.5 is a CVE fix release for :ref:`3001 `. + +Fixed +----- + +- CVE-2020-28243 - Fix local privilege escalation in the restartcheck module. + +- CVE-2020-28972 - Ensure authentication to vcenter, vsphere, and esxi server + validates the SSL/TLS certificate by default. If you want to skip SSL verification + you can use `verify_ssl: False`. + +- CVE-2020-35662 - Ensure the asam runner, qingcloud, splunk returner, panos + proxy, cimc proxy, zenoss module, esxi module, vsphere module, glassfish + module, bigip module, and keystone module validate SSL by default. If you want + to skip SSL verification you can use `verify_ssl: False`. + +- CVE-2021-3148 - Fix a command injection in the Salt-API when using the + Salt-SSH client. + +- CVE-2021-3144 - Fix eauth tokens can be used once after expiration + +- CVE-2021-25281 - Fix salt-api so it honors eauth credentials for the + wheel_async client. + +- CVE-2021-25282 - Fix the salt.wheel.pillar_roots.write method so it is not + vulnerable to directory traversal. + +- CVE-2021-25283 - Fix the jinja render to protect against server side template + injection attacks. + +- CVE-2021-25284 - Fix cmdmod so it will not log credentials to log levels info + and error. + +- CVE-2021-3197 - Fix ssh client to remove ProxyCommand from arguments provided + by cli and netapi. diff --git a/doc/topics/releases/3002.3.rst b/doc/topics/releases/3002.3.rst new file mode 100644 index 00000000000..ebc8cc4466e --- /dev/null +++ b/doc/topics/releases/3002.3.rst @@ -0,0 +1,41 @@ +.. _release-3002-3: + +========================= +Salt 3002.3 Release Notes +========================= + +Version 3002.3 is a CVE fix release for :ref:`3002 `. + +Fixed +----- + +- CVE-2020-28243 - Fix local privilege escalation in the restartcheck module. + +- CVE-2020-28972 - Ensure authentication to vcenter, vsphere, and esxi server + validates the SSL/TLS certificate by default. If you want to skip SSL verification + you can use `verify_ssl: False`. + +- CVE-2020-35662 - Ensure the asam runner, qingcloud, splunk returner, panos + proxy, cimc proxy, zenoss module, esxi module, vsphere module, glassfish + module, bigip module, and keystone module validate SSL by default. If you want + to skip SSL verification you can use `verify_ssl: False`. + +- CVE-2021-3148 - Fix a command injection in the Salt-API when using the + Salt-SSH client. + +- CVE-2021-3144 - Fix eauth tokens can be used once after expiration + +- CVE-2021-25281 - Fix salt-api so it honors eauth credentials for the + wheel_async client. + +- CVE-2021-25282 - Fix the salt.wheel.pillar_roots.write method so it is not + vulnerable to directory traversal. + +- CVE-2021-25283 - Fix the jinja render to protect against server side template + injection attacks. + +- CVE-2021-25284 - Fix cmdmod so it will not log credentials to log levels info + and error. + +- CVE-2021-3197 - Fix ssh client to remove ProxyCommand from arguments provided + by cli and netapi. From eb5a10b8330e89c956098b80ef9135a9d9016408 Mon Sep 17 00:00:00 2001 From: Frode Gundersen Date: Mon, 25 Jan 2021 16:15:07 +0000 Subject: [PATCH 62/69] Update docs 3002.3 --- CHANGELOG.md | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05c843ba08b..62641d4db56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,29 @@ Versions are `MAJOR.PATCH`. Salt 3002.3 (2021-01-25) ======================== -No significant changes. +Fixed +----- +- CVE-2020-28243 - Fix local privilege escalation in the restartcheck module. (CVE-2020-28243) +- CVE-2020-28972 - Ensure authentication to vcenter, vsphere, and esxi server + validates the SSL/TLS certificate by default. If you want to skip SSL verification + you can use `verify_ssl: False`. (CVE-2020-28972) +- CVE-2020-35662 - Ensure the asam runner, qingcloud, splunk returner, panos + proxy, cimc proxy, zenoss module, esxi module, vsphere module, glassfish + module, bigip module, and keystone module validate SSL by default. If you want + to skip SSL verification you can use `verify_ssl: False`. (CVE-2020-35662) +- CVE-2021-25281 - Fix salt-api so it honors eauth credentials for the + wheel_async client. (CVE-2021-25281) +- CVE-2021-25282 - Fix the salt.wheel.pillar_roots.write method so it is not + vulnerable to directory traversal. (CVE-2021-25282) +- CVE-2021-25283 - Fix the jinja render to protect against server side template + injection attacks. (CVE-2021-25283) +- CVE-2021-25284 - Fix cmdmod so it will not log credentials to log levels info + and error. (CVE-2021-25284) +- CVE-2021-3144 - Fix eauth tokens can be used once after expiration. (CVE-2021-3144) +- CVE-2021-3148 - Fix a command injection in the Salt-API when using the Salt-SSH client. (CVE-2021-3148) +- CVE-2021-3197 - Fix ssh client to remove ProxyCommand from arguments provided + by cli and netapi. (CVE-2021-3197) Salt 3002.2 (2020-11-16) ======================== @@ -279,6 +300,42 @@ Added This flag will be deprecated in the Phosphorus release when this functionality becomes the default. (#58652) +Salt 3001.5 +=========== + +Fixed +----- + +- CVE-2020-28243 - Fix local privilege escalation in the restartcheck module. (CVE-2020-28243) +- CVE-2020-28972 - Ensure authentication to vcenter, vsphere, and esxi server + validates the SSL/TLS certificate by default. If you want to skip SSL verification + you can use `verify_ssl: False`. (CVE-2020-28972) +- CVE-2020-35662 - Ensure the asam runner, qingcloud, splunk returner, panos + proxy, cimc proxy, zenoss module, esxi module, vsphere module, glassfish + module, bigip module, and keystone module validate SSL by default. If you want + to skip SSL verification you can use `verify_ssl: False`. (CVE-2020-35662) +- CVE-2021-25281 - Fix salt-api so it honors eauth credentials for the + wheel_async client. (CVE-2021-25281) +- CVE-2021-25282 - Fix the salt.wheel.pillar_roots.write method so it is not + vulnerable to directory traversal. (CVE-2021-25282) +- CVE-2021-25283 - Fix the jinja render to protect against server side template + injection attacks. (CVE-2021-25283) +- CVE-2021-25284 - Fix cmdmod so it will not log credentials to log levels info + and error. (CVE-2021-25284) +- CVE-2021-3144 - Fix eauth tokens can be used once after expiration. (CVE-2021-3144) +- CVE-2021-3148 - Fix a command injection in the Salt-API when using the Salt-SSH client. (CVE-2021-3148) +- CVE-2021-3197 - Fix ssh client to remove ProxyCommand from arguments provided + by cli and netapi. (CVE-2021-3197) + + +Salt 3001.4 +=========== + +Fixed +----- + +- Fixes salt-ssh authentication when using tty (#58922) + Salt 3001.3 =========== @@ -725,6 +782,41 @@ 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.7 +=========== + +Fixed +----- + +- CVE-2020-28243 - Fix local privilege escalation in the restartcheck module. (CVE-2020-28243) +- CVE-2020-28972 - Ensure authentication to vcenter, vsphere, and esxi server + validates the SSL/TLS certificate by default. If you want to skip SSL verification + you can use `verify_ssl: False`. (CVE-2020-28972) +- CVE-2020-35662 - Ensure the asam runner, qingcloud, splunk returner, panos + proxy, cimc proxy, zenoss module, esxi module, vsphere module, glassfish + module, bigip module, and keystone module validate SSL by default. If you want + to skip SSL verification you can use `verify_ssl: False`. (CVE-2020-35662) +- CVE-2021-25281 - Fix salt-api so it honors eauth credentials for the + wheel_async client. (CVE-2021-25281) +- CVE-2021-25282 - Fix the salt.wheel.pillar_roots.write method so it is not + vulnerable to directory traversal. (CVE-2021-25282) +- CVE-2021-25283 - Fix the jinja render to protect against server side template + injection attacks. (CVE-2021-25283) +- CVE-2021-25284 - Fix cmdmod so it will not log credentials to log levels info + and error. (CVE-2021-25284) +- CVE-2021-3144 - Fix eauth tokens can be used once after expiration. (CVE-2021-3144) +- CVE-2021-3148 - Fix a command injection in the Salt-API when using the Salt-SSH client. (CVE-2021-3148) +- CVE-2021-3197 - Fix ssh client to remove ProxyCommand from arguments provided + by cli and netapi. (CVE-2021-3197) + +Salt 3000.6 +=========== + +Fixed +----- + +- Fixes salt-ssh authentication when using tty (#58922) + Salt 3000.5 =========== From 95630ea01e66d2b461fc40b0a41f163ae65317a5 Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Wed, 3 Feb 2021 13:53:37 -0700 Subject: [PATCH 63/69] Runners fix --- changelog/165.fixed | 1 + salt/client/mixins.py | 33 +++++++++++++++++++++++++++++---- salt/master.py | 2 +- salt/runner.py | 2 +- 4 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 changelog/165.fixed diff --git a/changelog/165.fixed b/changelog/165.fixed new file mode 100644 index 00000000000..0066356a8d0 --- /dev/null +++ b/changelog/165.fixed @@ -0,0 +1 @@ +Fix runners that broke when patching for CVE-2021-25281 diff --git a/salt/client/mixins.py b/salt/client/mixins.py index b33ee54f274..9ffdc667eff 100644 --- a/salt/client/mixins.py +++ b/salt/client/mixins.py @@ -487,8 +487,8 @@ class AsyncClientMixin(object): def _proc_function(self, fun, low, user, tag, jid, daemonize=True): """ - Run this method in a multiprocess target to execute the function in a - multiprocess and fire the return data on the event bus + Run this method in a multiprocess target to execute the function on the + master and fire the return data on the event bus """ if daemonize and not salt.utils.platform.is_windows(): # Shutdown the multiprocessing before daemonizing @@ -506,6 +506,27 @@ class AsyncClientMixin(object): return self.low(fun, low, full_return=False) + def _proc_function_local(self, fun, low, user, tag, jid, daemonize=True): + """ + Run this method in a multiprocess target to execute the function + locally and fire the return data on the event bus + """ + if daemonize and not salt.utils.platform.is_windows(): + # Shutdown the multiprocessing before daemonizing + salt.log.setup.shutdown_multiprocessing_logging() + + salt.utils.process.daemonize() + + # Reconfigure multiprocessing logging after daemonizing + salt.log.setup.setup_multiprocessing_logging() + + # pack a few things into low + low["__jid__"] = jid + low["__user__"] = user + low["__tag__"] = tag + + return self.low(fun, low) + def cmd_async(self, low): """ Execute a function asynchronously; eauth is respected @@ -532,14 +553,18 @@ class AsyncClientMixin(object): tag = salt.utils.event.tagify(jid, prefix=self.tag_prefix) return {"tag": tag, "jid": jid} - def asynchronous(self, fun, low, user="UNKNOWN", pub=None): + def asynchronous(self, fun, low, user="UNKNOWN", pub=None, local=False): """ Execute the function in a multiprocess and return the event tag to use to watch for the return """ + if local: + proc_func = self._proc_function_local + else: + proc_func = self._proc_function async_pub = pub if pub is not None else self._gen_async_pub() proc = salt.utils.process.SignalHandlingProcess( - target=self._proc_function, + target=proc_func, name="ProcessFunc", args=(fun, low, user, async_pub["tag"], async_pub["jid"]), ) diff --git a/salt/master.py b/salt/master.py index 1c91c28209f..edb0d6b7ac9 100644 --- a/salt/master.py +++ b/salt/master.py @@ -2128,7 +2128,7 @@ class ClearFuncs(TransportMethods): fun = clear_load.pop("fun") runner_client = salt.runner.RunnerClient(self.opts) return runner_client.asynchronous( - fun, clear_load.get("kwarg", {}), username + fun, clear_load.get("kwarg", {}), username, local=True ) except Exception as exc: # pylint: disable=broad-except log.error("Exception occurred while introspecting %s: %s", fun, exc) diff --git a/salt/runner.py b/salt/runner.py index e15aa6e8e8f..b15d8bce440 100644 --- a/salt/runner.py +++ b/salt/runner.py @@ -287,7 +287,7 @@ class Runner(RunnerClient): outputter = None display_output(ret, outputter, self.opts) else: - ret = self._proc_function( + ret = self._proc_function_local( self.opts["fun"], low, user, From caa0321e3300f1890b017c4a510c64f5ae682190 Mon Sep 17 00:00:00 2001 From: Bryce Larson Date: Fri, 5 Feb 2021 01:57:02 +0000 Subject: [PATCH 64/69] update requirements to point to a sha instead of a branch for vsphere-automation-sdk-python --- requirements/static/ci/git-sources.txt | 4 ++-- requirements/static/ci/py3.5/linux.log | 0 requirements/static/ci/py3.5/linux.txt | 4 ++-- requirements/static/ci/py3.6/linux.log | 0 requirements/static/ci/py3.6/linux.txt | 4 ++-- requirements/static/ci/py3.7/linux.txt | 4 ++-- requirements/static/ci/py3.8/linux.txt | 4 ++-- requirements/static/ci/py3.9/linux.txt | 4 ++-- 8 files changed, 12 insertions(+), 12 deletions(-) create mode 100644 requirements/static/ci/py3.5/linux.log create mode 100644 requirements/static/ci/py3.6/linux.log diff --git a/requirements/static/ci/git-sources.txt b/requirements/static/ci/git-sources.txt index e6afbd10e60..2c46e11010d 100644 --- a/requirements/static/ci/git-sources.txt +++ b/requirements/static/ci/git-sources.txt @@ -1,2 +1,2 @@ ---extra-index-url=https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/master/lib/ --e git+https://github.com/vmware/vsphere-automation-sdk-python.git#egg=vSphere-Automation-SDK +--extra-index-url=https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/9f62581527f4960e35d4d52da7d013b1a0ebbf11/lib/ +-e git+https://github.com/vmware/vsphere-automation-sdk-python.git@9f62581527f4960e35d4d52da7d013b1a0ebbf11#egg=vSphere-Automation-SDK diff --git a/requirements/static/ci/py3.5/linux.log b/requirements/static/ci/py3.5/linux.log new file mode 100644 index 00000000000..e69de29bb2d diff --git a/requirements/static/ci/py3.5/linux.txt b/requirements/static/ci/py3.5/linux.txt index b30592b74fc..452ccd5e6ba 100644 --- a/requirements/static/ci/py3.5/linux.txt +++ b/requirements/static/ci/py3.5/linux.txt @@ -4,9 +4,9 @@ # # pip-compile -o requirements/static/ci/py3.5/linux.txt -v requirements/static/pkg/py3.5/linux.txt requirements/pytest.txt requirements/static/ci/git-sources.txt requirements/static/ci/linux.in # ---extra-index-url https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/master/lib/ +--extra-index-url https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/9f62581527f4960e35d4d52da7d013b1a0ebbf11/lib/ --e git+https://github.com/vmware/vsphere-automation-sdk-python.git#egg=vSphere-Automation-SDK +-e git+https://github.com/vmware/vsphere-automation-sdk-python.git@9f62581527f4960e35d4d52da7d013b1a0ebbf11#egg=vSphere-Automation-SDK adal==1.2.3 # via azure-datalake-store, msrestazure apache-libcloud==2.0.0 appdirs==1.4.4 # via virtualenv diff --git a/requirements/static/ci/py3.6/linux.log b/requirements/static/ci/py3.6/linux.log new file mode 100644 index 00000000000..e69de29bb2d diff --git a/requirements/static/ci/py3.6/linux.txt b/requirements/static/ci/py3.6/linux.txt index 404316cab78..ff56a2912b1 100644 --- a/requirements/static/ci/py3.6/linux.txt +++ b/requirements/static/ci/py3.6/linux.txt @@ -4,9 +4,9 @@ # # pip-compile -o requirements/static/ci/py3.6/linux.txt -v requirements/static/pkg/py3.6/linux.txt requirements/pytest.txt requirements/static/ci/git-sources.txt requirements/static/ci/linux.in # ---extra-index-url https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/master/lib/ +--extra-index-url https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/9f62581527f4960e35d4d52da7d013b1a0ebbf11/lib/ --e git+https://github.com/vmware/vsphere-automation-sdk-python.git#egg=vSphere-Automation-SDK +-e git+https://github.com/vmware/vsphere-automation-sdk-python.git@9f62581527f4960e35d4d52da7d013b1a0ebbf11#egg=vSphere-Automation-SDK adal==1.2.3 # via azure-datalake-store, msrestazure apache-libcloud==2.0.0 appdirs==1.4.4 # via virtualenv diff --git a/requirements/static/ci/py3.7/linux.txt b/requirements/static/ci/py3.7/linux.txt index ab552ac8f08..0c5a0f8d9e6 100644 --- a/requirements/static/ci/py3.7/linux.txt +++ b/requirements/static/ci/py3.7/linux.txt @@ -4,9 +4,9 @@ # # pip-compile -o requirements/static/ci/py3.7/linux.txt -v requirements/static/pkg/py3.7/linux.txt requirements/pytest.txt requirements/static/ci/git-sources.txt requirements/static/ci/linux.in # ---extra-index-url https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/master/lib/ +--extra-index-url https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/9f62581527f4960e35d4d52da7d013b1a0ebbf11/lib/ --e git+https://github.com/vmware/vsphere-automation-sdk-python.git#egg=vSphere-Automation-SDK +-e git+https://github.com/vmware/vsphere-automation-sdk-python.git@9f62581527f4960e35d4d52da7d013b1a0ebbf11#egg=vSphere-Automation-SDK adal==1.2.3 # via azure-datalake-store, msrestazure apache-libcloud==2.0.0 appdirs==1.4.4 # via virtualenv diff --git a/requirements/static/ci/py3.8/linux.txt b/requirements/static/ci/py3.8/linux.txt index c7d6935a843..335705e77a2 100644 --- a/requirements/static/ci/py3.8/linux.txt +++ b/requirements/static/ci/py3.8/linux.txt @@ -4,9 +4,9 @@ # # pip-compile -o requirements/static/ci/py3.8/linux.txt -v requirements/static/pkg/py3.8/linux.txt requirements/pytest.txt requirements/static/ci/git-sources.txt requirements/static/ci/linux.in # ---extra-index-url https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/master/lib/ +--extra-index-url https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/9f62581527f4960e35d4d52da7d013b1a0ebbf11/lib/ --e git+https://github.com/vmware/vsphere-automation-sdk-python.git#egg=vSphere-Automation-SDK +-e git+https://github.com/vmware/vsphere-automation-sdk-python.git@9f62581527f4960e35d4d52da7d013b1a0ebbf11#egg=vSphere-Automation-SDK adal==1.2.3 # via azure-datalake-store, msrestazure apache-libcloud==2.0.0 appdirs==1.4.4 # via virtualenv diff --git a/requirements/static/ci/py3.9/linux.txt b/requirements/static/ci/py3.9/linux.txt index 859c63d13c3..f42ed69ba69 100644 --- a/requirements/static/ci/py3.9/linux.txt +++ b/requirements/static/ci/py3.9/linux.txt @@ -4,9 +4,9 @@ # # pip-compile -o requirements/static/ci/py3.9/linux.txt -v requirements/static/pkg/py3.9/linux.txt requirements/pytest.txt requirements/static/ci/git-sources.txt requirements/static/ci/linux.in # ---extra-index-url https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/master/lib/ +--extra-index-url https://cdn.githubraw.com/vmware/vsphere-automation-sdk-python/9f62581527f4960e35d4d52da7d013b1a0ebbf11/lib/ --e git+https://github.com/vmware/vsphere-automation-sdk-python.git#egg=vSphere-Automation-SDK +-e git+https://github.com/vmware/vsphere-automation-sdk-python.git@9f62581527f4960e35d4d52da7d013b1a0ebbf11#egg=vSphere-Automation-SDK adal==1.2.3 # via azure-datalake-store, msrestazure apache-libcloud==2.0.0 appdirs==1.4.4 # via virtualenv From b71ae1f2eb3e2b3aed973559008ff254bbdb9130 Mon Sep 17 00:00:00 2001 From: Bryce Larson Date: Fri, 5 Feb 2021 00:58:59 +0000 Subject: [PATCH 65/69] fix pre-commit --- salt/client/mixins.py | 33 ++++++++++++--------------- salt/master.py | 4 ---- salt/runner.py | 52 ++++++++++++++++++------------------------- 3 files changed, 36 insertions(+), 53 deletions(-) diff --git a/salt/client/mixins.py b/salt/client/mixins.py index 9ffdc667eff..91cd98d1a25 100644 --- a/salt/client/mixins.py +++ b/salt/client/mixins.py @@ -1,10 +1,7 @@ -# coding: utf-8 """ A collection of mixins useful for the various *Client interfaces """ -# Import Python libs -from __future__ import absolute_import, print_function, unicode_literals, with_statement import copy as pycopy import fnmatch @@ -14,10 +11,7 @@ import traceback import weakref from collections.abc import Mapping, MutableMapping -# Import Salt libs import salt.exceptions - -# Import 3rd-party libs import salt.ext.tornado.stack_context import salt.log.setup import salt.minion @@ -122,7 +116,7 @@ class ClientFuncsDict(MutableMapping): return iter(self.client.functions) -class SyncClientMixin(object): +class SyncClientMixin: """ A mixin for *Client interfaces to abstract common function execution """ @@ -182,7 +176,7 @@ class SyncClientMixin(object): ) if ret is None: raise salt.exceptions.SaltClientTimeout( - "RunnerClient job '{0}' timed out".format(job["jid"]), + "RunnerClient job '{}' timed out".format(job["jid"]), jid=job["jid"], ) @@ -281,7 +275,7 @@ class SyncClientMixin(object): return True try: - return self.opts["{0}_returns".format(class_name)] + return self.opts["{}_returns".format(class_name)] except KeyError: # No such option, assume this isn't one we care about gating and # just return True. @@ -308,7 +302,7 @@ class SyncClientMixin(object): tag = low.get("__tag__", salt.utils.event.tagify(jid, prefix=self.tag_prefix)) data = { - "fun": "{0}.{1}".format(self.client, fun), + "fun": "{}.{}".format(self.client, fun), "jid": jid, "user": low.get("__user__", "UNKNOWN"), } @@ -353,14 +347,14 @@ class SyncClientMixin(object): # namespace only once per module-- not per func completed_funcs = [] - for mod_name in six.iterkeys(self_functions): + for mod_name in self_functions.keys(): if "." not in mod_name: continue mod, _ = mod_name.split(".", 1) if mod in completed_funcs: continue completed_funcs.append(mod) - for global_key, value in six.iteritems(func_globals): + for global_key, value in func_globals.items(): self.functions[mod_name].__globals__[global_key] = value # There are some discrepancies of what a "low" structure is in the @@ -398,7 +392,7 @@ class SyncClientMixin(object): except TypeError as exc: data[ "return" - ] = "\nPassed invalid arguments: {0}\n\nUsage:\n{1}".format( + ] = "\nPassed invalid arguments: {}\n\nUsage:\n{}".format( exc, func.__doc__ ) try: @@ -413,9 +407,9 @@ class SyncClientMixin(object): ) except (Exception, SystemExit) as ex: # pylint: disable=broad-except if isinstance(ex, salt.exceptions.NotImplemented): - data["return"] = six.text_type(ex) + data["return"] = str(ex) else: - data["return"] = "Exception occurred in {0} {1}: {2}".format( + data["return"] = "Exception occurred in {} {}: {}".format( self.client, fun, traceback.format_exc(), ) data["success"] = False @@ -477,7 +471,7 @@ class SyncClientMixin(object): return salt.utils.doc.strip_rst(docs) -class AsyncClientMixin(object): +class AsyncClientMixin: """ A mixin for *Client interfaces to enable easy asynchronous function execution """ @@ -602,9 +596,10 @@ class AsyncClientMixin(object): if suffix == "ret": # Check if outputter was passed in the return data. If this is the case, # then the return data will be a dict two keys: 'data' and 'outputter' - if isinstance(event.get("return"), dict) and set(event["return"]) == set( - ("data", "outputter") - ): + if isinstance(event.get("return"), dict) and set(event["return"]) == { + "data", + "outputter", + }: event_data = event["return"]["data"] outputter = event["return"]["outputter"] else: diff --git a/salt/master.py b/salt/master.py index edb0d6b7ac9..02e3b3bb86d 100644 --- a/salt/master.py +++ b/salt/master.py @@ -3,7 +3,6 @@ This module contains all of the routines needed to set up a master server, this involves preparing the three listeners and the workers needed by the master. """ -# Import python libs import collections import copy @@ -23,8 +22,6 @@ import salt.acl import salt.auth import salt.client import salt.client.ssh.client - -# Import salt libs import salt.crypt import salt.daemons.masterapi import salt.defaults.exitcodes @@ -89,7 +86,6 @@ except ImportError: # resource is not available on windows HAS_RESOURCE = False -# Import halite libs try: import halite # pylint: disable=import-error diff --git a/salt/runner.py b/salt/runner.py index b15d8bce440..ebdc069f1a4 100644 --- a/salt/runner.py +++ b/salt/runner.py @@ -1,15 +1,11 @@ -# -*- coding: utf-8 -*- """ Execute salt convenience routines """ -# Import python libs -from __future__ import absolute_import, print_function, unicode_literals import logging import os -# Import salt libs import salt.exceptions import salt.loader import salt.minion @@ -24,7 +20,7 @@ from salt.utils.lazy import verify_fun log = logging.getLogger(__name__) -class RunnerClient(mixins.SyncClientMixin, mixins.AsyncClientMixin, object): +class RunnerClient(mixins.SyncClientMixin, mixins.AsyncClientMixin): """ The interface used by the :command:`salt-run` CLI tool on the Salt Master @@ -80,21 +76,19 @@ class RunnerClient(mixins.SyncClientMixin, mixins.AsyncClientMixin, object): fun = low.pop("fun") verify_fun(self.functions, fun) - eauth_creds = dict( - [ - (i, low.pop(i)) - for i in [ - "username", - "password", - "eauth", - "token", - "client", - "user", - "key", - ] - if i in low + eauth_creds = { + i: low.pop(i) + for i in [ + "username", + "password", + "eauth", + "token", + "client", + "user", + "key", ] - ) + if i in low + } # Run name=value args through parse_input. We don't need to run kwargs # through because there is no way to send name=value strings in the low @@ -171,9 +165,7 @@ class RunnerClient(mixins.SyncClientMixin, mixins.AsyncClientMixin, object): """ Execute a function """ - return super(RunnerClient, self).cmd( - fun, arg, pub_data, kwarg, print_event, full_return - ) + return super().cmd(fun, arg, pub_data, kwarg, print_event, full_return) class Runner(RunnerClient): @@ -182,7 +174,7 @@ class Runner(RunnerClient): """ def __init__(self, opts, context=None): - super(Runner, self).__init__(opts, context=context) + super().__init__(opts, context=context) self.returners = salt.loader.returners(opts, self.functions, context=context) self.outputters = salt.loader.outputters(opts) @@ -191,9 +183,9 @@ class Runner(RunnerClient): Print out the documentation! """ arg = self.opts.get("fun", None) - docs = super(Runner, self).get_docs(arg) + docs = super().get_docs(arg) for fun in sorted(docs): - display_output("{0}:".format(fun), "text", self.opts) + display_output("{}:".format(fun), "text", self.opts) print(docs[fun]) # TODO: move to mixin whenever we want a salt-wheel cli @@ -233,7 +225,7 @@ class Runner(RunnerClient): low["key"] = salt.utils.stringutils.to_unicode( fp_.readline() ) - except IOError: + except OSError: low["token"] = self.opts["token"] # If using eauth and a token hasn't already been loaded into @@ -300,24 +292,24 @@ class Runner(RunnerClient): evt.fire_event( { "success": False, - "return": "{0}".format(exc), + "return": "{}".format(exc), "retcode": 254, "fun": self.opts["fun"], "fun_args": fun_args, "jid": self.jid, }, - tag="salt/run/{0}/ret".format(self.jid), + tag="salt/run/{}/ret".format(self.jid), ) # Attempt to grab documentation if "fun" in low: - ret = self.get_docs("{0}*".format(low["fun"])) + ret = self.get_docs("{}*".format(low["fun"])) else: ret = None # If we didn't get docs returned then # return the `not availble` message. if not ret: - ret = "{0}".format(exc) + ret = "{}".format(exc) if not self.opts.get("quiet", False): display_output(ret, "nested", self.opts) else: From c63ad28fafc64f7ce9c30793b514576ce8db7849 Mon Sep 17 00:00:00 2001 From: Frode Gundersen Date: Fri, 5 Feb 2021 14:28:31 -0700 Subject: [PATCH 66/69] Update docs 3002.4 --- CHANGELOG.md | 25 +++ changelog/165.fixed | 1 - doc/man/salt-api.1 | 2 +- doc/man/salt-call.1 | 2 +- doc/man/salt-cloud.1 | 2 +- doc/man/salt-cp.1 | 2 +- doc/man/salt-key.1 | 2 +- doc/man/salt-master.1 | 2 +- doc/man/salt-minion.1 | 2 +- doc/man/salt-proxy.1 | 2 +- doc/man/salt-run.1 | 2 +- doc/man/salt-ssh.1 | 2 +- doc/man/salt-syndic.1 | 2 +- doc/man/salt-unity.1 | 2 +- doc/man/salt.1 | 2 +- doc/man/salt.7 | 361 ++++++++++++++++++++++++++++----- doc/man/spm.1 | 2 +- doc/topics/releases/3000.8.rst | 12 ++ doc/topics/releases/3001.6.rst | 12 ++ doc/topics/releases/3002.4.rst | 12 ++ 20 files changed, 383 insertions(+), 68 deletions(-) delete mode 100644 changelog/165.fixed create mode 100644 doc/topics/releases/3000.8.rst create mode 100644 doc/topics/releases/3001.6.rst create mode 100644 doc/topics/releases/3002.4.rst diff --git a/CHANGELOG.md b/CHANGELOG.md index 62641d4db56..87b680d5852 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,15 @@ Versions are `MAJOR.PATCH`. # Changelog +Salt 3002.4 (2021-02-05) +======================== + +Fixed +----- + +- Fix runners that broke when patching for CVE-2021-25281 + + Salt 3002.3 (2021-01-25) ======================== @@ -300,6 +309,14 @@ Added This flag will be deprecated in the Phosphorus release when this functionality becomes the default. (#58652) +Salt 3001.6 (2021-02-05) +======================== + +Fixed +----- + +- Fix runners that broke when patching for CVE-2021-25281 + Salt 3001.5 =========== @@ -782,6 +799,14 @@ 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.8 (2021-02-05) +======================== + +Fixed +----- + +- Fix runners that broke when patching for CVE-2021-25281 + Salt 3000.7 =========== diff --git a/changelog/165.fixed b/changelog/165.fixed deleted file mode 100644 index 0066356a8d0..00000000000 --- a/changelog/165.fixed +++ /dev/null @@ -1 +0,0 @@ -Fix runners that broke when patching for CVE-2021-25281 diff --git a/doc/man/salt-api.1 b/doc/man/salt-api.1 index 4b8efef98fa..ae314a27fe9 100644 --- a/doc/man/salt-api.1 +++ b/doc/man/salt-api.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-API" "1" "Jan 14, 2021" "3002.3" "Salt" +.TH "SALT-API" "1" "Feb 05, 2021" "3002.4" "Salt" .SH NAME salt-api \- salt-api Command . diff --git a/doc/man/salt-call.1 b/doc/man/salt-call.1 index 6b0d865cdfb..efbe205cc31 100644 --- a/doc/man/salt-call.1 +++ b/doc/man/salt-call.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-CALL" "1" "Jan 14, 2021" "3002.3" "Salt" +.TH "SALT-CALL" "1" "Feb 05, 2021" "3002.4" "Salt" .SH NAME salt-call \- salt-call Documentation . diff --git a/doc/man/salt-cloud.1 b/doc/man/salt-cloud.1 index 7fc5010e8e7..eebbf25b1c3 100644 --- a/doc/man/salt-cloud.1 +++ b/doc/man/salt-cloud.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-CLOUD" "1" "Jan 14, 2021" "3002.3" "Salt" +.TH "SALT-CLOUD" "1" "Feb 05, 2021" "3002.4" "Salt" .SH NAME salt-cloud \- Salt Cloud Command . diff --git a/doc/man/salt-cp.1 b/doc/man/salt-cp.1 index cb3e5dfe059..e0a6b616eda 100644 --- a/doc/man/salt-cp.1 +++ b/doc/man/salt-cp.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-CP" "1" "Jan 14, 2021" "3002.3" "Salt" +.TH "SALT-CP" "1" "Feb 05, 2021" "3002.4" "Salt" .SH NAME salt-cp \- salt-cp Documentation . diff --git a/doc/man/salt-key.1 b/doc/man/salt-key.1 index 505e06796a1..62fea65ca69 100644 --- a/doc/man/salt-key.1 +++ b/doc/man/salt-key.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-KEY" "1" "Jan 14, 2021" "3002.3" "Salt" +.TH "SALT-KEY" "1" "Feb 05, 2021" "3002.4" "Salt" .SH NAME salt-key \- salt-key Documentation . diff --git a/doc/man/salt-master.1 b/doc/man/salt-master.1 index c1433ac11dc..c3a5c2ffe5e 100644 --- a/doc/man/salt-master.1 +++ b/doc/man/salt-master.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-MASTER" "1" "Jan 14, 2021" "3002.3" "Salt" +.TH "SALT-MASTER" "1" "Feb 05, 2021" "3002.4" "Salt" .SH NAME salt-master \- salt-master Documentation . diff --git a/doc/man/salt-minion.1 b/doc/man/salt-minion.1 index b47f0c7a863..eb760d3f160 100644 --- a/doc/man/salt-minion.1 +++ b/doc/man/salt-minion.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-MINION" "1" "Jan 14, 2021" "3002.3" "Salt" +.TH "SALT-MINION" "1" "Feb 05, 2021" "3002.4" "Salt" .SH NAME salt-minion \- salt-minion Documentation . diff --git a/doc/man/salt-proxy.1 b/doc/man/salt-proxy.1 index defb449dd29..e08aecdb91a 100644 --- a/doc/man/salt-proxy.1 +++ b/doc/man/salt-proxy.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-PROXY" "1" "Jan 14, 2021" "3002.3" "Salt" +.TH "SALT-PROXY" "1" "Feb 05, 2021" "3002.4" "Salt" .SH NAME salt-proxy \- salt-proxy Documentation . diff --git a/doc/man/salt-run.1 b/doc/man/salt-run.1 index 11d53fabb4e..634dc390cf8 100644 --- a/doc/man/salt-run.1 +++ b/doc/man/salt-run.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-RUN" "1" "Jan 14, 2021" "3002.3" "Salt" +.TH "SALT-RUN" "1" "Feb 05, 2021" "3002.4" "Salt" .SH NAME salt-run \- salt-run Documentation . diff --git a/doc/man/salt-ssh.1 b/doc/man/salt-ssh.1 index fa558bf6183..c3b901eee43 100644 --- a/doc/man/salt-ssh.1 +++ b/doc/man/salt-ssh.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-SSH" "1" "Jan 14, 2021" "3002.3" "Salt" +.TH "SALT-SSH" "1" "Feb 05, 2021" "3002.4" "Salt" .SH NAME salt-ssh \- salt-ssh Documentation . diff --git a/doc/man/salt-syndic.1 b/doc/man/salt-syndic.1 index b1a25c79824..45499dafc71 100644 --- a/doc/man/salt-syndic.1 +++ b/doc/man/salt-syndic.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-SYNDIC" "1" "Jan 14, 2021" "3002.3" "Salt" +.TH "SALT-SYNDIC" "1" "Feb 05, 2021" "3002.4" "Salt" .SH NAME salt-syndic \- salt-syndic Documentation . diff --git a/doc/man/salt-unity.1 b/doc/man/salt-unity.1 index 8a288461193..a4461d1191a 100644 --- a/doc/man/salt-unity.1 +++ b/doc/man/salt-unity.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT-UNITY" "1" "Jan 14, 2021" "3002.3" "Salt" +.TH "SALT-UNITY" "1" "Feb 05, 2021" "3002.4" "Salt" .SH NAME salt-unity \- salt-unity Command . diff --git a/doc/man/salt.1 b/doc/man/salt.1 index 64f5f05c546..033bd82b85f 100644 --- a/doc/man/salt.1 +++ b/doc/man/salt.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT" "1" "Jan 14, 2021" "3002.3" "Salt" +.TH "SALT" "1" "Feb 05, 2021" "3002.4" "Salt" .SH NAME salt \- salt . diff --git a/doc/man/salt.7 b/doc/man/salt.7 index 8c36ca002a8..0c0187790bb 100644 --- a/doc/man/salt.7 +++ b/doc/man/salt.7 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SALT" "7" "Jan 14, 2021" "3002.3" "Salt" +.TH "SALT" "7" "Feb 05, 2021" "3002.4" "Salt" .SH NAME salt \- Salt Documentation . @@ -31388,6 +31388,7 @@ splunk_http_forwarder: indexer: sourcetype: index: + verify_ssl: true .ft P .fi .UNINDENT @@ -31398,7 +31399,7 @@ Run a test by using \fBsalt\-call test.ping \-\-return splunk\fP Written by Scott Pack (github.com/scottjpack) .INDENT 0.0 .TP -.B class salt.returners.splunk.http_event_collector(token, http_event_server, host=\(aq\(aq, http_event_port=\(aq8088\(aq, http_event_server_ssl=True, max_bytes=100000) +.B class salt.returners.splunk.http_event_collector(token, http_event_server, host=\(aq\(aq, http_event_port=\(aq8088\(aq, http_event_server_ssl=True, max_bytes=100000, verify_ssl=True) .INDENT 7.0 .TP .B batchEvent(payload, eventtime=\(aq\(aq) @@ -191333,7 +191334,7 @@ Passes through all the parameters described in the \fI\%utils.http.query function\fP: .INDENT 7.0 .TP -.B salt.utils.http.query(url, method=\(aqGET\(aq, params=None, data=None, data_file=None, header_dict=None, header_list=None, header_file=None, username=None, password=None, auth=None, decode=False, decode_type=\(aqauto\(aq, status=False, headers=False, text=False, cookies=None, cookie_jar=None, cookie_format=\(aqlwp\(aq, persist_session=False, session_cookie_jar=None, data_render=False, data_renderer=None, header_render=False, header_renderer=None, template_dict=None, test=False, test_url=None, node=\(aqminion\(aq, port=80, opts=None, backend=None, ca_bundle=None, verify_ssl=None, cert=None, text_out=None, headers_out=None, decode_out=None, stream=False, streaming_callback=None, header_callback=None, handle=False, agent=\(aqSalt/3002.2\(aq, hide_fields=None, raise_error=True, formdata=False, formdata_fieldname=None, formdata_filename=None, decode_body=True, **kwargs) +.B salt.utils.http.query(url, method=\(aqGET\(aq, params=None, data=None, data_file=None, header_dict=None, header_list=None, header_file=None, username=None, password=None, auth=None, decode=False, decode_type=\(aqauto\(aq, status=False, headers=False, text=False, cookies=None, cookie_jar=None, cookie_format=\(aqlwp\(aq, persist_session=False, session_cookie_jar=None, data_render=False, data_renderer=None, header_render=False, header_renderer=None, template_dict=None, test=False, test_url=None, node=\(aqminion\(aq, port=80, opts=None, backend=None, ca_bundle=None, verify_ssl=None, cert=None, text_out=None, headers_out=None, decode_out=None, stream=False, streaming_callback=None, header_callback=None, handle=False, agent=\(aqSalt/3002.4\(aq, hide_fields=None, raise_error=True, formdata=False, formdata_fieldname=None, formdata_filename=None, decode_body=True, **kwargs) Query a resource, and decode the return data .UNINDENT .INDENT 7.0 @@ -200665,6 +200666,7 @@ keystone.password: verybadpass keystone.tenant: admin keystone.tenant_id: f80919baedab48ec8931f200c65a50df keystone.auth_url: \(aqhttp://127.0.0.1:5000/v2.0/\(aq +keystone.verify_ssl: True .ft P .fi .UNINDENT @@ -200696,6 +200698,7 @@ openstack1: keystone.tenant: admin keystone.tenant_id: f80919baedab48ec8931f200c65a50df keystone.auth_url: \(aqhttp://127.0.0.1:5000/v2.0/\(aq + keystone.verify_ssl: True openstack2: keystone.user: admin @@ -200703,6 +200706,7 @@ openstack2: keystone.tenant: admin keystone.tenant_id: f80919baedab48ec8931f200c65a50df keystone.auth_url: \(aqhttp://127.0.0.2:5000/v2.0/\(aq + keystone.verify_ssl: True .ft P .fi .UNINDENT @@ -303916,7 +303920,7 @@ salt \(aq*\(aq vsphere.add_capacity_to_diskgroup .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.add_host_to_dvs(host, username, password, vmknic_name, vmnic_name, dvs_name, target_portgroup_name, uplink_portgroup_name, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.add_host_to_dvs(host, username, password, vmknic_name, vmnic_name, dvs_name, target_portgroup_name, uplink_portgroup_name, protocol=None, port=None, host_names=None, verify_ssl=True) Adds an ESXi host to a vSphere Distributed Virtual Switch and migrates the desired adapters to the DVS from the standard switch. .INDENT 7.0 @@ -303957,6 +303961,9 @@ using the default port. Default port is \fB443\fP\&. .TP .B host_names: An array of VMware host names to migrate +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -304202,7 +304209,7 @@ salt \(aq*\(aq vsphere.assign_license license_key=00000:00000 .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.attach_tag(object_id, tag_id, managed_obj=\(aqClusterComputeResource\(aq, server=None, username=None, password=None, service_instance=None) +.B salt.modules.vsphere.attach_tag(object_id, tag_id, managed_obj=\(aqClusterComputeResource\(aq, server=None, username=None, password=None, service_instance=None, verify_ssl=None, ca_bundle=None) Attach an existing tag to an input object. .sp The tag needs to meet the cardinality (\fICategoryModel.cardinality\fP) and @@ -304241,6 +304248,10 @@ for the resources being created and deleted. \fBusername\fP (\fIbasestring\fP) \-\- Username associated with the vCenter center. .IP \(bu 2 \fBpassword\fP (\fIbasestring\fP) \-\- Password associated with the vCenter center. +.IP \(bu 2 +\fBverify_ssl\fP (\fIboolean\fP) \-\- Verify the SSL certificate. Default: True +.IP \(bu 2 +\fBca_bundle\fP (\fIbasestring\fP) \-\- Path to the ca bundle to use when verifying SSL certificates. .UNINDENT .TP .B Returns @@ -304563,7 +304574,7 @@ salt \(aq*\(aq vsphere.create_storage_policy policy_name=\(aqpolicy name\(aq .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.create_tag(name, description, category_id, server=None, username=None, password=None, service_instance=None) +.B salt.modules.vsphere.create_tag(name, description, category_id, server=None, username=None, password=None, service_instance=None, verify_ssl=None, ca_bundle=None) Create a tag under a category with given description. .sp CLI Example: @@ -304593,6 +304604,10 @@ salt vm_minion vsphere.create_tag \fBdescription\fP (\fI\%str\fP) \-\- Given description of tag category. .IP \(bu 2 \fBcategory_id\fP (\fI\%str\fP) \-\- Value of category_id representative of the category created previously. +.IP \(bu 2 +\fBverify_ssl\fP (\fIboolean\fP) \-\- Verify the SSL certificate. Default: True +.IP \(bu 2 +\fBca_bundle\fP (\fIbasestring\fP) \-\- Path to the ca bundle to use when verifying SSL certificates. .UNINDENT .TP .B Returns @@ -304622,7 +304637,7 @@ if you do not have the privilege to create tag. .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.create_tag_category(name, description, cardinality, server=None, username=None, password=None, service_instance=None) +.B salt.modules.vsphere.create_tag_category(name, description, cardinality, server=None, username=None, password=None, service_instance=None, verify_ssl=None, ca_bundle=None) Create a category with given cardinality. .sp CLI Example: @@ -304652,6 +304667,10 @@ salt vm_minion vsphere.create_tag_category \fBusername\fP (\fIbasestring\fP) \-\- Username associated with the vCenter center. .IP \(bu 2 \fBpassword\fP (\fIbasestring\fP) \-\- Password associated with the vCenter center. +.IP \(bu 2 +\fBverify_ssl\fP (\fIboolean\fP) \-\- Verify the SSL certificate. Default: True +.IP \(bu 2 +\fBca_bundle\fP (\fIbasestring\fP) \-\- Path to the ca bundle to use when verifying SSL certificates. .UNINDENT .TP .B Returns @@ -304880,7 +304899,7 @@ vCenter service instance for connection and configuration .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.delete_tag(tag_id, server=None, username=None, password=None, service_instance=None) +.B salt.modules.vsphere.delete_tag(tag_id, server=None, username=None, password=None, service_instance=None, verify_ssl=None, ca_bundle=None) Delete a tag. .sp CLI Example: @@ -304908,6 +304927,10 @@ The parameter must be an identifier for the resource type: \fBusername\fP (\fIbasestring\fP) \-\- Username associated with the vCenter center. .IP \(bu 2 \fBpassword\fP (\fIbasestring\fP) \-\- Password associated with the vCenter center. +.IP \(bu 2 +\fBverify_ssl\fP (\fIboolean\fP) \-\- Verify the SSL certificate. Default: True +.IP \(bu 2 +\fBca_bundle\fP (\fIbasestring\fP) \-\- Path to the ca bundle to use when verifying SSL certificates. .UNINDENT .TP .B Raise @@ -304926,7 +304949,7 @@ if you do not have the privilege to create a category. .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.delete_tag_category(category_id, server=None, username=None, password=None, service_instance=None) +.B salt.modules.vsphere.delete_tag_category(category_id, server=None, username=None, password=None, service_instance=None, verify_ssl=None, ca_bundle=None) Delete a category. .sp CLI Example: @@ -304954,6 +304977,10 @@ The parameter must be an identifier for the resource type: \fBusername\fP (\fIbasestring\fP) \-\- Username associated with the vCenter center. .IP \(bu 2 \fBpassword\fP (\fIbasestring\fP) \-\- Password associated with the vCenter center. +.IP \(bu 2 +\fBverify_ssl\fP (\fIboolean\fP) \-\- Verify the SSL certificate. Default: True +.IP \(bu 2 +\fBca_bundle\fP (\fIbasestring\fP) \-\- Path to the ca bundle to use when verifying SSL certificates. .UNINDENT .TP .B Raise @@ -305317,7 +305344,7 @@ salt \(aq*\(aq vsphere.get_host_cache .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.get_host_datetime(host, username, password, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.get_host_datetime(host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True) Get the date/time information for a given host or list of host_names. .INDENT 7.0 .TP @@ -305346,6 +305373,9 @@ vCenter the hosts for which to get date/time information. If host_names is not provided, the date/time information will be retrieved for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -305366,7 +305396,7 @@ salt \(aq*\(aq vsphere.get_host_datetime my.vcenter.location root bad\-password .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.get_ntp_config(host, username, password, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.get_ntp_config(host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True) Get the NTP configuration information for a given host or list of host_names. .INDENT 7.0 .TP @@ -305395,6 +305425,9 @@ vCenter the hosts for which to get ntp configuration information. If host_names is not provided, the NTP configuration will be retrieved for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -305456,7 +305489,7 @@ See note above .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.get_service_policy(host, username, password, service_name, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.get_service_policy(host, username, password, service_name, protocol=None, port=None, host_names=None, verify_ssl=True) Get the service name\(aqs policy for a given host or list of hosts. .INDENT 7.0 .TP @@ -305519,6 +305552,9 @@ vCenter the hosts for which to get service policy information. If host_names is not provided, the service policy information will be retrieved for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -305539,7 +305575,7 @@ salt \(aq*\(aq vsphere.get_service_policy my.vcenter.location root bad\-password .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.get_service_running(host, username, password, service_name, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.get_service_running(host, username, password, service_name, protocol=None, port=None, host_names=None, verify_ssl=True) Get the service name\(aqs running state for a given host or list of hosts. .INDENT 7.0 .TP @@ -305602,6 +305638,9 @@ vCenter the hosts for which to get the service\(aqs running state. If host_names is not provided, the service\(aqs running state will be retrieved for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -305622,7 +305661,7 @@ salt \(aq*\(aq vsphere.get_service_running my.vcenter.location root bad\-passwor .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.get_ssh_key(host, username, password, protocol=None, port=None, certificate_verify=False) +.B salt.modules.vsphere.get_ssh_key(host, username, password, protocol=None, port=None, certificate_verify=None) Retrieve the authorized_keys entry for root. This function only works for ESXi, not vCenter. .INDENT 7.0 @@ -305641,7 +305680,7 @@ This function only works for ESXi, not vCenter. \fBport\fP \-\- defaults to 443 for https .IP \(bu 2 \fBcertificate_verify\fP \-\- If true require that the SSL connection present -a valid certificate +a valid certificate. Default: True .UNINDENT .TP .B Returns @@ -305786,7 +305825,7 @@ Default is None. .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.get_vmotion_enabled(host, username, password, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.get_vmotion_enabled(host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True) Get the VMotion enabled status for a given host or a list of host_names. Returns \fBTrue\fP if VMotion is enabled, \fBFalse\fP if it is not enabled. .INDENT 7.0 @@ -305816,6 +305855,9 @@ tell vCenter which hosts to check if VMotion is enabled. If host_names is not provided, the VMotion status will be retrieved for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -305836,7 +305878,7 @@ salt \(aq*\(aq vsphere.get_vmotion_enabled my.vcenter.location root bad\-passwor .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.get_vsan_eligible_disks(host, username, password, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.get_vsan_eligible_disks(host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True) Returns a list of VSAN\-eligible disks for a given host or list of host_names. .INDENT 7.0 .TP @@ -305865,6 +305907,9 @@ tell vCenter which hosts to check if any VSAN\-eligible disks are available. If host_names is not provided, the VSAN\-eligible disks will be retrieved for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -305885,7 +305930,7 @@ salt \(aq*\(aq vsphere.get_vsan_eligible_disks my.vcenter.location root bad\-pas .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.get_vsan_enabled(host, username, password, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.get_vsan_enabled(host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True) Get the VSAN enabled status for a given host or a list of host_names. Returns \fBTrue\fP if VSAN is enabled, \fBFalse\fP if it is not enabled, and \fBNone\fP if a VSAN Host Config is unset, per host. @@ -305916,6 +305961,9 @@ tell vCenter which hosts to check if VSAN enabled. If host_names is not provided, the VSAN status will be retrieved for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -305992,7 +306040,7 @@ salt \(aq*\(aq vsphere.list_assigned_licenses .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_attached_tags(object_id, managed_obj=\(aqClusterComputeResource\(aq, server=None, username=None, password=None, service_instance=None) +.B salt.modules.vsphere.list_attached_tags(object_id, managed_obj=\(aqClusterComputeResource\(aq, server=None, username=None, password=None, service_instance=None, verify_ssl=None, ca_bundle=None) List existing tags a user has access to. .sp CLI Example: @@ -306022,6 +306070,10 @@ for the resources being created and deleted. \fBusername\fP (\fIbasestring\fP) \-\- Username associated with the vCenter center. .IP \(bu 2 \fBpassword\fP (\fIbasestring\fP) \-\- Password associated with the vCenter center. +.IP \(bu 2 +\fBverify_ssl\fP (\fIboolean\fP) \-\- Verify the SSL certificate. Default: True +.IP \(bu 2 +\fBca_bundle\fP (\fIbasestring\fP) \-\- Path to the ca bundle to use when verifying SSL certificates. .UNINDENT .TP .B Returns @@ -306101,7 +306153,7 @@ salt \(aq*\(aq vsphere.list_cluster .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_clusters(host, username, password, protocol=None, port=None) +.B salt.modules.vsphere.list_clusters(host, username, password, protocol=None, port=None, verify_ssl=True) Returns a list of clusters for the specified host. .INDENT 7.0 .TP @@ -306121,6 +306173,9 @@ protocol. Default protocol is \fBhttps\fP\&. .B port Optionally set to alternate port if the host is not using the default port. Default port is \fB443\fP\&. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -306137,7 +306192,7 @@ salt \(aq*\(aq vsphere.list_clusters 1.2.3.4 root bad\-password .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_datacenters(host, username, password, protocol=None, port=None) +.B salt.modules.vsphere.list_datacenters(host, username, password, protocol=None, port=None, verify_ssl=True) Returns a list of datacenters for the specified host. .INDENT 7.0 .TP @@ -306157,6 +306212,9 @@ protocol. Default protocol is \fBhttps\fP\&. .B port Optionally set to alternate port if the host is not using the default port. Default port is \fB443\fP\&. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -306207,7 +306265,7 @@ salt \(aq*\(aq vsphere.list_datacenters_via_proxy datacenter_names=[dc1, dc2] .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_datastore_clusters(host, username, password, protocol=None, port=None) +.B salt.modules.vsphere.list_datastore_clusters(host, username, password, protocol=None, port=None, verify_ssl=True) Returns a list of datastore clusters for the specified host. .INDENT 7.0 .TP @@ -306227,6 +306285,9 @@ protocol. Default protocol is \fBhttps\fP\&. .B port Optionally set to alternate port if the host is not using the default port. Default port is \fB443\fP\&. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -306243,7 +306304,7 @@ salt \(aq*\(aq vsphere.list_datastore_clusters 1.2.3.4 root bad\-password .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_datastores(host, username, password, protocol=None, port=None) +.B salt.modules.vsphere.list_datastores(host, username, password, protocol=None, port=None, verify_ssl=True) Returns a list of datastores for the specified host. .INDENT 7.0 .TP @@ -306263,6 +306324,9 @@ protocol. Default protocol is \fBhttps\fP\&. .B port Optionally set to alternate port if the host is not using the default port. Default port is \fB443\fP\&. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -306505,7 +306569,7 @@ salt \(aq*\(aq vsphere.list_dvportgroups dvs=dvs1 portgroup_names=[pg1] .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_dvs(host, username, password, protocol=None, port=None) +.B salt.modules.vsphere.list_dvs(host, username, password, protocol=None, port=None, verify_ssl=True) Returns a list of distributed virtual switches for the specified host. .INDENT 7.0 .TP @@ -306525,6 +306589,9 @@ protocol. Default protocol is \fBhttps\fP\&. .B port Optionally set to alternate port if the host is not using the default port. Default port is \fB443\fP\&. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -306569,7 +306636,7 @@ salt \(aq*\(aq vsphere.list_dvss dvs_names=[dvs1,dvs2] .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_folders(host, username, password, protocol=None, port=None) +.B salt.modules.vsphere.list_folders(host, username, password, protocol=None, port=None, verify_ssl=True) Returns a list of folders for the specified host. .INDENT 7.0 .TP @@ -306589,6 +306656,9 @@ protocol. Default protocol is \fBhttps\fP\&. .B port Optionally set to alternate port if the host is not using the default port. Default port is \fB443\fP\&. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -306605,7 +306675,7 @@ salt \(aq*\(aq vsphere.list_folders 1.2.3.4 root bad\-password .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_hosts(host, username, password, protocol=None, port=None) +.B salt.modules.vsphere.list_hosts(host, username, password, protocol=None, port=None, verify_ssl=True) Returns a list of hosts for the specified VMware environment. .INDENT 7.0 .TP @@ -306625,6 +306695,9 @@ protocol. Default protocol is \fBhttps\fP\&. .B port Optionally set to alternate port if the host is not using the default port. Default port is \fB443\fP\&. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -306702,7 +306775,7 @@ salt \(aq*\(aq vsphere.list_licenses .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_networks(host, username, password, protocol=None, port=None) +.B salt.modules.vsphere.list_networks(host, username, password, protocol=None, port=None, verify_ssl=True) Returns a list of networks for the specified host. .INDENT 7.0 .TP @@ -306722,6 +306795,9 @@ protocol. Default protocol is \fBhttps\fP\&. .B port Optionally set to alternate port if the host is not using the default port. Default port is \fB443\fP\&. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -306738,7 +306814,7 @@ salt \(aq*\(aq vsphere.list_networks 1.2.3.4 root bad\-password .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_non_ssds(host, username, password, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.list_non_ssds(host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True) Returns a list of Non\-SSD disks for the given host or list of host_names. .sp \fBNOTE:\fP @@ -306777,6 +306853,9 @@ tell vCenter the hosts for which to retrieve Non\-SSD disks. If host_names is not provided, Non\-SSD disks will be retrieved for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -306797,7 +306876,7 @@ salt \(aq*\(aq vsphere.list_non_ssds my.vcenter.location root bad\-password .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_resourcepools(host, username, password, protocol=None, port=None) +.B salt.modules.vsphere.list_resourcepools(host, username, password, protocol=None, port=None, verify_ssl=True) Returns a list of resource pools for the specified host. .INDENT 7.0 .TP @@ -306817,6 +306896,9 @@ protocol. Default protocol is \fBhttps\fP\&. .B port Optionally set to alternate port if the host is not using the default port. Default port is \fB443\fP\&. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -306833,7 +306915,7 @@ salt \(aq*\(aq vsphere.list_resourcepools 1.2.3.4 root bad\-password .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_ssds(host, username, password, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.list_ssds(host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True) Returns a list of SSDs for the given host or list of host_names. .INDENT 7.0 .TP @@ -306862,6 +306944,9 @@ tell vCenter the hosts for which to retrieve SSDs. If host_names is not provided, SSDs will be retrieved for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -306909,7 +306994,7 @@ salt \(aq*\(aq vsphere.list_storage_policy policy_names=[policy_name] .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_tag_categories(server=None, username=None, password=None, service_instance=None) +.B salt.modules.vsphere.list_tag_categories(server=None, username=None, password=None, service_instance=None, verify_ssl=None, ca_bundle=None) List existing categories a user has access to. .sp CLI Example: @@ -306933,6 +307018,10 @@ salt vm_minion vsphere.list_tag_categories \fBusername\fP (\fIbasestring\fP) \-\- Username associated with the vCenter center. .IP \(bu 2 \fBpassword\fP (\fIbasestring\fP) \-\- Password associated with the vCenter center. +.IP \(bu 2 +\fBverify_ssl\fP (\fIboolean\fP) \-\- Verify the SSL certificate. Default: True +.IP \(bu 2 +\fBca_bundle\fP (\fIbasestring\fP) \-\- Path to the ca bundle to use when verifying SSL certificates. .UNINDENT .TP .B Returns @@ -306944,7 +307033,7 @@ list of str .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_tags(server=None, username=None, password=None, service_instance=None) +.B salt.modules.vsphere.list_tags(server=None, username=None, password=None, service_instance=None, verify_ssl=None, ca_bundle=None) List existing tags a user has access to. .sp CLI Example: @@ -306968,6 +307057,10 @@ salt vm_minion vsphere.list_tags \fBusername\fP (\fIbasestring\fP) \-\- Username associated with the vCenter center. .IP \(bu 2 \fBpassword\fP (\fIbasestring\fP) \-\- Password associated with the vCenter center. +.IP \(bu 2 +\fBverify_ssl\fP (\fIboolean\fP) \-\- Verify the SSL certificate. Default: True +.IP \(bu 2 +\fBca_bundle\fP (\fIbasestring\fP) \-\- Path to the ca bundle to use when verifying SSL certificates. .UNINDENT .TP .B Returns @@ -307003,7 +307096,7 @@ salt \(aq*\(aq vsphere.list_uplink_dvportgroup dvs=dvs_name .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_vapps(host, username, password, protocol=None, port=None) +.B salt.modules.vsphere.list_vapps(host, username, password, protocol=None, port=None, verify_ssl=True) Returns a list of vApps for the specified host. .INDENT 7.0 .TP @@ -307023,6 +307116,9 @@ protocol. Default protocol is \fBhttps\fP\&. .B port Optionally set to alternate port if the host is not using the default port. Default port is \fB443\fP\&. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -307040,7 +307136,7 @@ salt \(aq*\(aq vsphere.list_vapps 1.2.3.4 root bad\-password .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.list_vms(host, username, password, protocol=None, port=None) +.B salt.modules.vsphere.list_vms(host, username, password, protocol=None, port=None, verify_ssl=True) Returns a list of VMs for the specified host. .INDENT 7.0 .TP @@ -307060,6 +307156,9 @@ protocol. Default protocol is \fBhttps\fP\&. .B port Optionally set to alternate port if the host is not using the default port. Default port is \fB443\fP\&. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -307360,7 +307459,7 @@ salt \(aq*\(aq vsphere.reset_syslog_config my.vcenter.location root bad\-passwor .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.service_restart(host, username, password, service_name, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.service_restart(host, username, password, service_name, protocol=None, port=None, host_names=None, verify_ssl=True) Restart the named service for the given host or list of hosts. .INDENT 7.0 .TP @@ -307423,6 +307522,9 @@ vCenter the hosts for which to restart the service. If host_names is not provided, the service will be restarted for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -307443,7 +307545,7 @@ salt \(aq*\(aq vsphere.service_restart my.vcenter.location root bad\-password \( .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.service_start(host, username, password, service_name, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.service_start(host, username, password, service_name, protocol=None, port=None, host_names=None, verify_ssl=True) Start the named service for the given host or list of hosts. .INDENT 7.0 .TP @@ -307506,6 +307608,9 @@ vCenter the hosts for which to start the service. If host_names is not provided, the service will be started for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -307526,7 +307631,7 @@ salt \(aq*\(aq vsphere.service_start my.vcenter.location root bad\-password \(aq .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.service_stop(host, username, password, service_name, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.service_stop(host, username, password, service_name, protocol=None, port=None, host_names=None, verify_ssl=True) Stop the named service for the given host or list of hosts. .INDENT 7.0 .TP @@ -307589,6 +307694,9 @@ vCenter the hosts for which to stop the service. If host_names is not provided, the service will be stopped for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -307692,7 +307800,7 @@ salt \(aq*\(aq vsphere.set_coredump_network_config my.vcenter.location root bad\ .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.set_ntp_config(host, username, password, ntp_servers, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.set_ntp_config(host, username, password, ntp_servers, protocol=None, port=None, host_names=None, verify_ssl=True) Set NTP configuration for a given host of list of host_names. .INDENT 7.0 .TP @@ -307725,6 +307833,9 @@ vCenter which hosts to configure ntp servers. If host_names is not provided, the NTP servers will be configured for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -307745,7 +307856,7 @@ salt \(aq*\(aq vsphere.ntp_configure my.vcenter.location root bad\-password \(aq .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.set_service_policy(host, username, password, service_name, service_policy, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.set_service_policy(host, username, password, service_name, service_policy, protocol=None, port=None, host_names=None, verify_ssl=True) Set the service name\(aqs policy for a given host or list of hosts. .INDENT 7.0 .TP @@ -307811,6 +307922,9 @@ vCenter the hosts for which to set the service policy. If host_names is not provided, the service policy information will be retrieved for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -307969,7 +308083,7 @@ salt \(aq*\(aq vsphere.syslog_service_reload my.vcenter.location root bad\-passw .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.system_info(host, username, password, protocol=None, port=None) +.B salt.modules.vsphere.system_info(host, username, password, protocol=None, port=None, verify_ssl=True) Return system information about a VMware environment. .INDENT 7.0 .TP @@ -307989,6 +308103,9 @@ protocol. Default protocol is \fBhttps\fP\&. .B port Optionally set to alternate port if the host is not using the default port. Default port is \fB443\fP\&. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -308156,7 +308273,7 @@ salt \(aq*\(aq vsphere.update_dvs dvs_dict=$dvs_dict dvs=dvs1 .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.update_host_datetime(host, username, password, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.update_host_datetime(host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True) Update the date/time on the given host or list of host_names. This function should be used with caution since network delays and execution delays can result in time skews. .INDENT 7.0 @@ -308186,6 +308303,9 @@ tell vCenter which hosts should update their date/time. If host_names is not provided, the date/time will be updated for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -308206,7 +308326,7 @@ salt \(aq*\(aq vsphere.update_date_time my.vcenter.location root bad\-password .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.update_host_password(host, username, password, new_password, protocol=None, port=None) +.B salt.modules.vsphere.update_host_password(host, username, password, new_password, protocol=None, port=None, verify_ssl=True) Update the password for a given host. .sp \fBNOTE:\fP @@ -308236,6 +308356,9 @@ protocol. Default protocol is \fBhttps\fP\&. .B port Optionally set to alternate port if the host is not using the default port. Default port is \fB443\fP\&. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -308333,7 +308456,7 @@ vCenter service instance for connection and configuration .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.upload_ssh_key(host, username, password, ssh_key=None, ssh_key_file=None, protocol=None, port=None, certificate_verify=False) +.B salt.modules.vsphere.upload_ssh_key(host, username, password, ssh_key=None, ssh_key_file=None, protocol=None, port=None, certificate_verify=None) Upload an ssh key for root to an ESXi host via http PUT. This function only works for ESXi, not vCenter. Only one ssh key can be uploaded for root. Uploading a second key will @@ -308359,7 +308482,7 @@ ssh_key_file, but not both. \fBport\fP \-\- defaults to 443 for https .IP \(bu 2 \fBcertificate_verify\fP \-\- If true require that the SSL connection present -a valid certificate +a valid certificate. Default: True .UNINDENT .TP .B Returns @@ -308382,7 +308505,7 @@ salt \(aq*\(aq vsphere.upload_ssh_key my.esxi.host root bad\-password ssh_key_fi .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.vmotion_disable(host, username, password, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.vmotion_disable(host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True) Disable vMotion for a given host or list of host_names. .INDENT 7.0 .TP @@ -308411,6 +308534,9 @@ tell vCenter which hosts should disable VMotion. If host_names is not provided, VMotion will be disabled for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -308431,7 +308557,7 @@ salt \(aq*\(aq vsphere.vmotion_disable my.vcenter.location root bad\-password .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.vmotion_enable(host, username, password, protocol=None, port=None, host_names=None, device=\(aqvmk0\(aq) +.B salt.modules.vsphere.vmotion_enable(host, username, password, protocol=None, port=None, host_names=None, device=\(aqvmk0\(aq, verify_ssl=True) Enable vMotion for a given host or list of host_names. .INDENT 7.0 .TP @@ -308464,6 +308590,9 @@ information is used for a single ESXi host. .B device The device that uniquely identifies the VirtualNic that will be used for VMotion for each host. Defaults to \fBvmk0\fP\&. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -308484,7 +308613,7 @@ salt \(aq*\(aq vsphere.vmotion_enable my.vcenter.location root bad\-password .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.vsan_add_disks(host, username, password, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.vsan_add_disks(host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True) Add any VSAN\-eligible disks to the VSAN System for the given host or list of host_names. .INDENT 7.0 .TP @@ -308514,6 +308643,9 @@ VSAN system. If host_names is not provided, VSAN\-eligible disks will be added to the hosts\(aqs VSAN system for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -308534,7 +308666,7 @@ salt \(aq*\(aq vsphere.vsan_add_disks my.vcenter.location root bad\-password .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.vsan_disable(host, username, password, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.vsan_disable(host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True) Disable VSAN for a given host or list of host_names. .INDENT 7.0 .TP @@ -308563,6 +308695,9 @@ tell vCenter which hosts should disable VSAN. If host_names is not provided, VSAN will be disabled for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -308583,7 +308718,7 @@ salt \(aq*\(aq vsphere.vsan_disable my.vcenter.location root bad\-password .UNINDENT .INDENT 0.0 .TP -.B salt.modules.vsphere.vsan_enable(host, username, password, protocol=None, port=None, host_names=None) +.B salt.modules.vsphere.vsan_enable(host, username, password, protocol=None, port=None, host_names=None, verify_ssl=True) Enable VSAN for a given host or list of host_names. .INDENT 7.0 .TP @@ -308612,6 +308747,9 @@ tell vCenter which hosts should enable VSAN. If host_names is not provided, VSAN will be enabled for the \fBhost\fP location instead. This is useful for when service instance connection information is used for a single ESXi host. +.TP +.B verify_ssl +Verify the SSL certificate. Default: True .UNINDENT .sp CLI Example: @@ -332573,6 +332711,8 @@ zenoss: hostname: https://zenoss.example.com username: admin password: admin123 + verify_ssl: True + ca_bundle: /etc/ssl/certs/ca\-certificates.crt .ft P .fi .UNINDENT @@ -349873,6 +350013,7 @@ proxy: host: username: password: + verify_ssl: True .ft P .fi .UNINDENT @@ -353023,6 +353164,7 @@ proxy: host: username: password: + verify_ssl: True .ft P .fi .UNINDENT @@ -355097,9 +355239,11 @@ asam: prov1.domain.com username: "testuser" password: "verybadpass" + verify_ssl: true prov2.domain.com username: "testuser" password: "verybadpass" + verify_ssl: true .ft P .fi .UNINDENT @@ -391769,7 +391913,7 @@ configure\-host\-password: .UNINDENT .INDENT 0.0 .TP -.B salt.states.esxi.ssh_configured(name, service_running, ssh_key=None, ssh_key_file=None, service_policy=None, service_restart=False, certificate_verify=False) +.B salt.states.esxi.ssh_configured(name, service_running, ssh_key=None, ssh_key_file=None, service_policy=None, service_restart=False, certificate_verify=None) Manage the SSH configuration for a host including whether or not SSH is running or the presence of a given SSH key. Note: Only one ssh key can be uploaded for root. Uploading a second key will replace any existing key. @@ -391812,7 +391956,7 @@ previous running state. Default is \fBFalse\fP\&. .TP .B certificate_verify If set to \fBTrue\fP, the SSL connection must present a valid certificate. -Default is \fBFalse\fP\&. +Default is \fBTrue\fP\&. .UNINDENT .sp Example: @@ -441552,7 +441696,7 @@ eauth user must be authorized to execute runner modules: (\fB@runner\fP). Only the \fBmaster_call()\fP below supports eauth. .INDENT 7.0 .TP -.B asynchronous(fun, low, user=\(aqUNKNOWN\(aq, pub=None) +.B asynchronous(fun, low, user=\(aqUNKNOWN\(aq, pub=None, local=False) Execute the function in a multiprocess and return the event tag to use to watch for the return .UNINDENT @@ -441638,7 +441782,7 @@ wheel = salt.wheel.WheelClient(opts) .UNINDENT .INDENT 7.0 .TP -.B asynchronous(fun, low, user=\(aqUNKNOWN\(aq, pub=None) +.B asynchronous(fun, low, user=\(aqUNKNOWN\(aq, pub=None, local=False) Execute the function in a multiprocess and return the event tag to use to watch for the return .UNINDENT @@ -455002,6 +455146,43 @@ Fixes salt\-ssh authentication when using tty (#58922) .IP \(bu 2 Revert LazyLoader finalizer. Removed the weakref.finalizer code. On some occasions, the finalized would run when trying to load a new module, firing a race condition. (#58947) .UNINDENT +.SS Salt 3002.3 Release Notes +.sp +Version 3002.3 is a CVE fix release for 3002\&. +.SS Fixed +.INDENT 0.0 +.IP \(bu 2 +CVE\-2020\-28243 \- Fix local privilege escalation in the restartcheck module. +.IP \(bu 2 +CVE\-2020\-28972 \- Ensure authentication to vcenter, vsphere, and esxi server +validates the SSL/TLS certificate by default. If you want to skip SSL verification +you can use \fIverify_ssl: False\fP\&. +.IP \(bu 2 +CVE\-2020\-35662 \- Ensure the asam runner, qingcloud, splunk returner, panos +proxy, cimc proxy, zenoss module, esxi module, vsphere module, glassfish +module, bigip module, and keystone module validate SSL by default. If you want +to skip SSL verification you can use \fIverify_ssl: False\fP\&. +.IP \(bu 2 +CVE\-2021\-3148 \- Fix a command injection in the Salt\-API when using the +Salt\-SSH client. +.IP \(bu 2 +CVE\-2021\-3144 \- Fix eauth tokens can be used once after expiration +.IP \(bu 2 +CVE\-2021\-25281 \- Fix salt\-api so it honors eauth credentials for the +wheel_async client. +.IP \(bu 2 +CVE\-2021\-25282 \- Fix the salt.wheel.pillar_roots.write method so it is not +vulnerable to directory traversal. +.IP \(bu 2 +CVE\-2021\-25283 \- Fix the jinja render to protect against server side template +injection attacks. +.IP \(bu 2 +CVE\-2021\-25284 \- Fix cmdmod so it will not log credentials to log levels info +and error. +.IP \(bu 2 +CVE\-2021\-3197 \- Fix ssh client to remove ProxyCommand from arguments provided +by cli and netapi. +.UNINDENT .SS Salt 3001 Release Notes \- Codename Sodium .SS Python 2 Dropped .sp @@ -455327,6 +455508,43 @@ Prior to this change eauth was not properly validated when calling Salt ssh via the salt\-api. Any value for \(aqeauth\(aq or \(aqtoken\(aq would allow a user to bypass authentication and make calls to Salt ssh. (CVE\-2020\-25592) .UNINDENT +.SS Salt 3001.5 Release Notes +.sp +Version 3001.5 is a CVE fix release for 3001\&. +.SS Fixed +.INDENT 0.0 +.IP \(bu 2 +CVE\-2020\-28243 \- Fix local privilege escalation in the restartcheck module. +.IP \(bu 2 +CVE\-2020\-28972 \- Ensure authentication to vcenter, vsphere, and esxi server +validates the SSL/TLS certificate by default. If you want to skip SSL verification +you can use \fIverify_ssl: False\fP\&. +.IP \(bu 2 +CVE\-2020\-35662 \- Ensure the asam runner, qingcloud, splunk returner, panos +proxy, cimc proxy, zenoss module, esxi module, vsphere module, glassfish +module, bigip module, and keystone module validate SSL by default. If you want +to skip SSL verification you can use \fIverify_ssl: False\fP\&. +.IP \(bu 2 +CVE\-2021\-3148 \- Fix a command injection in the Salt\-API when using the +Salt\-SSH client. +.IP \(bu 2 +CVE\-2021\-3144 \- Fix eauth tokens can be used once after expiration +.IP \(bu 2 +CVE\-2021\-25281 \- Fix salt\-api so it honors eauth credentials for the +wheel_async client. +.IP \(bu 2 +CVE\-2021\-25282 \- Fix the salt.wheel.pillar_roots.write method so it is not +vulnerable to directory traversal. +.IP \(bu 2 +CVE\-2021\-25283 \- Fix the jinja render to protect against server side template +injection attacks. +.IP \(bu 2 +CVE\-2021\-25284 \- Fix cmdmod so it will not log credentials to log levels info +and error. +.IP \(bu 2 +CVE\-2021\-3197 \- Fix ssh client to remove ProxyCommand from arguments provided +by cli and netapi. +.UNINDENT .SS Salt 3000 Release Notes \- Codename Neon .SS Security Advisory .sp @@ -457382,6 +457600,43 @@ Prior to this change eauth was not properly validated when calling Salt ssh via the salt\-api. Any value for \(aqeauth\(aq or \(aqtoken\(aq would allow a user to bypass authentication and make calls to Salt ssh. (CVE\-2020\-25592) .UNINDENT +.SS Salt 3000.7 Release Notes +.sp +Version 3000.7 is a CVE fix release for 3000\&. +.SS Fixed +.INDENT 0.0 +.IP \(bu 2 +CVE\-2020\-28243 \- Fix local privilege escalation in the restartcheck module. +.IP \(bu 2 +CVE\-2020\-28972 \- Ensure authentication to vcenter, vsphere, and esxi server +validates the SSL/TLS certificate by default. If you want to skip SSL verification +you can use \fIverify_ssl: False\fP\&. +.IP \(bu 2 +CVE\-2020\-35662 \- Ensure the asam runner, qingcloud, splunk returner, panos +proxy, cimc proxy, zenoss module, esxi module, vsphere module, glassfish +module, bigip module, and keystone module validate SSL by default. If you want +to skip SSL verification you can use \fIverify_ssl: False\fP\&. +.IP \(bu 2 +CVE\-2021\-3148 \- Fix a command injection in the Salt\-API when using the +Salt\-SSH client. +.IP \(bu 2 +CVE\-2021\-3144 \- Fix eauth tokens can be used once after expiration +.IP \(bu 2 +CVE\-2021\-25281 \- Fix salt\-api so it honors eauth credentials for the +wheel_async client. +.IP \(bu 2 +CVE\-2021\-25282 \- Fix the salt.wheel.pillar_roots.write method so it is not +vulnerable to directory traversal. +.IP \(bu 2 +CVE\-2021\-25283 \- Fix the jinja render to protect against server side template +injection attacks. +.IP \(bu 2 +CVE\-2021\-25284 \- Fix cmdmod so it will not log credentials to log levels info +and error. +.IP \(bu 2 +CVE\-2021\-3197 \- Fix ssh client to remove ProxyCommand from arguments provided +by cli and netapi. +.UNINDENT .SS Salt 2019.2.0 Release Notes \- Codename Fluorine .SS Python 2.7 Deprecation .sp diff --git a/doc/man/spm.1 b/doc/man/spm.1 index 7387624bf48..9a37a1d5ce3 100644 --- a/doc/man/spm.1 +++ b/doc/man/spm.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "SPM" "1" "Jan 14, 2021" "3002.3" "Salt" +.TH "SPM" "1" "Feb 05, 2021" "3002.4" "Salt" .SH NAME spm \- Salt Package Manager Command . diff --git a/doc/topics/releases/3000.8.rst b/doc/topics/releases/3000.8.rst new file mode 100644 index 00000000000..da047967248 --- /dev/null +++ b/doc/topics/releases/3000.8.rst @@ -0,0 +1,12 @@ +.. _release-3000-8: + +========================= +Salt 3000.8 Release Notes +========================= + +Version 3000.8 is a big fix release for :ref:`3000 `. + +Fixed +----- + +- Fix runners that broke when patching for CVE-2021-25281 diff --git a/doc/topics/releases/3001.6.rst b/doc/topics/releases/3001.6.rst new file mode 100644 index 00000000000..ed12fab579d --- /dev/null +++ b/doc/topics/releases/3001.6.rst @@ -0,0 +1,12 @@ +.. _release-3001-6: + +========================= +Salt 3001.6 Release Notes +========================= + +Version 3001.6 is a bug fix release for :ref:`3001 `. + +Fixed +----- + +- Fix runners that broke when patching for CVE-2021-25281 diff --git a/doc/topics/releases/3002.4.rst b/doc/topics/releases/3002.4.rst new file mode 100644 index 00000000000..7c6594474cb --- /dev/null +++ b/doc/topics/releases/3002.4.rst @@ -0,0 +1,12 @@ +.. _release-3002-4: + +========================= +Salt 3002.4 Release Notes +========================= + +Version 3002.4 is a bugfix release for :ref:`3002 `. + +Fixed +----- + +- Fix runners that broke when patching for CVE-2021-25281 From 27165797ac9361e7f0136fc9a2a66d5430ede56e Mon Sep 17 00:00:00 2001 From: Frode Gundersen Date: Fri, 5 Feb 2021 14:34:11 -0700 Subject: [PATCH 67/69] Update 3000.8.rst --- doc/topics/releases/3000.8.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/topics/releases/3000.8.rst b/doc/topics/releases/3000.8.rst index da047967248..1c6ba9b3914 100644 --- a/doc/topics/releases/3000.8.rst +++ b/doc/topics/releases/3000.8.rst @@ -4,7 +4,7 @@ Salt 3000.8 Release Notes ========================= -Version 3000.8 is a big fix release for :ref:`3000 `. +Version 3000.8 is a bug fix release for :ref:`3000 `. Fixed ----- From 896906e30e98a156bd2b3bbc312a22aec8bfc066 Mon Sep 17 00:00:00 2001 From: Daniel Wozniak Date: Tue, 9 Feb 2021 10:19:55 -0700 Subject: [PATCH 68/69] [3002.4] Fix Runners in SSE (#175) * Runners fix * Rework runner fix --- changelog/165.fixed | 1 + salt/client/mixins.py | 34 +++++++++++++++++++++++++++++----- salt/wheel/__init__.py | 4 ++-- 3 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 changelog/165.fixed diff --git a/changelog/165.fixed b/changelog/165.fixed new file mode 100644 index 00000000000..0066356a8d0 --- /dev/null +++ b/changelog/165.fixed @@ -0,0 +1 @@ +Fix runners that broke when patching for CVE-2021-25281 diff --git a/salt/client/mixins.py b/salt/client/mixins.py index 91cd98d1a25..204f6427768 100644 --- a/salt/client/mixins.py +++ b/salt/client/mixins.py @@ -479,7 +479,7 @@ class AsyncClientMixin: client = None tag_prefix = None - def _proc_function(self, fun, low, user, tag, jid, daemonize=True): + def _proc_function_remote(self, fun, low, user, tag, jid, daemonize=True): """ Run this method in a multiprocess target to execute the function on the master and fire the return data on the event bus @@ -498,7 +498,31 @@ class AsyncClientMixin: low["__user__"] = user low["__tag__"] = tag - return self.low(fun, low, full_return=False) + try: + return self.cmd_sync(low) + except salt.exceptions.EauthAuthenticationError as exc: + log.error(exc) + + def _proc_function(self, fun, low, user, tag, jid, daemonize=True): + """ + Run this method in a multiprocess target to execute the function + locally and fire the return data on the event bus + """ + if daemonize and not salt.utils.platform.is_windows(): + # Shutdown the multiprocessing before daemonizing + salt.log.setup.shutdown_multiprocessing_logging() + + salt.utils.process.daemonize() + + # Reconfigure multiprocessing logging after daemonizing + salt.log.setup.setup_multiprocessing_logging() + + # pack a few things into low + low["__jid__"] = jid + low["__user__"] = user + low["__tag__"] = tag + + return self.low(fun, low) def _proc_function_local(self, fun, low, user, tag, jid, daemonize=True): """ @@ -547,15 +571,15 @@ class AsyncClientMixin: tag = salt.utils.event.tagify(jid, prefix=self.tag_prefix) return {"tag": tag, "jid": jid} - def asynchronous(self, fun, low, user="UNKNOWN", pub=None, local=False): + def asynchronous(self, fun, low, user="UNKNOWN", pub=None, local=True): """ Execute the function in a multiprocess and return the event tag to use to watch for the return """ if local: - proc_func = self._proc_function_local - else: proc_func = self._proc_function + else: + proc_func = self._proc_function_remote async_pub = pub if pub is not None else self._gen_async_pub() proc = salt.utils.process.SignalHandlingProcess( target=proc_func, diff --git a/salt/wheel/__init__.py b/salt/wheel/__init__.py index 38792a10f6c..27ab3c9ad41 100644 --- a/salt/wheel/__init__.py +++ b/salt/wheel/__init__.py @@ -123,8 +123,8 @@ class WheelClient( }) {'jid': '20131219224744416681', 'tag': 'salt/wheel/20131219224744416681'} """ - fun = low.pop("fun") - return self.asynchronous(fun, low) + fun = low.get("fun") + return self.asynchronous(fun, low, local=False) def cmd( self, From ee4824df9d3df08b0749a1a2809af5678abddecf Mon Sep 17 00:00:00 2001 From: Frode Gundersen Date: Tue, 9 Feb 2021 10:41:26 -0700 Subject: [PATCH 69/69] Docsupdate for 3002.4 --- CHANGELOG.md | 14 ++++++++------ changelog/165.fixed | 1 - doc/topics/releases/3000.8.rst | 1 + doc/topics/releases/3001.6.rst | 1 + doc/topics/releases/3002.4.rst | 3 ++- 5 files changed, 12 insertions(+), 8 deletions(-) delete mode 100644 changelog/165.fixed diff --git a/CHANGELOG.md b/CHANGELOG.md index 87b680d5852..4a5a963d1fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,14 +7,14 @@ Versions are `MAJOR.PATCH`. # Changelog -Salt 3002.4 (2021-02-05) +Salt 3002.4 (2021-02-09) ======================== Fixed ----- - Fix runners that broke when patching for CVE-2021-25281 - +- Fix issue with runners in SSE Salt 3002.3 (2021-01-25) ======================== @@ -309,13 +309,14 @@ Added This flag will be deprecated in the Phosphorus release when this functionality becomes the default. (#58652) -Salt 3001.6 (2021-02-05) +Salt 3001.6 (2021-02-09) ======================== Fixed ----- -- Fix runners that broke when patching for CVE-2021-25281 +- Fix runners that broke when patching for CVE-2021-25281 +- Fix issue with runners in SSE Salt 3001.5 =========== @@ -799,13 +800,14 @@ 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.8 (2021-02-05) +Salt 3000.8 (2021-02-09) ======================== Fixed ----- -- Fix runners that broke when patching for CVE-2021-25281 +- Fix runners that broke when patching for CVE-2021-25281 +- Fix issue with runners in SSE Salt 3000.7 =========== diff --git a/changelog/165.fixed b/changelog/165.fixed deleted file mode 100644 index 0066356a8d0..00000000000 --- a/changelog/165.fixed +++ /dev/null @@ -1 +0,0 @@ -Fix runners that broke when patching for CVE-2021-25281 diff --git a/doc/topics/releases/3000.8.rst b/doc/topics/releases/3000.8.rst index 1c6ba9b3914..960b315f42d 100644 --- a/doc/topics/releases/3000.8.rst +++ b/doc/topics/releases/3000.8.rst @@ -10,3 +10,4 @@ Fixed ----- - Fix runners that broke when patching for CVE-2021-25281 +- Fix issue with runners in SSE diff --git a/doc/topics/releases/3001.6.rst b/doc/topics/releases/3001.6.rst index ed12fab579d..747daa56f7c 100644 --- a/doc/topics/releases/3001.6.rst +++ b/doc/topics/releases/3001.6.rst @@ -10,3 +10,4 @@ Fixed ----- - Fix runners that broke when patching for CVE-2021-25281 +- Fix issue with runners in SSE diff --git a/doc/topics/releases/3002.4.rst b/doc/topics/releases/3002.4.rst index 7c6594474cb..68bc9078dbb 100644 --- a/doc/topics/releases/3002.4.rst +++ b/doc/topics/releases/3002.4.rst @@ -4,9 +4,10 @@ Salt 3002.4 Release Notes ========================= -Version 3002.4 is a bugfix release for :ref:`3002 `. +Version 3002.4 is a bug fix release for :ref:`3002 `. Fixed ----- - Fix runners that broke when patching for CVE-2021-25281 +- Fix issue with runners in SSE