Unify TLS/SSL config for Redfish modules with new common argument spec and docs fragment; add validate_certs and ca_path options (#9964)
Some checks failed
EOL CI / EOL Sanity (Ⓐ2.15) (push) Has been cancelled
EOL CI / EOL Units (Ⓐ2.15+py2.7) (push) Has been cancelled
EOL CI / EOL Units (Ⓐ2.15+py3.10) (push) Has been cancelled
EOL CI / EOL Units (Ⓐ2.15+py3.5) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+alpine3+py:azp/posix/1/) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+alpine3+py:azp/posix/2/) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+alpine3+py:azp/posix/3/) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+fedora37+py:azp/posix/1/) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+fedora37+py:azp/posix/2/) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+fedora37+py:azp/posix/3/) (push) Has been cancelled
import-galaxy / Test to import built collection artifact with Galaxy importer (push) Has been cancelled
Verify REUSE / check (push) Has been cancelled

Unify TLS/SSL config for Redfish modules with new common argument spec and docs fragment.
This commit is contained in:
Felix Fontein 2025-04-10 07:08:04 +02:00 committed by GitHub
parent d7edd34ba4
commit 1375cb65d6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 453 additions and 301 deletions

View file

@ -38,6 +38,21 @@ FAIL_MSG = 'Issuing a data modification command without specifying the '\
'than one %(resource)s is no longer allowed. Use the `resource_id` '\
'option to specify the target %(resource)s ID.'
# Use together with the community.general.redfish docs fragment
REDFISH_COMMON_ARGUMENT_SPEC = {
"validate_certs": {
"type": "bool",
"default": False,
},
"ca_path": {
"type": "path",
},
"ciphers": {
"type": "list",
"elements": "str",
},
}
class RedfishUtils(object):
@ -53,8 +68,10 @@ class RedfishUtils(object):
self.resource_id = resource_id
self.data_modification = data_modification
self.strip_etag_quotes = strip_etag_quotes
self.ciphers = ciphers
self.ciphers = ciphers if ciphers is not None else module.params.get("ciphers")
self._vendor = None
self.validate_certs = module.params.get("validate_certs", False)
self.ca_path = module.params.get("ca_path")
def _auth_params(self, headers):
"""
@ -132,6 +149,17 @@ class RedfishUtils(object):
resp['msg'] = 'Properties in %s are already set' % uri
return resp
def _request(self, uri, **kwargs):
kwargs.setdefault("validate_certs", self.validate_certs)
kwargs.setdefault("follow_redirects", "all")
kwargs.setdefault("use_proxy", True)
kwargs.setdefault("timeout", self.timeout)
kwargs.setdefault("ciphers", self.ciphers)
kwargs.setdefault("ca_path", self.ca_path)
resp = open_url(uri, **kwargs)
headers = {k.lower(): v for (k, v) in resp.info().items()}
return resp, headers
# The following functions are to send GET/POST/PATCH/DELETE requests
def get_request(self, uri, override_headers=None, allow_no_resp=False, timeout=None):
req_headers = dict(GET_HEADERS)
@ -145,12 +173,15 @@ class RedfishUtils(object):
# in case the caller will be using sessions later.
if uri == (self.root_uri + self.service_root):
basic_auth = False
resp = open_url(uri, method="GET", headers=req_headers,
url_username=username, url_password=password,
force_basic_auth=basic_auth, validate_certs=False,
follow_redirects='all',
use_proxy=True, timeout=timeout, ciphers=self.ciphers)
headers = {k.lower(): v for (k, v) in resp.info().items()}
resp, headers = self._request(
uri,
method="GET",
headers=req_headers,
url_username=username,
url_password=password,
force_basic_auth=basic_auth,
timeout=timeout,
)
try:
if headers.get('content-encoding') == 'gzip' and LooseVersion(ansible_version) < LooseVersion('2.14'):
# Older versions of Ansible do not automatically decompress the data
@ -194,18 +225,20 @@ class RedfishUtils(object):
req_headers['content-type'] = multipart_encoder[1]
else:
data = json.dumps(pyld)
resp = open_url(uri, data=data,
headers=req_headers, method="POST",
url_username=username, url_password=password,
force_basic_auth=basic_auth, validate_certs=False,
follow_redirects='all',
use_proxy=True, timeout=self.timeout, ciphers=self.ciphers)
resp, headers = self._request(
uri,
data=data,
headers=req_headers,
method="POST",
url_username=username,
url_password=password,
force_basic_auth=basic_auth,
)
try:
data = json.loads(to_native(resp.read()))
except Exception as e:
# No response data; this is okay in many cases
data = None
headers = {k.lower(): v for (k, v) in resp.info().items()}
except HTTPError as e:
msg, data = self._get_extended_message(e)
return {'ret': False,
@ -248,12 +281,15 @@ class RedfishUtils(object):
username, password, basic_auth = self._auth_params(req_headers)
try:
resp = open_url(uri, data=json.dumps(pyld),
headers=req_headers, method="PATCH",
url_username=username, url_password=password,
force_basic_auth=basic_auth, validate_certs=False,
follow_redirects='all',
use_proxy=True, timeout=self.timeout, ciphers=self.ciphers)
resp, dummy = self._request(
uri,
data=json.dumps(pyld),
headers=req_headers,
method="PATCH",
url_username=username,
url_password=password,
force_basic_auth=basic_auth,
)
except HTTPError as e:
msg, data = self._get_extended_message(e)
return {'ret': False, 'changed': False,
@ -283,12 +319,15 @@ class RedfishUtils(object):
req_headers['If-Match'] = etag
username, password, basic_auth = self._auth_params(req_headers)
try:
resp = open_url(uri, data=json.dumps(pyld),
headers=req_headers, method="PUT",
url_username=username, url_password=password,
force_basic_auth=basic_auth, validate_certs=False,
follow_redirects='all',
use_proxy=True, timeout=self.timeout, ciphers=self.ciphers)
resp, dummy = self._request(
uri,
data=json.dumps(pyld),
headers=req_headers,
method="PUT",
url_username=username,
url_password=password,
force_basic_auth=basic_auth,
)
except HTTPError as e:
msg, data = self._get_extended_message(e)
return {'ret': False,
@ -309,12 +348,15 @@ class RedfishUtils(object):
username, password, basic_auth = self._auth_params(req_headers)
try:
data = json.dumps(pyld) if pyld else None
resp = open_url(uri, data=data,
headers=req_headers, method="DELETE",
url_username=username, url_password=password,
force_basic_auth=basic_auth, validate_certs=False,
follow_redirects='all',
use_proxy=True, timeout=self.timeout, ciphers=self.ciphers)
resp, dummy = self._request(
uri,
data=data,
headers=req_headers,
method="DELETE",
url_username=username,
url_password=password,
force_basic_auth=basic_auth,
)
except HTTPError as e:
msg, data = self._get_extended_message(e)
return {'ret': False,