mirror of
https://github.com/ansible-collections/community.crypto.git
synced 2026-03-26 21:33:25 +00:00
Replace % and str.format() with f-strings (#875)
* Replace % and str.format() with f-strings. * Apply suggestions from review.
This commit is contained in:
@@ -32,9 +32,7 @@ class PrivateKeyModule:
|
||||
try:
|
||||
data = base64.b64decode(module.params["content"])
|
||||
except Exception as e:
|
||||
module.fail_json(
|
||||
msg="Cannot decode Base64 encoded data: {0}".format(e)
|
||||
)
|
||||
module.fail_json(msg=f"Cannot decode Base64 encoded data: {e}")
|
||||
else:
|
||||
data = to_bytes(module.params["content"])
|
||||
module_backend.set_existing(data)
|
||||
|
||||
@@ -54,9 +54,7 @@ from ansible_collections.community.crypto.plugins.plugin_utils.gnupg import (
|
||||
def gpg_fingerprint(input):
|
||||
if not isinstance(input, string_types):
|
||||
raise AnsibleFilterError(
|
||||
"The input for the community.crypto.gpg_fingerprint filter must be a string; got {type} instead".format(
|
||||
type=type(input)
|
||||
)
|
||||
f"The input for the community.crypto.gpg_fingerprint filter must be a string; got {type(input)} instead"
|
||||
)
|
||||
try:
|
||||
gpg = PluginGPGRunner()
|
||||
|
||||
@@ -292,19 +292,16 @@ def openssl_csr_info_filter(data, name_encoding="ignore"):
|
||||
"""Extract information from X.509 PEM certificate."""
|
||||
if not isinstance(data, string_types):
|
||||
raise AnsibleFilterError(
|
||||
"The community.crypto.openssl_csr_info input must be a text type, not %s"
|
||||
% type(data)
|
||||
f"The community.crypto.openssl_csr_info input must be a text type, not {type(data)}"
|
||||
)
|
||||
if not isinstance(name_encoding, string_types):
|
||||
raise AnsibleFilterError(
|
||||
"The name_encoding option must be of a text type, not %s"
|
||||
% type(name_encoding)
|
||||
f"The name_encoding option must be of a text type, not {type(name_encoding)}"
|
||||
)
|
||||
name_encoding = to_native(name_encoding)
|
||||
if name_encoding not in ("ignore", "idna", "unicode"):
|
||||
raise AnsibleFilterError(
|
||||
'The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "%s"'
|
||||
% name_encoding
|
||||
f'The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "{name_encoding}"'
|
||||
)
|
||||
|
||||
module = FilterModuleMock({"name_encoding": name_encoding})
|
||||
|
||||
@@ -167,17 +167,15 @@ def openssl_privatekey_info_filter(
|
||||
"""Extract information from X.509 PEM certificate."""
|
||||
if not isinstance(data, string_types):
|
||||
raise AnsibleFilterError(
|
||||
"The community.crypto.openssl_privatekey_info input must be a text type, not %s"
|
||||
% type(data)
|
||||
f"The community.crypto.openssl_privatekey_info input must be a text type, not {type(data)}"
|
||||
)
|
||||
if passphrase is not None and not isinstance(passphrase, string_types):
|
||||
raise AnsibleFilterError(
|
||||
"The passphrase option must be a text type, not %s" % type(passphrase)
|
||||
f"The passphrase option must be a text type, not {type(passphrase)}"
|
||||
)
|
||||
if not isinstance(return_private_key_data, bool):
|
||||
raise AnsibleFilterError(
|
||||
"The return_private_key_data option must be a boolean, not %s"
|
||||
% type(return_private_key_data)
|
||||
f"The return_private_key_data option must be a boolean, not {type(return_private_key_data)}"
|
||||
)
|
||||
|
||||
module = FilterModuleMock({})
|
||||
|
||||
@@ -142,8 +142,7 @@ def openssl_publickey_info_filter(data):
|
||||
"""Extract information from OpenSSL PEM public key."""
|
||||
if not isinstance(data, string_types):
|
||||
raise AnsibleFilterError(
|
||||
"The community.crypto.openssl_publickey_info input must be a text type, not %s"
|
||||
% type(data)
|
||||
f"The community.crypto.openssl_publickey_info input must be a text type, not {type(data)}"
|
||||
)
|
||||
|
||||
module = FilterModuleMock({})
|
||||
|
||||
@@ -50,9 +50,7 @@ from ansible_collections.community.crypto.plugins.module_utils.serial import (
|
||||
def parse_serial_filter(input):
|
||||
if not isinstance(input, string_types):
|
||||
raise AnsibleFilterError(
|
||||
"The input for the community.crypto.parse_serial filter must be a string; got {type} instead".format(
|
||||
type=type(input)
|
||||
)
|
||||
f"The input for the community.crypto.parse_serial filter must be a string; got {type(input)} instead"
|
||||
)
|
||||
try:
|
||||
return parse_serial(to_native(input))
|
||||
|
||||
@@ -50,8 +50,7 @@ def split_pem_filter(data):
|
||||
"""Split PEM file."""
|
||||
if not isinstance(data, string_types):
|
||||
raise AnsibleFilterError(
|
||||
"The community.crypto.split_pem input must be a text type, not %s"
|
||||
% type(data)
|
||||
f"The community.crypto.split_pem input must be a text type, not {type(data)}"
|
||||
)
|
||||
|
||||
data = to_text(data)
|
||||
|
||||
@@ -48,9 +48,7 @@ from ansible_collections.community.crypto.plugins.module_utils.serial import to_
|
||||
def to_serial_filter(input):
|
||||
if not isinstance(input, integer_types):
|
||||
raise AnsibleFilterError(
|
||||
"The input for the community.crypto.to_serial filter must be an integer; got {type} instead".format(
|
||||
type=type(input)
|
||||
)
|
||||
f"The input for the community.crypto.to_serial filter must be an integer; got {type(input)} instead"
|
||||
)
|
||||
if input < 0:
|
||||
raise AnsibleFilterError(
|
||||
|
||||
@@ -326,19 +326,16 @@ def x509_certificate_info_filter(data, name_encoding="ignore"):
|
||||
"""Extract information from X.509 PEM certificate."""
|
||||
if not isinstance(data, string_types):
|
||||
raise AnsibleFilterError(
|
||||
"The community.crypto.x509_certificate_info input must be a text type, not %s"
|
||||
% type(data)
|
||||
f"The community.crypto.x509_certificate_info input must be a text type, not {type(data)}"
|
||||
)
|
||||
if not isinstance(name_encoding, string_types):
|
||||
raise AnsibleFilterError(
|
||||
"The name_encoding option must be of a text type, not %s"
|
||||
% type(name_encoding)
|
||||
f"The name_encoding option must be of a text type, not {type(name_encoding)}"
|
||||
)
|
||||
name_encoding = to_native(name_encoding)
|
||||
if name_encoding not in ("ignore", "idna", "unicode"):
|
||||
raise AnsibleFilterError(
|
||||
'The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "%s"'
|
||||
% name_encoding
|
||||
f'The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "{name_encoding}"'
|
||||
)
|
||||
|
||||
module = FilterModuleMock({"name_encoding": name_encoding})
|
||||
|
||||
@@ -177,24 +177,20 @@ def x509_crl_info_filter(data, name_encoding="ignore", list_revoked_certificates
|
||||
"""Extract information from X.509 PEM certificate."""
|
||||
if not isinstance(data, string_types):
|
||||
raise AnsibleFilterError(
|
||||
"The community.crypto.x509_crl_info input must be a text type, not %s"
|
||||
% type(data)
|
||||
f"The community.crypto.x509_crl_info input must be a text type, not {type(data)}"
|
||||
)
|
||||
if not isinstance(name_encoding, string_types):
|
||||
raise AnsibleFilterError(
|
||||
"The name_encoding option must be of a text type, not %s"
|
||||
% type(name_encoding)
|
||||
f"The name_encoding option must be of a text type, not {type(name_encoding)}"
|
||||
)
|
||||
if not isinstance(list_revoked_certificates, bool):
|
||||
raise AnsibleFilterError(
|
||||
"The list_revoked_certificates option must be a boolean, not %s"
|
||||
% type(list_revoked_certificates)
|
||||
f"The list_revoked_certificates option must be a boolean, not {type(list_revoked_certificates)}"
|
||||
)
|
||||
name_encoding = to_native(name_encoding)
|
||||
if name_encoding not in ("ignore", "idna", "unicode"):
|
||||
raise AnsibleFilterError(
|
||||
'The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "%s"'
|
||||
% name_encoding
|
||||
f'The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "{name_encoding}"'
|
||||
)
|
||||
|
||||
data = to_bytes(data)
|
||||
|
||||
@@ -66,7 +66,7 @@ def _decode_retry(module, response, info, retry_count):
|
||||
if retry_count >= RETRY_COUNT:
|
||||
raise ACMEProtocolException(
|
||||
module,
|
||||
msg="Giving up after {retry} retries".format(retry=RETRY_COUNT),
|
||||
msg=f"Giving up after {RETRY_COUNT} retries",
|
||||
info=info,
|
||||
response=response,
|
||||
)
|
||||
@@ -77,8 +77,7 @@ def _decode_retry(module, response, info, retry_count):
|
||||
except (TypeError, ValueError):
|
||||
retry_after = 10
|
||||
module.log(
|
||||
"Retrieved a %s HTTP status on %s, retrying in %s seconds"
|
||||
% (format_http_status(info["status"]), info["url"], retry_after)
|
||||
f"Retrieved a {format_http_status(info['status'])} HTTP status on {info['url']}, retrying in {retry_after} seconds"
|
||||
)
|
||||
|
||||
time.sleep(retry_after)
|
||||
@@ -94,9 +93,7 @@ def _assert_fetch_url_success(
|
||||
allow_server_error=True,
|
||||
):
|
||||
if info["status"] < 0:
|
||||
raise NetworkException(
|
||||
msg="Failure downloading %s, %s" % (info["url"], info["msg"])
|
||||
)
|
||||
raise NetworkException(msg=f"Failure downloading {info['url']}, {info['msg']}")
|
||||
|
||||
if (
|
||||
(300 <= info["status"] < 400 and not allow_redirect)
|
||||
@@ -169,16 +166,12 @@ class ACMEDirectory:
|
||||
continue
|
||||
if info["status"] not in (200, 204):
|
||||
raise NetworkException(
|
||||
"Failed to get replay-nonce, got status {0}".format(
|
||||
format_http_status(info["status"])
|
||||
)
|
||||
f"Failed to get replay-nonce, got status {format_http_status(info['status'])}"
|
||||
)
|
||||
if "replay-nonce" in info:
|
||||
return info["replay-nonce"]
|
||||
self.module.log(
|
||||
"HEAD to {0} did return status {1}, but no replay-nonce header!".format(
|
||||
url, format_http_status(info["status"])
|
||||
)
|
||||
f"HEAD to {url} did return status {format_http_status(info['status'])}, but no replay-nonce header!"
|
||||
)
|
||||
if retry_count >= 5:
|
||||
raise ACMEProtocolException(
|
||||
@@ -228,9 +221,7 @@ class ACMEClient:
|
||||
passphrase=self.account_key_passphrase,
|
||||
)
|
||||
except KeyParsingError as e:
|
||||
raise ModuleFailException(
|
||||
"Error while parsing account key: {msg}".format(msg=e.msg)
|
||||
)
|
||||
raise ModuleFailException(f"Error while parsing account key: {e.msg}")
|
||||
self.account_jwk = self.account_key_data["jwk"]
|
||||
self.account_jws_header = {
|
||||
"alg": self.account_key_data["alg"],
|
||||
@@ -276,7 +267,7 @@ class ACMEClient:
|
||||
protected64 = nopad_b64(self.module.jsonify(protected).encode("utf8"))
|
||||
except Exception as e:
|
||||
raise ModuleFailException(
|
||||
"Failed to encode payload / headers as JSON: {0}".format(e)
|
||||
f"Failed to encode payload / headers as JSON: {e}"
|
||||
)
|
||||
|
||||
return self.backend.sign(payload64, protected64, key_data)
|
||||
@@ -287,16 +278,13 @@ class ACMEClient:
|
||||
"""
|
||||
if self._debug:
|
||||
with open("acme.log", "ab") as f:
|
||||
f.write(
|
||||
"[{0}] {1}\n".format(
|
||||
datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%s"), msg
|
||||
).encode("utf-8")
|
||||
)
|
||||
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%s")
|
||||
f.write(f"[{timestamp}] {msg}\n".encode("utf-8"))
|
||||
if data is not None:
|
||||
f.write(
|
||||
"{0}\n\n".format(
|
||||
json.dumps(data, indent=2, sort_keys=True)
|
||||
).encode("utf-8")
|
||||
f"{json.dumps(data, indent=2, sort_keys=True)}\n\n".encode(
|
||||
"utf-8"
|
||||
)
|
||||
)
|
||||
|
||||
def send_signed_request(
|
||||
@@ -389,9 +377,7 @@ class ACMEClient:
|
||||
result = content
|
||||
except ValueError:
|
||||
raise NetworkException(
|
||||
"Failed to parse the ACME response: {0} {1}".format(
|
||||
url, content
|
||||
)
|
||||
f"Failed to parse the ACME response: {url} {content}"
|
||||
)
|
||||
else:
|
||||
result = content
|
||||
@@ -471,9 +457,7 @@ class ACMEClient:
|
||||
parsed_json_result = True
|
||||
except ValueError:
|
||||
raise NetworkException(
|
||||
"Failed to parse the ACME response: {0} {1}".format(
|
||||
uri, content
|
||||
)
|
||||
f"Failed to parse the ACME response: {uri} {content}"
|
||||
)
|
||||
else:
|
||||
result = content
|
||||
@@ -513,9 +497,7 @@ class ACMEClient:
|
||||
cert_filename=cert_filename,
|
||||
cert_content=cert_content,
|
||||
)
|
||||
url = "{base}/{cert_id}".format(
|
||||
base=self.directory.directory["renewalInfo"].rstrip("/"), cert_id=cert_id
|
||||
)
|
||||
url = f"{self.directory.directory['renewalInfo'].rstrip('/')}/{cert_id}"
|
||||
|
||||
data, info = self.get_request(
|
||||
url, parse_json_result=True, fail_on_error=True, get_only=True
|
||||
@@ -593,31 +575,25 @@ def create_backend(module, needs_acme_v2=True):
|
||||
if CRYPTOGRAPHY_VERSION is None:
|
||||
msg = missing_required_lib("cryptography")
|
||||
else:
|
||||
msg = "Unexpected error while preparing cryptography: {0}".format(
|
||||
CRYPTOGRAPHY_ERROR.splitlines()[-1]
|
||||
)
|
||||
msg = f"Unexpected error while preparing cryptography: {CRYPTOGRAPHY_ERROR.splitlines()[-1]}"
|
||||
module.fail_json(msg=msg, exception=CRYPTOGRAPHY_ERROR)
|
||||
if not HAS_CURRENT_CRYPTOGRAPHY:
|
||||
# We succeeded importing cryptography, but its version is too old.
|
||||
mrl = missing_required_lib(
|
||||
f"cryptography >= {CRYPTOGRAPHY_MINIMAL_VERSION}"
|
||||
)
|
||||
module.fail_json(
|
||||
msg="Found cryptography, but only version {0}. {1}".format(
|
||||
CRYPTOGRAPHY_VERSION,
|
||||
missing_required_lib(
|
||||
"cryptography >= {0}".format(CRYPTOGRAPHY_MINIMAL_VERSION)
|
||||
),
|
||||
)
|
||||
msg=f"Found cryptography, but only version {CRYPTOGRAPHY_VERSION}. {mrl}"
|
||||
)
|
||||
module.debug(
|
||||
"Using cryptography backend (library version {0})".format(
|
||||
CRYPTOGRAPHY_VERSION
|
||||
)
|
||||
f"Using cryptography backend (library version {CRYPTOGRAPHY_VERSION})"
|
||||
)
|
||||
module_backend = CryptographyBackend(module)
|
||||
elif backend == "openssl":
|
||||
module.debug("Using OpenSSL binary backend")
|
||||
module_backend = OpenSSLCLIBackend(module)
|
||||
else:
|
||||
module.fail_json(msg='Unknown crypto backend "{0}"!'.format(backend))
|
||||
module.fail_json(msg=f'Unknown crypto backend "{backend}"!')
|
||||
|
||||
# Check common module parameters
|
||||
if not module.params["validate_certs"]:
|
||||
|
||||
@@ -91,14 +91,12 @@ class CryptographyChainMatcher(ChainMatcher):
|
||||
except Exception:
|
||||
if criterium_idx is None:
|
||||
module.warn(
|
||||
"Criterium has invalid {0} value. Ignoring criterium.".format(
|
||||
name
|
||||
)
|
||||
f"Criterium has invalid {name} value. Ignoring criterium."
|
||||
)
|
||||
else:
|
||||
module.warn(
|
||||
"Criterium {0} in select_chain has invalid {1} value. "
|
||||
"Ignoring criterium.".format(criterium_idx, name)
|
||||
f"Criterium {criterium_idx} in select_chain has invalid {name} value. "
|
||||
"Ignoring criterium."
|
||||
)
|
||||
return None
|
||||
|
||||
@@ -181,9 +179,7 @@ class CryptographyChainMatcher(ChainMatcher):
|
||||
if matches:
|
||||
return True
|
||||
except Exception as e:
|
||||
self.module.warn(
|
||||
"Error while loading certificate {0}: {1}".format(cert, e)
|
||||
)
|
||||
self.module.warn(f"Error while loading certificate {cert}: {e}")
|
||||
return False
|
||||
|
||||
|
||||
@@ -211,7 +207,7 @@ class CryptographyBackend(CryptoBackend):
|
||||
backend=_cryptography_backend,
|
||||
)
|
||||
except Exception as e:
|
||||
raise KeyParsingError("error while loading key: {0}".format(e))
|
||||
raise KeyParsingError(f"error while loading key: {e}")
|
||||
if isinstance(key, cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey):
|
||||
pk = key.public_key().public_numbers()
|
||||
return {
|
||||
@@ -250,9 +246,7 @@ class CryptographyBackend(CryptoBackend):
|
||||
point_size = 66
|
||||
curve = "P-521"
|
||||
else:
|
||||
raise KeyParsingError(
|
||||
"unknown elliptic curve: {0}".format(pk.curve.name)
|
||||
)
|
||||
raise KeyParsingError(f"unknown elliptic curve: {pk.curve.name}")
|
||||
num_bytes = (bits + 7) // 8
|
||||
return {
|
||||
"key_obj": key,
|
||||
@@ -268,10 +262,10 @@ class CryptographyBackend(CryptoBackend):
|
||||
"point_size": point_size,
|
||||
}
|
||||
else:
|
||||
raise KeyParsingError('unknown key type "{0}"'.format(type(key)))
|
||||
raise KeyParsingError(f'unknown key type "{type(key)}"')
|
||||
|
||||
def sign(self, payload64, protected64, key_data):
|
||||
sign_payload = "{0}.{1}".format(protected64, payload64).encode("utf8")
|
||||
sign_payload = f"{protected64}.{payload64}".encode("utf8")
|
||||
if "mac_obj" in key_data:
|
||||
mac = key_data["mac_obj"]()
|
||||
mac.update(sign_payload)
|
||||
@@ -320,16 +314,12 @@ class CryptographyBackend(CryptoBackend):
|
||||
hashbytes = 64
|
||||
else:
|
||||
raise BackendException(
|
||||
"Unsupported MAC key algorithm for cryptography backend: {0}".format(
|
||||
alg
|
||||
)
|
||||
f"Unsupported MAC key algorithm for cryptography backend: {alg}"
|
||||
)
|
||||
key_bytes = base64.urlsafe_b64decode(key)
|
||||
if len(key_bytes) < hashbytes:
|
||||
raise BackendException(
|
||||
"{0} key must be at least {1} bytes long (after Base64 decoding)".format(
|
||||
alg, hashbytes
|
||||
)
|
||||
f"{alg} key must be at least {hashbytes} bytes long (after Base64 decoding)"
|
||||
)
|
||||
return {
|
||||
"mac_obj": lambda: cryptography.hazmat.primitives.hmac.HMAC(
|
||||
@@ -382,7 +372,7 @@ class CryptographyBackend(CryptoBackend):
|
||||
add_identifier(("ip", name.value.compressed))
|
||||
else:
|
||||
raise BackendException(
|
||||
"Found unsupported SAN identifier {0}".format(name)
|
||||
f"Found unsupported SAN identifier {name}"
|
||||
)
|
||||
return result
|
||||
|
||||
@@ -425,10 +415,8 @@ class CryptographyBackend(CryptoBackend):
|
||||
)
|
||||
except Exception as e:
|
||||
if cert_filename is None:
|
||||
raise BackendException("Cannot parse certificate: {0}".format(e))
|
||||
raise BackendException(
|
||||
"Cannot parse certificate {0}: {1}".format(cert_filename, e)
|
||||
)
|
||||
raise BackendException(f"Cannot parse certificate: {e}")
|
||||
raise BackendException(f"Cannot parse certificate {cert_filename}: {e}")
|
||||
|
||||
if now is None:
|
||||
now = self.get_now()
|
||||
@@ -460,10 +448,8 @@ class CryptographyBackend(CryptoBackend):
|
||||
)
|
||||
except Exception as e:
|
||||
if cert_filename is None:
|
||||
raise BackendException("Cannot parse certificate: {0}".format(e))
|
||||
raise BackendException(
|
||||
"Cannot parse certificate {0}: {1}".format(cert_filename, e)
|
||||
)
|
||||
raise BackendException(f"Cannot parse certificate: {e}")
|
||||
raise BackendException(f"Cannot parse certificate {cert_filename}: {e}")
|
||||
|
||||
ski = None
|
||||
try:
|
||||
|
||||
@@ -44,7 +44,7 @@ _OPENSSL_ENVIRONMENT_UPDATE = dict(LANG="C", LC_ALL="C", LC_MESSAGES="C", LC_CTY
|
||||
|
||||
def _extract_date(out_text, name, cert_filename_suffix=""):
|
||||
try:
|
||||
date_str = re.search(r"\s+%s\s*:\s+(.*)" % name, out_text).group(1)
|
||||
date_str = re.search(rf"\s+{name}\s*:\s+(.*)", out_text).group(1)
|
||||
# For some reason Python's strptime() does not return any timezone information,
|
||||
# even though the information is there and a supported timezone for all supported
|
||||
# Python implementations (GMT). So we have to modify the datetime object by
|
||||
@@ -53,12 +53,10 @@ def _extract_date(out_text, name, cert_filename_suffix=""):
|
||||
datetime.datetime.strptime(date_str, "%b %d %H:%M:%S %Y %Z")
|
||||
)
|
||||
except AttributeError:
|
||||
raise BackendException(
|
||||
"No '{0}' date found{1}".format(name, cert_filename_suffix)
|
||||
)
|
||||
raise BackendException(f"No '{name}' date found{cert_filename_suffix}")
|
||||
except ValueError as exc:
|
||||
raise BackendException(
|
||||
"Failed to parse '{0}' date{1}: {2}".format(name, cert_filename_suffix, exc)
|
||||
f"Failed to parse '{name}' date{cert_filename_suffix}: {exc}"
|
||||
)
|
||||
|
||||
|
||||
@@ -67,20 +65,18 @@ def _decode_octets(octets_text):
|
||||
|
||||
|
||||
def _extract_octets(out_text, name, required=True, potential_prefixes=None):
|
||||
regexp = r"\s+%s:\s*\n\s+%s([A-Fa-f0-9]{2}(?::[A-Fa-f0-9]{2})*)\s*\n" % (
|
||||
name,
|
||||
(
|
||||
("(?:%s)" % "|".join(re.escape(pp) for pp in potential_prefixes))
|
||||
if potential_prefixes
|
||||
else ""
|
||||
),
|
||||
part = (
|
||||
f"(?:{'|'.join(re.escape(pp) for pp in potential_prefixes)})"
|
||||
if potential_prefixes
|
||||
else ""
|
||||
)
|
||||
regexp = rf"\s+{name}:\s*\n\s+{part}([A-Fa-f0-9]{{2}}(?::[A-Fa-f0-9]{{2}})*)\s*\n"
|
||||
match = re.search(regexp, out_text, re.MULTILINE | re.DOTALL)
|
||||
if match is not None:
|
||||
return _decode_octets(match.group(1))
|
||||
if not required:
|
||||
return None
|
||||
raise BackendException("No '{0}' octet string found".format(name))
|
||||
raise BackendException(f"No '{name}' octet string found")
|
||||
|
||||
|
||||
class OpenSSLCLIBackend(CryptoBackend):
|
||||
@@ -111,7 +107,7 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
except Exception:
|
||||
pass
|
||||
raise KeyParsingError(
|
||||
"failed to create temporary content file: %s" % to_native(err),
|
||||
f"failed to create temporary content file: {err}",
|
||||
exception=traceback.format_exc(),
|
||||
)
|
||||
f.close()
|
||||
@@ -132,7 +128,7 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
# FIXME: add some kind of auto-detection
|
||||
account_key_type = "rsa"
|
||||
if account_key_type not in ("rsa", "ec"):
|
||||
raise KeyParsingError('unknown key type "%s"' % account_key_type)
|
||||
raise KeyParsingError(f'unknown key type "{account_key_type}"')
|
||||
|
||||
openssl_keydump_cmd = [
|
||||
self.openssl_binary,
|
||||
@@ -149,9 +145,7 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
)
|
||||
if rc != 0:
|
||||
raise BackendException(
|
||||
"Error while running {cmd}: {stderr}".format(
|
||||
cmd=" ".join(openssl_keydump_cmd), stderr=to_text(err)
|
||||
)
|
||||
f"Error while running {' '.join(openssl_keydump_cmd)}: {to_text(err)}"
|
||||
)
|
||||
|
||||
out_text = to_text(out, errors="surrogate_or_strict")
|
||||
@@ -166,9 +160,9 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
pub_exp = re.search(
|
||||
r"\npublicExponent: ([0-9]+)", out_text, re.MULTILINE | re.DOTALL
|
||||
).group(1)
|
||||
pub_exp = "{0:x}".format(int(pub_exp))
|
||||
pub_exp = f"{int(pub_exp):x}"
|
||||
if len(pub_exp) % 2:
|
||||
pub_exp = "0{0}".format(pub_exp)
|
||||
pub_exp = f"0{pub_exp}"
|
||||
|
||||
return {
|
||||
"key_file": key_file,
|
||||
@@ -214,12 +208,12 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
curve = "P-521"
|
||||
else:
|
||||
raise KeyParsingError(
|
||||
"unknown elliptic curve: %s / %s" % (asn1_oid_curve, nist_curve)
|
||||
f"unknown elliptic curve: {asn1_oid_curve} / {nist_curve}"
|
||||
)
|
||||
num_bytes = (bits + 7) // 8
|
||||
if len(pub_hex) != 2 * num_bytes:
|
||||
raise KeyParsingError(
|
||||
"bad elliptic curve point (%s / %s)" % (asn1_oid_curve, nist_curve)
|
||||
f"bad elliptic curve point ({asn1_oid_curve} / {nist_curve})"
|
||||
)
|
||||
return {
|
||||
"key_file": key_file,
|
||||
@@ -236,7 +230,7 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
}
|
||||
|
||||
def sign(self, payload64, protected64, key_data):
|
||||
sign_payload = "{0}.{1}".format(protected64, payload64).encode("utf8")
|
||||
sign_payload = f"{protected64}.{payload64}".encode("utf8")
|
||||
if key_data["type"] == "hmac":
|
||||
hex_key = to_native(
|
||||
binascii.hexlify(base64.urlsafe_b64decode(key_data["jwk"]["k"]))
|
||||
@@ -245,7 +239,7 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
"-mac",
|
||||
"hmac",
|
||||
"-macopt",
|
||||
"hexkey:{0}".format(hex_key),
|
||||
f"hexkey:{hex_key}",
|
||||
"-binary",
|
||||
]
|
||||
else:
|
||||
@@ -253,7 +247,7 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
openssl_sign_cmd = [
|
||||
self.openssl_binary,
|
||||
"dgst",
|
||||
"-{0}".format(key_data["hash"]),
|
||||
f"-{key_data['hash']}",
|
||||
] + cmd_postfix
|
||||
|
||||
rc, out, err = self.module.run_command(
|
||||
@@ -265,9 +259,7 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
)
|
||||
if rc != 0:
|
||||
raise BackendException(
|
||||
"Error while running {cmd}: {stderr}".format(
|
||||
cmd=" ".join(openssl_sign_cmd), stderr=to_text(err)
|
||||
)
|
||||
f"Error while running {' '.join(openssl_sign_cmd)}: {to_text(err)}"
|
||||
)
|
||||
|
||||
if key_data["type"] == "ec":
|
||||
@@ -279,14 +271,13 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
)
|
||||
expected_len = 2 * key_data["point_size"]
|
||||
sig = re.findall(
|
||||
r"prim:\s+INTEGER\s+:([0-9A-F]{1,%s})\n" % expected_len,
|
||||
rf"prim:\s+INTEGER\s+:([0-9A-F]{{1,{expected_len}}})\n",
|
||||
to_text(der_out, errors="surrogate_or_strict"),
|
||||
)
|
||||
if len(sig) != 2:
|
||||
der_output = to_text(der_out, errors="surrogate_or_strict")
|
||||
raise BackendException(
|
||||
"failed to generate Elliptic Curve signature; cannot parse DER output: {0}".format(
|
||||
to_text(der_out, errors="surrogate_or_strict")
|
||||
)
|
||||
f"failed to generate Elliptic Curve signature; cannot parse DER output: {der_output}"
|
||||
)
|
||||
sig[0] = (expected_len - len(sig[0])) * "0" + sig[0]
|
||||
sig[1] = (expected_len - len(sig[1])) * "0" + sig[1]
|
||||
@@ -311,14 +302,12 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
hashbytes = 64
|
||||
else:
|
||||
raise BackendException(
|
||||
"Unsupported MAC key algorithm for OpenSSL backend: {0}".format(alg)
|
||||
f"Unsupported MAC key algorithm for OpenSSL backend: {alg}"
|
||||
)
|
||||
key_bytes = base64.urlsafe_b64decode(key)
|
||||
if len(key_bytes) < hashbytes:
|
||||
raise BackendException(
|
||||
"{0} key must be at least {1} bytes long (after Base64 decoding)".format(
|
||||
alg, hashbytes
|
||||
)
|
||||
f"{alg} key must be at least {hashbytes} bytes long (after Base64 decoding)"
|
||||
)
|
||||
return {
|
||||
"type": "hmac",
|
||||
@@ -370,9 +359,7 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
)
|
||||
if rc != 0:
|
||||
raise BackendException(
|
||||
"Error while running {cmd}: {stderr}".format(
|
||||
cmd=" ".join(openssl_csr_cmd), stderr=to_text(err)
|
||||
)
|
||||
f"Error while running {' '.join(openssl_csr_cmd)}: {to_text(err)}"
|
||||
)
|
||||
|
||||
identifiers = set()
|
||||
@@ -404,9 +391,7 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
elif san.lower().startswith("ip address:"):
|
||||
add_identifier(("ip", self._normalize_ip(san[11:])))
|
||||
else:
|
||||
raise BackendException(
|
||||
'Found unsupported SAN identifier "{0}"'.format(san)
|
||||
)
|
||||
raise BackendException(f'Found unsupported SAN identifier "{san}"')
|
||||
return result
|
||||
|
||||
def get_csr_identifiers(self, csr_filename=None, csr_content=None):
|
||||
@@ -438,7 +423,7 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
elif cert_filename is not None:
|
||||
if not os.path.exists(cert_filename):
|
||||
return -1
|
||||
cert_filename_suffix = " in {0}".format(cert_filename)
|
||||
cert_filename_suffix = f" in {cert_filename}"
|
||||
else:
|
||||
return -1
|
||||
|
||||
@@ -459,9 +444,7 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
)
|
||||
if rc != 0:
|
||||
raise BackendException(
|
||||
"Error while running {cmd}: {stderr}".format(
|
||||
cmd=" ".join(openssl_cert_cmd), stderr=to_text(err)
|
||||
)
|
||||
f"Error while running {' '.join(openssl_cert_cmd)}: {to_text(err)}"
|
||||
)
|
||||
|
||||
out_text = to_text(out, errors="surrogate_or_strict")
|
||||
@@ -489,7 +472,7 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
filename = cert_filename
|
||||
data = None
|
||||
if cert_filename is not None:
|
||||
cert_filename_suffix = " in {0}".format(cert_filename)
|
||||
cert_filename_suffix = f" in {cert_filename}"
|
||||
else:
|
||||
filename = "/dev/stdin"
|
||||
data = to_bytes(cert_content)
|
||||
@@ -512,9 +495,7 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
)
|
||||
if rc != 0:
|
||||
raise BackendException(
|
||||
"Error while running {cmd}: {stderr}".format(
|
||||
cmd=" ".join(openssl_cert_cmd), stderr=to_text(err)
|
||||
)
|
||||
f"Error while running {' '.join(openssl_cert_cmd)}: {to_text(err)}"
|
||||
)
|
||||
|
||||
out_text = to_text(out, errors="surrogate_or_strict")
|
||||
|
||||
@@ -53,15 +53,13 @@ def _reduce_fractional_digits(timestamp_str):
|
||||
# RFC 3339 (https://www.rfc-editor.org/info/rfc3339)
|
||||
m = _FRACTIONAL_MATCHER.match(timestamp_str)
|
||||
if not m:
|
||||
raise BackendException(
|
||||
"Cannot parse ISO 8601 timestamp {0!r}".format(timestamp_str)
|
||||
)
|
||||
raise BackendException(f"Cannot parse ISO 8601 timestamp {timestamp_str!r}")
|
||||
timestamp, fractional, timezone = m.groups()
|
||||
if len(fractional) > 7:
|
||||
# Python does not support anything smaller than microseconds
|
||||
# (Golang supports nanoseconds, Boulder often emits more fractional digits, which Python chokes on)
|
||||
fractional = fractional[:7]
|
||||
return "%s%s%s" % (timestamp, fractional, timezone)
|
||||
return f"{timestamp}{fractional}{timezone}"
|
||||
|
||||
|
||||
def _parse_acme_timestamp(timestamp_str, with_timezone):
|
||||
@@ -87,9 +85,7 @@ def _parse_acme_timestamp(timestamp_str, with_timezone):
|
||||
if with_timezone
|
||||
else remove_timezone(result)
|
||||
)
|
||||
raise BackendException(
|
||||
"Cannot parse ISO 8601 timestamp {0!r}".format(timestamp_str)
|
||||
)
|
||||
raise BackendException(f"Cannot parse ISO 8601 timestamp {timestamp_str!r}")
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
|
||||
@@ -62,7 +62,7 @@ class ACMECertificateClient:
|
||||
raise ModuleFailException(msg="Account does not exist or is deactivated.")
|
||||
|
||||
if self.csr is not None and not os.path.exists(self.csr):
|
||||
raise ModuleFailException("CSR %s not found" % (self.csr))
|
||||
raise ModuleFailException(f"CSR {self.csr} not found")
|
||||
|
||||
# Extract list of identifiers from CSR
|
||||
if self.csr is not None or self.csr_content is not None:
|
||||
@@ -84,9 +84,7 @@ class ACMECertificateClient:
|
||||
)
|
||||
except ValueError as exc:
|
||||
self.module.warn(
|
||||
"Error while parsing criterium: {error}. Ignoring criterium.".format(
|
||||
error=exc
|
||||
)
|
||||
f"Error while parsing criterium: {exc}. Ignoring criterium."
|
||||
)
|
||||
return select_chain_matcher
|
||||
|
||||
@@ -154,17 +152,13 @@ class ACMECertificateClient:
|
||||
for authz in order.authorizations.values():
|
||||
if authz.status not in ("valid", "pending"):
|
||||
bad_authzs.append(
|
||||
"{authz} (status={status!r})".format(
|
||||
authz=authz.combined_identifier,
|
||||
status=authz.status,
|
||||
)
|
||||
f"{authz.combined_identifier} (status={authz.status!r})"
|
||||
)
|
||||
if bad_authzs:
|
||||
bad_authzs = ", ".join(sorted(bad_authzs))
|
||||
raise ModuleFailException(
|
||||
"Some of the authorizations for the order are in a bad state, so the order"
|
||||
" can no longer be satisfied: {bad_authzs}".format(
|
||||
bad_authzs=", ".join(sorted(bad_authzs)),
|
||||
),
|
||||
f" can no longer be satisfied: {bad_authzs}",
|
||||
)
|
||||
|
||||
def collect_invalid_authzs(self, order):
|
||||
@@ -201,18 +195,14 @@ class ACMECertificateClient:
|
||||
alt_cert = CertificateChain.download(self.client, alternate)
|
||||
except ModuleFailException as e:
|
||||
self.module.warn(
|
||||
"Error while downloading alternative certificate {0}: {1}".format(
|
||||
alternate, e
|
||||
)
|
||||
f"Error while downloading alternative certificate {alternate}: {e}"
|
||||
)
|
||||
continue
|
||||
if alt_cert.cert is not None:
|
||||
alternate_chains.append(alt_cert)
|
||||
else:
|
||||
self.module.warn(
|
||||
"Error while downloading alternative certificate {0}: no certificate found".format(
|
||||
alternate
|
||||
)
|
||||
f"Error while downloading alternative certificate {alternate}: no certificate found"
|
||||
)
|
||||
return alternate_chains
|
||||
|
||||
@@ -222,22 +212,18 @@ class ACMECertificateClient:
|
||||
"""
|
||||
if order.status != "valid":
|
||||
raise ModuleFailException(
|
||||
"The order must be valid, but has state {state!r}!".format(
|
||||
state=order.state
|
||||
)
|
||||
f"The order must be valid, but has state {order.state!r}!"
|
||||
)
|
||||
|
||||
if not order.certificate_uri:
|
||||
raise ModuleFailException(
|
||||
"Order's crtificate URL {url!r} is empty!".format(
|
||||
url=order.certificate_uri
|
||||
)
|
||||
f"Order's crtificate URL {order.certificate_uri!r} is empty!"
|
||||
)
|
||||
|
||||
cert = CertificateChain.download(self.client, order.certificate_uri)
|
||||
if cert.cert is None:
|
||||
raise ModuleFailException(
|
||||
"Certificate at {url} is empty!".format(url=order.certificate_uri)
|
||||
f"Certificate at {order.certificate_uri} is empty!"
|
||||
)
|
||||
|
||||
alternate_chains = None
|
||||
@@ -256,7 +242,7 @@ class ACMECertificateClient:
|
||||
for identifier, authz in order.authorizations.items():
|
||||
if authz.status != "valid":
|
||||
authz.raise_error(
|
||||
'Status is {status!r} and not "valid"'.format(status=authz.status),
|
||||
f'Status is {authz.status!r} and not "valid"',
|
||||
module=self.module,
|
||||
)
|
||||
|
||||
@@ -269,7 +255,7 @@ class ACMECertificateClient:
|
||||
for chain in chains:
|
||||
if matcher.match(chain):
|
||||
self.module.debug(
|
||||
"Found matching chain for criterium {0}".format(criterium_idx)
|
||||
f"Found matching chain for criterium {criterium_idx}"
|
||||
)
|
||||
return chain
|
||||
return None
|
||||
@@ -312,9 +298,7 @@ class ACMECertificateClient:
|
||||
pass
|
||||
if authz is None or authz.status != "deactivated":
|
||||
self.module.warn(
|
||||
warning="Could not deactivate authz object {0}.".format(
|
||||
authz_uri
|
||||
)
|
||||
warning=f"Could not deactivate authz object {authz_uri}."
|
||||
)
|
||||
else:
|
||||
for authz in order.authorizations.values():
|
||||
@@ -325,7 +309,5 @@ class ACMECertificateClient:
|
||||
pass
|
||||
if authz.status != "deactivated":
|
||||
self.module.warn(
|
||||
warning="Could not deactivate authz object {0}.".format(
|
||||
authz.url
|
||||
)
|
||||
warning=f"Could not deactivate authz object {authz.url}."
|
||||
)
|
||||
|
||||
@@ -44,9 +44,7 @@ class CertificateChain:
|
||||
"application/pem-certificate-chain"
|
||||
):
|
||||
raise ModuleFailException(
|
||||
"Cannot download certificate chain from {0}, as content type is not application/pem-certificate-chain: {1} (headers: {2})".format(
|
||||
url, content, info
|
||||
)
|
||||
f"Cannot download certificate chain from {url}, as content type is not application/pem-certificate-chain: {content} (headers: {info})"
|
||||
)
|
||||
|
||||
result = cls(url)
|
||||
@@ -63,9 +61,7 @@ class CertificateChain:
|
||||
|
||||
if result.cert is None:
|
||||
raise ModuleFailException(
|
||||
"Failed to parse certificate chain download from {0}: {1} (headers: {2})".format(
|
||||
url, content, info
|
||||
)
|
||||
f"Failed to parse certificate chain download from {url}: {content} (headers: {info})"
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
@@ -37,11 +37,11 @@ def create_key_authorization(client, token):
|
||||
client.account_jwk, sort_keys=True, separators=(",", ":")
|
||||
)
|
||||
thumbprint = nopad_b64(hashlib.sha256(accountkey_json.encode("utf8")).digest())
|
||||
return "{0}.{1}".format(token, thumbprint)
|
||||
return f"{token}.{thumbprint}"
|
||||
|
||||
|
||||
def combine_identifier(identifier_type, identifier):
|
||||
return "{type}:{identifier}".format(type=identifier_type, identifier=identifier)
|
||||
return f"{identifier_type}:{identifier}"
|
||||
|
||||
|
||||
def normalize_combined_identifier(identifier):
|
||||
@@ -55,9 +55,7 @@ def split_identifier(identifier):
|
||||
parts = identifier.split(":", 1)
|
||||
if len(parts) != 2:
|
||||
raise ModuleFailException(
|
||||
'Identifier "{identifier}" is not of the form <type>:<identifier>'.format(
|
||||
identifier=identifier
|
||||
)
|
||||
f'Identifier "{identifier}" is not of the form <type>:<identifier>'
|
||||
)
|
||||
return parts
|
||||
|
||||
@@ -94,7 +92,7 @@ class Challenge:
|
||||
if self.type == "http-01":
|
||||
# https://tools.ietf.org/html/rfc8555#section-8.3
|
||||
return {
|
||||
"resource": ".well-known/acme-challenge/{token}".format(token=token),
|
||||
"resource": f".well-known/acme-challenge/{token}",
|
||||
"resource_value": key_authorization,
|
||||
}
|
||||
|
||||
@@ -104,9 +102,7 @@ class Challenge:
|
||||
# https://tools.ietf.org/html/rfc8555#section-8.4
|
||||
resource = "_acme-challenge"
|
||||
value = nopad_b64(hashlib.sha256(to_bytes(key_authorization)).digest())
|
||||
record = "{0}.{1}".format(
|
||||
resource, identifier[2:] if identifier.startswith("*.") else identifier
|
||||
)
|
||||
record = f"{resource}.{identifier[2:] if identifier.startswith('*.') else identifier}"
|
||||
return {
|
||||
"resource": resource,
|
||||
"resource_value": value,
|
||||
@@ -152,7 +148,7 @@ class Authorization:
|
||||
self.identifier = data["identifier"]["value"]
|
||||
self.identifier_type = data["identifier"]["type"]
|
||||
if data.get("wildcard", False):
|
||||
self.identifier = "*.{0}".format(self.identifier)
|
||||
self.identifier = f"*.{self.identifier}"
|
||||
|
||||
def __init__(self, url):
|
||||
self.url = url
|
||||
@@ -238,23 +234,17 @@ class Authorization:
|
||||
# details for all of them before failing
|
||||
for challenge in self.challenges:
|
||||
if challenge.status == "invalid":
|
||||
msg = "Challenge {type}".format(type=challenge.type)
|
||||
msg = f"Challenge {challenge.type}"
|
||||
if "error" in challenge.data:
|
||||
msg = "{msg}: {problem}".format(
|
||||
msg=msg,
|
||||
problem=format_error_problem(
|
||||
challenge.data["error"],
|
||||
subproblem_prefix="{0}.".format(challenge.type),
|
||||
),
|
||||
problem = format_error_problem(
|
||||
challenge.data["error"],
|
||||
subproblem_prefix=f"{challenge.type}.",
|
||||
)
|
||||
msg = f"{msg}: {problem}"
|
||||
error_details.append(msg)
|
||||
raise ACMEProtocolException(
|
||||
module,
|
||||
"Failed to validate challenge for {identifier}: {error}. {details}".format(
|
||||
identifier=self.combined_identifier,
|
||||
error=error_msg,
|
||||
details="; ".join(error_details),
|
||||
),
|
||||
f"Failed to validate challenge for {self.combined_identifier}: {error_msg}. {'; '.join(error_details)}",
|
||||
extras=dict(
|
||||
identifier=self.combined_identifier,
|
||||
authorization=self.data,
|
||||
@@ -287,10 +277,7 @@ class Authorization:
|
||||
challenge = self.find_challenge(challenge_type)
|
||||
if challenge is None:
|
||||
raise ModuleFailException(
|
||||
'Found no challenge of type "{challenge}" for identifier {identifier}!'.format(
|
||||
challenge=challenge_type,
|
||||
identifier=self.combined_identifier,
|
||||
)
|
||||
f'Found no challenge of type "{challenge_type}" for identifier {self.combined_identifier}!'
|
||||
)
|
||||
|
||||
challenge.call_validate(client)
|
||||
|
||||
@@ -14,7 +14,7 @@ def format_http_status(status_code):
|
||||
expl = http_responses.get(status_code)
|
||||
if not expl:
|
||||
return str(status_code)
|
||||
return "%d %s" % (status_code, expl)
|
||||
return f"{status_code} {expl}"
|
||||
|
||||
|
||||
def format_error_problem(problem, subproblem_prefix=""):
|
||||
@@ -22,26 +22,18 @@ def format_error_problem(problem, subproblem_prefix=""):
|
||||
"type", "about:blank"
|
||||
) # https://www.rfc-editor.org/rfc/rfc7807#section-3.1
|
||||
if "title" in problem:
|
||||
msg = 'Error "{title}" ({type})'.format(
|
||||
type=error_type,
|
||||
title=problem["title"],
|
||||
)
|
||||
msg = f'Error "{problem["title"]}" ({error_type})'
|
||||
else:
|
||||
msg = "Error {type}".format(type=error_type)
|
||||
msg = f"Error {error_type}"
|
||||
if "detail" in problem:
|
||||
msg += ': "{detail}"'.format(detail=problem["detail"])
|
||||
msg += f': "{problem["detail"]}"'
|
||||
subproblems = problem.get("subproblems")
|
||||
if subproblems is not None:
|
||||
msg = "{msg} Subproblems:".format(msg=msg)
|
||||
msg = f"{msg} Subproblems:"
|
||||
for index, problem in enumerate(subproblems):
|
||||
index_str = "{prefix}{index}".format(prefix=subproblem_prefix, index=index)
|
||||
msg = "{msg}\n({index}) {problem}".format(
|
||||
msg=msg,
|
||||
index=index_str,
|
||||
problem=format_error_problem(
|
||||
problem, subproblem_prefix="{0}.".format(index_str)
|
||||
),
|
||||
)
|
||||
index_str = f"{subproblem_prefix}{index}"
|
||||
problem = format_error_problem(problem, subproblem_prefix=f"{index_str}.")
|
||||
msg = f"{msg}\n({index_str}) {problem}"
|
||||
return msg
|
||||
|
||||
|
||||
@@ -116,55 +108,37 @@ class ACMEProtocolException(ModuleFailException):
|
||||
):
|
||||
error_type = content_json["type"]
|
||||
if "status" in content_json and content_json["status"] != code:
|
||||
code_msg = (
|
||||
"status {problem_code} (HTTP status: {http_code})".format(
|
||||
http_code=format_http_status(code),
|
||||
problem_code=content_json["status"],
|
||||
)
|
||||
)
|
||||
code_msg = f"status {content_json['status']} (HTTP status: {format_http_status(code)})"
|
||||
else:
|
||||
code_msg = "status {problem_code}".format(
|
||||
problem_code=format_http_status(code)
|
||||
)
|
||||
code_msg = f"status {format_http_status(code)}"
|
||||
if code == -1 and info.get("msg"):
|
||||
code_msg = "error: {msg}".format(msg=info["msg"])
|
||||
code_msg = f"error: {info['msg']}"
|
||||
subproblems = content_json.pop("subproblems", None)
|
||||
add_msg = " {problem}.".format(
|
||||
problem=format_error_problem(content_json)
|
||||
)
|
||||
add_msg = f" {format_error_problem(content_json)}."
|
||||
extras["problem"] = content_json
|
||||
extras["subproblems"] = subproblems or []
|
||||
if subproblems is not None:
|
||||
add_msg = "{add_msg} Subproblems:".format(add_msg=add_msg)
|
||||
add_msg = f"{add_msg} Subproblems:"
|
||||
for index, problem in enumerate(subproblems):
|
||||
add_msg = "{add_msg}\n({index}) {problem}.".format(
|
||||
add_msg=add_msg,
|
||||
index=index,
|
||||
problem=format_error_problem(
|
||||
problem, subproblem_prefix="{0}.".format(index)
|
||||
),
|
||||
problem = format_error_problem(
|
||||
problem, subproblem_prefix=f"{index}."
|
||||
)
|
||||
add_msg = f"{add_msg}\n({index}) {problem}."
|
||||
else:
|
||||
code_msg = "HTTP status {code}".format(code=format_http_status(code))
|
||||
code_msg = f"HTTP status {format_http_status(code)}"
|
||||
if code == -1 and info.get("msg"):
|
||||
code_msg = "error: {msg}".format(msg=info["msg"])
|
||||
code_msg = f"error: {info['msg']}"
|
||||
if content_json is not None:
|
||||
add_msg = " The JSON error result: {content}".format(
|
||||
content=content_json
|
||||
)
|
||||
add_msg = f" The JSON error result: {content_json}"
|
||||
elif content is not None:
|
||||
add_msg = " The raw error result: {content}".format(
|
||||
content=to_text(content)
|
||||
)
|
||||
msg = "{msg} for {url} with {code}".format(msg=msg, url=url, code=code_msg)
|
||||
add_msg = f" The raw error result: {to_text(content)}"
|
||||
msg = f"{msg} for {url} with {code_msg}"
|
||||
elif content_json is not None:
|
||||
add_msg = " The JSON result: {content}".format(content=content_json)
|
||||
add_msg = f" The JSON result: {content_json}"
|
||||
elif content is not None:
|
||||
add_msg = " The raw result: {content}".format(content=to_text(content))
|
||||
add_msg = f" The raw result: {to_text(content)}"
|
||||
|
||||
super(ACMEProtocolException, self).__init__(
|
||||
"{msg}.{add_msg}".format(msg=msg, add_msg=add_msg), **extras
|
||||
)
|
||||
super(ACMEProtocolException, self).__init__(f"{msg}.{add_msg}", **extras)
|
||||
self.problem = {}
|
||||
self.subproblems = []
|
||||
self.error_code = error_code
|
||||
|
||||
@@ -22,7 +22,7 @@ def read_file(fn, mode="b"):
|
||||
with open(fn, "r" + mode) as f:
|
||||
return f.read()
|
||||
except Exception as e:
|
||||
raise ModuleFailException('Error while reading file "{0}": {1}'.format(fn, e))
|
||||
raise ModuleFailException(f'Error while reading file "{fn}": {e}')
|
||||
|
||||
|
||||
# This function was adapted from an earlier version of https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/uri.py
|
||||
@@ -44,7 +44,7 @@ def write_file(module, dest, content):
|
||||
pass
|
||||
os.remove(tmpsrc)
|
||||
raise ModuleFailException(
|
||||
"failed to create temporary content file: %s" % to_native(err),
|
||||
f"failed to create temporary content file: {err}",
|
||||
exception=traceback.format_exc(),
|
||||
)
|
||||
f.close()
|
||||
@@ -56,26 +56,26 @@ def write_file(module, dest, content):
|
||||
os.remove(tmpsrc)
|
||||
except Exception:
|
||||
pass
|
||||
raise ModuleFailException("Source %s does not exist" % (tmpsrc))
|
||||
raise ModuleFailException(f"Source {tmpsrc} does not exist")
|
||||
if not os.access(tmpsrc, os.R_OK):
|
||||
os.remove(tmpsrc)
|
||||
raise ModuleFailException("Source %s not readable" % (tmpsrc))
|
||||
raise ModuleFailException(f"Source {tmpsrc} not readable")
|
||||
checksum_src = module.sha1(tmpsrc)
|
||||
# check if there is no dest file
|
||||
if os.path.exists(dest):
|
||||
# raise an error if copy has no permission on dest
|
||||
if not os.access(dest, os.W_OK):
|
||||
os.remove(tmpsrc)
|
||||
raise ModuleFailException("Destination %s not writable" % (dest))
|
||||
raise ModuleFailException(f"Destination {dest} not writable")
|
||||
if not os.access(dest, os.R_OK):
|
||||
os.remove(tmpsrc)
|
||||
raise ModuleFailException("Destination %s not readable" % (dest))
|
||||
raise ModuleFailException(f"Destination {dest} not readable")
|
||||
checksum_dest = module.sha1(dest)
|
||||
else:
|
||||
dirname = os.path.dirname(dest) or "."
|
||||
if not os.access(dirname, os.W_OK):
|
||||
os.remove(tmpsrc)
|
||||
raise ModuleFailException("Destination dir %s not writable" % (dirname))
|
||||
raise ModuleFailException(f"Destination dir {dirname} not writable")
|
||||
if checksum_src != checksum_dest:
|
||||
try:
|
||||
shutil.copyfile(tmpsrc, dest)
|
||||
@@ -83,7 +83,7 @@ def write_file(module, dest, content):
|
||||
except Exception as err:
|
||||
os.remove(tmpsrc)
|
||||
raise ModuleFailException(
|
||||
"failed to copy %s to %s: %s" % (tmpsrc, dest, to_native(err)),
|
||||
f"failed to copy {tmpsrc} to {dest}: {to_native(err)}",
|
||||
exception=traceback.format_exc(),
|
||||
)
|
||||
os.remove(tmpsrc)
|
||||
|
||||
@@ -133,11 +133,7 @@ class Order:
|
||||
):
|
||||
if message_callback:
|
||||
message_callback(
|
||||
"Stop passing `replaces={replaces}` due to error {code} {type} when creating ACME order".format(
|
||||
code=exc.error_code,
|
||||
type=exc.error_type,
|
||||
replaces=replaces_cert_id,
|
||||
)
|
||||
f"Stop passing `replaces={replaces_cert_id}` due to error {exc.error_code} {exc.error_type} when creating ACME order"
|
||||
)
|
||||
replaces_cert_id = None
|
||||
continue
|
||||
@@ -167,9 +163,7 @@ class Order:
|
||||
if self.status != "valid":
|
||||
raise ACMEProtocolException(
|
||||
client.module,
|
||||
'Failed to wait for order to complete; got status "{status}"'.format(
|
||||
status=self.status
|
||||
),
|
||||
f'Failed to wait for order to complete; got status "{self.status}"',
|
||||
content_json=self.data,
|
||||
)
|
||||
|
||||
@@ -198,9 +192,7 @@ class Order:
|
||||
if self.status not in ["procesing", "valid", "invalid"]:
|
||||
raise ACMEProtocolException(
|
||||
client.module,
|
||||
'Failed to finalize order; got status "{status}"'.format(
|
||||
status=self.status
|
||||
),
|
||||
f'Failed to finalize order; got status "{self.status}"',
|
||||
info=info,
|
||||
content_json=result,
|
||||
)
|
||||
|
||||
@@ -32,9 +32,8 @@ def der_to_pem(der_cert):
|
||||
"""
|
||||
Convert the DER format certificate in der_cert to a PEM format certificate and return it.
|
||||
"""
|
||||
return """-----BEGIN CERTIFICATE-----\n{0}\n-----END CERTIFICATE-----\n""".format(
|
||||
"\n".join(textwrap.wrap(base64.b64encode(der_cert).decode("utf8"), 64))
|
||||
)
|
||||
content = "\n".join(textwrap.wrap(base64.b64encode(der_cert).decode("utf8"), 64))
|
||||
return f"-----BEGIN CERTIFICATE-----\n{content}\n-----END CERTIFICATE-----\n"
|
||||
|
||||
|
||||
def pem_to_der(pem_filename=None, pem_content=None):
|
||||
@@ -52,7 +51,7 @@ def pem_to_der(pem_filename=None, pem_content=None):
|
||||
lines = list(f)
|
||||
except Exception as err:
|
||||
raise ModuleFailException(
|
||||
"cannot load PEM file {0}: {1}".format(pem_filename, to_native(err)),
|
||||
f"cannot load PEM file {pem_filename}: {to_native(err)}",
|
||||
exception=traceback.format_exc(),
|
||||
)
|
||||
else:
|
||||
@@ -104,7 +103,7 @@ def parse_retry_after(value, relative_with_timezone=True, now=None):
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
raise ValueError("Cannot parse Retry-After header value %s" % repr(value))
|
||||
raise ValueError(f"Cannot parse Retry-After header value {repr(value)}")
|
||||
|
||||
|
||||
def compute_cert_id(
|
||||
@@ -138,4 +137,4 @@ def compute_cert_id(
|
||||
serial = to_native(base64.urlsafe_b64encode(serial_bytes)).replace("=", "")
|
||||
|
||||
# Compose cert ID
|
||||
return "{aki}.{serial}".format(aki=aki, serial=serial)
|
||||
return f"{aki}.{serial}"
|
||||
|
||||
@@ -82,8 +82,7 @@ def serialize_asn1_string_as_der(value):
|
||||
|
||||
if value_type != "UTF8":
|
||||
raise ValueError(
|
||||
'The ASN.1 serialized string is not a known type "{0}", only UTF8 types are '
|
||||
"supported".format(value_type)
|
||||
f'The ASN.1 serialized string is not a known type "{value_type}", only UTF8 types are supported'
|
||||
)
|
||||
|
||||
b_value = to_bytes(asn1_value, encoding="utf-8", errors="surrogate_or_strict")
|
||||
@@ -117,7 +116,7 @@ def pack_asn1(tag_class, constructed, tag_number, b_data):
|
||||
b_asn1_data = bytearray()
|
||||
|
||||
if tag_class < 0 or tag_class > 3:
|
||||
raise ValueError("tag_class must be between 0 and 3 not %s" % tag_class)
|
||||
raise ValueError(f"tag_class must be between 0 and 3 not {tag_class}")
|
||||
|
||||
# Bit 8 and 7 denotes the class.
|
||||
identifier_octets = tag_class << 6
|
||||
|
||||
@@ -15,9 +15,7 @@ for dotted, names in OID_MAP.items():
|
||||
for name in names:
|
||||
if name in NORMALIZE_NAMES and OID_LOOKUP[name] != dotted:
|
||||
raise AssertionError(
|
||||
'Name collision during setup: "{0}" for OIDs {1} and {2}'.format(
|
||||
name, dotted, OID_LOOKUP[name]
|
||||
)
|
||||
f'Name collision during setup: "{name}" for OIDs {dotted} and {OID_LOOKUP[name]}'
|
||||
)
|
||||
NORMALIZE_NAMES[name] = names[0]
|
||||
NORMALIZE_NAMES_SHORT[name] = names[-1]
|
||||
@@ -25,9 +23,7 @@ for dotted, names in OID_MAP.items():
|
||||
for alias, original in [("userID", "userId")]:
|
||||
if alias in NORMALIZE_NAMES:
|
||||
raise AssertionError(
|
||||
'Name collision during adding aliases: "{0}" (alias for "{1}") is already mapped to OID {2}'.format(
|
||||
alias, original, OID_LOOKUP[alias]
|
||||
)
|
||||
f'Name collision during adding aliases: "{alias}" (alias for "{original}") is already mapped to OID {OID_LOOKUP[alias]}'
|
||||
)
|
||||
NORMALIZE_NAMES[alias] = original
|
||||
NORMALIZE_NAMES_SHORT[alias] = NORMALIZE_NAMES_SHORT[original]
|
||||
|
||||
@@ -242,7 +242,7 @@ def cryptography_name_to_oid(name):
|
||||
if dotted is None:
|
||||
if DOTTED_OID.match(name):
|
||||
return x509.oid.ObjectIdentifier(name)
|
||||
raise OpenSSLObjectError('Cannot find OID for "{0}"'.format(name))
|
||||
raise OpenSSLObjectError(f'Cannot find OID for "{name}"')
|
||||
return x509.oid.ObjectIdentifier(dotted)
|
||||
|
||||
|
||||
@@ -297,7 +297,7 @@ else:
|
||||
def _parse_dn_component(name, sep=b",", decode_remainder=True):
|
||||
m = DN_COMPONENT_START_RE.match(name)
|
||||
if not m:
|
||||
raise OpenSSLObjectError('cannot start part in "{0}"'.format(to_text(name)))
|
||||
raise OpenSSLObjectError(f'cannot start part in "{to_text(name)}"')
|
||||
oid = cryptography_name_to_oid(to_text(m.group(1)))
|
||||
idx = len(m.group(0))
|
||||
decoded_name = []
|
||||
@@ -314,7 +314,7 @@ def _parse_dn_component(name, sep=b",", decode_remainder=True):
|
||||
idx2 = DN_HEX_LETTER.find(ch2.lower())
|
||||
if idx1 < 0 or idx2 < 0:
|
||||
raise OpenSSLObjectError(
|
||||
'Invalid hex sequence entry "{0}"'.format(to_text(ch1 + ch2))
|
||||
f'Invalid hex sequence entry "{to_text(ch1 + ch2)}"'
|
||||
)
|
||||
idx += 2
|
||||
decoded_name.append(_int_to_byte(idx1 * 16 + idx2))
|
||||
@@ -333,17 +333,13 @@ def _parse_dn_component(name, sep=b",", decode_remainder=True):
|
||||
if idx1 >= 0:
|
||||
if idx + 2 >= length:
|
||||
raise OpenSSLObjectError(
|
||||
'Hex escape sequence "\\{0}" incomplete at end of string'.format(
|
||||
to_text(ch)
|
||||
)
|
||||
f'Hex escape sequence "\\{to_text(ch)}" incomplete at end of string'
|
||||
)
|
||||
ch2 = name[idx + 2 : idx + 3]
|
||||
idx2 = DN_HEX_LETTER.find(ch2.lower())
|
||||
if idx2 < 0:
|
||||
raise OpenSSLObjectError(
|
||||
'Hex escape sequence "\\{0}" has invalid second letter'.format(
|
||||
to_text(ch + ch2)
|
||||
)
|
||||
f'Hex escape sequence "\\{to_text(ch + ch2)}" has invalid second letter'
|
||||
)
|
||||
ch = _int_to_byte(idx1 * 16 + idx2)
|
||||
idx += 1
|
||||
@@ -375,17 +371,13 @@ def _parse_dn(name):
|
||||
attribute, name = _parse_dn_component(name, sep=sep)
|
||||
except OpenSSLObjectError as e:
|
||||
raise OpenSSLObjectError(
|
||||
'Error while parsing distinguished name "{0}": {1}'.format(
|
||||
to_text(original_name), e
|
||||
)
|
||||
f'Error while parsing distinguished name "{to_text(original_name)}": {e}'
|
||||
)
|
||||
result.append(attribute)
|
||||
if name:
|
||||
if name[0:1] != sep or len(name) < 2:
|
||||
raise OpenSSLObjectError(
|
||||
'Error while parsing distinguished name "{0}": unexpected end of string'.format(
|
||||
to_text(original_name)
|
||||
)
|
||||
f'Error while parsing distinguished name "{to_text(original_name)}": unexpected end of string'
|
||||
)
|
||||
name = name[1:]
|
||||
return result
|
||||
@@ -398,9 +390,7 @@ def cryptography_parse_relative_distinguished_name(rdn):
|
||||
names.append(_parse_dn_component(to_bytes(part), decode_remainder=False)[0])
|
||||
except OpenSSLObjectError as e:
|
||||
raise OpenSSLObjectError(
|
||||
'Error while parsing relative distinguished name "{0}": {1}'.format(
|
||||
part, e
|
||||
)
|
||||
f'Error while parsing relative distinguished name "{part}": {e}'
|
||||
)
|
||||
return cryptography.x509.RelativeDistinguishedName(names)
|
||||
|
||||
@@ -420,16 +410,14 @@ def _adjust_idn(value, idn_rewrite):
|
||||
if idn_rewrite == "idna" and _is_ascii(value):
|
||||
return value
|
||||
if idn_rewrite not in ("idna", "unicode"):
|
||||
raise ValueError('Invalid value for idn_rewrite: "{0}"'.format(idn_rewrite))
|
||||
raise ValueError(f'Invalid value for idn_rewrite: "{idn_rewrite}"')
|
||||
if not HAS_IDNA:
|
||||
what = "IDNA" if idn_rewrite == "unicode" else "Unicode"
|
||||
dest = "Unicode" if idn_rewrite == "unicode" else "IDNA"
|
||||
raise OpenSSLObjectError(
|
||||
missing_required_lib(
|
||||
"idna",
|
||||
reason='to transform {what} DNS name "{name}" to {dest}'.format(
|
||||
name=value,
|
||||
what="IDNA" if idn_rewrite == "unicode" else "Unicode",
|
||||
dest="Unicode" if idn_rewrite == "unicode" else "IDNA",
|
||||
),
|
||||
reason=f'to transform {what} DNS name "{value}" to {dest}',
|
||||
)
|
||||
)
|
||||
# Since IDNA does not like '*' or empty labels (except one empty label at the end),
|
||||
@@ -450,16 +438,11 @@ def _adjust_idn(value, idn_rewrite):
|
||||
elif idn_rewrite == "unicode" and part.startswith("xn--"):
|
||||
parts[index] = part.encode("ascii").decode("idna")
|
||||
except Exception as exc2003:
|
||||
what = "IDNA" if idn_rewrite == "unicode" else "Unicode"
|
||||
dest = "Unicode" if idn_rewrite == "unicode" else "IDNA"
|
||||
raise OpenSSLObjectError(
|
||||
'Error while transforming part "{part}" of {what} DNS name "{name}" to {dest}.'
|
||||
' IDNA2008 transformation resulted in "{exc2008}", IDNA2003 transformation resulted in "{exc2003}".'.format(
|
||||
part=part,
|
||||
name=value,
|
||||
what="IDNA" if idn_rewrite == "unicode" else "Unicode",
|
||||
dest="Unicode" if idn_rewrite == "unicode" else "IDNA",
|
||||
exc2003=exc2003,
|
||||
exc2008=exc2008,
|
||||
)
|
||||
f'Error while transforming part "{part}" of {what} DNS name "{value}" to {dest}.'
|
||||
f' IDNA2008 transformation resulted in "{exc2008}", IDNA2003 transformation resulted in "{exc2003}".'
|
||||
)
|
||||
return ".".join(parts)
|
||||
|
||||
@@ -468,18 +451,18 @@ def _adjust_idn_email(value, idn_rewrite):
|
||||
idx = value.find("@")
|
||||
if idx < 0:
|
||||
return value
|
||||
return "{0}@{1}".format(value[:idx], _adjust_idn(value[idx + 1 :], idn_rewrite))
|
||||
return f"{value[:idx]}@{_adjust_idn(value[idx + 1:], idn_rewrite)}"
|
||||
|
||||
|
||||
def _adjust_idn_url(value, idn_rewrite):
|
||||
url = urlparse(value)
|
||||
host = _adjust_idn(url.hostname, idn_rewrite)
|
||||
if url.username is not None and url.password is not None:
|
||||
host = "{0}:{1}@{2}".format(url.username, url.password, host)
|
||||
host = f"{url.username}:{url.password}@{host}"
|
||||
elif url.username is not None:
|
||||
host = "{0}@{1}".format(url.username, host)
|
||||
host = f"{url.username}@{host}"
|
||||
if url.port is not None:
|
||||
host = "{0}:{1}".format(host, url.port)
|
||||
host = f"{host}:{url.port}"
|
||||
return urlunparse(
|
||||
ParseResult(
|
||||
scheme=url.scheme,
|
||||
@@ -514,9 +497,7 @@ def cryptography_get_name(name, what="Subject Alternative Name"):
|
||||
if name.startswith("RID:"):
|
||||
m = re.match(r"^([0-9]+(?:\.[0-9]+)*)$", to_text(name[4:]))
|
||||
if not m:
|
||||
raise OpenSSLObjectError(
|
||||
'Cannot parse {what} "{name}"'.format(name=name, what=what)
|
||||
)
|
||||
raise OpenSSLObjectError(f'Cannot parse {what} "{name}"')
|
||||
return x509.RegisteredID(x509.oid.ObjectIdentifier(m.group(1)))
|
||||
if name.startswith("otherName:"):
|
||||
# otherName can either be a raw ASN.1 hex string or in the format that OpenSSL works with.
|
||||
@@ -534,9 +515,9 @@ def cryptography_get_name(name, what="Subject Alternative Name"):
|
||||
name = to_text(name[10:], errors="surrogate_or_strict")
|
||||
if ";" not in name:
|
||||
raise OpenSSLObjectError(
|
||||
'Cannot parse {what} otherName "{name}", must be in the '
|
||||
f'Cannot parse {what} otherName "{name}", must be in the '
|
||||
'format "otherName:<OID>;<ASN.1 OpenSSL Encoded String>" or '
|
||||
'"otherName:<OID>;<hex string>"'.format(name=name, what=what)
|
||||
'"otherName:<OID>;<hex string>"'
|
||||
)
|
||||
|
||||
oid, value = name.split(";", 1)
|
||||
@@ -547,21 +528,13 @@ def cryptography_get_name(name, what="Subject Alternative Name"):
|
||||
x509.Name(reversed(_parse_dn(to_bytes(name[8:]))))
|
||||
)
|
||||
except Exception as e:
|
||||
raise OpenSSLObjectError(
|
||||
'Cannot parse {what} "{name}": {error}'.format(
|
||||
name=name, what=what, error=e
|
||||
)
|
||||
)
|
||||
raise OpenSSLObjectError(f'Cannot parse {what} "{name}": {e}')
|
||||
if ":" not in name:
|
||||
raise OpenSSLObjectError(
|
||||
'Cannot parse {what} "{name}" (forgot "DNS:" prefix?)'.format(
|
||||
name=name, what=what
|
||||
)
|
||||
f'Cannot parse {what} "{name}" (forgot "DNS:" prefix?)'
|
||||
)
|
||||
raise OpenSSLObjectError(
|
||||
'Cannot parse {what} "{name}" (potentially unsupported by cryptography backend)'.format(
|
||||
name=name, what=what
|
||||
)
|
||||
f'Cannot parse {what} "{name}" (potentially unsupported by cryptography backend)'
|
||||
)
|
||||
|
||||
|
||||
@@ -571,12 +544,12 @@ def _dn_escape_value(value):
|
||||
"""
|
||||
value = value.replace("\\", "\\\\")
|
||||
for ch in [",", "+", "<", ">", ";", '"']:
|
||||
value = value.replace(ch, "\\%s" % ch)
|
||||
value = value.replace(ch, f"\\{ch}")
|
||||
value = value.replace("\0", "\\00")
|
||||
if value.startswith((" ", "#")):
|
||||
value = "\\%s" % value[0] + value[1:]
|
||||
value = f"\\{value[0]}{value[1:]}"
|
||||
if value.endswith(" "):
|
||||
value = value[:-1] + "\\ "
|
||||
value = f"{value[:-1]}\\ "
|
||||
return value
|
||||
|
||||
|
||||
@@ -590,36 +563,29 @@ def cryptography_decode_name(name, idn_rewrite="ignore"):
|
||||
'idn_rewrite must be one of "ignore", "idna", or "unicode"'
|
||||
)
|
||||
if isinstance(name, x509.DNSName):
|
||||
return "DNS:{0}".format(_adjust_idn(name.value, idn_rewrite))
|
||||
return f"DNS:{_adjust_idn(name.value, idn_rewrite)}"
|
||||
if isinstance(name, x509.IPAddress):
|
||||
if isinstance(name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network)):
|
||||
return "IP:{0}/{1}".format(
|
||||
name.value.network_address.compressed, name.value.prefixlen
|
||||
)
|
||||
return "IP:{0}".format(name.value.compressed)
|
||||
return f"IP:{name.value.network_address.compressed}/{name.value.prefixlen}"
|
||||
return f"IP:{name.value.compressed}"
|
||||
if isinstance(name, x509.RFC822Name):
|
||||
return "email:{0}".format(_adjust_idn_email(name.value, idn_rewrite))
|
||||
return f"email:{_adjust_idn_email(name.value, idn_rewrite)}"
|
||||
if isinstance(name, x509.UniformResourceIdentifier):
|
||||
return "URI:{0}".format(_adjust_idn_url(name.value, idn_rewrite))
|
||||
return f"URI:{_adjust_idn_url(name.value, idn_rewrite)}"
|
||||
if isinstance(name, x509.DirectoryName):
|
||||
# According to https://datatracker.ietf.org/doc/html/rfc4514.html#section-2.1 the
|
||||
# list needs to be reversed, and joined by commas
|
||||
return "dirName:" + ",".join(
|
||||
[
|
||||
"{0}={1}".format(
|
||||
to_text(cryptography_oid_to_name(attribute.oid, short=True)),
|
||||
_dn_escape_value(attribute.value),
|
||||
)
|
||||
f"{to_text(cryptography_oid_to_name(attribute.oid, short=True))}={_dn_escape_value(attribute.value)}"
|
||||
for attribute in reversed(list(name.value))
|
||||
]
|
||||
)
|
||||
if isinstance(name, x509.RegisteredID):
|
||||
return "RID:{0}".format(name.value.dotted_string)
|
||||
return f"RID:{name.value.dotted_string}"
|
||||
if isinstance(name, x509.OtherName):
|
||||
return "otherName:{0};{1}".format(
|
||||
name.type_id.dotted_string, _get_hex(name.value)
|
||||
)
|
||||
raise OpenSSLObjectError('Cannot decode name "{0}"'.format(name))
|
||||
return f"otherName:{name.type_id.dotted_string};{_get_hex(name.value)}"
|
||||
raise OpenSSLObjectError(f'Cannot decode name "{name}"')
|
||||
|
||||
|
||||
def _cryptography_get_keyusage(usage):
|
||||
@@ -645,7 +611,7 @@ def _cryptography_get_keyusage(usage):
|
||||
return "encipher_only"
|
||||
if usage in ("Decipher Only", "decipherOnly"):
|
||||
return "decipher_only"
|
||||
raise OpenSSLObjectError('Unknown key usage "{0}"'.format(usage))
|
||||
raise OpenSSLObjectError(f'Unknown key usage "{usage}"')
|
||||
|
||||
|
||||
def cryptography_parse_key_usage_params(usages):
|
||||
@@ -685,9 +651,7 @@ def cryptography_get_basic_constraints(constraints):
|
||||
ca = False
|
||||
else:
|
||||
raise OpenSSLObjectError(
|
||||
'Unknown basic constraint value "{0}" for CA'.format(
|
||||
constraint[3:]
|
||||
)
|
||||
f'Unknown basic constraint value "{constraint[3:]}" for CA'
|
||||
)
|
||||
elif constraint.startswith("pathlen:"):
|
||||
v = constraint[len("pathlen:") :]
|
||||
@@ -695,12 +659,10 @@ def cryptography_get_basic_constraints(constraints):
|
||||
path_length = int(v)
|
||||
except Exception as e:
|
||||
raise OpenSSLObjectError(
|
||||
'Cannot parse path length constraint "{0}" ({1})'.format(v, e)
|
||||
f'Cannot parse path length constraint "{v}" ({e})'
|
||||
)
|
||||
else:
|
||||
raise OpenSSLObjectError(
|
||||
'Unknown basic constraint "{0}"'.format(constraint)
|
||||
)
|
||||
raise OpenSSLObjectError(f'Unknown basic constraint "{constraint}"')
|
||||
return ca, path_length
|
||||
|
||||
|
||||
@@ -958,7 +920,7 @@ def cryptography_verify_signature(signature, data, hash_algorithm, signer_public
|
||||
signer_public_key.verify(signature, data)
|
||||
return True
|
||||
raise OpenSSLObjectError(
|
||||
"Unsupported public key type {0}".format(type(signer_public_key))
|
||||
f"Unsupported public key type {type(signer_public_key)}"
|
||||
)
|
||||
except InvalidSignature:
|
||||
return False
|
||||
|
||||
@@ -162,9 +162,9 @@ else:
|
||||
def _convert_int_to_bytes(count, n):
|
||||
if n == 0 and count == 0:
|
||||
return ""
|
||||
h = "%x" % n
|
||||
h = f"{n:x}"
|
||||
if len(h) > 2 * count:
|
||||
raise Exception("Number {1} needs more than {0} bytes!".format(count, n))
|
||||
raise Exception(f"Number {n} needs more than {count} bytes!")
|
||||
return ("0" * (2 * count - len(h)) + h).decode("hex")
|
||||
|
||||
def _convert_bytes_to_int(data):
|
||||
@@ -174,7 +174,7 @@ else:
|
||||
return v
|
||||
|
||||
def _to_hex(no):
|
||||
return "%x" % no
|
||||
return f"{no:x}"
|
||||
|
||||
|
||||
def convert_int_to_bytes(no, count=None):
|
||||
|
||||
@@ -363,16 +363,14 @@ def select_backend(module, backend, provider):
|
||||
# Fail if no backend has been found
|
||||
if backend == "auto":
|
||||
module.fail_json(
|
||||
msg=(
|
||||
"Cannot detect the required Python library " "cryptography (>= {0})"
|
||||
).format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
msg=f"Cannot detect the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})"
|
||||
)
|
||||
|
||||
if backend == "cryptography":
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"
|
||||
),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
|
||||
@@ -31,17 +31,17 @@ class AcmeCertificateBackend(CertificateBackend):
|
||||
)
|
||||
if self.csr_content is None and not os.path.exists(self.csr_path):
|
||||
raise CertificateError(
|
||||
"The certificate signing request file %s does not exist" % self.csr_path
|
||||
f"The certificate signing request file {self.csr_path} does not exist"
|
||||
)
|
||||
|
||||
if not os.path.exists(self.accountkey_path):
|
||||
raise CertificateError(
|
||||
"The account key %s does not exist" % self.accountkey_path
|
||||
f"The account key {self.accountkey_path} does not exist"
|
||||
)
|
||||
|
||||
if not os.path.exists(self.challenge_path):
|
||||
raise CertificateError(
|
||||
"The challenge path %s does not exist" % self.challenge_path
|
||||
f"The challenge path {self.challenge_path} does not exist"
|
||||
)
|
||||
|
||||
self.acme_tiny_path = self.module.get_bin_path("acme-tiny", required=True)
|
||||
@@ -66,7 +66,7 @@ class AcmeCertificateBackend(CertificateBackend):
|
||||
except Exception:
|
||||
pass
|
||||
self.module.fail_json(
|
||||
msg="failed to create temporary CSR file: %s" % to_native(err),
|
||||
msg=f"failed to create temporary CSR file: {to_native(err)}",
|
||||
exception=traceback.format_exc(),
|
||||
)
|
||||
f.close()
|
||||
|
||||
@@ -56,9 +56,7 @@ class EntrustCertificateBackend(CertificateBackend):
|
||||
)
|
||||
if self.csr_content is None and not os.path.exists(self.csr_path):
|
||||
raise CertificateError(
|
||||
"The certificate signing request file {0} does not exist".format(
|
||||
self.csr_path
|
||||
)
|
||||
f"The certificate signing request file {self.csr_path} does not exist"
|
||||
)
|
||||
|
||||
self._ensure_csr_loaded()
|
||||
@@ -77,7 +75,7 @@ class EntrustCertificateBackend(CertificateBackend):
|
||||
self.module.fail_json(
|
||||
msg=(
|
||||
"Entrust provider does not currently support multiple validated organizations. Multiple organizations found in "
|
||||
"Subject DN: '{0}'. ".format(self.csr.subject)
|
||||
f"Subject DN: '{self.csr.subject}'. "
|
||||
)
|
||||
)
|
||||
# If no organization in the CSR, explicitly tell ECS that it should be blank in issued cert, not defaulted to
|
||||
@@ -98,11 +96,7 @@ class EntrustCertificateBackend(CertificateBackend):
|
||||
],
|
||||
)
|
||||
except SessionConfigurationException as e:
|
||||
module.fail_json(
|
||||
msg="Failed to initialize Entrust Provider: {0}".format(
|
||||
to_native(e.message)
|
||||
)
|
||||
)
|
||||
module.fail_json(msg=f"Failed to initialize Entrust Provider: {e.message}")
|
||||
|
||||
def generate_certificate(self):
|
||||
"""(Re-)Generate certificate."""
|
||||
@@ -138,9 +132,7 @@ class EntrustCertificateBackend(CertificateBackend):
|
||||
self.trackingId = result.get("trackingId")
|
||||
except RestOperationException as e:
|
||||
self.module.fail_json(
|
||||
msg="Failed to request new certificate from Entrust Certificate Services (ECS): {0}".format(
|
||||
to_native(e.message)
|
||||
)
|
||||
msg=f"Failed to request new certificate from Entrust Certificate Services (ECS): {e.message}"
|
||||
)
|
||||
|
||||
self.cert_bytes = to_bytes(result.get("endEntityCert"))
|
||||
@@ -159,9 +151,7 @@ class EntrustCertificateBackend(CertificateBackend):
|
||||
cert_details = self._get_cert_details()
|
||||
except RestOperationException as e:
|
||||
self.module.fail_json(
|
||||
msg="Failed to get status of existing certificate from Entrust Certificate Services (ECS): {0}.".format(
|
||||
to_native(e.message)
|
||||
)
|
||||
msg=f"Failed to get status of existing certificate from Entrust Certificate Services (ECS): {e.message}."
|
||||
)
|
||||
|
||||
# Always issue a new certificate if the certificate is expired, suspended or revoked
|
||||
@@ -189,8 +179,8 @@ class EntrustCertificateBackend(CertificateBackend):
|
||||
serial_number = None
|
||||
expiry = None
|
||||
if self.backend == "cryptography":
|
||||
serial_number = "{0:X}".format(
|
||||
cryptography_serial_number_of_cert(self.existing_certificate)
|
||||
serial_number = (
|
||||
f"{cryptography_serial_number_of_cert(self.existing_certificate):X}"
|
||||
)
|
||||
expiry = get_not_valid_after(self.existing_certificate)
|
||||
|
||||
|
||||
@@ -332,11 +332,9 @@ class CertificateInfoRetrievalCryptography(CertificateInfoRetrieval):
|
||||
x509.BasicConstraints
|
||||
)
|
||||
result = []
|
||||
result.append(
|
||||
"CA:{0}".format("TRUE" if ext_keyusage_ext.value.ca else "FALSE")
|
||||
)
|
||||
result.append(f"CA:{'TRUE' if ext_keyusage_ext.value.ca else 'FALSE'}")
|
||||
if ext_keyusage_ext.value.path_length is not None:
|
||||
result.append("pathlen:{0}".format(ext_keyusage_ext.value.path_length))
|
||||
result.append(f"pathlen:{ext_keyusage_ext.value.path_length}")
|
||||
return sorted(result), ext_keyusage_ext.critical
|
||||
except cryptography.x509.ExtensionNotFound:
|
||||
return None, False
|
||||
@@ -474,20 +472,17 @@ def select_backend(module, backend, content):
|
||||
# Success?
|
||||
if backend == "auto":
|
||||
module.fail_json(
|
||||
msg=(
|
||||
"Cannot detect any of the required Python libraries "
|
||||
"cryptography (>= {0})"
|
||||
).format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
msg=f"Cannot detect any of the required Python libraries cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})"
|
||||
)
|
||||
|
||||
if backend == "cryptography":
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"
|
||||
),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
return backend, CertificateInfoRetrievalCryptography(module, content)
|
||||
else:
|
||||
raise ValueError("Unsupported value for backend: {0}".format(backend))
|
||||
raise ValueError(f"Unsupported value for backend: {backend}")
|
||||
|
||||
@@ -93,21 +93,17 @@ class OwnCACertificateBackendCryptography(CertificateBackend):
|
||||
)
|
||||
if self.csr_content is None and not os.path.exists(self.csr_path):
|
||||
raise CertificateError(
|
||||
"The certificate signing request file {0} does not exist".format(
|
||||
self.csr_path
|
||||
)
|
||||
f"The certificate signing request file {self.csr_path} does not exist"
|
||||
)
|
||||
if self.ca_cert_content is None and not os.path.exists(self.ca_cert_path):
|
||||
raise CertificateError(
|
||||
"The CA certificate file {0} does not exist".format(self.ca_cert_path)
|
||||
f"The CA certificate file {self.ca_cert_path} does not exist"
|
||||
)
|
||||
if self.ca_privatekey_content is None and not os.path.exists(
|
||||
self.ca_privatekey_path
|
||||
):
|
||||
raise CertificateError(
|
||||
"The CA private key file {0} does not exist".format(
|
||||
self.ca_privatekey_path
|
||||
)
|
||||
f"The CA private key file {self.ca_privatekey_path} does not exist"
|
||||
)
|
||||
|
||||
self._ensure_csr_loaded()
|
||||
@@ -134,8 +130,7 @@ class OwnCACertificateBackendCryptography(CertificateBackend):
|
||||
if cryptography_key_needs_digest_for_signing(self.ca_private_key):
|
||||
if self.digest is None:
|
||||
raise CertificateError(
|
||||
"The digest %s is not supported with the cryptography backend"
|
||||
% module.params["ownca_digest"]
|
||||
f"The digest {module.params['ownca_digest']} is not supported with the cryptography backend"
|
||||
)
|
||||
else:
|
||||
self.digest = None
|
||||
|
||||
@@ -67,13 +67,11 @@ class SelfSignedCertificateBackendCryptography(CertificateBackend):
|
||||
|
||||
if self.csr_path is not None and not os.path.exists(self.csr_path):
|
||||
raise CertificateError(
|
||||
"The certificate signing request file {0} does not exist".format(
|
||||
self.csr_path
|
||||
)
|
||||
f"The certificate signing request file {self.csr_path} does not exist"
|
||||
)
|
||||
if self.privatekey_content is None and not os.path.exists(self.privatekey_path):
|
||||
raise CertificateError(
|
||||
"The private key file {0} does not exist".format(self.privatekey_path)
|
||||
f"The private key file {self.privatekey_path} does not exist"
|
||||
)
|
||||
|
||||
self._module = module
|
||||
@@ -90,9 +88,7 @@ class SelfSignedCertificateBackendCryptography(CertificateBackend):
|
||||
digest = self.digest
|
||||
if digest is None:
|
||||
self.module.fail_json(
|
||||
msg='Unsupported digest "{0}"'.format(
|
||||
module.params["selfsigned_digest"]
|
||||
)
|
||||
msg=f'Unsupported digest "{module.params["selfsigned_digest"]}"'
|
||||
)
|
||||
try:
|
||||
self.csr = csr.sign(self.privatekey, digest, default_backend())
|
||||
@@ -109,8 +105,7 @@ class SelfSignedCertificateBackendCryptography(CertificateBackend):
|
||||
if cryptography_key_needs_digest_for_signing(self.privatekey):
|
||||
if self.digest is None:
|
||||
raise CertificateError(
|
||||
"The digest %s is not supported with the cryptography backend"
|
||||
% module.params["selfsigned_digest"]
|
||||
f"The digest {module.params['selfsigned_digest']} is not supported with the cryptography backend"
|
||||
)
|
||||
else:
|
||||
self.digest = None
|
||||
|
||||
@@ -58,7 +58,7 @@ class CRLInfoRetrieval:
|
||||
else:
|
||||
self.crl = x509.load_der_x509_crl(self.content, default_backend())
|
||||
except ValueError as e:
|
||||
self.module.fail_json(msg="Error while decoding CRL: {0}".format(e))
|
||||
self.module.fail_json(msg=f"Error while decoding CRL: {e}")
|
||||
|
||||
result = {
|
||||
"changed": False,
|
||||
@@ -96,9 +96,7 @@ class CRLInfoRetrieval:
|
||||
def get_crl_info(module, content, list_revoked_certificates=True):
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
),
|
||||
msg=missing_required_lib(f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ class CertificateSigningRequestBackend:
|
||||
if not self.subjectAltName and module.params["use_common_name_for_san"]:
|
||||
for sub in self.subject:
|
||||
if sub[0] in ("commonName", "CN"):
|
||||
self.subjectAltName = ["DNS:%s" % sub[1]]
|
||||
self.subjectAltName = [f"DNS:{sub[1]}"]
|
||||
self.using_common_name_for_san = True
|
||||
break
|
||||
|
||||
@@ -174,7 +174,7 @@ class CertificateSigningRequestBackend:
|
||||
)
|
||||
except Exception as e:
|
||||
raise CertificateSigningRequestError(
|
||||
"Cannot parse subject_key_identifier: {0}".format(e)
|
||||
f"Cannot parse subject_key_identifier: {e}"
|
||||
)
|
||||
|
||||
if self.authority_key_identifier is not None:
|
||||
@@ -184,7 +184,7 @@ class CertificateSigningRequestBackend:
|
||||
)
|
||||
except Exception as e:
|
||||
raise CertificateSigningRequestError(
|
||||
"Cannot parse authority_key_identifier: {0}".format(e)
|
||||
f"Cannot parse authority_key_identifier: {e}"
|
||||
)
|
||||
|
||||
self.existing_csr = None
|
||||
@@ -337,9 +337,7 @@ def parse_crl_distribution_points(module, crl_distribution_points):
|
||||
result.append(cryptography.x509.DistributionPoint(**params))
|
||||
except (OpenSSLObjectError, ValueError) as e:
|
||||
raise OpenSSLObjectError(
|
||||
"Error while parsing CRL distribution point #{index}: {error}".format(
|
||||
index=index, error=e
|
||||
)
|
||||
f"Error while parsing CRL distribution point #{index}: {e}"
|
||||
)
|
||||
return result
|
||||
|
||||
@@ -446,9 +444,7 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
|
||||
critical=self.name_constraints_critical,
|
||||
)
|
||||
except TypeError as e:
|
||||
raise OpenSSLObjectError(
|
||||
"Error while parsing name constraint: {0}".format(e)
|
||||
)
|
||||
raise OpenSSLObjectError(f"Error while parsing name constraint: {e}")
|
||||
|
||||
if self.create_subject_key_identifier:
|
||||
csr = csr.add_extension(
|
||||
@@ -494,7 +490,7 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
|
||||
digest = select_message_digest(self.digest)
|
||||
if digest is None:
|
||||
raise CertificateSigningRequestError(
|
||||
'Unsupported digest "{0}"'.format(self.digest)
|
||||
f'Unsupported digest "{self.digest}"'
|
||||
)
|
||||
try:
|
||||
self.csr = csr.sign(self.privatekey, digest, self.cryptography_backend)
|
||||
@@ -518,7 +514,7 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
|
||||
# https://github.com/kjd/idna/commit/ebefacd3134d0f5da4745878620a6a1cba86d130
|
||||
# and then
|
||||
# https://github.com/kjd/idna/commit/ea03c7b5db7d2a99af082e0239da2b68aeea702a).
|
||||
msg = "Error while creating CSR: {0}\n".format(e)
|
||||
msg = f"Error while creating CSR: {e}\n"
|
||||
if self.using_common_name_for_san:
|
||||
self.module.fail_json(
|
||||
msg=msg
|
||||
@@ -813,23 +809,20 @@ def select_backend(module, backend):
|
||||
# Success?
|
||||
if backend == "auto":
|
||||
module.fail_json(
|
||||
msg=(
|
||||
"Cannot detect any of the required Python libraries "
|
||||
"cryptography (>= {0})"
|
||||
).format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
msg=f"Cannot detect any of the required Python libraries cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})"
|
||||
)
|
||||
|
||||
if backend == "cryptography":
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"
|
||||
),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
return backend, CertificateSigningRequestCryptographyBackend(module)
|
||||
else:
|
||||
raise Exception("Unsupported value for backend: {0}".format(backend))
|
||||
raise Exception(f"Unsupported value for backend: {backend}")
|
||||
|
||||
|
||||
def get_csr_argument_spec():
|
||||
|
||||
@@ -258,9 +258,9 @@ class CSRInfoRetrievalCryptography(CSRInfoRetrieval):
|
||||
ext_keyusage_ext = self.csr.extensions.get_extension_for_class(
|
||||
x509.BasicConstraints
|
||||
)
|
||||
result = ["CA:{0}".format("TRUE" if ext_keyusage_ext.value.ca else "FALSE")]
|
||||
result = [f"CA:{'TRUE' if ext_keyusage_ext.value.ca else 'FALSE'}"]
|
||||
if ext_keyusage_ext.value.path_length is not None:
|
||||
result.append("pathlen:{0}".format(ext_keyusage_ext.value.path_length))
|
||||
result.append(f"pathlen:{ext_keyusage_ext.value.path_length}")
|
||||
return sorted(result), ext_keyusage_ext.critical
|
||||
except cryptography.x509.ExtensionNotFound:
|
||||
return None, False
|
||||
@@ -380,16 +380,14 @@ def select_backend(module, backend, content, validate_signature=True):
|
||||
# Success?
|
||||
if backend == "auto":
|
||||
module.fail_json(
|
||||
msg=(
|
||||
"Cannot detect the required Python library " "cryptography (>= {0})"
|
||||
).format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
msg=f"Cannot detect the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})"
|
||||
)
|
||||
|
||||
if backend == "cryptography":
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"
|
||||
),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
@@ -397,4 +395,4 @@ def select_backend(module, backend, content, validate_signature=True):
|
||||
module, content, validate_signature=validate_signature
|
||||
)
|
||||
else:
|
||||
raise ValueError("Unsupported value for backend: {0}".format(backend))
|
||||
raise ValueError(f"Unsupported value for backend: {backend}")
|
||||
|
||||
@@ -273,7 +273,7 @@ class PrivateKeyCryptographyBackend(PrivateKeyBackend):
|
||||
ecclass = cryptography.hazmat.primitives.asymmetric.ec.__dict__.get(ectype)
|
||||
if ecclass is None:
|
||||
self.module.fail_json(
|
||||
msg="Your cryptography version does not support {0}".format(ectype)
|
||||
msg=f"Your cryptography version does not support {ectype}"
|
||||
)
|
||||
return ecclass
|
||||
|
||||
@@ -385,9 +385,7 @@ class PrivateKeyCryptographyBackend(PrivateKeyBackend):
|
||||
if self.type == "ECC" and self.curve in self.curves:
|
||||
if self.curves[self.curve]["deprecated"]:
|
||||
self.module.warn(
|
||||
"Elliptic curves of type {0} should not be used for new keys!".format(
|
||||
self.curve
|
||||
)
|
||||
f"Elliptic curves of type {self.curve} should not be used for new keys!"
|
||||
)
|
||||
self.private_key = (
|
||||
cryptography.hazmat.primitives.asymmetric.ec.generate_private_key(
|
||||
@@ -397,9 +395,7 @@ class PrivateKeyCryptographyBackend(PrivateKeyBackend):
|
||||
)
|
||||
except cryptography.exceptions.UnsupportedAlgorithm:
|
||||
self.module.fail_json(
|
||||
msg="Cryptography backend does not support the algorithm required for {0}".format(
|
||||
self.type
|
||||
)
|
||||
msg=f"Cryptography backend does not support the algorithm required for {self.type}"
|
||||
)
|
||||
|
||||
def get_private_key_data(self):
|
||||
@@ -426,9 +422,7 @@ class PrivateKeyCryptographyBackend(PrivateKeyBackend):
|
||||
)
|
||||
except AttributeError:
|
||||
self.module.fail_json(
|
||||
msg='Cryptography backend does not support the selected output format "{0}"'.format(
|
||||
self.format
|
||||
)
|
||||
msg=f'Cryptography backend does not support the selected output format "{self.format}"'
|
||||
)
|
||||
|
||||
# Select key encryption
|
||||
@@ -454,15 +448,11 @@ class PrivateKeyCryptographyBackend(PrivateKeyBackend):
|
||||
)
|
||||
except ValueError:
|
||||
self.module.fail_json(
|
||||
msg='Cryptography backend cannot serialize the private key in the required format "{0}"'.format(
|
||||
self.format
|
||||
)
|
||||
msg=f'Cryptography backend cannot serialize the private key in the required format "{self.format}"'
|
||||
)
|
||||
except Exception:
|
||||
self.module.fail_json(
|
||||
msg='Error while serializing the private key in the required format "{0}"'.format(
|
||||
self.format
|
||||
),
|
||||
msg=f'Error while serializing the private key in the required format "{self.format}"',
|
||||
exception=traceback.format_exc(),
|
||||
)
|
||||
|
||||
@@ -611,21 +601,19 @@ def select_backend(module, backend):
|
||||
# Success?
|
||||
if backend == "auto":
|
||||
module.fail_json(
|
||||
msg=(
|
||||
"Cannot detect the required Python library " "cryptography (>= {0})"
|
||||
).format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
msg=f"Cannot detect the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})"
|
||||
)
|
||||
if backend == "cryptography":
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"
|
||||
),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
return backend, PrivateKeyCryptographyBackend(module)
|
||||
else:
|
||||
raise Exception("Unsupported value for backend: {0}".format(backend))
|
||||
raise Exception(f"Unsupported value for backend: {backend}")
|
||||
|
||||
|
||||
def get_privatekey_argument_spec():
|
||||
|
||||
@@ -161,9 +161,7 @@ class PrivateKeyConvertCryptographyBackend(PrivateKeyConvertBackend):
|
||||
)
|
||||
except AttributeError:
|
||||
self.module.fail_json(
|
||||
msg='Cryptography backend does not support the selected output format "{0}"'.format(
|
||||
self.format
|
||||
)
|
||||
msg=f'Cryptography backend does not support the selected output format "{self.format}"'
|
||||
)
|
||||
|
||||
# Select key encryption
|
||||
@@ -186,15 +184,11 @@ class PrivateKeyConvertCryptographyBackend(PrivateKeyConvertBackend):
|
||||
)
|
||||
except ValueError:
|
||||
self.module.fail_json(
|
||||
msg='Cryptography backend cannot serialize the private key in the required format "{0}"'.format(
|
||||
self.format
|
||||
)
|
||||
msg=f'Cryptography backend cannot serialize the private key in the required format "{self.format}"'
|
||||
)
|
||||
except Exception:
|
||||
self.module.fail_json(
|
||||
msg='Error while serializing the private key in the required format "{0}"'.format(
|
||||
self.format
|
||||
),
|
||||
msg=f'Error while serializing the private key in the required format "{self.format}"',
|
||||
exception=traceback.format_exc(),
|
||||
)
|
||||
|
||||
@@ -285,9 +279,7 @@ class PrivateKeyConvertCryptographyBackend(PrivateKeyConvertBackend):
|
||||
def select_backend(module):
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
),
|
||||
msg=missing_required_lib(f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
return PrivateKeyConvertCryptographyBackend(module)
|
||||
|
||||
@@ -173,7 +173,7 @@ def _is_cryptography_key_consistent(
|
||||
return False
|
||||
# For X25519 and X448, there's no test yet.
|
||||
if warn_func is not None:
|
||||
warn_func("Cannot determine consistency for key of type %s" % type(key))
|
||||
warn_func(f"Cannot determine consistency for key of type {type(key)}")
|
||||
return None
|
||||
|
||||
|
||||
@@ -338,16 +338,14 @@ def select_backend(
|
||||
# Success?
|
||||
if backend == "auto":
|
||||
module.fail_json(
|
||||
msg=(
|
||||
"Cannot detect the required Python library " "cryptography (>= {0})"
|
||||
).format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
msg=f"Cannot detect the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})"
|
||||
)
|
||||
|
||||
if backend == "cryptography":
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"
|
||||
),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
@@ -359,4 +357,4 @@ def select_backend(
|
||||
check_consistency=check_consistency,
|
||||
)
|
||||
else:
|
||||
raise ValueError("Unsupported value for backend: {0}".format(backend))
|
||||
raise ValueError(f"Unsupported value for backend: {backend}")
|
||||
|
||||
@@ -84,7 +84,7 @@ def _get_cryptography_public_key_info(key):
|
||||
key_public_data["y"] = public_numbers.y
|
||||
key_public_data["exponent_size"] = key.curve.key_size
|
||||
else:
|
||||
key_type = "unknown ({0})".format(type(key))
|
||||
key_type = f"unknown ({type(key)})"
|
||||
return key_type, key_public_data
|
||||
|
||||
|
||||
@@ -174,17 +174,14 @@ def select_backend(module, backend, content=None, key=None):
|
||||
# Success?
|
||||
if backend == "auto":
|
||||
module.fail_json(
|
||||
msg=(
|
||||
"Cannot detect any of the required Python libraries "
|
||||
"cryptography (>= {0})"
|
||||
).format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
msg=f"Cannot detect any of the required Python libraries cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})"
|
||||
)
|
||||
|
||||
if backend == "cryptography":
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"
|
||||
),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
@@ -192,4 +189,4 @@ def select_backend(module, backend, content=None, key=None):
|
||||
module, content=content, key=key
|
||||
)
|
||||
else:
|
||||
raise ValueError("Unsupported value for backend: {0}".format(backend))
|
||||
raise ValueError(f"Unsupported value for backend: {backend}")
|
||||
|
||||
@@ -98,36 +98,24 @@ def _extract_type(line, start=PEM_START):
|
||||
def extract_pem(content, strict=False):
|
||||
lines = content.splitlines()
|
||||
if len(lines) < 3:
|
||||
raise ValueError(
|
||||
"PEM must have at least 3 lines, have only {count}".format(count=len(lines))
|
||||
)
|
||||
raise ValueError(f"PEM must have at least 3 lines, have only {len(lines)}")
|
||||
header_type = _extract_type(lines[0])
|
||||
if header_type is None:
|
||||
raise ValueError(
|
||||
"First line is not of format {start}...{end}: {line!r}".format(
|
||||
start=PEM_START, end=PEM_END, line=lines[0]
|
||||
)
|
||||
f"First line is not of format {PEM_START}...{PEM_END}: {lines[0]!r}"
|
||||
)
|
||||
footer_type = _extract_type(lines[-1], start=PEM_END_START)
|
||||
if strict:
|
||||
if header_type != footer_type:
|
||||
raise ValueError(
|
||||
"Header type ({header}) is different from footer type ({footer})".format(
|
||||
header=header_type, footer=footer_type
|
||||
)
|
||||
f"Header type ({header_type}) is different from footer type ({footer_type})"
|
||||
)
|
||||
for idx, line in enumerate(lines[1:-2]):
|
||||
if len(line) != 64:
|
||||
raise ValueError(
|
||||
"Line {idx} has length {len} instead of 64".format(
|
||||
idx=idx, len=len(line)
|
||||
)
|
||||
)
|
||||
raise ValueError(f"Line {idx} has length {len(line)} instead of 64")
|
||||
if not (0 < len(lines[-2]) <= 64):
|
||||
raise ValueError(
|
||||
"Last line has length {len}, should be in (0, 64]".format(
|
||||
len=len(lines[-2])
|
||||
)
|
||||
f"Last line has length {len(lines[-2])}, should be in (0, 64]"
|
||||
)
|
||||
content = lines[1:-1]
|
||||
return header_type, "".join(content)
|
||||
|
||||
@@ -179,7 +179,7 @@ def load_publickey(path=None, content=None, backend=None):
|
||||
content, backend=cryptography_backend()
|
||||
)
|
||||
except Exception as e:
|
||||
raise OpenSSLObjectError("Error while deserializing key: {0}".format(e))
|
||||
raise OpenSSLObjectError(f"Error while deserializing key: {e}")
|
||||
|
||||
|
||||
def load_certificate(
|
||||
@@ -209,9 +209,7 @@ def load_certificate(
|
||||
cert_content, cryptography_backend()
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise OpenSSLObjectError(
|
||||
"Cannot parse DER certificate: {0}".format(exc)
|
||||
)
|
||||
raise OpenSSLObjectError(f"Cannot parse DER certificate: {exc}")
|
||||
|
||||
|
||||
def load_certificate_request(path, content=None, backend="cryptography"):
|
||||
@@ -241,31 +239,30 @@ def parse_name_field(input_dict, name_field_name=None):
|
||||
for entry in value:
|
||||
if not isinstance(entry, six.string_types):
|
||||
raise TypeError(
|
||||
("Values %s must be strings" % error_str).format(
|
||||
f"Values {error_str} must be strings".format(
|
||||
key=key, name=name_field_name
|
||||
)
|
||||
)
|
||||
if not entry:
|
||||
raise ValueError(
|
||||
("Values for %s must not be empty strings" % error_str).format(
|
||||
key=key
|
||||
f"Values for {error_str} must not be empty strings".format(
|
||||
key=key, name=name_field_name
|
||||
)
|
||||
)
|
||||
result.append((key, entry))
|
||||
elif isinstance(value, six.string_types):
|
||||
if not value:
|
||||
raise ValueError(
|
||||
("Value for %s must not be an empty string" % error_str).format(
|
||||
key=key
|
||||
f"Value for {error_str} must not be an empty string".format(
|
||||
key=key, name=name_field_name
|
||||
)
|
||||
)
|
||||
result.append((key, value))
|
||||
else:
|
||||
raise TypeError(
|
||||
(
|
||||
"Value for %s must be either a string or a list of strings"
|
||||
% error_str
|
||||
).format(key=key)
|
||||
f"Value for {error_str} must be either a string or a list of strings"
|
||||
).format(key=key, name=name_field_name)
|
||||
)
|
||||
return result
|
||||
|
||||
@@ -277,17 +274,13 @@ def parse_ordered_name_field(input_list, name_field_name):
|
||||
for index, entry in enumerate(input_list):
|
||||
if len(entry) != 1:
|
||||
raise ValueError(
|
||||
"Entry #{index} in {name} must be a dictionary with exactly one key-value pair".format(
|
||||
name=name_field_name, index=index + 1
|
||||
)
|
||||
f"Entry #{index + 1} in {name_field_name} must be a dictionary with exactly one key-value pair"
|
||||
)
|
||||
try:
|
||||
result.extend(parse_name_field(entry, name_field_name=name_field_name))
|
||||
except (TypeError, ValueError) as exc:
|
||||
raise ValueError(
|
||||
"Error while processing entry #{index} in {name}: {error}".format(
|
||||
name=name_field_name, index=index + 1, error=exc
|
||||
)
|
||||
f"Error while processing entry #{index + 1} in {name_field_name}: {exc}"
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
@@ -73,12 +73,8 @@ def generate_docstring(operation_spec):
|
||||
if len(parameters) != 0:
|
||||
docs += "\tArguments:\n\n"
|
||||
for parameter in parameters:
|
||||
docs += "{0} ({1}:{2}): {3}\n".format(
|
||||
parameter.get("name"),
|
||||
parameter.get("type", "No Type"),
|
||||
"Required" if parameter.get("required", False) else "Not Required",
|
||||
parameter.get("description"),
|
||||
)
|
||||
req = "Required" if parameter.get("required", False) else "Not Required"
|
||||
docs += f"{parameter.get('name')} ({parameter.get('type', 'No Type')}:{req}): {parameter.get('description')}\n"
|
||||
|
||||
return docs
|
||||
|
||||
@@ -104,11 +100,8 @@ class RestOperation:
|
||||
self.parameters = {}
|
||||
else:
|
||||
self.parameters = parameters
|
||||
self.url = "{scheme}://{host}{base_path}{uri}".format(
|
||||
scheme="https",
|
||||
host=session._spec.get("host"),
|
||||
base_path=session._spec.get("basePath"),
|
||||
uri=uri,
|
||||
self.url = (
|
||||
f"https://{session._spec.get('host')}{session._spec.get('basePath')}{uri}"
|
||||
)
|
||||
|
||||
def restmethod(self, *args, **kwargs):
|
||||
@@ -204,7 +197,7 @@ class Resource:
|
||||
operation_name = "Patch"
|
||||
else:
|
||||
raise SessionConfigurationException(
|
||||
to_native("Invalid REST method type {0}".format(method))
|
||||
to_native(f"Invalid REST method type {method}")
|
||||
)
|
||||
|
||||
# Get the non-parameter parts of the URL and append to the operation name
|
||||
@@ -286,9 +279,7 @@ class ECSSession:
|
||||
):
|
||||
raise SessionConfigurationException(
|
||||
to_native(
|
||||
"OpenAPI specification was not found at location {0}.".format(
|
||||
entrust_api_specification_path
|
||||
)
|
||||
f"OpenAPI specification was not found at location {entrust_api_specification_path}."
|
||||
)
|
||||
)
|
||||
if not valid_file_format.match(entrust_api_specification_path):
|
||||
@@ -315,9 +306,7 @@ class ECSSession:
|
||||
except HTTPError as e:
|
||||
raise SessionConfigurationException(
|
||||
to_native(
|
||||
"Error downloading specification from address '{0}', received error code '{1}'".format(
|
||||
entrust_api_specification_path, e.getcode()
|
||||
)
|
||||
f"Error downloading specification from address '{entrust_api_specification_path}', received error code '{e.getcode()}'"
|
||||
)
|
||||
)
|
||||
else:
|
||||
@@ -344,9 +333,8 @@ class ECSSession:
|
||||
):
|
||||
raise SessionConfigurationException(
|
||||
to_native(
|
||||
"Parameter provided for entrust_api_specification_path of value '{0}' was not a valid file path or HTTPS address.".format(
|
||||
entrust_api_specification_path
|
||||
)
|
||||
f"Parameter provided for entrust_api_specification_path of value '{entrust_api_specification_path}'"
|
||||
" was not a valid file path or HTTPS address."
|
||||
)
|
||||
)
|
||||
|
||||
@@ -355,18 +343,14 @@ class ECSSession:
|
||||
if not file_path or not os.path.isfile(file_path):
|
||||
raise SessionConfigurationException(
|
||||
to_native(
|
||||
"Parameter provided for {0} of value '{1}' was not a valid file path.".format(
|
||||
required_file, file_path
|
||||
)
|
||||
f"Parameter provided for {required_file} of value '{file_path}' was not a valid file path."
|
||||
)
|
||||
)
|
||||
|
||||
for required_var in ["entrust_api_user", "entrust_api_key"]:
|
||||
if not kwargs.get(required_var):
|
||||
raise SessionConfigurationException(
|
||||
to_native(
|
||||
"Parameter provided for {0} was missing.".format(required_var)
|
||||
)
|
||||
to_native(f"Parameter provided for {required_var} was missing.")
|
||||
)
|
||||
|
||||
config["entrust_api_cert"] = kwargs.get("entrust_api_cert")
|
||||
|
||||
@@ -39,19 +39,15 @@ def get_fingerprint_from_stdout(stdout):
|
||||
parts = line.split(":")
|
||||
if len(parts) <= 9 or not parts[9]:
|
||||
raise GPGError(
|
||||
'Result line "{line}" does not have fingerprint as 10th component'.format(
|
||||
line=line
|
||||
)
|
||||
f'Result line "{line}" does not have fingerprint as 10th component'
|
||||
)
|
||||
return parts[9]
|
||||
raise GPGError(
|
||||
'Cannot extract fingerprint from stdout "{stdout}"'.format(stdout=stdout)
|
||||
)
|
||||
raise GPGError(f'Cannot extract fingerprint from stdout "{stdout}"')
|
||||
|
||||
|
||||
def get_fingerprint_from_file(gpg_runner, path):
|
||||
if not os.path.exists(path):
|
||||
raise GPGError("{path} does not exist".format(path=path))
|
||||
raise GPGError(f"{path} does not exist")
|
||||
stdout = gpg_runner.run_command(
|
||||
[
|
||||
"--no-keyring",
|
||||
|
||||
@@ -19,7 +19,7 @@ def load_file(path, module=None):
|
||||
except Exception as exc:
|
||||
if module is None:
|
||||
raise
|
||||
module.fail_json("Error while loading {0} - {1}".format(path, str(exc)))
|
||||
module.fail_json(f"Error while loading {path} - {exc}")
|
||||
|
||||
|
||||
def load_file_if_exists(path, module=None, ignore_errors=False):
|
||||
@@ -40,13 +40,13 @@ def load_file_if_exists(path, module=None, ignore_errors=False):
|
||||
return None
|
||||
if module is None:
|
||||
raise
|
||||
module.fail_json("Error while loading {0} - {1}".format(path, str(exc)))
|
||||
module.fail_json(f"Error while loading {path} - {exc}")
|
||||
except Exception as exc:
|
||||
if ignore_errors:
|
||||
return None
|
||||
if module is None:
|
||||
raise
|
||||
module.fail_json("Error while loading {0} - {1}".format(path, str(exc)))
|
||||
module.fail_json(f"Error while loading {path} - {exc}")
|
||||
|
||||
|
||||
def write_file(module, content, default_mode=None, path=None):
|
||||
@@ -83,9 +83,7 @@ def write_file(module, content, default_mode=None, path=None):
|
||||
os.remove(tmp_name)
|
||||
except Exception:
|
||||
pass
|
||||
module.fail_json(
|
||||
msg="Error while writing result into temporary file: {0}".format(e)
|
||||
)
|
||||
module.fail_json(msg=f"Error while writing result into temporary file: {e}")
|
||||
# Update destination to wanted permissions
|
||||
if os.path.exists(file_args["path"]):
|
||||
module.set_fs_attributes_if_different(file_args, False)
|
||||
@@ -101,4 +99,4 @@ def write_file(module, content, default_mode=None, path=None):
|
||||
os.remove(tmp_name)
|
||||
except Exception:
|
||||
pass
|
||||
module.fail_json(msg="Error while writing result: {0}".format(e))
|
||||
module.fail_json(msg=f"Error while writing result: {e}")
|
||||
|
||||
@@ -73,7 +73,7 @@ class OpensshModule:
|
||||
self._execute()
|
||||
except Exception as e:
|
||||
self.module.fail_json(
|
||||
msg="unexpected error occurred: %s" % to_native(e),
|
||||
msg=f"unexpected error occurred: {to_native(e)}",
|
||||
exception=traceback.format_exc(),
|
||||
)
|
||||
|
||||
@@ -125,8 +125,7 @@ class OpensshModule:
|
||||
if not os.path.isdir(base_dir):
|
||||
self.module.fail_json(
|
||||
name=base_dir,
|
||||
msg="The directory %s does not exist or the file is not a directory"
|
||||
% base_dir,
|
||||
msg=f"The directory {base_dir} does not exist or the file is not a directory",
|
||||
)
|
||||
|
||||
def _get_ssh_version(self):
|
||||
@@ -253,8 +252,7 @@ class KeygenCommand:
|
||||
os.chmod(private_key_path, stat.S_IWUSR + stat.S_IRUSR)
|
||||
except (IOError, OSError) as e:
|
||||
raise e(
|
||||
"The private key at %s is not writeable preventing a comment update"
|
||||
% private_key_path
|
||||
f"The private key at {private_key_path} is not writeable preventing a comment update"
|
||||
)
|
||||
|
||||
command = [self._bin_path, "-q"]
|
||||
@@ -332,7 +330,7 @@ class PublicKey:
|
||||
return not self == other
|
||||
|
||||
def __str__(self):
|
||||
return "%s %s" % (self._type_string, self._data)
|
||||
return f"{self._type_string} {self._data}"
|
||||
|
||||
@property
|
||||
def comment(self):
|
||||
|
||||
@@ -90,7 +90,7 @@ class KeypairBackend(OpensshModule):
|
||||
result = 256
|
||||
else:
|
||||
return self.module.fail_json(
|
||||
msg="%s is not a valid value for key type" % self.type
|
||||
msg=f"{self.type} is not a valid value for key type"
|
||||
)
|
||||
|
||||
return result
|
||||
@@ -100,8 +100,7 @@ class KeypairBackend(OpensshModule):
|
||||
|
||||
if os.path.isdir(self.private_key_path):
|
||||
self.module.fail_json(
|
||||
msg="%s is a directory. Please specify a path to a file."
|
||||
% self.private_key_path
|
||||
msg=f"{self.private_key_path} is a directory. Please specify a path to a file."
|
||||
)
|
||||
|
||||
def _execute(self):
|
||||
@@ -562,4 +561,4 @@ def select_backend(module, backend):
|
||||
module.fail_json(msg=missing_required_lib("cryptography >= 2.6"))
|
||||
return backend, KeypairBackendCryptography(module)
|
||||
else:
|
||||
raise ValueError("Unsupported value for backend: {0}".format(backend))
|
||||
raise ValueError(f"Unsupported value for backend: {backend}")
|
||||
|
||||
@@ -110,8 +110,7 @@ class OpensshCertificateTimeParameters:
|
||||
|
||||
if self._valid_from > self._valid_to:
|
||||
raise ValueError(
|
||||
"Valid from: %s must not be greater than Valid to: %s"
|
||||
% (valid_from, valid_to)
|
||||
f"Valid from: {valid_from} must not be greater than Valid to: {valid_to}"
|
||||
)
|
||||
|
||||
def __eq__(self, other):
|
||||
@@ -129,10 +128,7 @@ class OpensshCertificateTimeParameters:
|
||||
@property
|
||||
def validity_string(self):
|
||||
if not (self._valid_from == _ALWAYS and self._valid_to == _FOREVER):
|
||||
return "%s:%s" % (
|
||||
self.valid_from(date_format="openssh"),
|
||||
self.valid_to(date_format="openssh"),
|
||||
)
|
||||
return f"{self.valid_from(date_format='openssh')}:{self.valid_to(date_format='openssh')}"
|
||||
return ""
|
||||
|
||||
def valid_from(self, date_format):
|
||||
@@ -166,7 +162,7 @@ class OpensshCertificateTimeParameters:
|
||||
(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
|
||||
)
|
||||
else:
|
||||
raise ValueError("%s is not a valid format" % date_format)
|
||||
raise ValueError(f"{date_format} is not a valid format")
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
@@ -182,8 +178,7 @@ class OpensshCertificateTimeParameters:
|
||||
)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Value must be of type (str, unicode, int, long) not %s"
|
||||
% type(time_string_or_timestamp)
|
||||
f"Value must be of type (str, unicode, int, long) not {type(time_string_or_timestamp)}"
|
||||
)
|
||||
except ValueError:
|
||||
raise
|
||||
@@ -238,10 +233,10 @@ class OpensshCertificateOption:
|
||||
raise ValueError("type must be either 'critical' or 'extension'")
|
||||
|
||||
if not isinstance(name, six.string_types):
|
||||
raise TypeError("name must be a string not %s" % type(name))
|
||||
raise TypeError(f"name must be a string not {type(name)}")
|
||||
|
||||
if not isinstance(data, six.string_types):
|
||||
raise TypeError("data must be a string not %s" % type(data))
|
||||
raise TypeError(f"data must be a string not {type(data)}")
|
||||
|
||||
self._option_type = option_type
|
||||
self._name = name.lower()
|
||||
@@ -267,7 +262,7 @@ class OpensshCertificateOption:
|
||||
|
||||
def __str__(self):
|
||||
if self._data:
|
||||
return "%s=%s" % (self._name, self._data)
|
||||
return f"{self._name}={self._data}"
|
||||
return self._name
|
||||
|
||||
@property
|
||||
@@ -286,7 +281,7 @@ class OpensshCertificateOption:
|
||||
def from_string(cls, option_string):
|
||||
if not isinstance(option_string, six.string_types):
|
||||
raise ValueError(
|
||||
"option_string must be a string not %s" % type(option_string)
|
||||
f"option_string must be a string not {type(option_string)}"
|
||||
)
|
||||
option_type = None
|
||||
|
||||
@@ -356,7 +351,7 @@ class OpensshCertificateInfo:
|
||||
elif cert_type == "host" or cert_type == _HOST_TYPE:
|
||||
self._cert_type = _HOST_TYPE
|
||||
else:
|
||||
raise ValueError("%s is not a valid certificate type" % cert_type)
|
||||
raise ValueError(f"{cert_type} is not a valid certificate type")
|
||||
|
||||
def signing_key_fingerprint(self):
|
||||
return fingerprint(self.signing_key)
|
||||
@@ -447,8 +442,7 @@ class OpensshECDSACertificateInfo(OpensshCertificateInfo):
|
||||
)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Curve must be one of %s"
|
||||
% (b",".join(list(_ECDSA_CURVE_IDENTIFIERS.values()))).decode("UTF-8")
|
||||
"Curve must be one of {(b','.join(_ECDSA_CURVE_IDENTIFIERS.values())).decode('UTF-8')}"
|
||||
)
|
||||
|
||||
# See https://datatracker.ietf.org/doc/html/rfc4253#section-6.6
|
||||
@@ -500,13 +494,13 @@ class OpensshCertificate:
|
||||
@classmethod
|
||||
def load(cls, path):
|
||||
if not os.path.exists(path):
|
||||
raise ValueError("%s is not a valid path." % path)
|
||||
raise ValueError(f"{path} is not a valid path.")
|
||||
|
||||
try:
|
||||
with open(path, "rb") as cert_file:
|
||||
data = cert_file.read()
|
||||
except (IOError, OSError) as e:
|
||||
raise ValueError("%s cannot be opened for reading: %s" % (path, e))
|
||||
raise ValueError(f"{path} cannot be opened for reading: {e}")
|
||||
|
||||
try:
|
||||
format_identifier, b64_cert = data.split(b" ")[:2]
|
||||
@@ -520,7 +514,7 @@ class OpensshCertificate:
|
||||
break
|
||||
else:
|
||||
raise ValueError(
|
||||
"Invalid certificate format identifier: %s" % format_identifier
|
||||
f"Invalid certificate format identifier: {format_identifier}"
|
||||
)
|
||||
|
||||
parser = OpensshParser(cert)
|
||||
@@ -532,12 +526,11 @@ class OpensshCertificate:
|
||||
cert_info = cls._parse_cert_info(pub_key_type, parser)
|
||||
signature = parser.string()
|
||||
except (TypeError, ValueError) as e:
|
||||
raise ValueError("Invalid certificate data: %s" % e)
|
||||
raise ValueError(f"Invalid certificate data: {e}")
|
||||
|
||||
if parser.remaining_bytes():
|
||||
raise ValueError(
|
||||
"%s bytes of additional data was not parsed while loading %s"
|
||||
% (parser.remaining_bytes(), path)
|
||||
f"{parser.remaining_bytes()} bytes of additional data was not parsed while loading {path}"
|
||||
)
|
||||
|
||||
return cls(
|
||||
@@ -651,7 +644,7 @@ class OpensshCertificate:
|
||||
|
||||
def apply_directives(directives):
|
||||
if any(d not in _DIRECTIVES for d in directives):
|
||||
raise ValueError("directives must be one of %s" % ", ".join(_DIRECTIVES))
|
||||
raise ValueError(f"directives must be one of {', '.join(_DIRECTIVES)}")
|
||||
|
||||
directive_to_option = {
|
||||
"no-x11-forwarding": OpensshCertificateOption(
|
||||
@@ -696,7 +689,7 @@ def get_cert_info_object(key_type):
|
||||
elif key_type == "ed25519":
|
||||
cert_info = OpensshED25519CertificateInfo()
|
||||
else:
|
||||
raise ValueError("%s is not a valid key type" % key_type)
|
||||
raise ValueError(f"{key_type} is not a valid key type")
|
||||
|
||||
return cert_info
|
||||
|
||||
@@ -708,8 +701,8 @@ def get_option_type(name):
|
||||
result = "extension"
|
||||
else:
|
||||
raise ValueError(
|
||||
"%s is not a valid option. " % name
|
||||
+ "Custom options must start with 'critical:' or 'extension:' to indicate type"
|
||||
f"{name} is not a valid option. "
|
||||
"Custom options must start with 'critical:' or 'extension:' to indicate type"
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
@@ -137,8 +137,7 @@ class AsymmetricKeypair:
|
||||
|
||||
if keytype not in _ALGORITHM_PARAMETERS.keys():
|
||||
raise InvalidKeyTypeError(
|
||||
"%s is not a valid keytype. Valid keytypes are %s"
|
||||
% (keytype, ", ".join(_ALGORITHM_PARAMETERS.keys()))
|
||||
f"{keytype} is not a valid keytype. Valid keytypes are {', '.join(_ALGORITHM_PARAMETERS)}"
|
||||
)
|
||||
|
||||
if not size:
|
||||
@@ -146,7 +145,7 @@ class AsymmetricKeypair:
|
||||
else:
|
||||
if size not in _ALGORITHM_PARAMETERS[keytype]["valid_sizes"]:
|
||||
raise InvalidKeySizeError(
|
||||
"%s is not a valid key size for %s keys" % (size, keytype)
|
||||
f"{size} is not a valid key size for {keytype} keys"
|
||||
)
|
||||
|
||||
if passphrase:
|
||||
@@ -229,9 +228,7 @@ class AsymmetricKeypair:
|
||||
elif isinstance(privatekey, Ed25519PrivateKey):
|
||||
keytype = "ed25519"
|
||||
else:
|
||||
raise InvalidKeyTypeError(
|
||||
"Key type '%s' is not supported" % type(privatekey)
|
||||
)
|
||||
raise InvalidKeyTypeError(f"Key type '{type(privatekey)}' is not supported")
|
||||
|
||||
return cls(
|
||||
keytype=keytype,
|
||||
@@ -363,7 +360,7 @@ class OpensshKeypair:
|
||||
"""
|
||||
|
||||
if comment is None:
|
||||
comment = "%s@%s" % (getuser(), gethostname())
|
||||
comment = f"{getuser()}@{gethostname()}"
|
||||
|
||||
asym_keypair = AsymmetricKeypair.generate(keytype, size, passphrase)
|
||||
openssh_privatekey = cls.encode_openssh_privatekey(asym_keypair, "SSH")
|
||||
@@ -457,7 +454,7 @@ class OpensshKeypair:
|
||||
validate_comment(comment)
|
||||
|
||||
encoded_publickey += (
|
||||
(" %s" % comment).encode(encoding=_TEXT_ENCODING) if comment else b""
|
||||
f" {comment}".encode(encoding=_TEXT_ENCODING) if comment else b""
|
||||
)
|
||||
|
||||
return encoded_publickey
|
||||
@@ -541,7 +538,7 @@ class OpensshKeypair:
|
||||
|
||||
self.__comment = comment
|
||||
encoded_comment = (
|
||||
(" %s" % self.__comment).encode(encoding=_TEXT_ENCODING)
|
||||
f" {self.__comment}".encode(encoding=_TEXT_ENCODING)
|
||||
if self.__comment
|
||||
else b""
|
||||
)
|
||||
@@ -578,12 +575,11 @@ def load_privatekey(path, passphrase, key_format):
|
||||
privatekey_loader = privatekey_loaders[key_format]
|
||||
except KeyError:
|
||||
raise InvalidKeyFormatError(
|
||||
"%s is not a valid key format (%s)"
|
||||
% (key_format, ",".join(privatekey_loaders.keys()))
|
||||
f"{key_format} is not a valid key format ({','.join(privatekey_loaders)})"
|
||||
)
|
||||
|
||||
if not os.path.exists(path):
|
||||
raise InvalidPrivateKeyFileError("No file was found at %s" % path)
|
||||
raise InvalidPrivateKeyFileError(f"No file was found at {path}")
|
||||
|
||||
try:
|
||||
with open(path, "rb") as f:
|
||||
@@ -631,12 +627,11 @@ def load_publickey(path, key_format):
|
||||
publickey_loader = publickey_loaders[key_format]
|
||||
except KeyError:
|
||||
raise InvalidKeyFormatError(
|
||||
"%s is not a valid key format (%s)"
|
||||
% (key_format, ",".join(publickey_loaders.keys()))
|
||||
f"{key_format} is not a valid key format ({','.join(publickey_loaders)})"
|
||||
)
|
||||
|
||||
if not os.path.exists(path):
|
||||
raise InvalidPublicKeyFileError("No file was found at %s" % path)
|
||||
raise InvalidPublicKeyFileError(f"No file was found at {path}")
|
||||
|
||||
try:
|
||||
with open(path, "rb") as f:
|
||||
@@ -689,13 +684,13 @@ def get_encryption_algorithm(passphrase):
|
||||
|
||||
def validate_comment(comment):
|
||||
if not hasattr(comment, "encode"):
|
||||
raise InvalidCommentError("%s cannot be encoded to text" % comment)
|
||||
raise InvalidCommentError(f"{comment} cannot be encoded to text")
|
||||
|
||||
|
||||
def extract_comment(path):
|
||||
|
||||
if not os.path.exists(path):
|
||||
raise InvalidPublicKeyFileError("No file was found at %s" % path)
|
||||
raise InvalidPublicKeyFileError(f"No file was found at {path}")
|
||||
|
||||
try:
|
||||
with open(path, "rb") as f:
|
||||
@@ -715,6 +710,5 @@ def calculate_fingerprint(openssh_publickey):
|
||||
decoded_pubkey = b64decode(openssh_publickey.split(b" ")[1])
|
||||
digest.update(decoded_pubkey)
|
||||
|
||||
return "SHA256:%s" % b64encode(digest.finalize()).decode(
|
||||
encoding=_TEXT_ENCODING
|
||||
).rstrip("=")
|
||||
value = b64encode(digest.finalize()).decode(encoding=_TEXT_ENCODING).rstrip("=")
|
||||
return f"SHA256:{value}"
|
||||
|
||||
@@ -91,7 +91,7 @@ class OpensshParser:
|
||||
|
||||
def __init__(self, data):
|
||||
if not isinstance(data, (bytes, bytearray)):
|
||||
raise TypeError("Data must be bytes-like not %s" % type(data))
|
||||
raise TypeError(f"Data must be bytes-like not {type(data)}")
|
||||
|
||||
self._data = memoryview(data) if PY3 else data
|
||||
self._pos = 0
|
||||
@@ -174,7 +174,7 @@ class OpensshParser:
|
||||
|
||||
def _check_position(self, offset):
|
||||
if self._pos + offset > len(self._data):
|
||||
raise ValueError("Insufficient data remaining at position: %s" % self._pos)
|
||||
raise ValueError(f"Insufficient data remaining at position: {self._pos}")
|
||||
elif self._pos + offset < 0:
|
||||
raise ValueError("Position cannot be less than zero.")
|
||||
else:
|
||||
@@ -210,7 +210,7 @@ class OpensshParser:
|
||||
signature_data["R"] = cls._big_int(signature_blob[:32], "little")
|
||||
signature_data["S"] = cls._big_int(signature_blob[32:], "little")
|
||||
else:
|
||||
raise ValueError("%s is not a valid signature type" % signature_type)
|
||||
raise ValueError(f"{signature_type} is not a valid signature type")
|
||||
|
||||
signature_data["signature_type"] = signature_type
|
||||
|
||||
@@ -220,7 +220,7 @@ class OpensshParser:
|
||||
def _big_int(cls, raw_string, byte_order, signed=False):
|
||||
if byte_order not in ("big", "little"):
|
||||
raise ValueError(
|
||||
"Byte_order must be one of (big, little) not %s" % byte_order
|
||||
f"Byte_order must be one of (big, little) not {byte_order}"
|
||||
)
|
||||
|
||||
if PY3:
|
||||
@@ -279,7 +279,7 @@ class _OpensshWriter:
|
||||
if buffer is not None:
|
||||
if not isinstance(buffer, (bytes, bytearray)):
|
||||
raise TypeError(
|
||||
"Buffer must be a bytes-like object not %s" % type(buffer)
|
||||
f"Buffer must be a bytes-like object not {type(buffer)}"
|
||||
)
|
||||
else:
|
||||
buffer = bytearray()
|
||||
@@ -288,7 +288,7 @@ class _OpensshWriter:
|
||||
|
||||
def boolean(self, value):
|
||||
if not isinstance(value, bool):
|
||||
raise TypeError("Value must be of type bool not %s" % type(value))
|
||||
raise TypeError(f"Value must be of type bool not {type(value)}")
|
||||
|
||||
self._buff.extend(_BOOLEAN.pack(value))
|
||||
|
||||
@@ -296,10 +296,10 @@ class _OpensshWriter:
|
||||
|
||||
def uint32(self, value):
|
||||
if not isinstance(value, int):
|
||||
raise TypeError("Value must be of type int not %s" % type(value))
|
||||
raise TypeError(f"Value must be of type int not {type(value)}")
|
||||
if value < 0 or value > _UINT32_MAX:
|
||||
raise ValueError(
|
||||
"Value must be a positive integer less than %s" % _UINT32_MAX
|
||||
f"Value must be a positive integer less than {_UINT32_MAX}"
|
||||
)
|
||||
|
||||
self._buff.extend(_UINT32.pack(value))
|
||||
@@ -308,10 +308,10 @@ class _OpensshWriter:
|
||||
|
||||
def uint64(self, value):
|
||||
if not isinstance(value, (long, int)):
|
||||
raise TypeError("Value must be of type (long, int) not %s" % type(value))
|
||||
raise TypeError(f"Value must be of type (long, int) not {type(value)}")
|
||||
if value < 0 or value > _UINT64_MAX:
|
||||
raise ValueError(
|
||||
"Value must be a positive integer less than %s" % _UINT64_MAX
|
||||
f"Value must be a positive integer less than {_UINT64_MAX}"
|
||||
)
|
||||
|
||||
self._buff.extend(_UINT64.pack(value))
|
||||
@@ -320,7 +320,7 @@ class _OpensshWriter:
|
||||
|
||||
def string(self, value):
|
||||
if not isinstance(value, (bytes, bytearray)):
|
||||
raise TypeError("Value must be bytes-like not %s" % type(value))
|
||||
raise TypeError(f"Value must be bytes-like not {type(value)}")
|
||||
self.uint32(len(value))
|
||||
self._buff.extend(value)
|
||||
|
||||
@@ -328,7 +328,7 @@ class _OpensshWriter:
|
||||
|
||||
def mpint(self, value):
|
||||
if not isinstance(value, (int, long)):
|
||||
raise TypeError("Value must be of type (long, int) not %s" % type(value))
|
||||
raise TypeError(f"Value must be of type (long, int) not {type(value)}")
|
||||
|
||||
self.string(self._int_to_mpint(value))
|
||||
|
||||
@@ -336,18 +336,18 @@ class _OpensshWriter:
|
||||
|
||||
def name_list(self, value):
|
||||
if not isinstance(value, list):
|
||||
raise TypeError("Value must be a list of byte strings not %s" % type(value))
|
||||
raise TypeError(f"Value must be a list of byte strings not {type(value)}")
|
||||
|
||||
try:
|
||||
self.string(",".join(value).encode("ASCII"))
|
||||
except UnicodeEncodeError as e:
|
||||
raise ValueError("Name-list's must consist of US-ASCII characters: %s" % e)
|
||||
raise ValueError(f"Name-list's must consist of US-ASCII characters: {e}")
|
||||
|
||||
return self
|
||||
|
||||
def string_list(self, value):
|
||||
if not isinstance(value, list):
|
||||
raise TypeError("Value must be a list of byte string not %s" % type(value))
|
||||
raise TypeError(f"Value must be a list of byte string not {type(value)}")
|
||||
|
||||
writer = _OpensshWriter()
|
||||
for s in value:
|
||||
|
||||
@@ -37,9 +37,7 @@ def parse_serial(value):
|
||||
raise ValueError("the value is not in range [0, 255]")
|
||||
except ValueError as exc:
|
||||
raise ValueError(
|
||||
"The {idx}{th} part {part!r} is not a hexadecimal number in range [0, 255]: {exc}".format(
|
||||
idx=i + 1, th=th(i + 1), part=part, exc=exc
|
||||
)
|
||||
f"The {i + 1}{th(i + 1)} part {part!r} is not a hexadecimal number in range [0, 255]: {exc}"
|
||||
)
|
||||
result = (result << 8) | part_value
|
||||
return result
|
||||
|
||||
@@ -146,7 +146,7 @@ def get_relative_time_option(
|
||||
result = to_native(input_string)
|
||||
if result is None:
|
||||
raise OpenSSLObjectError(
|
||||
'The timespec "%s" for %s is not valid' % input_string, input_name
|
||||
f'The timespec "{input_string}" for {input_name} is not valid'
|
||||
)
|
||||
# Relative time
|
||||
if result.startswith("+") or result.startswith("-"):
|
||||
@@ -179,5 +179,5 @@ def get_relative_time_option(
|
||||
return add_or_remove_timezone(res, with_timezone=with_timezone)
|
||||
|
||||
raise OpenSSLObjectError(
|
||||
'The time spec "%s" for %s is invalid' % (input_string, input_name)
|
||||
f'The time spec "{input_string}" for {input_name} is invalid'
|
||||
)
|
||||
|
||||
@@ -229,8 +229,7 @@ def main():
|
||||
base64.urlsafe_b64decode(key)
|
||||
except Exception as e:
|
||||
module.fail_json(
|
||||
msg="Key for external_account_binding must be Base64 URL encoded (%s)"
|
||||
% e
|
||||
msg=f"Key for external_account_binding must be Base64 URL encoded ({e})"
|
||||
)
|
||||
module.params["external_account_binding"]["key"] = key
|
||||
|
||||
@@ -296,7 +295,7 @@ def main():
|
||||
)
|
||||
except KeyParsingError as e:
|
||||
raise ModuleFailException(
|
||||
"Error while parsing new account key: {msg}".format(msg=e.msg)
|
||||
f"Error while parsing new account key: {e.msg}"
|
||||
)
|
||||
# Verify that the account exists and has not been deactivated
|
||||
created, account_data = account.setup_account(allow_creation=False)
|
||||
|
||||
@@ -233,9 +233,7 @@ def get_orders_list(module, client, orders_url):
|
||||
if not res.get("orders"):
|
||||
if orders:
|
||||
module.warn(
|
||||
"When retrieving orders list part {0}, got empty result list".format(
|
||||
orders_url
|
||||
)
|
||||
f"When retrieving orders list part {orders_url}, got empty result list"
|
||||
)
|
||||
break
|
||||
# Add order URLs to result list
|
||||
|
||||
@@ -643,9 +643,7 @@ class ACMECertificateClient:
|
||||
)
|
||||
except ValueError as exc:
|
||||
self.module.warn(
|
||||
"Error while parsing criterium: {error}. Ignoring criterium.".format(
|
||||
error=exc
|
||||
)
|
||||
f"Error while parsing criterium: {exc}. Ignoring criterium."
|
||||
)
|
||||
|
||||
if self.profile is not None:
|
||||
@@ -654,9 +652,7 @@ class ACMECertificateClient:
|
||||
raise ModuleFailException(msg="The ACME CA does not support profiles.")
|
||||
if self.profile not in meta_profiles:
|
||||
raise ModuleFailException(
|
||||
msg="The ACME CA does not support selected profile {0!r}.".format(
|
||||
self.profile
|
||||
)
|
||||
msg=f"The ACME CA does not support selected profile {self.profile!r}."
|
||||
)
|
||||
|
||||
# Make sure account exists
|
||||
@@ -678,7 +674,7 @@ class ACMECertificateClient:
|
||||
self.changed = created or updated
|
||||
|
||||
if self.csr is not None and not os.path.exists(self.csr):
|
||||
raise ModuleFailException("CSR %s not found" % (self.csr))
|
||||
raise ModuleFailException(f"CSR {self.csr} not found")
|
||||
|
||||
# Extract list of identifiers from CSR
|
||||
self.identifiers = self.client.backend.get_ordered_csr_identifiers(
|
||||
@@ -758,9 +754,7 @@ class ACMECertificateClient:
|
||||
and self.challenge not in data[authz.identifier]
|
||||
):
|
||||
raise ModuleFailException(
|
||||
"Found no challenge of type '{0}' for identifier {1}!".format(
|
||||
self.challenge, type_identifier
|
||||
)
|
||||
f"Found no challenge of type '{self.challenge}' for identifier {type_identifier}!"
|
||||
)
|
||||
# Get DNS challenge data
|
||||
data_dns = {}
|
||||
@@ -812,9 +806,7 @@ class ACMECertificateClient:
|
||||
alt_cert = CertificateChain.download(self.client, alternate)
|
||||
except ModuleFailException as e:
|
||||
self.module.warn(
|
||||
"Error while downloading alternative certificate {0}: {1}".format(
|
||||
alternate, e
|
||||
)
|
||||
f"Error while downloading alternative certificate {alternate}: {e}"
|
||||
)
|
||||
continue
|
||||
alternate_chains.append(alt_cert)
|
||||
@@ -825,7 +817,7 @@ class ACMECertificateClient:
|
||||
for chain in chains:
|
||||
if matcher.match(chain):
|
||||
self.module.debug(
|
||||
"Found matching chain for criterium {0}".format(criterium_idx)
|
||||
f"Found matching chain for criterium {criterium_idx}"
|
||||
)
|
||||
return chain
|
||||
return None
|
||||
@@ -844,13 +836,11 @@ class ACMECertificateClient:
|
||||
)
|
||||
if authz is None:
|
||||
raise ModuleFailException(
|
||||
'Found no authorization information for "{identifier}"!'.format(
|
||||
identifier=combine_identifier(identifier_type, identifier)
|
||||
)
|
||||
f'Found no authorization information for "{combine_identifier(identifier_type, identifier)}"!'
|
||||
)
|
||||
if authz.status != "valid":
|
||||
authz.raise_error(
|
||||
'Status is "{status}" and not "valid"'.format(status=authz.status),
|
||||
f'Status is "{authz.status}" and not "valid"',
|
||||
module=self.module,
|
||||
)
|
||||
|
||||
@@ -911,7 +901,7 @@ class ACMECertificateClient:
|
||||
pass
|
||||
if authz.status != "deactivated":
|
||||
self.module.warn(
|
||||
warning="Could not deactivate authz object {0}.".format(authz.url)
|
||||
warning=f"Could not deactivate authz object {authz.url}."
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -98,9 +98,7 @@ def main():
|
||||
# ignore errors
|
||||
pass
|
||||
if authz.status != "deactivated":
|
||||
module.warn(
|
||||
warning="Could not deactivate authz object {0}.".format(authz.url)
|
||||
)
|
||||
module.warn(warning=f"Could not deactivate authz object {authz.url}.")
|
||||
|
||||
module.exit_json(changed=changed)
|
||||
except ModuleFailException as e:
|
||||
|
||||
@@ -414,9 +414,7 @@ def main():
|
||||
)
|
||||
if profile not in meta_profiles:
|
||||
raise ModuleFailException(
|
||||
msg="The ACME CA does not support selected profile {0!r}.".format(
|
||||
profile
|
||||
)
|
||||
msg=f"The ACME CA does not support selected profile {profile!r}."
|
||||
)
|
||||
|
||||
order = None
|
||||
|
||||
@@ -271,13 +271,10 @@ def main():
|
||||
|
||||
missing_challenge_authzs = [k for k, v in challenges.items() if v is None]
|
||||
if missing_challenge_authzs:
|
||||
missing_challenge_authzs = ", ".join(sorted(missing_challenge_authzs))
|
||||
raise ModuleFailException(
|
||||
"The challenge parameter must be supplied if there are pending authorizations."
|
||||
" The following authorizations are pending: {missing_challenge_authzs}".format(
|
||||
missing_challenge_authzs=", ".join(
|
||||
sorted(missing_challenge_authzs)
|
||||
),
|
||||
)
|
||||
f" The following authorizations are pending: {missing_challenge_authzs}"
|
||||
)
|
||||
|
||||
bad_challenge_authzs = [
|
||||
@@ -286,18 +283,15 @@ def main():
|
||||
if authz.find_challenge(challenges[authz.combined_identifier]) is None
|
||||
]
|
||||
if bad_challenge_authzs:
|
||||
raise ModuleFailException(
|
||||
"The following authorizations do not support the selected challenges: {authz_challenges_pairs}".format(
|
||||
authz_challenges_pairs=", ".join(
|
||||
sorted(
|
||||
"{authz} with {challenge}".format(
|
||||
authz=authz, challenge=challenges[authz]
|
||||
)
|
||||
for authz in bad_challenge_authzs
|
||||
)
|
||||
),
|
||||
authz_challenges_pairs = ", ".join(
|
||||
sorted(
|
||||
f"{authz} with {challenges[authz]}"
|
||||
for authz in bad_challenge_authzs
|
||||
)
|
||||
)
|
||||
raise ModuleFailException(
|
||||
f"The following authorizations do not support the selected challenges: {authz_challenges_pairs}"
|
||||
)
|
||||
|
||||
really_pending_authzs = [
|
||||
authz
|
||||
|
||||
@@ -231,7 +231,7 @@ def main():
|
||||
)
|
||||
except ModuleFailException as e:
|
||||
if module.params["treat_parsing_error_as_non_existing"]:
|
||||
complete(True, msg="Certificate cannot be parsed: {0}".format(e.msg))
|
||||
complete(True, msg=f"Certificate cannot be parsed: {e.msg}")
|
||||
e.do_fail(module)
|
||||
|
||||
result["parsable"] = True
|
||||
@@ -265,24 +265,18 @@ def main():
|
||||
)
|
||||
msg_append = ""
|
||||
if "explanationURL" in renewal_info:
|
||||
msg_append = ". Information on renewal interval: {0}".format(
|
||||
renewal_info["explanationURL"]
|
||||
)
|
||||
msg_append = f". Information on renewal interval: {renewal_info['explanationURL']}"
|
||||
result["supports_ari"] = True
|
||||
if now > window_end:
|
||||
complete(
|
||||
True,
|
||||
msg="The suggested renewal interval provided by ARI is in the past{0}".format(
|
||||
msg_append
|
||||
),
|
||||
msg=f"The suggested renewal interval provided by ARI is in the past{msg_append}",
|
||||
)
|
||||
if module.params["ari_algorithm"] == "start":
|
||||
if now > window_start:
|
||||
complete(
|
||||
True,
|
||||
msg="The suggested renewal interval provided by ARI has begun{0}".format(
|
||||
msg_append
|
||||
),
|
||||
msg=f"The suggested renewal interval provided by ARI has begun{msg_append}",
|
||||
)
|
||||
else:
|
||||
random_time = backend.interpolate_timestamp(
|
||||
@@ -291,10 +285,7 @@ def main():
|
||||
if now > random_time:
|
||||
complete(
|
||||
True,
|
||||
msg="The picked random renewal time {0} in sugested renewal internal provided by ARI is in the past{1}".format(
|
||||
random_time,
|
||||
msg_append,
|
||||
),
|
||||
msg=f"The picked random renewal time {random_time} in sugested renewal internal provided by ARI is in the past{msg_append}",
|
||||
)
|
||||
|
||||
if module.params["remaining_days"] is not None:
|
||||
@@ -302,7 +293,7 @@ def main():
|
||||
if remaining_days < module.params["remaining_days"]:
|
||||
complete(
|
||||
True,
|
||||
msg="The certificate expires in {0} days".format(remaining_days),
|
||||
msg=f"The certificate expires in {remaining_days} days",
|
||||
)
|
||||
|
||||
if module.params["remaining_percentage"] is not None:
|
||||
@@ -314,10 +305,8 @@ def main():
|
||||
if timestamp < now:
|
||||
complete(
|
||||
True,
|
||||
msg="The remaining percentage {0}% of the certificate's lifespan was reached on {1}".format(
|
||||
module.params["remaining_percentage"] * 100,
|
||||
timestamp,
|
||||
),
|
||||
msg=f"The remaining percentage {module.params['remaining_percentage'] * 100}%"
|
||||
f" of the certificate's lifespan was reached on {timestamp}",
|
||||
)
|
||||
|
||||
complete(False)
|
||||
|
||||
@@ -182,9 +182,7 @@ def main():
|
||||
private_key, private_key_content, passphrase=passphrase
|
||||
)
|
||||
except KeyParsingError as e:
|
||||
raise ModuleFailException(
|
||||
"Error while parsing private key: {msg}".format(msg=e.msg)
|
||||
)
|
||||
raise ModuleFailException(f"Error while parsing private key: {e.msg}")
|
||||
# Step 2: sign revokation request with private key
|
||||
jws_header = {
|
||||
"alg": private_key_data["alg"],
|
||||
|
||||
@@ -259,7 +259,7 @@ def main():
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
raise ModuleFailException("Error while loading private key: {0}".format(e))
|
||||
raise ModuleFailException(f"Error while loading private key: {e}")
|
||||
|
||||
# Some common attributes
|
||||
domain = to_text(challenge_data["resource"])
|
||||
@@ -276,7 +276,7 @@ def main():
|
||||
san = cryptography.x509.IPAddress(ipaddress.ip_address(identifier))
|
||||
else:
|
||||
raise ModuleFailException(
|
||||
'Unsupported identifier type "{0}"'.format(identifier_type)
|
||||
f'Unsupported identifier type "{identifier_type}"'
|
||||
)
|
||||
|
||||
# Generate regular self-signed certificate
|
||||
|
||||
@@ -212,18 +212,16 @@ def is_parent(module, cert, potential_parent):
|
||||
public_key.verify(cert.cert.signature, cert.cert.tbs_certificate_bytes)
|
||||
else:
|
||||
# Unknown public key type
|
||||
module.warn('Unknown public key type "{0}"'.format(public_key))
|
||||
module.warn(f'Unknown public key type "{public_key}"')
|
||||
return False
|
||||
return True
|
||||
except cryptography.exceptions.InvalidSignature:
|
||||
return False
|
||||
except cryptography.exceptions.UnsupportedAlgorithm:
|
||||
module.warn(
|
||||
'Unsupported algorithm "{0}"'.format(cert.cert.signature_hash_algorithm)
|
||||
)
|
||||
module.warn(f'Unsupported algorithm "{cert.cert.signature_hash_algorithm}"')
|
||||
return False
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Unknown error on signature validation: {0}".format(e))
|
||||
module.fail_json(msg=f"Unknown error on signature validation: {e}")
|
||||
|
||||
|
||||
def parse_PEM_list(module, text, source, fail_on_error=True):
|
||||
@@ -239,9 +237,7 @@ def parse_PEM_list(module, text, source, fail_on_error=True):
|
||||
)
|
||||
result.append(Certificate(cert_pem, cert))
|
||||
except Exception as e:
|
||||
msg = "Cannot parse certificate #{0} from {1}: {2}".format(
|
||||
len(result) + 1, source, e
|
||||
)
|
||||
msg = f"Cannot parse certificate #{len(result) + 1} from {source}: {e}"
|
||||
if fail_on_error:
|
||||
module.fail_json(msg=msg)
|
||||
else:
|
||||
@@ -262,7 +258,7 @@ def load_PEM_list(module, path, fail_on_error=True):
|
||||
fail_on_error=fail_on_error,
|
||||
)
|
||||
except Exception as e:
|
||||
msg = "Cannot read certificate file {0}: {1}".format(path, e)
|
||||
msg = f"Cannot read certificate file {path}: {e}"
|
||||
if fail_on_error:
|
||||
module.fail_json(msg=msg)
|
||||
else:
|
||||
@@ -357,9 +353,9 @@ def main():
|
||||
if not is_parent(module, chain[i - 1], parent):
|
||||
module.fail_json(
|
||||
msg=(
|
||||
"Cannot verify input chain: certificate #{2}: {3} is not issuer "
|
||||
+ "of certificate #{0}: {1}"
|
||||
).format(i, format_cert(chain[i - 1]), i + 1, format_cert(parent))
|
||||
f"Cannot verify input chain: certificate #{i + 1}: {format_cert(parent)} is not issuer "
|
||||
f"of certificate #{i}: {format_cert(chain[i - 1])}"
|
||||
)
|
||||
)
|
||||
|
||||
# Load intermediate certificates
|
||||
@@ -392,9 +388,7 @@ def main():
|
||||
current = intermediate
|
||||
else:
|
||||
module.fail_json(
|
||||
msg="Cannot complete chain. Stuck at certificate {0}".format(
|
||||
format_cert(current)
|
||||
)
|
||||
msg=f"Cannot complete chain. Stuck at certificate {format_cert(current)}"
|
||||
)
|
||||
|
||||
# Return results
|
||||
|
||||
@@ -665,16 +665,12 @@ class EcsCertificate:
|
||||
],
|
||||
)
|
||||
except SessionConfigurationException as e:
|
||||
module.fail_json(
|
||||
msg="Failed to initialize Entrust Provider: {0}".format(to_native(e))
|
||||
)
|
||||
module.fail_json(msg=f"Failed to initialize Entrust Provider: {e}")
|
||||
try:
|
||||
self.ecs_client.GetAppVersion()
|
||||
except RestOperationException as e:
|
||||
module.fail_json(
|
||||
msg="Please verify credential information. Received exception when testing ECS connection: {0}".format(
|
||||
to_native(e.message)
|
||||
)
|
||||
msg=f"Please verify credential information. Received exception when testing ECS connection: {e.message}"
|
||||
)
|
||||
|
||||
# Conversion of the fields that go into the 'tracking' parameter of the request object
|
||||
@@ -744,7 +740,7 @@ class EcsCertificate:
|
||||
try:
|
||||
# Use serial_number to identify if certificate is an Entrust Certificate
|
||||
# with an associated tracking ID
|
||||
serial_number = "{0:X}".format(self.cert.serial_number)
|
||||
serial_number = f"{self.cert.serial_number:X}"
|
||||
cert_results = self.ecs_client.GetCertificates(
|
||||
serialNumber=serial_number
|
||||
).get("certificates", {})
|
||||
@@ -764,9 +760,7 @@ class EcsCertificate:
|
||||
self.cert_days = calculate_cert_days(self.cert_details.get("expiresAfter"))
|
||||
except RestOperationException as e:
|
||||
module.fail_json(
|
||||
'Failed to get details of certificate with tracking_id="{0}", Error: '.format(
|
||||
self.tracking_id
|
||||
),
|
||||
f'Failed to get details of certificate with tracking_id="{self.tracking_id}", Error: ',
|
||||
to_native(e.message),
|
||||
)
|
||||
|
||||
@@ -782,10 +776,9 @@ class EcsCertificate:
|
||||
and module.params["tracking_id"] != self.tracking_id
|
||||
):
|
||||
module.warn(
|
||||
'tracking_id parameter of "{0}" provided, but will be ignored. Valid certificate was present in path "{1}" with '
|
||||
'tracking_id of "{2}".'.format(
|
||||
module.params["tracking_id"], self.path, self.tracking_id
|
||||
)
|
||||
f'tracking_id parameter of "{module.params["tracking_id"]}" provided, but will be ignored.'
|
||||
f' Valid certificate was present in path "{self.path}" with '
|
||||
f'tracking_id of "{self.tracking_id}".'
|
||||
)
|
||||
|
||||
# If we did not end up setting tracking_id based on existing cert, get from module params
|
||||
@@ -822,10 +815,10 @@ class EcsCertificate:
|
||||
# We will be performing a reissue operation.
|
||||
if self.request_type != "new" and not self.tracking_id:
|
||||
module.warn(
|
||||
'No existing Entrust certificate found in path={0} and no tracking_id was provided, setting request_type to "new" for this task'
|
||||
"run. Future playbook runs that point to the pathination file in {1} will use request_type={2}".format(
|
||||
self.path, self.path, self.request_type
|
||||
)
|
||||
f"No existing Entrust certificate found in path={self.path}"
|
||||
' and no tracking_id was provided, setting request_type to "new" for this task'
|
||||
"run. Future playbook runs that point to the pathination file"
|
||||
f" in {self.path} will use request_type={self.request_type}"
|
||||
)
|
||||
self.request_type = "new"
|
||||
elif self.request_type == "new" and self.tracking_id:
|
||||
@@ -860,9 +853,7 @@ class EcsCertificate:
|
||||
self.set_cert_details(module)
|
||||
except RestOperationException as e:
|
||||
module.fail_json(
|
||||
msg="Failed to request new certificate from Entrust (ECS) {0}".format(
|
||||
e.message
|
||||
)
|
||||
msg=f"Failed to request new certificate from Entrust (ECS) {e.message}"
|
||||
)
|
||||
|
||||
if self.request_type != "validate_only":
|
||||
@@ -1020,9 +1011,7 @@ def main():
|
||||
MINIMAL_CRYPTOGRAPHY_VERSION
|
||||
):
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
),
|
||||
msg=missing_required_lib(f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
|
||||
@@ -1033,9 +1022,7 @@ def main():
|
||||
or module.params["request_type"] == "validate_only"
|
||||
):
|
||||
module.fail_json(
|
||||
msg='The tracking_id field is invalid when request_type="{0}".'.format(
|
||||
module.params["request_type"]
|
||||
)
|
||||
msg=f'The tracking_id field is invalid when request_type="{module.params["request_type"]}".'
|
||||
)
|
||||
|
||||
# A reissued request can not specify an expiration date or lifetime
|
||||
@@ -1053,15 +1040,12 @@ def main():
|
||||
module_params_csr = module.params["csr"]
|
||||
if module_params_csr is None:
|
||||
module.fail_json(
|
||||
msg="The csr field is required when request_type={0}".format(
|
||||
module.params["request_type"]
|
||||
)
|
||||
msg=f"The csr field is required when request_type={module.params['request_type']}"
|
||||
)
|
||||
elif not os.path.exists(module_params_csr):
|
||||
module.fail_json(
|
||||
msg="The csr field of {0} was not a valid path. csr is required when request_type={1}".format(
|
||||
module_params_csr, module.params["request_type"]
|
||||
)
|
||||
msg=f"The csr field of {module_params_csr} was not a valid path."
|
||||
f" csr is required when request_type={module.params['request_type']}"
|
||||
)
|
||||
|
||||
if module.params["ou"] and len(module.params["ou"]) > 1:
|
||||
@@ -1088,9 +1072,7 @@ def main():
|
||||
if module.params["cert_expiry"]:
|
||||
if not validate_cert_expiry(module.params["cert_expiry"]):
|
||||
module.fail_json(
|
||||
msg='The "cert_expiry" parameter of "{0}" is not a valid date or date-time'.format(
|
||||
module.params["cert_expiry"]
|
||||
)
|
||||
msg=f'The "cert_expiry" parameter of "{module.params["cert_expiry"]}" is not a valid date or date-time'
|
||||
)
|
||||
|
||||
certificate = EcsCertificate(module)
|
||||
|
||||
@@ -275,15 +275,13 @@ class EcsDomain:
|
||||
)
|
||||
except SessionConfigurationException as e:
|
||||
module.fail_json(
|
||||
msg="Failed to initialize Entrust Provider: {0}".format(to_native(e))
|
||||
msg=f"Failed to initialize Entrust Provider: {to_native(e)}"
|
||||
)
|
||||
try:
|
||||
self.ecs_client.GetAppVersion()
|
||||
except RestOperationException as e:
|
||||
module.fail_json(
|
||||
msg="Please verify credential information. Received exception when testing ECS connection: {0}".format(
|
||||
to_native(e.message)
|
||||
)
|
||||
msg=f"Please verify credential information. Received exception when testing ECS connection: {e.message}"
|
||||
)
|
||||
|
||||
def set_domain_details(self, domain_details):
|
||||
@@ -405,9 +403,7 @@ class EcsDomain:
|
||||
self.set_domain_details(result)
|
||||
except RestOperationException as e:
|
||||
module.fail_json(
|
||||
msg="Failed to request domain validation from Entrust (ECS) {0}".format(
|
||||
e.message
|
||||
)
|
||||
msg=f"Failed to request domain validation from Entrust (ECS) {e.message}"
|
||||
)
|
||||
|
||||
def dump(self):
|
||||
@@ -467,9 +463,7 @@ def main():
|
||||
and module.params["verification_method"] != "email"
|
||||
):
|
||||
module.fail_json(
|
||||
msg='The verification_email field is invalid when verification_method="{0}".'.format(
|
||||
module.params["verification_method"]
|
||||
)
|
||||
msg=f'The verification_email field is invalid when verification_method="{module.params["verification_method"]}".'
|
||||
)
|
||||
|
||||
domain = EcsDomain(module)
|
||||
|
||||
@@ -369,8 +369,7 @@ def main():
|
||||
if get_certificate_chain and sys.version_info < (3, 10):
|
||||
module.fail_json(
|
||||
msg="get_certificate_chain=true can only be used with Python 3.10 (Python 3.13+ officially supports this). "
|
||||
"The Python version used to run the get_certificate module is %s"
|
||||
% sys.version
|
||||
f"The Python version used to run the get_certificate module is {sys.version}"
|
||||
)
|
||||
|
||||
backend = module.params.get("select_crypto_backend")
|
||||
@@ -388,16 +387,14 @@ def main():
|
||||
# Success?
|
||||
if backend == "auto":
|
||||
module.fail_json(
|
||||
msg=(
|
||||
"Cannot detect the required Python library " "cryptography (>= {0})"
|
||||
).format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
msg=f"Cannot detect the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})"
|
||||
)
|
||||
|
||||
if backend == "cryptography":
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"
|
||||
),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
@@ -437,14 +434,12 @@ def main():
|
||||
# Note: get_server_certificate does not support SNI!
|
||||
cert = get_server_certificate((host, port), ca_certs=ca_cert)
|
||||
except Exception as e:
|
||||
module.fail_json(
|
||||
msg="Failed to get cert from {0}:{1}, error: {2}".format(host, port, e)
|
||||
)
|
||||
module.fail_json(msg=f"Failed to get cert from {host}:{port}, error: {e}")
|
||||
else:
|
||||
# Python >= 2.7.9
|
||||
try:
|
||||
if proxy_host:
|
||||
connect = "CONNECT %s:%s HTTP/1.0\r\n\r\n" % (host, port)
|
||||
connect = f"CONNECT {host}:{port} HTTP/1.0\r\n\r\n"
|
||||
sock = socket()
|
||||
atexit.register(sock.close)
|
||||
sock.connect((proxy_host, proxy_port))
|
||||
@@ -489,9 +484,7 @@ def main():
|
||||
# If tls_ctx_option_attr is not an integer
|
||||
else:
|
||||
module.fail_json(
|
||||
msg="Failed to determine the numeric value for {0}".format(
|
||||
tls_ctx_option_str
|
||||
)
|
||||
msg=f"Failed to determine the numeric value for {tls_ctx_option_str}"
|
||||
)
|
||||
# If the item is an integer
|
||||
elif isinstance(tls_ctx_option, int):
|
||||
@@ -500,9 +493,7 @@ def main():
|
||||
# If the item is not a string nor integer
|
||||
else:
|
||||
module.fail_json(
|
||||
msg="tls_ctx_options must be a string or integer, got {0!r}".format(
|
||||
tls_ctx_option
|
||||
)
|
||||
msg=f"tls_ctx_options must be a string or integer, got {tls_ctx_option!r}"
|
||||
)
|
||||
tls_ctx_option_int = (
|
||||
0 # make pylint happy; this code is actually unreachable
|
||||
@@ -513,9 +504,7 @@ def main():
|
||||
ctx.options |= tls_ctx_option_int
|
||||
except Exception:
|
||||
module.fail_json(
|
||||
msg="Failed to add {0} to CTX options".format(
|
||||
tls_ctx_option_str or tls_ctx_option_int
|
||||
)
|
||||
msg=f"Failed to add {tls_ctx_option_str or tls_ctx_option_int} to CTX options"
|
||||
)
|
||||
|
||||
tls_sock = ctx.wrap_socket(sock, server_hostname=server_name or host)
|
||||
@@ -568,15 +557,11 @@ def main():
|
||||
except Exception as e:
|
||||
if proxy_host:
|
||||
module.fail_json(
|
||||
msg="Failed to get cert via proxy {0}:{1} from {2}:{3}, error: {4}".format(
|
||||
proxy_host, proxy_port, host, port, e
|
||||
)
|
||||
msg=f"Failed to get cert via proxy {proxy_host}:{proxy_port} from {host}:{port}, error: {e}"
|
||||
)
|
||||
else:
|
||||
module.fail_json(
|
||||
msg="Failed to get cert from {0}:{1}, error: {2}".format(
|
||||
host, port, e
|
||||
)
|
||||
msg=f"Failed to get cert from {host}:{port}, error: {e}"
|
||||
)
|
||||
|
||||
result["cert"] = cert
|
||||
|
||||
@@ -493,9 +493,7 @@ class Handler:
|
||||
return b64decode(to_native(passphrase))
|
||||
except Exception as exc:
|
||||
self._module.fail_json(
|
||||
"Error while base64-decoding '{parameter_name}': {exc}".format(
|
||||
parameter_name=parameter_name, exc=exc
|
||||
)
|
||||
f"Error while base64-decoding '{parameter_name}': {exc}"
|
||||
)
|
||||
|
||||
def _run_command(self, command, data=None):
|
||||
@@ -531,10 +529,10 @@ class Handler:
|
||||
|
||||
if result[RETURN_CODE] != 0:
|
||||
raise ValueError(
|
||||
"Error while generating LUKS name for %s: %s" % (device, result[STDERR])
|
||||
f"Error while generating LUKS name for {device}: {result[STDERR]}"
|
||||
)
|
||||
dev_uuid = result[STDOUT].strip()
|
||||
return "luks-%s" % dev_uuid
|
||||
return f"luks-{dev_uuid}"
|
||||
|
||||
|
||||
class CryptHandler(Handler):
|
||||
@@ -551,7 +549,7 @@ class CryptHandler(Handler):
|
||||
result = self._run_command([self._lsblk_bin, device, "-nlo", "type,name"])
|
||||
if result[RETURN_CODE] != 0:
|
||||
raise ValueError(
|
||||
"Error while obtaining LUKS name for %s: %s" % (device, result[STDERR])
|
||||
f"Error while obtaining LUKS name for {device}: {result[STDERR]}"
|
||||
)
|
||||
|
||||
for line in result[STDOUT].splitlines(False):
|
||||
@@ -595,9 +593,9 @@ class CryptHandler(Handler):
|
||||
"""check if a keyslot is set"""
|
||||
result = self._run_command([self._cryptsetup_bin, "luksDump", device])
|
||||
if result[RETURN_CODE] != 0:
|
||||
raise ValueError("Error while dumping LUKS header from %s" % (device,))
|
||||
result_luks1 = "Key Slot %d: ENABLED" % (keyslot) in result[STDOUT]
|
||||
result_luks2 = " %d: luks2" % (keyslot) in result[STDOUT]
|
||||
raise ValueError(f"Error while dumping LUKS header from {device}")
|
||||
result_luks1 = f"Key Slot {keyslot}: ENABLED" in result[STDOUT]
|
||||
result_luks2 = f" {keyslot}: luks2" in result[STDOUT]
|
||||
return result_luks1 or result_luks2
|
||||
|
||||
def _add_pbkdf_options(self, options, pbkdf):
|
||||
@@ -657,9 +655,7 @@ class CryptHandler(Handler):
|
||||
|
||||
result = self._run_command(args, data=passphrase)
|
||||
if result[RETURN_CODE] != 0:
|
||||
raise ValueError(
|
||||
"Error while creating LUKS on %s: %s" % (device, result[STDERR])
|
||||
)
|
||||
raise ValueError(f"Error while creating LUKS on {device}: {result[STDERR]}")
|
||||
|
||||
def run_luks_open(
|
||||
self,
|
||||
@@ -696,14 +692,13 @@ class CryptHandler(Handler):
|
||||
result = self._run_command(args, data=passphrase)
|
||||
if result[RETURN_CODE] != 0:
|
||||
raise ValueError(
|
||||
"Error while opening LUKS container on %s: %s"
|
||||
% (device, result[STDERR])
|
||||
f"Error while opening LUKS container on {device}: {result[STDERR]}"
|
||||
)
|
||||
|
||||
def run_luks_close(self, name):
|
||||
result = self._run_command([self._cryptsetup_bin, "close", name])
|
||||
if result[RETURN_CODE] != 0:
|
||||
raise ValueError("Error while closing LUKS container %s" % (name))
|
||||
raise ValueError(f"Error while closing LUKS container {name}")
|
||||
|
||||
def run_luks_remove(self, device):
|
||||
wipefs_bin = self._module.get_bin_path("wipefs", True)
|
||||
@@ -714,8 +709,7 @@ class CryptHandler(Handler):
|
||||
result = self._run_command([wipefs_bin, "--all", device])
|
||||
if result[RETURN_CODE] != 0:
|
||||
raise ValueError(
|
||||
"Error while wiping LUKS container signatures for %s: %s"
|
||||
% (device, result[STDERR])
|
||||
f"Error while wiping LUKS container signatures for {device}: {result[STDERR]}"
|
||||
)
|
||||
|
||||
# For LUKS2, sometimes both `cryptsetup erase` and `wipefs` do **not**
|
||||
@@ -725,8 +719,7 @@ class CryptHandler(Handler):
|
||||
wipe_luks_headers(device)
|
||||
except Exception as exc:
|
||||
raise ValueError(
|
||||
"Error while wiping LUKS container signatures for %s: %s"
|
||||
% (device, exc)
|
||||
f"Error while wiping LUKS container signatures for {device}: {exc}"
|
||||
)
|
||||
|
||||
def run_luks_add_key(
|
||||
@@ -766,8 +759,7 @@ class CryptHandler(Handler):
|
||||
result = self._run_command(args, data=b"".join(data) or None)
|
||||
if result[RETURN_CODE] != 0:
|
||||
raise ValueError(
|
||||
"Error while adding new LUKS keyslot to %s: %s"
|
||||
% (device, result[STDERR])
|
||||
f"Error while adding new LUKS keyslot to {device}: {result[STDERR]}"
|
||||
)
|
||||
|
||||
def run_luks_remove_key(
|
||||
@@ -779,7 +771,7 @@ class CryptHandler(Handler):
|
||||
if not force_remove_last_key:
|
||||
result = self._run_command([self._cryptsetup_bin, "luksDump", device])
|
||||
if result[RETURN_CODE] != 0:
|
||||
raise ValueError("Error while dumping LUKS header from %s" % (device,))
|
||||
raise ValueError(f"Error while dumping LUKS header from {device}")
|
||||
keyslot_count = 0
|
||||
keyslot_area = False
|
||||
keyslot_re = re.compile(r"^Key Slot [0-9]+: ENABLED")
|
||||
@@ -802,9 +794,8 @@ class CryptHandler(Handler):
|
||||
keyslot_area = False
|
||||
if keyslot_count < 2:
|
||||
self._module.fail_json(
|
||||
msg="LUKS device %s has less than two active keyslots. "
|
||||
"To be able to remove a key, please set "
|
||||
"`force_remove_last_key` to `true`." % device
|
||||
msg=f"LUKS device {device} has less than two active keyslots. "
|
||||
"To be able to remove a key, please set `force_remove_last_key` to `true`."
|
||||
)
|
||||
|
||||
if keyslot is None:
|
||||
@@ -820,7 +811,7 @@ class CryptHandler(Handler):
|
||||
result = self._run_command(args, data=passphrase)
|
||||
if result[RETURN_CODE] != 0:
|
||||
raise ValueError(
|
||||
"Error while removing LUKS key from %s: %s" % (device, result[STDERR])
|
||||
f"Error while removing LUKS key from {device}: {result[STDERR]}"
|
||||
)
|
||||
|
||||
def luks_test_key(self, device, keyfile, passphrase, keyslot=None):
|
||||
@@ -859,8 +850,7 @@ class CryptHandler(Handler):
|
||||
return False
|
||||
|
||||
raise ValueError(
|
||||
"Error while testing whether keyslot exists on %s: %s"
|
||||
% (device, result[STDERR])
|
||||
f"Error while testing whether keyslot exists on {device}: {result[STDERR]}"
|
||||
)
|
||||
|
||||
|
||||
@@ -921,8 +911,7 @@ class ConditionsHandler(Handler):
|
||||
# the container is already open but with different name:
|
||||
# suspicious. back off
|
||||
self._module.fail_json(
|
||||
msg="LUKS container is already opened "
|
||||
"under different name '%s'." % name
|
||||
msg=f"LUKS container is already opened under different name '{name}'."
|
||||
)
|
||||
|
||||
# container is opened and the names match
|
||||
@@ -1069,13 +1058,11 @@ class ConditionsHandler(Handler):
|
||||
|
||||
if luks_type == "luks1" and not 0 <= self._module.params[param] <= 7:
|
||||
self._module.fail_json(
|
||||
msg="%s must be between 0 and 7 when using LUKS1."
|
||||
% self._module.params[param]
|
||||
msg=f"{self._module.params[param]} must be between 0 and 7 when using LUKS1."
|
||||
)
|
||||
elif luks_type == "luks2" and not 0 <= self._module.params[param] <= 31:
|
||||
self._module.fail_json(
|
||||
msg="%s must be between 0 and 31 when using LUKS2."
|
||||
% self._module.params[param]
|
||||
msg=f"{self._module.params[param]} must be between 0 and 31 when using LUKS2."
|
||||
)
|
||||
|
||||
|
||||
@@ -1151,7 +1138,7 @@ def run_module():
|
||||
statinfo = os.stat(module.params["device"])
|
||||
mode = statinfo.st_mode
|
||||
if not stat.S_ISBLK(mode) and not stat.S_ISCHR(mode):
|
||||
raise Exception("{0} is not a device".format(module.params["device"]))
|
||||
raise Exception(f"{module.params['device']} is not a device")
|
||||
except Exception as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
@@ -1202,7 +1189,7 @@ def run_module():
|
||||
module.params["pbkdf"],
|
||||
)
|
||||
except ValueError as e:
|
||||
module.fail_json(msg="luks_device error: %s" % e)
|
||||
module.fail_json(msg=f"luks_device error: {e}")
|
||||
result["changed"] = True
|
||||
if module.check_mode:
|
||||
module.exit_json(**result)
|
||||
@@ -1219,7 +1206,7 @@ def run_module():
|
||||
try:
|
||||
name = crypt.generate_luks_name(conditions.device)
|
||||
except ValueError as e:
|
||||
module.fail_json(msg="luks_device error: %s" % e)
|
||||
module.fail_json(msg=f"luks_device error: {e}")
|
||||
if not module.check_mode:
|
||||
try:
|
||||
crypt.run_luks_open(
|
||||
@@ -1235,7 +1222,7 @@ def run_module():
|
||||
name,
|
||||
)
|
||||
except ValueError as e:
|
||||
module.fail_json(msg="luks_device error: %s" % e)
|
||||
module.fail_json(msg=f"luks_device error: {e}")
|
||||
result["name"] = name
|
||||
result["changed"] = True
|
||||
if module.check_mode:
|
||||
@@ -1247,14 +1234,14 @@ def run_module():
|
||||
try:
|
||||
name = crypt.get_container_name_by_device(conditions.device)
|
||||
except ValueError as e:
|
||||
module.fail_json(msg="luks_device error: %s" % e)
|
||||
module.fail_json(msg=f"luks_device error: {e}")
|
||||
else:
|
||||
name = module.params["name"]
|
||||
if not module.check_mode:
|
||||
try:
|
||||
crypt.run_luks_close(name)
|
||||
except ValueError as e:
|
||||
module.fail_json(msg="luks_device error: %s" % e)
|
||||
module.fail_json(msg=f"luks_device error: {e}")
|
||||
result["name"] = name
|
||||
result["changed"] = True
|
||||
if module.check_mode:
|
||||
@@ -1274,7 +1261,7 @@ def run_module():
|
||||
module.params["pbkdf"],
|
||||
)
|
||||
except ValueError as e:
|
||||
module.fail_json(msg="luks_device error: %s" % e)
|
||||
module.fail_json(msg=f"luks_device error: {e}")
|
||||
result["changed"] = True
|
||||
if module.check_mode:
|
||||
module.exit_json(**result)
|
||||
@@ -1292,7 +1279,7 @@ def run_module():
|
||||
force_remove_last_key=last_key,
|
||||
)
|
||||
except ValueError as e:
|
||||
module.fail_json(msg="luks_device error: %s" % e)
|
||||
module.fail_json(msg=f"luks_device error: {e}")
|
||||
result["changed"] = True
|
||||
if module.check_mode:
|
||||
module.exit_json(**result)
|
||||
@@ -1303,7 +1290,7 @@ def run_module():
|
||||
try:
|
||||
crypt.run_luks_remove(conditions.device)
|
||||
except ValueError as e:
|
||||
module.fail_json(msg="luks_device error: %s" % e)
|
||||
module.fail_json(msg=f"luks_device error: {e}")
|
||||
result["changed"] = True
|
||||
if module.check_mode:
|
||||
module.exit_json(**result)
|
||||
|
||||
@@ -360,7 +360,7 @@ class Certificate(OpensshModule):
|
||||
elif LooseVersion(ssh_version) < LooseVersion("7.6"):
|
||||
self.module.fail_json(
|
||||
msg="Signing with CA key in ssh agent requires ssh 7.6 or newer."
|
||||
+ " Your version is: %s" % ssh_version
|
||||
+ f" Your version is: {ssh_version}"
|
||||
)
|
||||
|
||||
def _exists(self):
|
||||
@@ -371,10 +371,8 @@ class Certificate(OpensshModule):
|
||||
self.original_data = OpensshCertificate.load(self.path)
|
||||
except (TypeError, ValueError) as e:
|
||||
if self.regenerate in ("never", "fail"):
|
||||
self.module.fail_json(
|
||||
msg="Unable to read existing certificate: %s" % to_native(e)
|
||||
)
|
||||
self.module.warn("Unable to read existing certificate: %s" % to_native(e))
|
||||
self.module.fail_json(msg=f"Unable to read existing certificate: {e}")
|
||||
self.module.warn(f"Unable to read existing certificate: {e}")
|
||||
|
||||
def _set_time_parameters(self):
|
||||
try:
|
||||
@@ -486,15 +484,13 @@ class Certificate(OpensshModule):
|
||||
self._safe_secure_move([(temp_certificate, self.path)])
|
||||
except OSError as e:
|
||||
self.module.fail_json(
|
||||
msg="Unable to write certificate to %s: %s" % (self.path, to_native(e))
|
||||
msg=f"Unable to write certificate to {self.path}: {e}"
|
||||
)
|
||||
|
||||
try:
|
||||
self.data = OpensshCertificate.load(self.path)
|
||||
except (TypeError, ValueError) as e:
|
||||
self.module.fail_json(
|
||||
msg="Unable to read new certificate: %s" % to_native(e)
|
||||
)
|
||||
self.module.fail_json(msg=f"Unable to read new certificate: {e}")
|
||||
|
||||
def _generate_temp_certificate(self):
|
||||
key_copy = os.path.join(self.module.tmpdir, os.path.basename(self.public_key))
|
||||
@@ -502,9 +498,7 @@ class Certificate(OpensshModule):
|
||||
try:
|
||||
self.module.preserved_copy(self.public_key, key_copy)
|
||||
except OSError as e:
|
||||
self.module.fail_json(
|
||||
msg="Unable to stage temporary key: %s" % to_native(e)
|
||||
)
|
||||
self.module.fail_json(msg=f"Unable to stage temporary key: {e}")
|
||||
self.module.add_cleanup_file(key_copy)
|
||||
|
||||
self.ssh_keygen.generate_certificate(
|
||||
@@ -535,7 +529,7 @@ class Certificate(OpensshModule):
|
||||
os.remove(self.path)
|
||||
except OSError as e:
|
||||
self.module.fail_json(
|
||||
msg="Unable to remove existing certificate: %s" % to_native(e)
|
||||
msg=f"Unable to remove existing certificate: {to_native(e)}"
|
||||
)
|
||||
|
||||
@property
|
||||
|
||||
@@ -337,8 +337,7 @@ def main():
|
||||
if not os.path.isdir(base_dir):
|
||||
module.fail_json(
|
||||
name=base_dir,
|
||||
msg="The directory %s does not exist or the file is not a directory"
|
||||
% base_dir,
|
||||
msg=f"The directory {base_dir} does not exist or the file is not a directory",
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@@ -341,9 +341,7 @@ def main():
|
||||
with open(module.params["path"], "rb") as f:
|
||||
data = f.read()
|
||||
except (IOError, OSError) as e:
|
||||
module.fail_json(
|
||||
msg="Error while reading CSR file from disk: {0}".format(e)
|
||||
)
|
||||
module.fail_json(msg=f"Error while reading CSR file from disk: {e}")
|
||||
|
||||
backend, module_backend = select_backend(
|
||||
module, module.params["select_crypto_backend"], data, validate_signature=True
|
||||
|
||||
@@ -285,7 +285,7 @@ class DHParameterOpenSSL(DHParameterBase):
|
||||
try:
|
||||
module.atomic_move(os.path.abspath(tmpsrc), os.path.abspath(self.path))
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to write to file %s: %s" % (self.path, str(e)))
|
||||
module.fail_json(msg=f"Failed to write to file {self.path}: {str(e)}")
|
||||
|
||||
def _check_params_valid(self, module):
|
||||
"""Check if the params are in the correct state"""
|
||||
@@ -381,8 +381,7 @@ def main():
|
||||
if not os.path.isdir(base_dir):
|
||||
module.fail_json(
|
||||
name=base_dir,
|
||||
msg="The directory '%s' does not exist or the file is not a directory"
|
||||
% base_dir,
|
||||
msg=f"The directory '{base_dir}' does not exist or the file is not a directory",
|
||||
)
|
||||
|
||||
if module.params["state"] == "present":
|
||||
@@ -405,9 +404,9 @@ def main():
|
||||
if backend == "auto":
|
||||
module.fail_json(
|
||||
msg=(
|
||||
"Cannot detect either the required Python library cryptography (>= {0}) "
|
||||
f"Cannot detect either the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION}) "
|
||||
"or the OpenSSL binary openssl"
|
||||
).format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
)
|
||||
)
|
||||
|
||||
if backend == "openssl":
|
||||
@@ -416,7 +415,7 @@ def main():
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"
|
||||
),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
|
||||
@@ -737,24 +737,20 @@ def select_backend(module, backend):
|
||||
# Success?
|
||||
if backend == "auto":
|
||||
module.fail_json(
|
||||
msg=(
|
||||
"Cannot detect the required Python library cryptography (>= {0})"
|
||||
).format(
|
||||
MINIMAL_CRYPTOGRAPHY_VERSION,
|
||||
)
|
||||
msg=f"Cannot detect the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})"
|
||||
)
|
||||
|
||||
if backend == "cryptography":
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"
|
||||
),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
return backend, PkcsCryptography(module)
|
||||
else:
|
||||
raise ValueError("Unsupported value for backend: {0}".format(backend))
|
||||
raise ValueError(f"Unsupported value for backend: {backend}")
|
||||
|
||||
|
||||
def main():
|
||||
@@ -812,8 +808,7 @@ def main():
|
||||
if not os.path.isdir(base_dir):
|
||||
module.fail_json(
|
||||
name=base_dir,
|
||||
msg="The directory '%s' does not exist or the path is not a directory"
|
||||
% base_dir,
|
||||
msg=f"The directory '{base_dir}' does not exist or the path is not a directory",
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -862,7 +857,7 @@ def main():
|
||||
result = pkcs12.dump()
|
||||
result["changed"] = changed
|
||||
if os.path.exists(module.params["path"]):
|
||||
file_mode = "%04o" % stat.S_IMODE(os.stat(module.params["path"]).st_mode)
|
||||
file_mode = f"{stat.S_IMODE(os.stat(module.params['path']).st_mode):04o}"
|
||||
result["mode"] = file_mode
|
||||
|
||||
module.exit_json(**result)
|
||||
|
||||
@@ -268,8 +268,7 @@ def main():
|
||||
if not os.path.isdir(base_dir):
|
||||
module.fail_json(
|
||||
name=base_dir,
|
||||
msg="The directory %s does not exist or the file is not a directory"
|
||||
% base_dir,
|
||||
msg=f"The directory {base_dir} does not exist or the file is not a directory",
|
||||
)
|
||||
|
||||
backend, module_backend = select_backend(
|
||||
|
||||
@@ -146,8 +146,7 @@ def main():
|
||||
if not os.path.isdir(base_dir):
|
||||
module.fail_json(
|
||||
name=base_dir,
|
||||
msg="The directory %s does not exist or the file is not a directory"
|
||||
% base_dir,
|
||||
msg=f"The directory {base_dir} does not exist or the file is not a directory",
|
||||
)
|
||||
|
||||
module_backend = select_backend(module=module)
|
||||
|
||||
@@ -242,8 +242,7 @@ def main():
|
||||
data = f.read()
|
||||
except (IOError, OSError) as e:
|
||||
module.fail_json(
|
||||
msg="Error while reading private key file from disk: {0}".format(e),
|
||||
**result,
|
||||
msg=f"Error while reading private key file from disk: {e}", **result
|
||||
)
|
||||
|
||||
result["can_load_key"] = True
|
||||
|
||||
@@ -301,7 +301,7 @@ class PublicKey(OpenSSLObject):
|
||||
|
||||
if self.privatekey_content is None and not os.path.exists(self.privatekey_path):
|
||||
raise PublicKeyError(
|
||||
"The private key %s does not exist" % self.privatekey_path
|
||||
f"The private key {self.privatekey_path} does not exist"
|
||||
)
|
||||
|
||||
if not self.check(module, perms_required=False) or self.force:
|
||||
@@ -461,9 +461,7 @@ def main():
|
||||
# Success?
|
||||
if backend == "auto":
|
||||
module.fail_json(
|
||||
msg=(
|
||||
"Cannot detect the required Python library " "cryptography (>= {0})"
|
||||
).format(minimal_cryptography_version)
|
||||
msg=f"Cannot detect the required Python library cryptography (>= {minimal_cryptography_version})",
|
||||
)
|
||||
|
||||
if module.params["format"] == "OpenSSH" and backend != "cryptography":
|
||||
@@ -473,7 +471,7 @@ def main():
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(minimal_cryptography_version)
|
||||
f"cryptography >= {minimal_cryptography_version}"
|
||||
),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
@@ -482,8 +480,7 @@ def main():
|
||||
if not os.path.isdir(base_dir):
|
||||
module.fail_json(
|
||||
name=base_dir,
|
||||
msg="The directory '%s' does not exist or the file is not a directory"
|
||||
% base_dir,
|
||||
msg=f"The directory '{base_dir}' does not exist or the file is not a directory",
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@@ -190,8 +190,7 @@ def main():
|
||||
data = f.read()
|
||||
except (IOError, OSError) as e:
|
||||
module.fail_json(
|
||||
msg="Error while reading public key file from disk: {0}".format(e),
|
||||
**result,
|
||||
msg=f"Error while reading public key file from disk: {e}", **result
|
||||
)
|
||||
|
||||
backend, module_backend = select_backend(
|
||||
|
||||
@@ -230,9 +230,7 @@ class SignatureCryptography(SignatureBase):
|
||||
|
||||
if signature is None:
|
||||
self.module.fail_json(
|
||||
msg="Unsupported key type. Your cryptography version is {0}".format(
|
||||
CRYPTOGRAPHY_VERSION
|
||||
)
|
||||
msg=f"Unsupported key type. Your cryptography version is {CRYPTOGRAPHY_VERSION}"
|
||||
)
|
||||
|
||||
result["signature"] = base64.b64encode(signature)
|
||||
@@ -261,7 +259,7 @@ def main():
|
||||
if not os.path.isfile(module.params["path"]):
|
||||
module.fail_json(
|
||||
name=module.params["path"],
|
||||
msg="The file {0} does not exist".format(module.params["path"]),
|
||||
msg=f"The file {module.params['path']} does not exist",
|
||||
)
|
||||
|
||||
backend = module.params["select_crypto_backend"]
|
||||
@@ -279,16 +277,14 @@ def main():
|
||||
# Success?
|
||||
if backend == "auto":
|
||||
module.fail_json(
|
||||
msg=(
|
||||
"Cannot detect the required Python library " "cryptography (>= {0})"
|
||||
).format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
msg=f"Cannot detect the required Python library cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})",
|
||||
)
|
||||
try:
|
||||
if backend == "cryptography":
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"
|
||||
),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
|
||||
@@ -252,9 +252,7 @@ class SignatureInfoCryptography(SignatureInfoBase):
|
||||
|
||||
if not verified:
|
||||
self.module.fail_json(
|
||||
msg="Unsupported key type. Your cryptography version is {0}".format(
|
||||
CRYPTOGRAPHY_VERSION
|
||||
)
|
||||
msg=f"Unsupported key type. Your cryptography version is {CRYPTOGRAPHY_VERSION}"
|
||||
)
|
||||
result["valid"] = valid
|
||||
return result
|
||||
@@ -282,7 +280,7 @@ def main():
|
||||
if not os.path.isfile(module.params["path"]):
|
||||
module.fail_json(
|
||||
name=module.params["path"],
|
||||
msg="The file {0} does not exist".format(module.params["path"]),
|
||||
msg=f"The file {module.params['path']} does not exist",
|
||||
)
|
||||
|
||||
backend = module.params["select_crypto_backend"]
|
||||
@@ -300,17 +298,14 @@ def main():
|
||||
# Success?
|
||||
if backend == "auto":
|
||||
module.fail_json(
|
||||
msg=(
|
||||
"Cannot detect any of the required Python libraries "
|
||||
"cryptography (>= {0})"
|
||||
).format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
msg=f"Cannot detect any of the required Python libraries cryptography (>= {MINIMAL_CRYPTOGRAPHY_VERSION})"
|
||||
)
|
||||
try:
|
||||
if backend == "cryptography":
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"
|
||||
),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
|
||||
@@ -386,8 +386,7 @@ def main():
|
||||
if not os.path.isdir(base_dir):
|
||||
module.fail_json(
|
||||
name=base_dir,
|
||||
msg="The directory %s does not exist or the file is not a directory"
|
||||
% base_dir,
|
||||
msg=f"The directory {base_dir} does not exist or the file is not a directory",
|
||||
)
|
||||
|
||||
provider = module.params["provider"]
|
||||
|
||||
@@ -152,16 +152,12 @@ def parse_certificate(input, strict=False):
|
||||
pems = split_pem_list(to_text(input))
|
||||
if len(pems) > 1 and strict:
|
||||
raise ValueError(
|
||||
"The input contains {count} PEM objects, expecting only one since strict=true".format(
|
||||
count=len(pems)
|
||||
)
|
||||
f"The input contains {len(pems)} PEM objects, expecting only one since strict=true"
|
||||
)
|
||||
pem_header_type, content = extract_pem(pems[0], strict=strict)
|
||||
if strict and pem_header_type not in ("CERTIFICATE", "X509 CERTIFICATE"):
|
||||
raise ValueError(
|
||||
"type is {type!r}, expecting CERTIFICATE or X509 CERTIFICATE".format(
|
||||
type=pem_header_type
|
||||
)
|
||||
f"type is {pem_header_type!r}, expecting CERTIFICATE or X509 CERTIFICATE"
|
||||
)
|
||||
input = base64.b64decode(content)
|
||||
else:
|
||||
@@ -187,18 +183,14 @@ class X509CertificateConvertModule(OpenSSLObject):
|
||||
try:
|
||||
self.input = base64.b64decode(self.input)
|
||||
except Exception as exc:
|
||||
module.fail_json(
|
||||
msg="Cannot Base64 decode src_content: {exc}".format(exc=exc)
|
||||
)
|
||||
module.fail_json(msg=f"Cannot Base64 decode src_content: {exc}")
|
||||
else:
|
||||
try:
|
||||
with open(self.src_path, "rb") as f:
|
||||
self.input = f.read()
|
||||
except Exception as exc:
|
||||
module.fail_json(
|
||||
msg="Failure while reading file {fn}: {exc}".format(
|
||||
fn=self.src_path, exc=exc
|
||||
)
|
||||
msg=f"Failure while reading file {self.src_path}: {exc}"
|
||||
)
|
||||
|
||||
self.format = module.params["format"]
|
||||
@@ -210,7 +202,7 @@ class X509CertificateConvertModule(OpenSSLObject):
|
||||
self.input, strict=self.strict
|
||||
)
|
||||
except Exception as exc:
|
||||
module.fail_json(msg="Error while parsing PEM: {exc}".format(exc=exc))
|
||||
module.fail_json(msg=f"Error while parsing PEM: {exc}")
|
||||
|
||||
if module.params["verify_cert_parsable"]:
|
||||
self.verify_cert_parsable(module)
|
||||
@@ -237,16 +229,14 @@ class X509CertificateConvertModule(OpenSSLObject):
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"
|
||||
),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
try:
|
||||
load_der_x509_certificate(self.input, default_backend())
|
||||
except Exception as exc:
|
||||
module.fail_json(
|
||||
msg="Error while parsing certificate: {exc}".format(exc=exc)
|
||||
)
|
||||
module.fail_json(msg=f"Error while parsing certificate: {exc}")
|
||||
|
||||
def needs_conversion(self):
|
||||
if self.dest_content is None or self.dest_content_format is None:
|
||||
@@ -263,11 +253,9 @@ class X509CertificateConvertModule(OpenSSLObject):
|
||||
if self.format == "der":
|
||||
return self.input
|
||||
data = to_bytes(base64.b64encode(self.input))
|
||||
lines = [to_bytes("{0}{1}{2}".format(PEM_START, self.wanted_pem_type, PEM_END))]
|
||||
lines = [to_bytes(f"{PEM_START}{self.wanted_pem_type}{PEM_END}")]
|
||||
lines += [data[i : i + 64] for i in range(0, len(data), 64)]
|
||||
lines.append(
|
||||
to_bytes("{0}{1}{2}\n".format(PEM_END_START, self.wanted_pem_type, PEM_END))
|
||||
)
|
||||
lines.append(to_bytes(f"{PEM_END_START}{self.wanted_pem_type}{PEM_END}\n"))
|
||||
return b"\n".join(lines)
|
||||
|
||||
def generate(self, module):
|
||||
@@ -323,8 +311,7 @@ def main():
|
||||
if not os.path.isdir(base_dir):
|
||||
module.fail_json(
|
||||
name=base_dir,
|
||||
msg="The directory %s does not exist or the file is not a directory"
|
||||
% base_dir,
|
||||
msg=f"The directory {base_dir} does not exist or the file is not a directory",
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@@ -431,9 +431,7 @@ def main():
|
||||
with open(module.params["path"], "rb") as f:
|
||||
data = f.read()
|
||||
except (IOError, OSError) as e:
|
||||
module.fail_json(
|
||||
msg="Error while reading certificate file from disk: {0}".format(e)
|
||||
)
|
||||
module.fail_json(msg=f"Error while reading certificate file from disk: {e}")
|
||||
|
||||
backend, module_backend = select_backend(
|
||||
module, module.params["select_crypto_backend"], data
|
||||
@@ -444,12 +442,10 @@ def main():
|
||||
for k, v in valid_at.items():
|
||||
if not isinstance(v, string_types):
|
||||
module.fail_json(
|
||||
msg="The value for valid_at.{0} must be of type string (got {1})".format(
|
||||
k, type(v)
|
||||
)
|
||||
msg=f"The value for valid_at.{k} must be of type string (got {type(v)})"
|
||||
)
|
||||
valid_at[k] = get_relative_time_option(
|
||||
v, "valid_at.{0}".format(k), with_timezone=CRYPTOGRAPHY_TIMEZONE
|
||||
v, f"valid_at.{k}", with_timezone=CRYPTOGRAPHY_TIMEZONE
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@@ -560,9 +560,7 @@ class CRL(OpenSSLObject):
|
||||
|
||||
self.digest = select_message_digest(module.params["digest"])
|
||||
if self.digest is None:
|
||||
raise CRLError(
|
||||
'The digest "{0}" is not supported'.format(module.params["digest"])
|
||||
)
|
||||
raise CRLError(f'The digest "{module.params["digest"]}" is not supported')
|
||||
|
||||
self.module = module
|
||||
|
||||
@@ -578,7 +576,7 @@ class CRL(OpenSSLObject):
|
||||
"invalidity_date": None,
|
||||
"invalidity_date_critical": False,
|
||||
}
|
||||
path_prefix = "revoked_certificates[{0}].".format(i)
|
||||
path_prefix = f"revoked_certificates[{i}]."
|
||||
if rc["path"] is not None or rc["content"] is not None:
|
||||
# Load certificate from file or content
|
||||
try:
|
||||
@@ -591,15 +589,11 @@ class CRL(OpenSSLObject):
|
||||
except OpenSSLObjectError as e:
|
||||
if rc["content"] is not None:
|
||||
module.fail_json(
|
||||
msg="Cannot parse certificate from {0}content: {1}".format(
|
||||
path_prefix, to_native(e)
|
||||
)
|
||||
msg=f"Cannot parse certificate from {path_prefix}content: {e}"
|
||||
)
|
||||
else:
|
||||
module.fail_json(
|
||||
msg='Cannot read certificate "{1}" from {0}path: {2}'.format(
|
||||
path_prefix, rc["path"], to_native(e)
|
||||
)
|
||||
msg=f'Cannot read certificate "{rc["path"]}" from {path_prefix}path: {e}'
|
||||
)
|
||||
else:
|
||||
# Specify serial_number (and potentially issuer) directly
|
||||
@@ -668,23 +662,17 @@ class CRL(OpenSSLObject):
|
||||
return check_type_int(value)
|
||||
except TypeError as exc:
|
||||
self.module.fail_json(
|
||||
msg="Error while parsing revoked_certificates[{idx}].serial_number as an integer: {exc}".format(
|
||||
idx=index + 1,
|
||||
exc=to_native(exc),
|
||||
)
|
||||
msg=f"Error while parsing revoked_certificates[{index + 1}].serial_number as an integer: {exc}"
|
||||
)
|
||||
if self.serial_numbers_format == "hex-octets":
|
||||
try:
|
||||
return parse_serial(check_type_str(value))
|
||||
except (TypeError, ValueError) as exc:
|
||||
self.module.fail_json(
|
||||
msg="Error while parsing revoked_certificates[{idx}].serial_number as an colon-separated hex octet string: {exc}".format(
|
||||
idx=index + 1,
|
||||
exc=to_native(exc),
|
||||
)
|
||||
msg=f"Error while parsing revoked_certificates[{index + 1}].serial_number as an colon-separated hex octet string: {exc}"
|
||||
)
|
||||
raise RuntimeError(
|
||||
"Unexpected value %s of serial_numbers" % (self.serial_numbers_format,)
|
||||
f"Unexpected value {self.serial_numbers_format} of serial_numbers"
|
||||
)
|
||||
|
||||
def _get_info(self, data):
|
||||
@@ -1026,9 +1014,7 @@ def main():
|
||||
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
"cryptography >= {0}".format(MINIMAL_CRYPTOGRAPHY_VERSION)
|
||||
),
|
||||
msg=missing_required_lib(f"cryptography >= {MINIMAL_CRYPTOGRAPHY_VERSION}"),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR,
|
||||
)
|
||||
|
||||
|
||||
@@ -207,18 +207,14 @@ def main():
|
||||
with open(module.params["path"], "rb") as f:
|
||||
data = f.read()
|
||||
except (IOError, OSError) as e:
|
||||
module.fail_json(
|
||||
msg="Error while reading CRL file from disk: {0}".format(e)
|
||||
)
|
||||
module.fail_json(msg=f"Error while reading CRL file from disk: {e}")
|
||||
else:
|
||||
data = module.params["content"].encode("utf-8")
|
||||
if not identify_pem_format(data):
|
||||
try:
|
||||
data = base64.b64decode(module.params["content"])
|
||||
except (binascii.Error, TypeError) as e:
|
||||
module.fail_json(
|
||||
msg="Error while Base64 decoding content: {0}".format(e)
|
||||
)
|
||||
module.fail_json(msg=f"Error while Base64 decoding content: {e}")
|
||||
|
||||
try:
|
||||
result = get_crl_info(
|
||||
|
||||
@@ -99,9 +99,7 @@ class AnsibleActionModule:
|
||||
# Before ansible-core 2.14.2, deprecations were always for aliases:
|
||||
if "name" in d:
|
||||
self.deprecate(
|
||||
"Alias '{name}' is deprecated. See the module docs for more information".format(
|
||||
name=d["name"]
|
||||
),
|
||||
f"Alias '{d['name']}' is deprecated. See the module docs for more information",
|
||||
version=d.get("version"),
|
||||
date=d.get("date"),
|
||||
collection_name=d.get("collection_name"),
|
||||
@@ -116,19 +114,13 @@ class AnsibleActionModule:
|
||||
)
|
||||
|
||||
for w in self._validation_result._warnings:
|
||||
self.warn(
|
||||
"Both option {option} and its alias {alias} are set.".format(
|
||||
option=w["option"], alias=w["alias"]
|
||||
)
|
||||
)
|
||||
self.warn(f"Both option {w['option']} and its alias {w['alias']} are set.")
|
||||
|
||||
# Fail for validation errors, even in check mode
|
||||
if error:
|
||||
msg = self._validation_result.errors.msg
|
||||
if isinstance(error, UnsupportedError):
|
||||
msg = "Unsupported parameters for ({name}) {kind}: {msg}".format(
|
||||
name=self._name, kind="module", msg=msg
|
||||
)
|
||||
msg = f"Unsupported parameters for ({self._name}) module: {msg}"
|
||||
|
||||
self.fail_json(msg=msg)
|
||||
|
||||
@@ -140,7 +132,7 @@ class AnsibleActionModule:
|
||||
if isinstance(warning, string_types):
|
||||
self.__warnings.append(warning)
|
||||
else:
|
||||
raise TypeError("warn requires a string not a %s" % type(warning))
|
||||
raise TypeError(f"warn requires a string not a {type(warning)}")
|
||||
|
||||
def deprecate(self, msg, version=None, date=None, collection_name=None):
|
||||
if version is not None and date is not None:
|
||||
@@ -161,7 +153,7 @@ class AnsibleActionModule:
|
||||
{"msg": msg, "version": version, "collection_name": collection_name}
|
||||
)
|
||||
else:
|
||||
raise TypeError("deprecate requires a string not a %s" % type(msg))
|
||||
raise TypeError(f"deprecate requires a string not a {type(msg)}")
|
||||
|
||||
def _return_formatted(self, kwargs):
|
||||
if "invocation" not in kwargs:
|
||||
|
||||
@@ -44,12 +44,9 @@ class PluginGPGRunner(GPGRunner):
|
||||
stdout = to_native(stdout, errors="surrogate_or_replace")
|
||||
stderr = to_native(stderr, errors="surrogate_or_replace")
|
||||
if check_rc and p.returncode != 0:
|
||||
stdout_n = (to_native(stdout, errors="surrogate_or_replace"),)
|
||||
stderr_n = (to_native(stderr, errors="surrogate_or_replace"),)
|
||||
raise GPGError(
|
||||
'Running {cmd} yielded return code {rc} with stdout: "{stdout}" and stderr: "{stderr}")'.format(
|
||||
cmd=" ".join(command),
|
||||
rc=p.returncode,
|
||||
stdout=to_native(stdout, errors="surrogate_or_replace"),
|
||||
stderr=to_native(stderr, errors="surrogate_or_replace"),
|
||||
)
|
||||
f'Running {" ".join(command)} yielded return code {p.returncode} with stdout: "{stdout_n}" and stderr: "{stderr_n}")'
|
||||
)
|
||||
return p.returncode, stdout, stderr
|
||||
|
||||
@@ -78,7 +78,7 @@ TEST_CASES = [
|
||||
@pytest.mark.parametrize("value, expected", TEST_CASES)
|
||||
def test_serialize_asn1_string_as_der(value, expected):
|
||||
actual = serialize_asn1_string_as_der(value)
|
||||
print("%s | %s" % (value, base64.b16encode(actual).decode()))
|
||||
print(f"{value} | {base64.b16encode(actual).decode()}")
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@@ -121,10 +121,8 @@ def test_test_cases(value, expected, tmp_path):
|
||||
b_data = fd.read()
|
||||
|
||||
hex_str = base64.b16encode(b_data).decode().lower()
|
||||
print(
|
||||
"%s | \\x%s"
|
||||
% (value, "\\x".join([hex_str[i : i + 2] for i in range(0, len(hex_str), 2)]))
|
||||
)
|
||||
value = "\\x".join([hex_str[i : i + 2] for i in range(0, len(hex_str), 2)])
|
||||
print(f"{value} | \\x{value}")
|
||||
|
||||
# This is a know edge case where openssl asn1parse does not work properly.
|
||||
if value != "UTF8:café":
|
||||
|
||||
@@ -201,7 +201,7 @@ if (
|
||||
],
|
||||
)
|
||||
def test_parse_dn_component_failure(name, options, message):
|
||||
with pytest.raises(OpenSSLObjectError, match="^%s$" % re.escape(message)):
|
||||
with pytest.raises(OpenSSLObjectError, match=f"^{re.escape(message)}$"):
|
||||
_parse_dn_component(name, **options)
|
||||
|
||||
|
||||
@@ -245,5 +245,5 @@ def test_parse_dn(name, expected):
|
||||
],
|
||||
)
|
||||
def test_parse_dn_failure(name, message):
|
||||
with pytest.raises(OpenSSLObjectError, match="^%s$" % re.escape(message)):
|
||||
with pytest.raises(OpenSSLObjectError, match=f"^{re.escape(message)}$"):
|
||||
_parse_dn(name)
|
||||
|
||||
@@ -144,7 +144,7 @@ def test_default_key_params(keytype, size, passphrase, comment):
|
||||
"ed25519": 256,
|
||||
}
|
||||
|
||||
default_comment = "%s@%s" % (getuser(), gethostname())
|
||||
default_comment = f"{getuser()}@{gethostname()}"
|
||||
pair = OpensshKeypair.generate(
|
||||
keytype=keytype, size=size, passphrase=passphrase, comment=comment
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user