mirror of
https://github.com/ansible-collections/community.crypto.git
synced 2026-05-06 13:22:58 +00:00
Work on issues found by pylint (#896)
* Look at possibly-used-before-assignment. * Use latest beta releases of ansible-core 2.19 for mypy and pylint. * Look at unsupported-*. * Look at unknown-option-value. * Look at redefined-builtin. * Look at superfluous-parens. * Look at unspecified-encoding. * Adjust to new cryptography version and to ansible-core 2.17's pylint. * Look at super-with-arguments. * Look at no-else-*. * Look at try-except-raise. * Look at inconsistent-return-statements. * Look at redefined-outer-name. * Look at redefined-argument-from-local. * Look at attribute-defined-outside-init. * Look at unused-variable. * Look at protected-access. * Look at raise-missing-from. * Look at arguments-differ. * Look at useless-suppression and use-symbolic-message-instead. * Look at consider-using-dict-items. * Look at consider-using-in. * Look at consider-using-set-comprehension. * Look at consider-using-with. * Look at use-dict-literal.
This commit is contained in:
@@ -184,25 +184,29 @@ from ansible_collections.community.crypto.plugins.module_utils._acme.errors impo
|
||||
def main() -> t.NoReturn:
|
||||
argument_spec = create_default_argspec()
|
||||
argument_spec.update_argspec(
|
||||
terms_agreed=dict(type="bool", default=False),
|
||||
state=dict(
|
||||
type="str", required=True, choices=["absent", "present", "changed_key"]
|
||||
),
|
||||
allow_creation=dict(type="bool", default=True),
|
||||
contact=dict(type="list", elements="str", default=[]),
|
||||
new_account_key_src=dict(type="path"),
|
||||
new_account_key_content=dict(type="str", no_log=True),
|
||||
new_account_key_passphrase=dict(type="str", no_log=True),
|
||||
external_account_binding=dict(
|
||||
type="dict",
|
||||
options=dict(
|
||||
kid=dict(type="str", required=True),
|
||||
alg=dict(
|
||||
type="str", required=True, choices=["HS256", "HS384", "HS512"]
|
||||
),
|
||||
key=dict(type="str", required=True, no_log=True),
|
||||
),
|
||||
),
|
||||
terms_agreed={"type": "bool", "default": False},
|
||||
state={
|
||||
"type": "str",
|
||||
"required": True,
|
||||
"choices": ["absent", "present", "changed_key"],
|
||||
},
|
||||
allow_creation={"type": "bool", "default": True},
|
||||
contact={"type": "list", "elements": "str", "default": []},
|
||||
new_account_key_src={"type": "path"},
|
||||
new_account_key_content={"type": "str", "no_log": True},
|
||||
new_account_key_passphrase={"type": "str", "no_log": True},
|
||||
external_account_binding={
|
||||
"type": "dict",
|
||||
"options": {
|
||||
"kid": {"type": "str", "required": True},
|
||||
"alg": {
|
||||
"type": "str",
|
||||
"required": True,
|
||||
"choices": ["HS256", "HS384", "HS512"],
|
||||
},
|
||||
"key": {"type": "str", "required": True, "no_log": True},
|
||||
},
|
||||
},
|
||||
)
|
||||
argument_spec.update(
|
||||
mutually_exclusive=[("new_account_key_src", "new_account_key_content")],
|
||||
@@ -254,7 +258,7 @@ def main() -> t.NoReturn:
|
||||
if not module.check_mode:
|
||||
# Deactivate it
|
||||
deactivate_payload = {"status": "deactivated"}
|
||||
result, info = client.send_signed_request(
|
||||
result, _info = client.send_signed_request(
|
||||
t.cast(str, client.account_uri),
|
||||
deactivate_payload,
|
||||
error_msg="Failed to deactivate account",
|
||||
@@ -302,7 +306,7 @@ def main() -> t.NoReturn:
|
||||
except KeyParsingError as e:
|
||||
raise ModuleFailException(
|
||||
f"Error while parsing new account key: {e.msg}"
|
||||
)
|
||||
) from e
|
||||
# Verify that the account exists and has not been deactivated
|
||||
created, account_data = account.setup_account(allow_creation=False)
|
||||
if created:
|
||||
@@ -335,18 +339,18 @@ def main() -> t.NoReturn:
|
||||
key_data=new_key_data,
|
||||
)
|
||||
# Send request and verify result
|
||||
result, info = client.send_signed_request(
|
||||
result, _info = client.send_signed_request(
|
||||
url,
|
||||
data,
|
||||
error_msg="Failed to rollover account key",
|
||||
expected_status_codes=[200],
|
||||
)
|
||||
if module._diff:
|
||||
if module._diff: # pylint: disable=protected-access
|
||||
client.account_key_data = new_key_data
|
||||
if client.account_jws_header:
|
||||
client.account_jws_header["alg"] = new_key_data["alg"]
|
||||
diff_after = account.get_account_data() or {}
|
||||
elif module._diff:
|
||||
elif module._diff: # pylint: disable=protected-access
|
||||
# Kind of fake diff_after
|
||||
diff_after = dict(diff_before)
|
||||
diff_after["public_account_key"] = new_key_data["jwk"]
|
||||
@@ -355,7 +359,7 @@ def main() -> t.NoReturn:
|
||||
"changed": changed,
|
||||
"account_uri": client.account_uri,
|
||||
}
|
||||
if module._diff:
|
||||
if module._diff: # pylint: disable=protected-access
|
||||
result["diff"] = {
|
||||
"before": diff_before,
|
||||
"after": diff_after,
|
||||
|
||||
@@ -273,9 +273,11 @@ def get_order(client: ACMEClient, order_url: str) -> dict[str, t.Any]:
|
||||
def main() -> t.NoReturn:
|
||||
argument_spec = create_default_argspec()
|
||||
argument_spec.update_argspec(
|
||||
retrieve_orders=dict(
|
||||
type="str", default="ignore", choices=["ignore", "url_list", "object_list"]
|
||||
),
|
||||
retrieve_orders={
|
||||
"type": "str",
|
||||
"default": "ignore",
|
||||
"choices": ["ignore", "url_list", "object_list"],
|
||||
},
|
||||
)
|
||||
module = argument_spec.create_ansible_module(supports_check_mode=True)
|
||||
backend = create_backend(module, needs_acme_v2=True)
|
||||
|
||||
@@ -109,8 +109,8 @@ from ansible_collections.community.crypto.plugins.module_utils._acme.errors impo
|
||||
def main() -> t.NoReturn:
|
||||
argument_spec = create_default_argspec(with_account=False)
|
||||
argument_spec.update_argspec(
|
||||
certificate_path=dict(type="path"),
|
||||
certificate_content=dict(type="str"),
|
||||
certificate_path={"type": "path"},
|
||||
certificate_content={"type": "str"},
|
||||
)
|
||||
argument_spec.update(
|
||||
required_one_of=[("certificate_path", "certificate_content")],
|
||||
|
||||
@@ -578,7 +578,6 @@ from ansible_collections.community.crypto.plugins.module_utils._acme.certificate
|
||||
from ansible_collections.community.crypto.plugins.module_utils._acme.challenges import (
|
||||
combine_identifier,
|
||||
normalize_combined_identifier,
|
||||
split_identifier,
|
||||
wait_for_validation,
|
||||
)
|
||||
from ansible_collections.community.crypto.plugins.module_utils._acme.errors import (
|
||||
@@ -760,7 +759,6 @@ class ACMECertificateClient:
|
||||
data: dict[str, t.Any] = {}
|
||||
data_dns: dict[str, list[str]] = {}
|
||||
for type_identifier, authz in self.authorizations.items():
|
||||
identifier_type, identifier = split_identifier(type_identifier)
|
||||
# Skip valid authentications: their challenges are already valid
|
||||
# and do not need to be returned
|
||||
if authz.status == "valid":
|
||||
@@ -802,7 +800,7 @@ class ACMECertificateClient:
|
||||
|
||||
# Step 2: validate pending challenges
|
||||
authzs_to_wait_for = []
|
||||
for type_identifier, authz in self.authorizations.items():
|
||||
for authz in self.authorizations.values():
|
||||
if authz.status == "pending":
|
||||
if self.challenge is not None:
|
||||
authz.call_validate(
|
||||
@@ -951,52 +949,54 @@ def main() -> t.NoReturn:
|
||||
argument_spec = create_default_argspec(with_certificate=True)
|
||||
argument_spec.argument_spec["csr"]["aliases"] = ["src"]
|
||||
argument_spec.update_argspec(
|
||||
modify_account=dict(type="bool", default=True),
|
||||
account_email=dict(type="str"),
|
||||
agreement=dict(
|
||||
type="str",
|
||||
removed_in_version="4.0.0",
|
||||
removed_from_collection="community.crypto",
|
||||
),
|
||||
terms_agreed=dict(type="bool", default=False),
|
||||
challenge=dict(
|
||||
type="str",
|
||||
default="http-01",
|
||||
choices=["http-01", "dns-01", "tls-alpn-01", NO_CHALLENGE],
|
||||
),
|
||||
data=dict(type="dict"),
|
||||
dest=dict(type="path", aliases=["cert"]),
|
||||
fullchain_dest=dict(type="path", aliases=["fullchain"]),
|
||||
chain_dest=dict(type="path", aliases=["chain"]),
|
||||
remaining_days=dict(type="int", default=10),
|
||||
deactivate_authzs=dict(type="bool", default=False),
|
||||
force=dict(type="bool", default=False),
|
||||
retrieve_all_alternates=dict(type="bool", default=False),
|
||||
select_chain=dict(
|
||||
type="list",
|
||||
elements="dict",
|
||||
options=dict(
|
||||
test_certificates=dict(
|
||||
type="str", default="all", choices=["first", "last", "all"]
|
||||
),
|
||||
issuer=dict(type="dict"),
|
||||
subject=dict(type="dict"),
|
||||
subject_key_identifier=dict(type="str"),
|
||||
authority_key_identifier=dict(type="str"),
|
||||
),
|
||||
),
|
||||
include_renewal_cert_id=dict(
|
||||
type="str",
|
||||
choices=["never", "when_ari_supported", "always"],
|
||||
default="never",
|
||||
),
|
||||
profile=dict(type="str"),
|
||||
order_creation_error_strategy=dict(
|
||||
type="str",
|
||||
default="auto",
|
||||
choices=["auto", "always", "fail", "retry_without_replaces_cert_id"],
|
||||
),
|
||||
order_creation_max_retries=dict(type="int", default=3),
|
||||
modify_account={"type": "bool", "default": True},
|
||||
account_email={"type": "str"},
|
||||
agreement={
|
||||
"type": "str",
|
||||
"removed_in_version": "4.0.0",
|
||||
"removed_from_collection": "community.crypto",
|
||||
},
|
||||
terms_agreed={"type": "bool", "default": False},
|
||||
challenge={
|
||||
"type": "str",
|
||||
"default": "http-01",
|
||||
"choices": ["http-01", "dns-01", "tls-alpn-01", NO_CHALLENGE],
|
||||
},
|
||||
data={"type": "dict"},
|
||||
dest={"type": "path", "aliases": ["cert"]},
|
||||
fullchain_dest={"type": "path", "aliases": ["fullchain"]},
|
||||
chain_dest={"type": "path", "aliases": ["chain"]},
|
||||
remaining_days={"type": "int", "default": 10},
|
||||
deactivate_authzs={"type": "bool", "default": False},
|
||||
force={"type": "bool", "default": False},
|
||||
retrieve_all_alternates={"type": "bool", "default": False},
|
||||
select_chain={
|
||||
"type": "list",
|
||||
"elements": "dict",
|
||||
"options": {
|
||||
"test_certificates": {
|
||||
"type": "str",
|
||||
"default": "all",
|
||||
"choices": ["first", "last", "all"],
|
||||
},
|
||||
"issuer": {"type": "dict"},
|
||||
"subject": {"type": "dict"},
|
||||
"subject_key_identifier": {"type": "str"},
|
||||
"authority_key_identifier": {"type": "str"},
|
||||
},
|
||||
},
|
||||
include_renewal_cert_id={
|
||||
"type": "str",
|
||||
"choices": ["never", "when_ari_supported", "always"],
|
||||
"default": "never",
|
||||
},
|
||||
profile={"type": "str"},
|
||||
order_creation_error_strategy={
|
||||
"type": "str",
|
||||
"default": "auto",
|
||||
"choices": ["auto", "always", "fail", "retry_without_replaces_cert_id"],
|
||||
},
|
||||
order_creation_max_retries={"type": "int", "default": 3},
|
||||
)
|
||||
argument_spec.update(
|
||||
required_one_of=[
|
||||
@@ -1045,9 +1045,9 @@ def main() -> t.NoReturn:
|
||||
if module.params["deactivate_authzs"]:
|
||||
client.deactivate_authzs()
|
||||
data, data_dns = client.get_challenges_data(first_step=is_first_step)
|
||||
auths = dict()
|
||||
auths = {}
|
||||
assert client.authorizations is not None
|
||||
for k, v in client.authorizations.items():
|
||||
for v in client.authorizations.values():
|
||||
# Remove "type:" from key
|
||||
auths[v.identifier] = v.to_json()
|
||||
module.exit_json(
|
||||
|
||||
@@ -70,7 +70,7 @@ from ansible_collections.community.crypto.plugins.module_utils._acme.orders impo
|
||||
def main() -> t.NoReturn:
|
||||
argument_spec = create_default_argspec()
|
||||
argument_spec.update_argspec(
|
||||
order_uri=dict(type="str", required=True),
|
||||
order_uri={"type": "str", "required": True},
|
||||
)
|
||||
module = argument_spec.create_ansible_module(supports_check_mode=True)
|
||||
|
||||
|
||||
@@ -388,15 +388,15 @@ from ansible_collections.community.crypto.plugins.module_utils._acme.errors impo
|
||||
def main() -> t.NoReturn:
|
||||
argument_spec = create_default_argspec(with_certificate=True)
|
||||
argument_spec.update_argspec(
|
||||
deactivate_authzs=dict(type="bool", default=True),
|
||||
replaces_cert_id=dict(type="str"),
|
||||
profile=dict(type="str"),
|
||||
order_creation_error_strategy=dict(
|
||||
type="str",
|
||||
default="auto",
|
||||
choices=["auto", "always", "fail", "retry_without_replaces_cert_id"],
|
||||
),
|
||||
order_creation_max_retries=dict(type="int", default=3),
|
||||
deactivate_authzs={"type": "bool", "default": True},
|
||||
replaces_cert_id={"type": "str"},
|
||||
profile={"type": "str"},
|
||||
order_creation_error_strategy={
|
||||
"type": "str",
|
||||
"default": "auto",
|
||||
"choices": ["auto", "always", "fail", "retry_without_replaces_cert_id"],
|
||||
},
|
||||
order_creation_max_retries={"type": "int", "default": 3},
|
||||
)
|
||||
module = argument_spec.create_ansible_module()
|
||||
|
||||
|
||||
@@ -340,29 +340,31 @@ if t.TYPE_CHECKING:
|
||||
def main() -> t.NoReturn:
|
||||
argument_spec = create_default_argspec(with_certificate=True)
|
||||
argument_spec.update_argspec(
|
||||
order_uri=dict(type="str", required=True),
|
||||
cert_dest=dict(type="path"),
|
||||
fullchain_dest=dict(type="path"),
|
||||
chain_dest=dict(type="path"),
|
||||
deactivate_authzs=dict(
|
||||
type="str",
|
||||
default="always",
|
||||
choices=["never", "always", "on_error", "on_success"],
|
||||
),
|
||||
retrieve_all_alternates=dict(type="bool", default=False),
|
||||
select_chain=dict(
|
||||
type="list",
|
||||
elements="dict",
|
||||
options=dict(
|
||||
test_certificates=dict(
|
||||
type="str", default="all", choices=["first", "last", "all"]
|
||||
),
|
||||
issuer=dict(type="dict"),
|
||||
subject=dict(type="dict"),
|
||||
subject_key_identifier=dict(type="str"),
|
||||
authority_key_identifier=dict(type="str"),
|
||||
),
|
||||
),
|
||||
order_uri={"type": "str", "required": True},
|
||||
cert_dest={"type": "path"},
|
||||
fullchain_dest={"type": "path"},
|
||||
chain_dest={"type": "path"},
|
||||
deactivate_authzs={
|
||||
"type": "str",
|
||||
"default": "always",
|
||||
"choices": ["never", "always", "on_error", "on_success"],
|
||||
},
|
||||
retrieve_all_alternates={"type": "bool", "default": False},
|
||||
select_chain={
|
||||
"type": "list",
|
||||
"elements": "dict",
|
||||
"options": {
|
||||
"test_certificates": {
|
||||
"type": "str",
|
||||
"default": "all",
|
||||
"choices": ["first", "last", "all"],
|
||||
},
|
||||
"issuer": {"type": "dict"},
|
||||
"subject": {"type": "dict"},
|
||||
"subject_key_identifier": {"type": "str"},
|
||||
"authority_key_identifier": {"type": "str"},
|
||||
},
|
||||
},
|
||||
)
|
||||
module = argument_spec.create_ansible_module()
|
||||
|
||||
@@ -371,7 +373,7 @@ def main() -> t.NoReturn:
|
||||
try:
|
||||
client = ACMECertificateClient(module=module, backend=backend)
|
||||
select_chain_matcher = client.parse_select_chain(module.params["select_chain"])
|
||||
other = dict()
|
||||
other = {}
|
||||
done = False
|
||||
order = None
|
||||
try:
|
||||
|
||||
@@ -374,7 +374,7 @@ from ansible_collections.community.crypto.plugins.module_utils._acme.errors impo
|
||||
def main() -> t.NoReturn:
|
||||
argument_spec = create_default_argspec(with_certificate=False)
|
||||
argument_spec.update_argspec(
|
||||
order_uri=dict(type="str", required=True),
|
||||
order_uri={"type": "str", "required": True},
|
||||
)
|
||||
module = argument_spec.create_ansible_module(supports_check_mode=True)
|
||||
|
||||
|
||||
@@ -252,9 +252,9 @@ if t.TYPE_CHECKING:
|
||||
def main() -> t.NoReturn:
|
||||
argument_spec = create_default_argspec(with_certificate=False)
|
||||
argument_spec.update_argspec(
|
||||
order_uri=dict(type="str", required=True),
|
||||
challenge=dict(type="str", choices=["http-01", "dns-01", "tls-alpn-01"]),
|
||||
deactivate_authzs=dict(type="bool", default=True),
|
||||
order_uri={"type": "str", "required": True},
|
||||
challenge={"type": "str", "choices": ["http-01", "dns-01", "tls-alpn-01"]},
|
||||
deactivate_authzs={"type": "bool", "default": True},
|
||||
)
|
||||
module = argument_spec.create_ansible_module()
|
||||
|
||||
@@ -330,13 +330,13 @@ def main() -> t.NoReturn:
|
||||
changed=len(authzs_with_challenges_to_wait_for) > 0,
|
||||
account_uri=client.client.account_uri,
|
||||
validating_challenges=[
|
||||
dict(
|
||||
identifier=authz.identifier,
|
||||
identifier_type=authz.identifier_type,
|
||||
authz_url=authz.url,
|
||||
challenge_type=challenge_type,
|
||||
challenge_url=challenge.url if challenge else None,
|
||||
)
|
||||
{
|
||||
"identifier": authz.identifier,
|
||||
"identifier_type": authz.identifier_type,
|
||||
"authz_url": authz.url,
|
||||
"challenge_type": challenge_type,
|
||||
"challenge_url": challenge.url if challenge else None,
|
||||
}
|
||||
for authz, challenge_type, challenge in authzs_with_challenges_to_wait_for
|
||||
],
|
||||
)
|
||||
|
||||
@@ -179,16 +179,18 @@ from ansible_collections.community.crypto.plugins.module_utils._acme.utils impor
|
||||
def main() -> t.NoReturn:
|
||||
argument_spec = create_default_argspec(with_account=False)
|
||||
argument_spec.update_argspec(
|
||||
certificate_path=dict(type="path"),
|
||||
certificate_content=dict(type="str"),
|
||||
use_ari=dict(type="bool", default=True),
|
||||
ari_algorithm=dict(
|
||||
type="str", choices=["standard", "start"], default="standard"
|
||||
),
|
||||
remaining_days=dict(type="int"),
|
||||
remaining_percentage=dict(type="float"),
|
||||
now=dict(type="str"),
|
||||
treat_parsing_error_as_non_existing=dict(type="bool", default=False),
|
||||
certificate_path={"type": "path"},
|
||||
certificate_content={"type": "str"},
|
||||
use_ari={"type": "bool", "default": True},
|
||||
ari_algorithm={
|
||||
"type": "str",
|
||||
"choices": ["standard", "start"],
|
||||
"default": "standard",
|
||||
},
|
||||
remaining_days={"type": "int"},
|
||||
remaining_percentage={"type": "float"},
|
||||
now={"type": "str"},
|
||||
treat_parsing_error_as_non_existing={"type": "bool", "default": False},
|
||||
)
|
||||
argument_spec.update(
|
||||
mutually_exclusive=[("certificate_path", "certificate_content")],
|
||||
@@ -196,13 +198,13 @@ def main() -> t.NoReturn:
|
||||
module = argument_spec.create_ansible_module(supports_check_mode=True)
|
||||
backend = create_backend(module, needs_acme_v2=True)
|
||||
|
||||
result = dict(
|
||||
changed=False,
|
||||
msg="The certificate is still valid and no condition was reached",
|
||||
exists=False,
|
||||
parsable=False,
|
||||
supports_ari=False,
|
||||
)
|
||||
result = {
|
||||
"changed": False,
|
||||
"msg": "The certificate is still valid and no condition was reached",
|
||||
"exists": False,
|
||||
"parsable": False,
|
||||
"supports_ari": False,
|
||||
}
|
||||
|
||||
def complete(should_renew: bool, **kwargs) -> t.NoReturn:
|
||||
result["should_renew"] = should_renew
|
||||
|
||||
@@ -134,11 +134,11 @@ from ansible_collections.community.crypto.plugins.module_utils._acme.utils impor
|
||||
def main() -> t.NoReturn:
|
||||
argument_spec = create_default_argspec(require_account_key=False)
|
||||
argument_spec.update_argspec(
|
||||
private_key_src=dict(type="path"),
|
||||
private_key_content=dict(type="str", no_log=True),
|
||||
private_key_passphrase=dict(type="str", no_log=True),
|
||||
certificate=dict(type="path", required=True),
|
||||
revoke_reason=dict(type="int"),
|
||||
private_key_src={"type": "path"},
|
||||
private_key_content={"type": "str", "no_log": True},
|
||||
private_key_passphrase={"type": "str", "no_log": True},
|
||||
certificate={"type": "path", "required": True},
|
||||
revoke_reason={"type": "int"},
|
||||
)
|
||||
argument_spec.update(
|
||||
required_one_of=[
|
||||
@@ -186,7 +186,9 @@ def main() -> t.NoReturn:
|
||||
passphrase=passphrase,
|
||||
)
|
||||
except KeyParsingError as e:
|
||||
raise ModuleFailException(f"Error while parsing private key: {e.msg}")
|
||||
raise ModuleFailException(
|
||||
f"Error while parsing private key: {e.msg}"
|
||||
) from e
|
||||
# Step 2: sign revokation request with private key
|
||||
jws_header = {
|
||||
"alg": private_key_data["alg"],
|
||||
|
||||
@@ -200,13 +200,13 @@ def encode_octet_string(octet_string: bytes) -> bytes:
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
challenge=dict(type="str", required=True, choices=["tls-alpn-01"]),
|
||||
challenge_data=dict(type="dict", required=True),
|
||||
private_key_src=dict(type="path"),
|
||||
private_key_content=dict(type="str", no_log=True),
|
||||
private_key_passphrase=dict(type="str", no_log=True),
|
||||
),
|
||||
argument_spec={
|
||||
"challenge": {"type": "str", "required": True, "choices": ["tls-alpn-01"]},
|
||||
"challenge_data": {"type": "dict", "required": True},
|
||||
"private_key_src": {"type": "path"},
|
||||
"private_key_content": {"type": "str", "no_log": True},
|
||||
"private_key_passphrase": {"type": "str", "no_log": True},
|
||||
},
|
||||
required_one_of=(["private_key_src", "private_key_content"],),
|
||||
mutually_exclusive=(["private_key_src", "private_key_content"],),
|
||||
)
|
||||
@@ -239,7 +239,7 @@ def main() -> t.NoReturn:
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
raise ModuleFailException(f"Error while loading private key: {e}")
|
||||
raise ModuleFailException(f"Error while loading private key: {e}") from e
|
||||
if isinstance(
|
||||
private_key,
|
||||
(
|
||||
@@ -317,6 +317,8 @@ def main() -> t.NoReturn:
|
||||
private_key,
|
||||
cryptography.hazmat.primitives.hashes.SHA256(),
|
||||
)
|
||||
else:
|
||||
raise AssertionError("Can never be reached") # pragma: no cover
|
||||
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
|
||||
@@ -240,12 +240,14 @@ from ansible_collections.community.crypto.plugins.module_utils._acme.errors impo
|
||||
def main() -> t.NoReturn:
|
||||
argument_spec = create_default_argspec(require_account_key=False)
|
||||
argument_spec.update_argspec(
|
||||
url=dict(type="str"),
|
||||
method=dict(
|
||||
type="str", choices=["get", "post", "directory-only"], default="get"
|
||||
),
|
||||
content=dict(type="str"),
|
||||
fail_on_acme_error=dict(type="bool", default=True),
|
||||
url={"type": "str"},
|
||||
method={
|
||||
"type": "str",
|
||||
"choices": ["get", "post", "directory-only"],
|
||||
"default": "get",
|
||||
},
|
||||
content={"type": "str"},
|
||||
fail_on_acme_error={"type": "bool", "default": True},
|
||||
)
|
||||
argument_spec.update(
|
||||
required_if=[
|
||||
@@ -263,7 +265,7 @@ def main() -> t.NoReturn:
|
||||
try:
|
||||
# Get hold of ACMEClient and ACMEAccount objects (includes directory)
|
||||
client = ACMEClient(module=module, backend=backend)
|
||||
method = module.params["method"]
|
||||
method: t.Literal["get", "post", "directory-only"] = module.params["method"]
|
||||
result["directory"] = client.directory.directory
|
||||
# Do we have to do more requests?
|
||||
if method != "directory-only":
|
||||
@@ -283,12 +285,14 @@ def main() -> t.NoReturn:
|
||||
encode_payload=False,
|
||||
fail_on_error=False,
|
||||
)
|
||||
else:
|
||||
raise AssertionError("Can never be reached") # pragma: no cover
|
||||
# Update results
|
||||
result.update(
|
||||
dict(
|
||||
headers=info,
|
||||
output_text=to_native(data),
|
||||
)
|
||||
{
|
||||
"headers": info,
|
||||
"output_text": to_native(data),
|
||||
}
|
||||
)
|
||||
# See if we can parse the result as JSON
|
||||
try:
|
||||
|
||||
@@ -328,12 +328,12 @@ def format_cert(cert: Certificate) -> str:
|
||||
def check_cycle(
|
||||
module: AnsibleModule,
|
||||
occured_certificates: set[cryptography.x509.Certificate],
|
||||
next: Certificate,
|
||||
next_certificate: Certificate,
|
||||
) -> None:
|
||||
"""
|
||||
Make sure that next is not in occured_certificates so far, and add it.
|
||||
Make sure that next_certificate is not in occured_certificates so far, and add it.
|
||||
"""
|
||||
next_cert = next.cert
|
||||
next_cert = next_certificate.cert
|
||||
if next_cert in occured_certificates:
|
||||
module.fail_json(msg="Found cycle while building certificate chain")
|
||||
occured_certificates.add(next_cert)
|
||||
@@ -341,11 +341,15 @@ def check_cycle(
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
input_chain=dict(type="str", required=True),
|
||||
root_certificates=dict(type="list", required=True, elements="path"),
|
||||
intermediate_certificates=dict(type="list", default=[], elements="path"),
|
||||
),
|
||||
argument_spec={
|
||||
"input_chain": {"type": "str", "required": True},
|
||||
"root_certificates": {"type": "list", "required": True, "elements": "path"},
|
||||
"intermediate_certificates": {
|
||||
"type": "list",
|
||||
"default": [],
|
||||
"elements": "path",
|
||||
},
|
||||
},
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@@ -382,7 +386,7 @@ def main() -> t.NoReturn:
|
||||
# Try to complete chain
|
||||
current: Certificate | None = chain[-1]
|
||||
completed = []
|
||||
occured_certificates = set([cert.cert for cert in chain])
|
||||
occured_certificates = {cert.cert for cert in chain}
|
||||
if current and current.cert in roots.certificate_by_cert:
|
||||
# Do not try to complete the chain when it is already ending with a root certificate
|
||||
current = None
|
||||
|
||||
@@ -161,6 +161,7 @@ CRYPTOGRAPHY_VERSION: str | None
|
||||
CRYPTOGRAPHY_IMP_ERR: str | None
|
||||
try:
|
||||
import cryptography
|
||||
import cryptography.hazmat.primitives.asymmetric
|
||||
from cryptography.exceptions import UnsupportedAlgorithm
|
||||
|
||||
try:
|
||||
@@ -216,13 +217,12 @@ def add_crypto_information(module: AnsibleModule) -> dict[str, t.Any]:
|
||||
has_dsa_sign = False
|
||||
try:
|
||||
# added in 0.5 - https://cryptography.io/en/latest/hazmat/primitives/asymmetric/dsa/
|
||||
import cryptography.hazmat.primitives.asymmetric.dsa
|
||||
from cryptography.hazmat.primitives.asymmetric import dsa
|
||||
|
||||
has_dsa = True
|
||||
try:
|
||||
# added later in 1.5
|
||||
# pylint: disable-next=pointless-statement
|
||||
cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey.sign
|
||||
dsa.DSAPrivateKey.sign # pylint: disable=pointless-statement
|
||||
has_dsa_sign = True
|
||||
except AttributeError:
|
||||
pass
|
||||
@@ -234,13 +234,12 @@ def add_crypto_information(module: AnsibleModule) -> dict[str, t.Any]:
|
||||
has_rsa_sign = False
|
||||
try:
|
||||
# added in 0.5 - https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/
|
||||
import cryptography.hazmat.primitives.asymmetric.rsa
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
|
||||
has_rsa = True
|
||||
try:
|
||||
# added later in 1.4
|
||||
# pylint: disable-next=pointless-statement
|
||||
cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey.sign
|
||||
rsa.RSAPrivateKey.sign # pylint: disable=pointless-statement
|
||||
has_rsa_sign = True
|
||||
except AttributeError:
|
||||
pass
|
||||
@@ -252,21 +251,17 @@ def add_crypto_information(module: AnsibleModule) -> dict[str, t.Any]:
|
||||
has_ed25519_sign = False
|
||||
try:
|
||||
# added in 2.6 - https://cryptography.io/en/latest/hazmat/primitives/asymmetric/ed25519/
|
||||
import cryptography.hazmat.primitives.asymmetric.ed25519
|
||||
from cryptography.hazmat.primitives.asymmetric.ed25519 import (
|
||||
Ed25519PrivateKey,
|
||||
)
|
||||
from cryptography.hazmat.primitives.asymmetric import ed25519
|
||||
|
||||
try:
|
||||
Ed25519PrivateKey.from_private_bytes(b"")
|
||||
ed25519.Ed25519PrivateKey.from_private_bytes(b"")
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
has_ed25519 = True
|
||||
try:
|
||||
# added with the primitive in 2.6
|
||||
# pylint: disable-next=pointless-statement
|
||||
cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey.sign
|
||||
ed25519.Ed25519PrivateKey.sign # pylint: disable=pointless-statement
|
||||
has_ed25519_sign = True
|
||||
except AttributeError:
|
||||
pass
|
||||
@@ -278,19 +273,17 @@ def add_crypto_information(module: AnsibleModule) -> dict[str, t.Any]:
|
||||
has_ed448_sign = False
|
||||
try:
|
||||
# added in 2.6 - https://cryptography.io/en/latest/hazmat/primitives/asymmetric/ed448/
|
||||
import cryptography.hazmat.primitives.asymmetric.ed448
|
||||
from cryptography.hazmat.primitives.asymmetric.ed448 import Ed448PrivateKey
|
||||
from cryptography.hazmat.primitives.asymmetric import ed448
|
||||
|
||||
try:
|
||||
Ed448PrivateKey.from_private_bytes(b"")
|
||||
ed448.Ed448PrivateKey.from_private_bytes(b"")
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
has_ed448 = True
|
||||
try:
|
||||
# added with the primitive in 2.6
|
||||
# pylint: disable-next=pointless-statement
|
||||
cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey.sign
|
||||
ed448.Ed448PrivateKey.sign # pylint: disable=pointless-statement
|
||||
has_ed448_sign = True
|
||||
except AttributeError:
|
||||
pass
|
||||
@@ -302,24 +295,21 @@ def add_crypto_information(module: AnsibleModule) -> dict[str, t.Any]:
|
||||
has_x25519_full = False
|
||||
try:
|
||||
# added in 2.0 - https://cryptography.io/en/latest/hazmat/primitives/asymmetric/x25519/
|
||||
import cryptography.hazmat.primitives.asymmetric.x25519
|
||||
from cryptography.hazmat.primitives.asymmetric import x25519
|
||||
|
||||
try:
|
||||
# added later in 2.5
|
||||
# pylint: disable-next=pointless-statement
|
||||
cryptography.hazmat.primitives.asymmetric.x25519.X25519PrivateKey.private_bytes
|
||||
x25519.X25519PrivateKey.private_bytes # pylint: disable=pointless-statement
|
||||
full = True
|
||||
except AttributeError:
|
||||
full = False
|
||||
|
||||
try:
|
||||
if full:
|
||||
cryptography.hazmat.primitives.asymmetric.x25519.X25519PrivateKey.from_private_bytes(
|
||||
b""
|
||||
)
|
||||
x25519.X25519PrivateKey.from_private_bytes(b"")
|
||||
else:
|
||||
# Some versions do not support serialization and deserialization - use generate() instead
|
||||
cryptography.hazmat.primitives.asymmetric.x25519.X25519PrivateKey.generate()
|
||||
x25519.X25519PrivateKey.generate()
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
@@ -332,12 +322,10 @@ def add_crypto_information(module: AnsibleModule) -> dict[str, t.Any]:
|
||||
has_x448 = False
|
||||
try:
|
||||
# added in 2.5 - https://cryptography.io/en/latest/hazmat/primitives/asymmetric/x448/
|
||||
import cryptography.hazmat.primitives.asymmetric.x448
|
||||
from cryptography.hazmat.primitives.asymmetric import x448
|
||||
|
||||
try:
|
||||
from cryptography.hazmat.primitives.asymmetric.x448 import X448PrivateKey
|
||||
|
||||
X448PrivateKey.from_private_bytes(b"")
|
||||
x448.X448PrivateKey.from_private_bytes(b"")
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
@@ -351,13 +339,12 @@ def add_crypto_information(module: AnsibleModule) -> dict[str, t.Any]:
|
||||
curves = []
|
||||
try:
|
||||
# added in 0.5 - https://cryptography.io/en/latest/hazmat/primitives/asymmetric/ec/
|
||||
import cryptography.hazmat.primitives.asymmetric.ec
|
||||
from cryptography.hazmat.primitives.asymmetric import ec
|
||||
|
||||
has_ec = True
|
||||
try:
|
||||
# added later in 1.5
|
||||
# pylint: disable-next=pointless-statement
|
||||
cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey.sign
|
||||
ec.EllipticCurvePrivateKey.sign # pylint: disable=pointless-statement
|
||||
has_ec_sign = True
|
||||
except AttributeError:
|
||||
pass
|
||||
@@ -365,14 +352,10 @@ def add_crypto_information(module: AnsibleModule) -> dict[str, t.Any]:
|
||||
pass
|
||||
else:
|
||||
for curve_name, constructor_name in CURVES:
|
||||
ecclass = cryptography.hazmat.primitives.asymmetric.ec.__dict__.get(
|
||||
constructor_name
|
||||
)
|
||||
ecclass = ec.__dict__.get(constructor_name)
|
||||
if ecclass:
|
||||
try:
|
||||
cryptography.hazmat.primitives.asymmetric.ec.generate_private_key(
|
||||
curve=ecclass()
|
||||
)
|
||||
ec.generate_private_key(curve=ecclass())
|
||||
curves.append(curve_name)
|
||||
except UnsupportedAlgorithm:
|
||||
pass
|
||||
@@ -419,7 +402,7 @@ def add_openssl_information(module: AnsibleModule) -> dict[str, t.Any]:
|
||||
}
|
||||
result["openssl"] = openssl_result
|
||||
|
||||
rc, out, err = module.run_command([openssl_binary, "version"])
|
||||
rc, out, _err = module.run_command([openssl_binary, "version"])
|
||||
if rc == 0:
|
||||
openssl_result["version_output"] = out
|
||||
parts = out.split(None, 2)
|
||||
|
||||
@@ -786,11 +786,7 @@ class EcsCertificate:
|
||||
self.set_cert_details(module)
|
||||
assert self.cert_details is not None
|
||||
|
||||
if (
|
||||
self.cert_status == "EXPIRED"
|
||||
or self.cert_status == "SUSPENDED"
|
||||
or self.cert_status == "REVOKED"
|
||||
):
|
||||
if self.cert_status in ("EXPIRED", "SUSPENDED", "REVOKED"):
|
||||
return False
|
||||
if self.cert_days < module.params["remaining_days"]:
|
||||
return False
|
||||
@@ -803,7 +799,7 @@ class EcsCertificate:
|
||||
|
||||
# Read the CSR contents
|
||||
if self.csr and os.path.exists(self.csr):
|
||||
with open(self.csr, "r") as csr_file:
|
||||
with open(self.csr, "r", encoding="utf-8") as csr_file:
|
||||
body["csr"] = csr_file.read()
|
||||
|
||||
# Check if the path is already a cert
|
||||
@@ -849,6 +845,8 @@ class EcsCertificate:
|
||||
result = self.ecs_client.ReissueCertRequest( # type: ignore[attr-defined] # pylint: disable=no-member
|
||||
trackingId=self.tracking_id, Body=body
|
||||
)
|
||||
else:
|
||||
raise AssertionError("Can never be reached") # pragma: no cover
|
||||
self.tracking_id = result.get("trackingId")
|
||||
self.set_cert_details(module)
|
||||
assert self.cert_details is not None
|
||||
@@ -914,61 +912,61 @@ class EcsCertificate:
|
||||
|
||||
|
||||
def custom_fields_spec() -> dict[str, dict[str, str]]:
|
||||
return dict(
|
||||
text1=dict(type="str"),
|
||||
text2=dict(type="str"),
|
||||
text3=dict(type="str"),
|
||||
text4=dict(type="str"),
|
||||
text5=dict(type="str"),
|
||||
text6=dict(type="str"),
|
||||
text7=dict(type="str"),
|
||||
text8=dict(type="str"),
|
||||
text9=dict(type="str"),
|
||||
text10=dict(type="str"),
|
||||
text11=dict(type="str"),
|
||||
text12=dict(type="str"),
|
||||
text13=dict(type="str"),
|
||||
text14=dict(type="str"),
|
||||
text15=dict(type="str"),
|
||||
number1=dict(type="float"),
|
||||
number2=dict(type="float"),
|
||||
number3=dict(type="float"),
|
||||
number4=dict(type="float"),
|
||||
number5=dict(type="float"),
|
||||
date1=dict(type="str"),
|
||||
date2=dict(type="str"),
|
||||
date3=dict(type="str"),
|
||||
date4=dict(type="str"),
|
||||
date5=dict(type="str"),
|
||||
email1=dict(type="str"),
|
||||
email2=dict(type="str"),
|
||||
email3=dict(type="str"),
|
||||
email4=dict(type="str"),
|
||||
email5=dict(type="str"),
|
||||
dropdown1=dict(type="str"),
|
||||
dropdown2=dict(type="str"),
|
||||
dropdown3=dict(type="str"),
|
||||
dropdown4=dict(type="str"),
|
||||
dropdown5=dict(type="str"),
|
||||
)
|
||||
return {
|
||||
"text1": {"type": "str"},
|
||||
"text2": {"type": "str"},
|
||||
"text3": {"type": "str"},
|
||||
"text4": {"type": "str"},
|
||||
"text5": {"type": "str"},
|
||||
"text6": {"type": "str"},
|
||||
"text7": {"type": "str"},
|
||||
"text8": {"type": "str"},
|
||||
"text9": {"type": "str"},
|
||||
"text10": {"type": "str"},
|
||||
"text11": {"type": "str"},
|
||||
"text12": {"type": "str"},
|
||||
"text13": {"type": "str"},
|
||||
"text14": {"type": "str"},
|
||||
"text15": {"type": "str"},
|
||||
"number1": {"type": "float"},
|
||||
"number2": {"type": "float"},
|
||||
"number3": {"type": "float"},
|
||||
"number4": {"type": "float"},
|
||||
"number5": {"type": "float"},
|
||||
"date1": {"type": "str"},
|
||||
"date2": {"type": "str"},
|
||||
"date3": {"type": "str"},
|
||||
"date4": {"type": "str"},
|
||||
"date5": {"type": "str"},
|
||||
"email1": {"type": "str"},
|
||||
"email2": {"type": "str"},
|
||||
"email3": {"type": "str"},
|
||||
"email4": {"type": "str"},
|
||||
"email5": {"type": "str"},
|
||||
"dropdown1": {"type": "str"},
|
||||
"dropdown2": {"type": "str"},
|
||||
"dropdown3": {"type": "str"},
|
||||
"dropdown4": {"type": "str"},
|
||||
"dropdown5": {"type": "str"},
|
||||
}
|
||||
|
||||
|
||||
def ecs_certificate_argument_spec() -> dict[str, dict[str, t.Any]]:
|
||||
return dict(
|
||||
backup=dict(type="bool", default=False),
|
||||
force=dict(type="bool", default=False),
|
||||
path=dict(type="path", required=True),
|
||||
full_chain_path=dict(type="path"),
|
||||
tracking_id=dict(type="int"),
|
||||
remaining_days=dict(type="int", default=30),
|
||||
request_type=dict(
|
||||
type="str",
|
||||
default="new",
|
||||
choices=["new", "renew", "reissue", "validate_only"],
|
||||
),
|
||||
cert_type=dict(
|
||||
type="str",
|
||||
choices=[
|
||||
return {
|
||||
"backup": {"type": "bool", "default": False},
|
||||
"force": {"type": "bool", "default": False},
|
||||
"path": {"type": "path", "required": True},
|
||||
"full_chain_path": {"type": "path"},
|
||||
"tracking_id": {"type": "int"},
|
||||
"remaining_days": {"type": "int", "default": 30},
|
||||
"request_type": {
|
||||
"type": "str",
|
||||
"default": "new",
|
||||
"choices": ["new", "renew", "reissue", "validate_only"],
|
||||
},
|
||||
"cert_type": {
|
||||
"type": "str",
|
||||
"choices": [
|
||||
"STANDARD_SSL",
|
||||
"ADVANTAGE_SSL",
|
||||
"UC_SSL",
|
||||
@@ -984,26 +982,27 @@ def ecs_certificate_argument_spec() -> dict[str, dict[str, t.Any]]:
|
||||
"CDS_ENT_PRO",
|
||||
"SMIME_ENT",
|
||||
],
|
||||
),
|
||||
csr=dict(type="str"),
|
||||
subject_alt_name=dict(type="list", elements="str"),
|
||||
eku=dict(
|
||||
type="str", choices=["SERVER_AUTH", "CLIENT_AUTH", "SERVER_AND_CLIENT_AUTH"]
|
||||
),
|
||||
ct_log=dict(type="bool"),
|
||||
client_id=dict(type="int", default=1),
|
||||
org=dict(type="str"),
|
||||
ou=dict(type="list", elements="str"),
|
||||
end_user_key_storage_agreement=dict(type="bool"),
|
||||
tracking_info=dict(type="str"),
|
||||
requester_name=dict(type="str", required=True),
|
||||
requester_email=dict(type="str", required=True),
|
||||
requester_phone=dict(type="str", required=True),
|
||||
additional_emails=dict(type="list", elements="str"),
|
||||
custom_fields=dict(type="dict", default=None, options=custom_fields_spec()),
|
||||
cert_expiry=dict(type="str"),
|
||||
cert_lifetime=dict(type="str", choices=["P1Y", "P2Y", "P3Y"]),
|
||||
)
|
||||
},
|
||||
"csr": {"type": "str"},
|
||||
"subject_alt_name": {"type": "list", "elements": "str"},
|
||||
"eku": {
|
||||
"type": "str",
|
||||
"choices": ["SERVER_AUTH", "CLIENT_AUTH", "SERVER_AND_CLIENT_AUTH"],
|
||||
},
|
||||
"ct_log": {"type": "bool"},
|
||||
"client_id": {"type": "int", "default": 1},
|
||||
"org": {"type": "str"},
|
||||
"ou": {"type": "list", "elements": "str"},
|
||||
"end_user_key_storage_agreement": {"type": "bool"},
|
||||
"tracking_info": {"type": "str"},
|
||||
"requester_name": {"type": "str", "required": True},
|
||||
"requester_email": {"type": "str", "required": True},
|
||||
"requester_phone": {"type": "str", "required": True},
|
||||
"additional_emails": {"type": "list", "elements": "str"},
|
||||
"custom_fields": {"type": "dict", "options": custom_fields_spec()},
|
||||
"cert_expiry": {"type": "str"},
|
||||
"cert_lifetime": {"type": "str", "choices": ["P1Y", "P2Y", "P3Y"]},
|
||||
}
|
||||
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
|
||||
@@ -268,6 +268,7 @@ class EcsDomain:
|
||||
# method of the domain, we'll use module.params when requesting a new
|
||||
# one, in case the verification method has changed.
|
||||
self.verification_method = None
|
||||
self.client_id: str | None = None
|
||||
|
||||
# Instantiate the ECS client and then try a no-op connection to verify credentials are valid
|
||||
try:
|
||||
@@ -321,18 +322,15 @@ class EcsDomain:
|
||||
clientId=module.params["client_id"], domain=module.params["domain_name"]
|
||||
)
|
||||
self.set_domain_details(domain_details)
|
||||
if (
|
||||
self.domain_status != "APPROVED"
|
||||
and self.domain_status != "INITIAL_VERIFICATION"
|
||||
and self.domain_status != "RE_VERIFICATION"
|
||||
if self.domain_status not in (
|
||||
"APPROVED",
|
||||
"INITIAL_VERIFICATION",
|
||||
"RE_VERIFICATION",
|
||||
):
|
||||
return False
|
||||
|
||||
# If domain verification is in process, we want to return the random values and treat it as a valid.
|
||||
if (
|
||||
self.domain_status == "INITIAL_VERIFICATION"
|
||||
or self.domain_status == "RE_VERIFICATION"
|
||||
):
|
||||
if self.domain_status in ("INITIAL_VERIFICATION", "RE_VERIFICATION"):
|
||||
# Unless the verification method has changed, in which case we need to do a reverify request.
|
||||
if self.verification_method != module.params["verification_method"]:
|
||||
return False
|
||||
@@ -383,7 +381,7 @@ class EcsDomain:
|
||||
module.params["verification_method"] == "dns"
|
||||
or module.params["verification_method"] == "web_server"
|
||||
):
|
||||
for i in range(4):
|
||||
for _i in range(4):
|
||||
# Check both that random values are now available, and that they're different than were populated by previous 'check'
|
||||
if module.params["verification_method"] == "dns":
|
||||
if (
|
||||
@@ -445,14 +443,16 @@ class EcsDomain:
|
||||
|
||||
|
||||
def ecs_domain_argument_spec() -> dict[str, dict[str, t.Any]]:
|
||||
return dict(
|
||||
client_id=dict(type="int", default=1),
|
||||
domain_name=dict(type="str", required=True),
|
||||
verification_method=dict(
|
||||
type="str", required=True, choices=["dns", "email", "manual", "web_server"]
|
||||
),
|
||||
verification_email=dict(type="str"),
|
||||
)
|
||||
return {
|
||||
"client_id": {"type": "int", "default": 1},
|
||||
"domain_name": {"type": "str", "required": True},
|
||||
"verification_method": {
|
||||
"type": "str",
|
||||
"required": True,
|
||||
"choices": ["dns", "email", "manual", "web_server"],
|
||||
},
|
||||
"verification_email": {"type": "str"},
|
||||
}
|
||||
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
|
||||
@@ -324,23 +324,25 @@ def send_starttls_packet(sock: socket, server_type: t.Literal["mysql"]) -> None:
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
ca_cert=dict(type="path"),
|
||||
host=dict(type="str", required=True),
|
||||
port=dict(type="int", required=True),
|
||||
proxy_host=dict(type="str"),
|
||||
proxy_port=dict(type="int", default=8080),
|
||||
server_name=dict(type="str"),
|
||||
timeout=dict(type="int", default=10),
|
||||
select_crypto_backend=dict(
|
||||
type="str", choices=["auto", "cryptography"], default="auto"
|
||||
),
|
||||
starttls=dict(type="str", choices=["mysql"]),
|
||||
ciphers=dict(type="list", elements="str"),
|
||||
asn1_base64=dict(type="bool", default=True),
|
||||
tls_ctx_options=dict(type="list", elements="raw"),
|
||||
get_certificate_chain=dict(type="bool", default=False),
|
||||
),
|
||||
argument_spec={
|
||||
"ca_cert": {"type": "path"},
|
||||
"host": {"type": "str", "required": True},
|
||||
"port": {"type": "int", "required": True},
|
||||
"proxy_host": {"type": "str"},
|
||||
"proxy_port": {"type": "int", "default": 8080},
|
||||
"server_name": {"type": "str"},
|
||||
"timeout": {"type": "int", "default": 10},
|
||||
"select_crypto_backend": {
|
||||
"type": "str",
|
||||
"default": "auto",
|
||||
"choices": ["auto", "cryptography"],
|
||||
},
|
||||
"starttls": {"type": "str", "choices": ["mysql"]},
|
||||
"ciphers": {"type": "list", "elements": "str"},
|
||||
"asn1_base64": {"type": "bool", "default": True},
|
||||
"tls_ctx_options": {"type": "list", "elements": "raw"},
|
||||
"get_certificate_chain": {"type": "bool", "default": False},
|
||||
},
|
||||
)
|
||||
|
||||
ca_cert: str | None = module.params.get("ca_cert")
|
||||
@@ -444,7 +446,8 @@ def main() -> t.NoReturn:
|
||||
|
||||
try:
|
||||
# Add the int value of the item to ctx options
|
||||
ctx.options |= tls_ctx_option_int
|
||||
# (pylint does not yet notice that module.fail_json cannot return)
|
||||
ctx.options |= tls_ctx_option_int # pylint: disable=possibly-used-before-assignment
|
||||
except Exception:
|
||||
module.fail_json(
|
||||
msg=f"Failed to add {tls_ctx_option_str or tls_ctx_option_int} to CTX options"
|
||||
@@ -465,9 +468,16 @@ def main() -> t.NoReturn:
|
||||
def _convert_chain(chain):
|
||||
if not chain:
|
||||
return []
|
||||
return [c.public_bytes(ssl._ssl.ENCODING_DER) for c in chain]
|
||||
return [
|
||||
c.public_bytes(
|
||||
ssl._ssl.ENCODING_DER # pylint: disable=protected-access
|
||||
)
|
||||
for c in chain
|
||||
]
|
||||
|
||||
ssl_obj = tls_sock._sslobj # This is of type ssl._ssl._SSLSocket
|
||||
ssl_obj = (
|
||||
tls_sock._sslobj # pylint: disable=protected-access
|
||||
) # This is of type ssl._ssl._SSLSocket
|
||||
verified_der_chain = _convert_chain(ssl_obj.get_verified_chain())
|
||||
unverified_der_chain = _convert_chain(ssl_obj.get_unverified_chain())
|
||||
else:
|
||||
@@ -482,7 +492,9 @@ def main() -> t.NoReturn:
|
||||
(
|
||||
c
|
||||
if isinstance(c, bytes)
|
||||
else c.public_bytes(ssl._ssl.ENCODING_DER)
|
||||
else c.public_bytes(
|
||||
ssl._ssl.ENCODING_DER # pylint: disable=protected-access
|
||||
)
|
||||
)
|
||||
for c in chain
|
||||
]
|
||||
|
||||
@@ -500,21 +500,21 @@ class Handler:
|
||||
|
||||
def get_device_by_uuid(self, uuid: str | None) -> str | None:
|
||||
"""Returns the device that holds UUID passed by user"""
|
||||
self._blkid_bin = self._module.get_bin_path("blkid", True)
|
||||
blkid_bin = self._module.get_bin_path("blkid", True)
|
||||
if uuid is None:
|
||||
return None
|
||||
rc, stdout, dummy = self._run_command([self._blkid_bin, "--uuid", uuid])
|
||||
rc, stdout, dummy = self._run_command([blkid_bin, "--uuid", uuid])
|
||||
if rc != 0:
|
||||
return None
|
||||
return stdout.strip()
|
||||
|
||||
def get_device_by_label(self, label: str) -> str | None:
|
||||
"""Returns the device that holds label passed by user"""
|
||||
self._blkid_bin = self._module.get_bin_path("blkid", True)
|
||||
blkid_bin = self._module.get_bin_path("blkid", True)
|
||||
label = self._module.params["label"]
|
||||
if label is None:
|
||||
return None
|
||||
rc, stdout, dummy = self._run_command([self._blkid_bin, "--label", label])
|
||||
rc, stdout, dummy = self._run_command([blkid_bin, "--label", label])
|
||||
if rc != 0:
|
||||
return None
|
||||
return stdout.strip()
|
||||
@@ -536,7 +536,7 @@ class Handler:
|
||||
class CryptHandler(Handler):
|
||||
|
||||
def __init__(self, module: AnsibleModule) -> None:
|
||||
super(CryptHandler, self).__init__(module)
|
||||
super().__init__(module)
|
||||
self._cryptsetup_bin = self._module.get_bin_path("cryptsetup", True)
|
||||
|
||||
def get_container_name_by_device(self, device: str) -> str | None:
|
||||
@@ -722,7 +722,7 @@ class CryptHandler(Handler):
|
||||
except Exception as exc:
|
||||
raise ValueError(
|
||||
f"Error while wiping LUKS container signatures for {device}: {exc}"
|
||||
)
|
||||
) from exc
|
||||
|
||||
def run_luks_add_key(
|
||||
self,
|
||||
@@ -869,7 +869,7 @@ class CryptHandler(Handler):
|
||||
class ConditionsHandler(Handler):
|
||||
|
||||
def __init__(self, module: AnsibleModule, crypthandler: CryptHandler) -> None:
|
||||
super(ConditionsHandler, self).__init__(module)
|
||||
super().__init__(module)
|
||||
self._crypthandler = crypthandler
|
||||
self.device = self.get_device_name()
|
||||
|
||||
@@ -953,6 +953,7 @@ class ConditionsHandler(Handler):
|
||||
) or self._module.params["state"] != "closed":
|
||||
# conditions for close not fulfilled
|
||||
return False
|
||||
luks_is_open = False
|
||||
|
||||
if self.device is not None:
|
||||
name = self._crypthandler.get_container_name_by_device(self.device)
|
||||
@@ -1084,52 +1085,58 @@ class ConditionsHandler(Handler):
|
||||
|
||||
def run_module() -> t.NoReturn:
|
||||
# available arguments/parameters that a user can pass
|
||||
module_args = dict(
|
||||
state=dict(
|
||||
type="str",
|
||||
default="present",
|
||||
choices=["present", "absent", "opened", "closed"],
|
||||
),
|
||||
device=dict(type="str"),
|
||||
name=dict(type="str"),
|
||||
keyfile=dict(type="path"),
|
||||
new_keyfile=dict(type="path"),
|
||||
remove_keyfile=dict(type="path"),
|
||||
passphrase=dict(type="str", no_log=True),
|
||||
new_passphrase=dict(type="str", no_log=True),
|
||||
remove_passphrase=dict(type="str", no_log=True),
|
||||
passphrase_encoding=dict(
|
||||
type="str", default="text", choices=["text", "base64"], no_log=False
|
||||
),
|
||||
keyslot=dict(type="int", no_log=False),
|
||||
new_keyslot=dict(type="int", no_log=False),
|
||||
remove_keyslot=dict(type="int", no_log=False),
|
||||
force_remove_last_key=dict(type="bool", default=False),
|
||||
keysize=dict(type="int"),
|
||||
label=dict(type="str"),
|
||||
uuid=dict(type="str"),
|
||||
type=dict(type="str", choices=["luks1", "luks2"]),
|
||||
cipher=dict(type="str"),
|
||||
hash=dict(type="str"),
|
||||
pbkdf=dict(
|
||||
type="dict",
|
||||
options=dict(
|
||||
iteration_time=dict(type="float"),
|
||||
iteration_count=dict(type="int"),
|
||||
algorithm=dict(type="str", choices=["argon2i", "argon2id", "pbkdf2"]),
|
||||
memory=dict(type="int"),
|
||||
parallel=dict(type="int"),
|
||||
),
|
||||
mutually_exclusive=[("iteration_time", "iteration_count")],
|
||||
),
|
||||
sector_size=dict(type="int"),
|
||||
perf_same_cpu_crypt=dict(type="bool", default=False),
|
||||
perf_submit_from_crypt_cpus=dict(type="bool", default=False),
|
||||
perf_no_read_workqueue=dict(type="bool", default=False),
|
||||
perf_no_write_workqueue=dict(type="bool", default=False),
|
||||
persistent=dict(type="bool", default=False),
|
||||
allow_discards=dict(type="bool", default=False),
|
||||
)
|
||||
module_args = {
|
||||
"state": {
|
||||
"type": "str",
|
||||
"default": "present",
|
||||
"choices": ["present", "absent", "opened", "closed"],
|
||||
},
|
||||
"device": {"type": "str"},
|
||||
"name": {"type": "str"},
|
||||
"keyfile": {"type": "path"},
|
||||
"new_keyfile": {"type": "path"},
|
||||
"remove_keyfile": {"type": "path"},
|
||||
"passphrase": {"type": "str", "no_log": True},
|
||||
"new_passphrase": {"type": "str", "no_log": True},
|
||||
"remove_passphrase": {"type": "str", "no_log": True},
|
||||
"passphrase_encoding": {
|
||||
"type": "str",
|
||||
"default": "text",
|
||||
"choices": ["text", "base64"],
|
||||
"no_log": False,
|
||||
},
|
||||
"keyslot": {"type": "int", "no_log": False},
|
||||
"new_keyslot": {"type": "int", "no_log": False},
|
||||
"remove_keyslot": {"type": "int", "no_log": False},
|
||||
"force_remove_last_key": {"type": "bool", "default": False},
|
||||
"keysize": {"type": "int"},
|
||||
"label": {"type": "str"},
|
||||
"uuid": {"type": "str"},
|
||||
"type": {"type": "str", "choices": ["luks1", "luks2"]},
|
||||
"cipher": {"type": "str"},
|
||||
"hash": {"type": "str"},
|
||||
"pbkdf": {
|
||||
"type": "dict",
|
||||
"options": {
|
||||
"iteration_time": {"type": "float"},
|
||||
"iteration_count": {"type": "int"},
|
||||
"algorithm": {
|
||||
"type": "str",
|
||||
"choices": ["argon2i", "argon2id", "pbkdf2"],
|
||||
},
|
||||
"memory": {"type": "int"},
|
||||
"parallel": {"type": "int"},
|
||||
},
|
||||
"mutually_exclusive": [("iteration_time", "iteration_count")],
|
||||
},
|
||||
"sector_size": {"type": "int"},
|
||||
"perf_same_cpu_crypt": {"type": "bool", "default": False},
|
||||
"perf_submit_from_crypt_cpus": {"type": "bool", "default": False},
|
||||
"perf_no_read_workqueue": {"type": "bool", "default": False},
|
||||
"perf_no_write_workqueue": {"type": "bool", "default": False},
|
||||
"persistent": {"type": "bool", "default": False},
|
||||
"allow_discards": {"type": "bool", "default": False},
|
||||
}
|
||||
|
||||
mutually_exclusive = [
|
||||
("keyfile", "passphrase"),
|
||||
@@ -1145,9 +1152,12 @@ def run_module() -> t.NoReturn:
|
||||
supports_check_mode=True,
|
||||
mutually_exclusive=mutually_exclusive,
|
||||
)
|
||||
module.run_command_environ_update = dict(
|
||||
LANG="C", LC_ALL="C", LC_MESSAGES="C", LC_CTYPE="C"
|
||||
)
|
||||
module.run_command_environ_update = {
|
||||
"LANG": "C",
|
||||
"LC_ALL": "C",
|
||||
"LC_MESSAGES": "C",
|
||||
"LC_CTYPE": "C",
|
||||
}
|
||||
|
||||
if module.params["device"] is not None:
|
||||
try:
|
||||
|
||||
@@ -304,7 +304,7 @@ from ansible_collections.community.crypto.plugins.module_utils._version import (
|
||||
|
||||
class Certificate(OpensshModule):
|
||||
def __init__(self, module: AnsibleModule) -> None:
|
||||
super(Certificate, self).__init__(module=module)
|
||||
super().__init__(module=module)
|
||||
self.ssh_keygen = KeygenCommand(self.module)
|
||||
|
||||
self.identifier: str = self.module.params["identifier"] or ""
|
||||
@@ -406,19 +406,18 @@ class Certificate(OpensshModule):
|
||||
def _should_generate(self) -> bool:
|
||||
if self.regenerate == "never":
|
||||
return self.original_data is None
|
||||
elif self.regenerate == "fail":
|
||||
if self.regenerate == "fail":
|
||||
if self.original_data and not self._is_fully_valid():
|
||||
self.module.fail_json(
|
||||
msg="Certificate does not match the provided options.",
|
||||
cert=get_cert_dict(self.original_data),
|
||||
)
|
||||
return self.original_data is None
|
||||
elif self.regenerate == "partial_idempotence":
|
||||
if self.regenerate == "partial_idempotence":
|
||||
return self.original_data is None or not self._is_partially_valid()
|
||||
elif self.regenerate == "full_idempotence":
|
||||
if self.regenerate == "full_idempotence":
|
||||
return self.original_data is None or not self._is_fully_valid()
|
||||
else:
|
||||
return True
|
||||
return True
|
||||
|
||||
def _is_fully_valid(self) -> bool:
|
||||
if self.original_data is None:
|
||||
@@ -542,10 +541,10 @@ class Certificate(OpensshModule):
|
||||
serial_number=self.serial_number,
|
||||
signature_algorithm=self.signature_algorithm,
|
||||
signing_key_path=self.signing_key,
|
||||
type=self.type,
|
||||
cert_type=self.type,
|
||||
time_parameters=self.time_parameters,
|
||||
use_agent=self.use_agent,
|
||||
environ_update=dict(TZ="UTC"),
|
||||
environ_update={"TZ": "UTC"},
|
||||
check_rc=True,
|
||||
)
|
||||
|
||||
@@ -625,38 +624,43 @@ def get_cert_dict(data: OpensshCertificate | None) -> dict[str, t.Any]:
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
force=dict(type="bool", default=False),
|
||||
identifier=dict(type="str"),
|
||||
options=dict(type="list", elements="str"),
|
||||
path=dict(type="path", required=True),
|
||||
pkcs11_provider=dict(type="str"),
|
||||
principals=dict(type="list", elements="str"),
|
||||
public_key=dict(type="path"),
|
||||
regenerate=dict(
|
||||
type="str",
|
||||
default="partial_idempotence",
|
||||
choices=[
|
||||
argument_spec={
|
||||
"force": {"type": "bool", "default": False},
|
||||
"identifier": {"type": "str"},
|
||||
"options": {"type": "list", "elements": "str"},
|
||||
"path": {"type": "path", "required": True},
|
||||
"pkcs11_provider": {"type": "str"},
|
||||
"principals": {"type": "list", "elements": "str"},
|
||||
"public_key": {"type": "path"},
|
||||
"regenerate": {
|
||||
"type": "str",
|
||||
"default": "partial_idempotence",
|
||||
"choices": [
|
||||
"never",
|
||||
"fail",
|
||||
"partial_idempotence",
|
||||
"full_idempotence",
|
||||
"always",
|
||||
],
|
||||
),
|
||||
signature_algorithm=dict(
|
||||
type="str", choices=["ssh-rsa", "rsa-sha2-256", "rsa-sha2-512"]
|
||||
),
|
||||
signing_key=dict(type="path"),
|
||||
serial_number=dict(type="int"),
|
||||
state=dict(type="str", default="present", choices=["absent", "present"]),
|
||||
type=dict(type="str", choices=["host", "user"]),
|
||||
use_agent=dict(type="bool", default=False),
|
||||
valid_at=dict(type="str"),
|
||||
valid_from=dict(type="str"),
|
||||
valid_to=dict(type="str"),
|
||||
ignore_timestamps=dict(type="bool", default=False),
|
||||
),
|
||||
},
|
||||
"signature_algorithm": {
|
||||
"type": "str",
|
||||
"choices": ["ssh-rsa", "rsa-sha2-256", "rsa-sha2-512"],
|
||||
},
|
||||
"signing_key": {"type": "path"},
|
||||
"serial_number": {"type": "int"},
|
||||
"state": {
|
||||
"type": "str",
|
||||
"default": "present",
|
||||
"choices": ["absent", "present"],
|
||||
},
|
||||
"type": {"type": "str", "choices": ["host", "user"]},
|
||||
"use_agent": {"type": "bool", "default": False},
|
||||
"valid_at": {"type": "str"},
|
||||
"valid_from": {"type": "str"},
|
||||
"valid_to": {"type": "str"},
|
||||
"ignore_timestamps": {"type": "bool", "default": False},
|
||||
},
|
||||
supports_check_mode=True,
|
||||
add_file_common_args=True,
|
||||
required_if=[
|
||||
|
||||
@@ -209,41 +209,45 @@ from ansible_collections.community.crypto.plugins.module_utils._openssh.backends
|
||||
def main() -> t.NoReturn:
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
state=dict(type="str", default="present", choices=["present", "absent"]),
|
||||
size=dict(type="int"),
|
||||
type=dict(
|
||||
type="str",
|
||||
default="rsa",
|
||||
choices=["rsa", "dsa", "rsa1", "ecdsa", "ed25519"],
|
||||
),
|
||||
force=dict(type="bool", default=False),
|
||||
path=dict(type="path", required=True),
|
||||
comment=dict(type="str"),
|
||||
regenerate=dict(
|
||||
type="str",
|
||||
default="partial_idempotence",
|
||||
choices=[
|
||||
argument_spec={
|
||||
"state": {
|
||||
"type": "str",
|
||||
"default": "present",
|
||||
"choices": ["present", "absent"],
|
||||
},
|
||||
"size": {"type": "int"},
|
||||
"type": {
|
||||
"type": "str",
|
||||
"default": "rsa",
|
||||
"choices": ["rsa", "dsa", "rsa1", "ecdsa", "ed25519"],
|
||||
},
|
||||
"force": {"type": "bool", "default": False},
|
||||
"path": {"type": "path", "required": True},
|
||||
"comment": {"type": "str"},
|
||||
"regenerate": {
|
||||
"type": "str",
|
||||
"default": "partial_idempotence",
|
||||
"choices": [
|
||||
"never",
|
||||
"fail",
|
||||
"partial_idempotence",
|
||||
"full_idempotence",
|
||||
"always",
|
||||
],
|
||||
),
|
||||
passphrase=dict(type="str", no_log=True),
|
||||
private_key_format=dict(
|
||||
type="str",
|
||||
default="auto",
|
||||
no_log=False,
|
||||
choices=["auto", "pkcs1", "pkcs8", "ssh"],
|
||||
),
|
||||
backend=dict(
|
||||
type="str",
|
||||
default="auto",
|
||||
choices=["auto", "cryptography", "opensshbin"],
|
||||
),
|
||||
),
|
||||
},
|
||||
"passphrase": {"type": "str", "no_log": True},
|
||||
"private_key_format": {
|
||||
"type": "str",
|
||||
"default": "auto",
|
||||
"no_log": False,
|
||||
"choices": ["auto", "pkcs1", "pkcs8", "ssh"],
|
||||
},
|
||||
"backend": {
|
||||
"type": "str",
|
||||
"default": "auto",
|
||||
"choices": ["auto", "cryptography", "opensshbin"],
|
||||
},
|
||||
},
|
||||
supports_check_mode=True,
|
||||
add_file_common_args=True,
|
||||
)
|
||||
|
||||
@@ -269,7 +269,7 @@ class CertificateSigningRequestModule(OpenSSLObject):
|
||||
def __init__(
|
||||
self, module: AnsibleModule, module_backend: CertificateSigningRequestBackend
|
||||
) -> None:
|
||||
super(CertificateSigningRequestModule, self).__init__(
|
||||
super().__init__(
|
||||
path=module.params["path"],
|
||||
state=module.params["state"],
|
||||
force=module.params["force"],
|
||||
@@ -308,7 +308,7 @@ class CertificateSigningRequestModule(OpenSSLObject):
|
||||
self.module_backend.set_existing(csr_bytes=None)
|
||||
if self.backup and not self.check_mode:
|
||||
self.backup_file = module.backup_local(self.path)
|
||||
super(CertificateSigningRequestModule, self).remove(module)
|
||||
super().remove(module)
|
||||
|
||||
def dump(self) -> dict[str, t.Any]:
|
||||
"""Serialize the object into a dictionary."""
|
||||
@@ -327,13 +327,17 @@ class CertificateSigningRequestModule(OpenSSLObject):
|
||||
def main() -> t.NoReturn:
|
||||
argument_spec = get_csr_argument_spec()
|
||||
argument_spec.argument_spec.update(
|
||||
dict(
|
||||
state=dict(type="str", default="present", choices=["absent", "present"]),
|
||||
force=dict(type="bool", default=False),
|
||||
path=dict(type="path", required=True),
|
||||
backup=dict(type="bool", default=False),
|
||||
return_content=dict(type="bool", default=False),
|
||||
)
|
||||
{
|
||||
"state": {
|
||||
"type": "str",
|
||||
"default": "present",
|
||||
"choices": ["absent", "present"],
|
||||
},
|
||||
"force": {"type": "bool", "default": False},
|
||||
"path": {"type": "path", "required": True},
|
||||
"backup": {"type": "bool", "default": False},
|
||||
"return_content": {"type": "bool", "default": False},
|
||||
}
|
||||
)
|
||||
argument_spec.required_if.extend(
|
||||
[("state", "present", rof, True) for rof in argument_spec.required_one_of]
|
||||
|
||||
@@ -321,16 +321,20 @@ from ansible_collections.community.crypto.plugins.module_utils._crypto.module_ba
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
path=dict(type="path"),
|
||||
content=dict(type="str"),
|
||||
name_encoding=dict(
|
||||
type="str", default="ignore", choices=["ignore", "idna", "unicode"]
|
||||
),
|
||||
select_crypto_backend=dict(
|
||||
type="str", default="auto", choices=["auto", "cryptography"]
|
||||
),
|
||||
),
|
||||
argument_spec={
|
||||
"path": {"type": "path"},
|
||||
"content": {"type": "str"},
|
||||
"name_encoding": {
|
||||
"type": "str",
|
||||
"default": "ignore",
|
||||
"choices": ["ignore", "idna", "unicode"],
|
||||
},
|
||||
"select_crypto_backend": {
|
||||
"type": "str",
|
||||
"default": "auto",
|
||||
"choices": ["auto", "cryptography"],
|
||||
},
|
||||
},
|
||||
required_one_of=(["path", "content"],),
|
||||
mutually_exclusive=(["path", "content"],),
|
||||
supports_check_mode=True,
|
||||
|
||||
@@ -178,9 +178,9 @@ class CertificateSigningRequestModule:
|
||||
def main() -> t.NoReturn:
|
||||
argument_spec = get_csr_argument_spec()
|
||||
argument_spec.argument_spec.update(
|
||||
dict(
|
||||
content=dict(type="str"),
|
||||
)
|
||||
{
|
||||
"content": {"type": "str"},
|
||||
}
|
||||
)
|
||||
module = argument_spec.create_ansible_module(
|
||||
supports_check_mode=True,
|
||||
|
||||
@@ -252,7 +252,7 @@ class DHParameterBase:
|
||||
class DHParameterAbsent(DHParameterBase):
|
||||
|
||||
def __init__(self, module: AnsibleModule) -> None:
|
||||
super(DHParameterAbsent, self).__init__(module)
|
||||
super().__init__(module)
|
||||
|
||||
def _do_generate(self, module: AnsibleModule) -> None:
|
||||
"""Actually generate the DH params."""
|
||||
@@ -265,7 +265,7 @@ class DHParameterAbsent(DHParameterBase):
|
||||
class DHParameterOpenSSL(DHParameterBase):
|
||||
|
||||
def __init__(self, module: AnsibleModule) -> None:
|
||||
super(DHParameterOpenSSL, self).__init__(module)
|
||||
super().__init__(module)
|
||||
self.openssl_bin = module.get_bin_path("openssl", True)
|
||||
|
||||
def _do_generate(self, module: AnsibleModule) -> None:
|
||||
@@ -320,7 +320,7 @@ class DHParameterOpenSSL(DHParameterBase):
|
||||
class DHParameterCryptography(DHParameterBase):
|
||||
|
||||
def __init__(self, module: AnsibleModule) -> None:
|
||||
super(DHParameterCryptography, self).__init__(module)
|
||||
super().__init__(module)
|
||||
|
||||
def _do_generate(self, module: AnsibleModule) -> None:
|
||||
"""Actually generate the DH params."""
|
||||
@@ -359,17 +359,23 @@ def main() -> t.NoReturn:
|
||||
"""Main function"""
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
state=dict(type="str", default="present", choices=["absent", "present"]),
|
||||
size=dict(type="int", default=4096),
|
||||
force=dict(type="bool", default=False),
|
||||
path=dict(type="path", required=True),
|
||||
backup=dict(type="bool", default=False),
|
||||
select_crypto_backend=dict(
|
||||
type="str", default="auto", choices=["auto", "cryptography", "openssl"]
|
||||
),
|
||||
return_content=dict(type="bool", default=False),
|
||||
),
|
||||
argument_spec={
|
||||
"state": {
|
||||
"type": "str",
|
||||
"default": "present",
|
||||
"choices": ["absent", "present"],
|
||||
},
|
||||
"size": {"type": "int", "default": 4096},
|
||||
"force": {"type": "bool", "default": False},
|
||||
"path": {"type": "path", "required": True},
|
||||
"backup": {"type": "bool", "default": False},
|
||||
"select_crypto_backend": {
|
||||
"type": "str",
|
||||
"default": "auto",
|
||||
"choices": ["auto", "cryptography", "openssl"],
|
||||
},
|
||||
"return_content": {"type": "bool", "default": False},
|
||||
},
|
||||
supports_check_mode=True,
|
||||
add_file_common_args=True,
|
||||
)
|
||||
|
||||
@@ -368,7 +368,7 @@ class Pkcs(OpenSSLObject):
|
||||
path: str
|
||||
|
||||
def __init__(self, module: AnsibleModule, iter_size_default: int = 2048) -> None:
|
||||
super(Pkcs, self).__init__(
|
||||
super().__init__(
|
||||
path=module.params["path"],
|
||||
state=module.params["state"],
|
||||
force=module.params["force"],
|
||||
@@ -413,7 +413,7 @@ class Pkcs(OpenSSLObject):
|
||||
with open(self.certificate_path, "rb") as fh:
|
||||
self.certificate_content = fh.read()
|
||||
except (IOError, OSError) as exc:
|
||||
raise PkcsError(exc)
|
||||
raise PkcsError(exc) from exc
|
||||
elif certificate_content is not None:
|
||||
self.certificate_content = to_bytes(certificate_content)
|
||||
|
||||
@@ -423,7 +423,7 @@ class Pkcs(OpenSSLObject):
|
||||
with open(self.privatekey_path, "rb") as fh:
|
||||
self.privatekey_content = fh.read()
|
||||
except (IOError, OSError) as exc:
|
||||
raise PkcsError(exc)
|
||||
raise PkcsError(exc) from exc
|
||||
elif privatekey_content is not None:
|
||||
self.privatekey_content = to_bytes(privatekey_content)
|
||||
|
||||
@@ -480,11 +480,9 @@ class Pkcs(OpenSSLObject):
|
||||
def _get_friendly_name(self, pkcs12: PKCS12) -> bytes | None:
|
||||
pass
|
||||
|
||||
def check(self, module: AnsibleModule, perms_required: bool = True) -> bool:
|
||||
def check(self, module: AnsibleModule, *, perms_required: bool = True) -> bool:
|
||||
"""Ensure the resource is in its desired state."""
|
||||
state_and_perms = super(Pkcs, self).check(
|
||||
module=module, perms_required=perms_required
|
||||
)
|
||||
state_and_perms = super().check(module=module, perms_required=perms_required)
|
||||
|
||||
def _check_pkey_passphrase() -> bool:
|
||||
if self.privatekey_passphrase:
|
||||
@@ -599,7 +597,7 @@ class Pkcs(OpenSSLObject):
|
||||
def remove(self, module: AnsibleModule) -> None:
|
||||
if self.backup:
|
||||
self.backup_file = module.backup_local(self.path)
|
||||
super(Pkcs, self).remove(module)
|
||||
super().remove(module)
|
||||
|
||||
def parse(self) -> tuple[
|
||||
bytes | None,
|
||||
@@ -616,7 +614,7 @@ class Pkcs(OpenSSLObject):
|
||||
pkcs12_content = pkcs12_fh.read()
|
||||
return self.parse_bytes(pkcs12_content)
|
||||
except IOError as exc:
|
||||
raise PkcsError(exc)
|
||||
raise PkcsError(exc) from exc
|
||||
|
||||
def generate(self, module: AnsibleModule) -> None:
|
||||
# Empty method because OpenSSLObject wants this
|
||||
@@ -635,7 +633,7 @@ class Pkcs(OpenSSLObject):
|
||||
|
||||
class PkcsCryptography(Pkcs):
|
||||
def __init__(self, module: AnsibleModule) -> None:
|
||||
super(PkcsCryptography, self).__init__(module, iter_size_default=50000)
|
||||
super().__init__(module, iter_size_default=50000)
|
||||
if (
|
||||
self.encryption_level == "compatibility2022"
|
||||
and not CRYPTOGRAPHY_HAS_COMPATIBILITY2022
|
||||
@@ -656,7 +654,7 @@ class PkcsCryptography(Pkcs):
|
||||
passphrase=self.privatekey_passphrase,
|
||||
)
|
||||
except OpenSSLBadPassphraseError as exc:
|
||||
raise PkcsError(exc)
|
||||
raise PkcsError(exc) from exc
|
||||
|
||||
cert = None
|
||||
if self.certificate_content:
|
||||
@@ -725,7 +723,7 @@ class PkcsCryptography(Pkcs):
|
||||
|
||||
return (pkey, crt, other_certs, friendly_name)
|
||||
except ValueError as exc:
|
||||
raise PkcsError(exc)
|
||||
raise PkcsError(exc) from exc
|
||||
|
||||
def _dump_privatekey(self, pkcs12: PKCS12) -> bytes | None:
|
||||
return (
|
||||
@@ -759,39 +757,49 @@ def select_backend(module: AnsibleModule) -> Pkcs:
|
||||
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
argument_spec = dict(
|
||||
action=dict(type="str", default="export", choices=["export", "parse"]),
|
||||
other_certificates=dict(
|
||||
type="list", elements="path", aliases=["ca_certificates"]
|
||||
),
|
||||
other_certificates_parse_all=dict(type="bool", default=False),
|
||||
other_certificates_content=dict(type="list", elements="str"),
|
||||
certificate_path=dict(type="path"),
|
||||
certificate_content=dict(type="str"),
|
||||
force=dict(type="bool", default=False),
|
||||
friendly_name=dict(type="str", aliases=["name"]),
|
||||
encryption_level=dict(
|
||||
type="str", choices=["auto", "compatibility2022"], default="auto"
|
||||
),
|
||||
iter_size=dict(type="int"),
|
||||
maciter_size=dict(
|
||||
type="int",
|
||||
removed_in_version="4.0.0",
|
||||
removed_from_collection="community.crypto",
|
||||
),
|
||||
passphrase=dict(type="str", no_log=True),
|
||||
path=dict(type="path", required=True),
|
||||
privatekey_passphrase=dict(type="str", no_log=True),
|
||||
privatekey_path=dict(type="path"),
|
||||
privatekey_content=dict(type="str", no_log=True),
|
||||
state=dict(type="str", default="present", choices=["absent", "present"]),
|
||||
src=dict(type="path"),
|
||||
backup=dict(type="bool", default=False),
|
||||
return_content=dict(type="bool", default=False),
|
||||
select_crypto_backend=dict(
|
||||
type="str", default="auto", choices=["auto", "cryptography"]
|
||||
),
|
||||
)
|
||||
argument_spec = {
|
||||
"action": {"type": "str", "default": "export", "choices": ["export", "parse"]},
|
||||
"other_certificates": {
|
||||
"type": "list",
|
||||
"elements": "path",
|
||||
"aliases": ["ca_certificates"],
|
||||
},
|
||||
"other_certificates_parse_all": {"type": "bool", "default": False},
|
||||
"other_certificates_content": {"type": "list", "elements": "str"},
|
||||
"certificate_path": {"type": "path"},
|
||||
"certificate_content": {"type": "str"},
|
||||
"force": {"type": "bool", "default": False},
|
||||
"friendly_name": {"type": "str", "aliases": ["name"]},
|
||||
"encryption_level": {
|
||||
"type": "str",
|
||||
"choices": ["auto", "compatibility2022"],
|
||||
"default": "auto",
|
||||
},
|
||||
"iter_size": {"type": "int"},
|
||||
"maciter_size": {
|
||||
"type": "int",
|
||||
"removed_in_version": "4.0.0",
|
||||
"removed_from_collection": "community.crypto",
|
||||
},
|
||||
"passphrase": {"type": "str", "no_log": True},
|
||||
"path": {"type": "path", "required": True},
|
||||
"privatekey_passphrase": {"type": "str", "no_log": True},
|
||||
"privatekey_path": {"type": "path"},
|
||||
"privatekey_content": {"type": "str", "no_log": True},
|
||||
"state": {
|
||||
"type": "str",
|
||||
"default": "present",
|
||||
"choices": ["absent", "present"],
|
||||
},
|
||||
"src": {"type": "path"},
|
||||
"backup": {"type": "bool", "default": False},
|
||||
"return_content": {"type": "bool", "default": False},
|
||||
"select_crypto_backend": {
|
||||
"type": "str",
|
||||
"default": "auto",
|
||||
"choices": ["auto", "cryptography"],
|
||||
},
|
||||
}
|
||||
|
||||
required_if = [
|
||||
["action", "parse", ["src"]],
|
||||
@@ -837,7 +845,7 @@ def main() -> t.NoReturn:
|
||||
pkcs12.write(module, pkcs12_content, 0o600)
|
||||
changed = True
|
||||
else:
|
||||
pkey, cert, other_certs, friendly_name = pkcs12.parse()
|
||||
pkey, cert, other_certs, _friendly_name = pkcs12.parse()
|
||||
dump_content = "".join(
|
||||
[
|
||||
to_native(pem)
|
||||
|
||||
@@ -185,7 +185,7 @@ class PrivateKeyModule(OpenSSLObject):
|
||||
def __init__(
|
||||
self, module: AnsibleModule, module_backend: PrivateKeyBackend
|
||||
) -> None:
|
||||
super(PrivateKeyModule, self).__init__(
|
||||
super().__init__(
|
||||
path=module.params["path"],
|
||||
state=module.params["state"],
|
||||
force=module.params["force"],
|
||||
@@ -216,8 +216,6 @@ class PrivateKeyModule(OpenSSLObject):
|
||||
self.backup_file = module.backup_local(self.path)
|
||||
self.module_backend.generate_private_key()
|
||||
privatekey_data = self.module_backend.get_private_key_data()
|
||||
if self.return_content:
|
||||
self.privatekey_bytes = privatekey_data
|
||||
write_file(module=module, content=privatekey_data, default_mode=0o600)
|
||||
self.changed = True
|
||||
elif self.module_backend.needs_conversion():
|
||||
@@ -227,8 +225,6 @@ class PrivateKeyModule(OpenSSLObject):
|
||||
self.backup_file = module.backup_local(self.path)
|
||||
self.module_backend.convert_private_key()
|
||||
privatekey_data = self.module_backend.get_private_key_data()
|
||||
if self.return_content:
|
||||
self.privatekey_bytes = privatekey_data
|
||||
write_file(module=module, content=privatekey_data, default_mode=0o600)
|
||||
self.changed = True
|
||||
|
||||
@@ -244,7 +240,7 @@ class PrivateKeyModule(OpenSSLObject):
|
||||
self.module_backend.set_existing(privatekey_bytes=None)
|
||||
if self.backup and not self.check_mode:
|
||||
self.backup_file = module.backup_local(self.path)
|
||||
super(PrivateKeyModule, self).remove(module)
|
||||
super().remove(module)
|
||||
|
||||
def dump(self) -> dict[str, t.Any]:
|
||||
"""Serialize the object into a dictionary."""
|
||||
@@ -262,13 +258,17 @@ def main() -> t.NoReturn:
|
||||
|
||||
argument_spec = get_privatekey_argument_spec()
|
||||
argument_spec.argument_spec.update(
|
||||
dict(
|
||||
state=dict(type="str", default="present", choices=["present", "absent"]),
|
||||
force=dict(type="bool", default=False),
|
||||
path=dict(type="path", required=True),
|
||||
backup=dict(type="bool", default=False),
|
||||
return_content=dict(type="bool", default=False),
|
||||
)
|
||||
{
|
||||
"state": {
|
||||
"type": "str",
|
||||
"default": "present",
|
||||
"choices": ["present", "absent"],
|
||||
},
|
||||
"force": {"type": "bool", "default": False},
|
||||
"path": {"type": "path", "required": True},
|
||||
"backup": {"type": "bool", "default": False},
|
||||
"return_content": {"type": "bool", "default": False},
|
||||
}
|
||||
)
|
||||
module = argument_spec.create_ansible_module(
|
||||
supports_check_mode=True,
|
||||
|
||||
@@ -89,7 +89,7 @@ class PrivateKeyConvertModule(OpenSSLObject):
|
||||
def __init__(
|
||||
self, module: AnsibleModule, module_backend: PrivateKeyConvertBackend
|
||||
) -> None:
|
||||
super(PrivateKeyConvertModule, self).__init__(
|
||||
super().__init__(
|
||||
path=module.params["dest_path"],
|
||||
state="present",
|
||||
force=False,
|
||||
@@ -145,10 +145,10 @@ def main() -> t.NoReturn:
|
||||
|
||||
argument_spec = get_privatekey_argument_spec()
|
||||
argument_spec.argument_spec.update(
|
||||
dict(
|
||||
dest_path=dict(type="path", required=True),
|
||||
backup=dict(type="bool", default=False),
|
||||
)
|
||||
{
|
||||
"dest_path": {"type": "path", "required": True},
|
||||
"backup": {"type": "bool", "default": False},
|
||||
}
|
||||
)
|
||||
module = argument_spec.create_ansible_module(
|
||||
supports_check_mode=True,
|
||||
|
||||
@@ -215,26 +215,28 @@ from ansible_collections.community.crypto.plugins.module_utils._crypto.module_ba
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
path=dict(type="path"),
|
||||
content=dict(type="str", no_log=True),
|
||||
passphrase=dict(type="str", no_log=True),
|
||||
return_private_key_data=dict(type="bool", default=False),
|
||||
check_consistency=dict(type="bool", default=False),
|
||||
select_crypto_backend=dict(
|
||||
type="str", default="auto", choices=["auto", "cryptography"]
|
||||
),
|
||||
),
|
||||
argument_spec={
|
||||
"path": {"type": "path"},
|
||||
"content": {"type": "str", "no_log": True},
|
||||
"passphrase": {"type": "str", "no_log": True},
|
||||
"return_private_key_data": {"type": "bool", "default": False},
|
||||
"check_consistency": {"type": "bool", "default": False},
|
||||
"select_crypto_backend": {
|
||||
"type": "str",
|
||||
"default": "auto",
|
||||
"choices": ["auto", "cryptography"],
|
||||
},
|
||||
},
|
||||
required_one_of=(["path", "content"],),
|
||||
mutually_exclusive=(["path", "content"],),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
result = dict(
|
||||
can_load_key=False,
|
||||
can_parse_key=False,
|
||||
key_is_consistent=None,
|
||||
)
|
||||
result = {
|
||||
"can_load_key": False,
|
||||
"can_parse_key": False,
|
||||
"key_is_consistent": None,
|
||||
}
|
||||
|
||||
if module.params["content"] is not None:
|
||||
data = module.params["content"].encode("utf-8")
|
||||
|
||||
@@ -233,7 +233,7 @@ class PublicKeyError(OpenSSLObjectError):
|
||||
class PublicKey(OpenSSLObject):
|
||||
|
||||
def __init__(self, module: AnsibleModule) -> None:
|
||||
super(PublicKey, self).__init__(
|
||||
super().__init__(
|
||||
path=module.params["path"],
|
||||
state=module.params["state"],
|
||||
force=module.params["force"],
|
||||
@@ -287,11 +287,10 @@ class PublicKey(OpenSSLObject):
|
||||
crypto_serialization.Encoding.OpenSSH,
|
||||
crypto_serialization.PublicFormat.OpenSSH,
|
||||
)
|
||||
else:
|
||||
return self.privatekey.public_key().public_bytes(
|
||||
crypto_serialization.Encoding.PEM,
|
||||
crypto_serialization.PublicFormat.SubjectPublicKeyInfo,
|
||||
)
|
||||
return self.privatekey.public_key().public_bytes(
|
||||
crypto_serialization.Encoding.PEM,
|
||||
crypto_serialization.PublicFormat.SubjectPublicKeyInfo,
|
||||
)
|
||||
|
||||
def generate(self, module: AnsibleModule) -> None:
|
||||
"""Generate the public key."""
|
||||
@@ -316,9 +315,9 @@ class PublicKey(OpenSSLObject):
|
||||
|
||||
self.changed = True
|
||||
except OpenSSLBadPassphraseError as exc:
|
||||
raise PublicKeyError(exc)
|
||||
raise PublicKeyError(exc) from exc
|
||||
except (IOError, OSError) as exc:
|
||||
raise PublicKeyError(exc)
|
||||
raise PublicKeyError(exc) from exc
|
||||
|
||||
self.fingerprint = get_fingerprint(
|
||||
path=self.privatekey_path,
|
||||
@@ -331,12 +330,10 @@ class PublicKey(OpenSSLObject):
|
||||
elif module.set_fs_attributes_if_different(file_args, False):
|
||||
self.changed = True
|
||||
|
||||
def check(self, module: AnsibleModule, perms_required: bool = True) -> bool:
|
||||
def check(self, module: AnsibleModule, *, perms_required: bool = True) -> bool:
|
||||
"""Ensure the resource is in its desired state."""
|
||||
|
||||
state_and_perms = super(PublicKey, self).check(
|
||||
module=module, perms_required=perms_required
|
||||
)
|
||||
state_and_perms = super().check(module=module, perms_required=perms_required)
|
||||
|
||||
def _check_privatekey() -> bool:
|
||||
if self.privatekey_path is not None and not os.path.exists(
|
||||
@@ -374,7 +371,7 @@ class PublicKey(OpenSSLObject):
|
||||
try:
|
||||
desired_publickey = self._create_publickey(module)
|
||||
except OpenSSLBadPassphraseError as exc:
|
||||
raise PublicKeyError(exc)
|
||||
raise PublicKeyError(exc) from exc
|
||||
|
||||
return publickey_content == desired_publickey
|
||||
|
||||
@@ -386,7 +383,7 @@ class PublicKey(OpenSSLObject):
|
||||
def remove(self, module: AnsibleModule) -> None:
|
||||
if self.backup:
|
||||
self.backup_file = module.backup_local(self.path)
|
||||
super(PublicKey, self).remove(module)
|
||||
super().remove(module)
|
||||
|
||||
def dump(self) -> dict[str, t.Any]:
|
||||
"""Serialize the object into a dictionary."""
|
||||
@@ -409,10 +406,10 @@ class PublicKey(OpenSSLObject):
|
||||
self.publickey_bytes.decode("utf-8") if self.publickey_bytes else None
|
||||
)
|
||||
|
||||
result["diff"] = dict(
|
||||
before=self.diff_before,
|
||||
after=self.diff_after,
|
||||
)
|
||||
result["diff"] = {
|
||||
"before": self.diff_before,
|
||||
"after": self.diff_after,
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
@@ -420,20 +417,26 @@ class PublicKey(OpenSSLObject):
|
||||
def main() -> t.NoReturn:
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
state=dict(type="str", default="present", choices=["present", "absent"]),
|
||||
force=dict(type="bool", default=False),
|
||||
path=dict(type="path", required=True),
|
||||
privatekey_path=dict(type="path"),
|
||||
privatekey_content=dict(type="str", no_log=True),
|
||||
format=dict(type="str", default="PEM", choices=["OpenSSH", "PEM"]),
|
||||
privatekey_passphrase=dict(type="str", no_log=True),
|
||||
backup=dict(type="bool", default=False),
|
||||
select_crypto_backend=dict(
|
||||
type="str", choices=["auto", "cryptography"], default="auto"
|
||||
),
|
||||
return_content=dict(type="bool", default=False),
|
||||
),
|
||||
argument_spec={
|
||||
"state": {
|
||||
"type": "str",
|
||||
"default": "present",
|
||||
"choices": ["present", "absent"],
|
||||
},
|
||||
"force": {"type": "bool", "default": False},
|
||||
"path": {"type": "path", "required": True},
|
||||
"privatekey_path": {"type": "path"},
|
||||
"privatekey_content": {"type": "str", "no_log": True},
|
||||
"format": {"type": "str", "default": "PEM", "choices": ["OpenSSH", "PEM"]},
|
||||
"privatekey_passphrase": {"type": "str", "no_log": True},
|
||||
"backup": {"type": "bool", "default": False},
|
||||
"select_crypto_backend": {
|
||||
"type": "str",
|
||||
"choices": ["auto", "cryptography"],
|
||||
"default": "auto",
|
||||
},
|
||||
"return_content": {"type": "bool", "default": False},
|
||||
},
|
||||
supports_check_mode=True,
|
||||
add_file_common_args=True,
|
||||
required_if=[
|
||||
|
||||
@@ -166,23 +166,25 @@ from ansible_collections.community.crypto.plugins.module_utils._crypto.module_ba
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
path=dict(type="path"),
|
||||
content=dict(type="str", no_log=True),
|
||||
select_crypto_backend=dict(
|
||||
type="str", default="auto", choices=["auto", "cryptography"]
|
||||
),
|
||||
),
|
||||
argument_spec={
|
||||
"path": {"type": "path"},
|
||||
"content": {"type": "str", "no_log": True},
|
||||
"select_crypto_backend": {
|
||||
"type": "str",
|
||||
"default": "auto",
|
||||
"choices": ["auto", "cryptography"],
|
||||
},
|
||||
},
|
||||
required_one_of=(["path", "content"],),
|
||||
mutually_exclusive=(["path", "content"],),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
result = dict(
|
||||
can_load_key=False,
|
||||
can_parse_key=False,
|
||||
key_is_consistent=None,
|
||||
)
|
||||
result = {
|
||||
"can_load_key": False,
|
||||
"can_parse_key": False,
|
||||
"key_is_consistent": None,
|
||||
}
|
||||
|
||||
if module.params["content"] is not None:
|
||||
data = module.params["content"].encode("utf-8")
|
||||
|
||||
@@ -134,7 +134,7 @@ from ansible_collections.community.crypto.plugins.module_utils._crypto.support i
|
||||
class SignatureBase(OpenSSLObject):
|
||||
|
||||
def __init__(self, module: AnsibleModule) -> None:
|
||||
super(SignatureBase, self).__init__(
|
||||
super().__init__(
|
||||
path=module.params["path"],
|
||||
state="present",
|
||||
force=False,
|
||||
@@ -163,7 +163,7 @@ class SignatureBase(OpenSSLObject):
|
||||
class SignatureCryptography(SignatureBase):
|
||||
|
||||
def __init__(self, module: AnsibleModule) -> None:
|
||||
super(SignatureCryptography, self).__init__(module)
|
||||
super().__init__(module)
|
||||
|
||||
def run(self) -> dict[str, t.Any]:
|
||||
_padding = cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15()
|
||||
@@ -224,20 +224,22 @@ class SignatureCryptography(SignatureBase):
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
raise OpenSSLObjectError(e)
|
||||
raise OpenSSLObjectError(e) from e
|
||||
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
privatekey_path=dict(type="path"),
|
||||
privatekey_content=dict(type="str", no_log=True),
|
||||
privatekey_passphrase=dict(type="str", no_log=True),
|
||||
path=dict(type="path", required=True),
|
||||
select_crypto_backend=dict(
|
||||
type="str", choices=["auto", "cryptography"], default="auto"
|
||||
),
|
||||
),
|
||||
argument_spec={
|
||||
"privatekey_path": {"type": "path"},
|
||||
"privatekey_content": {"type": "str", "no_log": True},
|
||||
"privatekey_passphrase": {"type": "str", "no_log": True},
|
||||
"path": {"type": "path", "required": True},
|
||||
"select_crypto_backend": {
|
||||
"type": "str",
|
||||
"choices": ["auto", "cryptography"],
|
||||
"default": "auto",
|
||||
},
|
||||
},
|
||||
mutually_exclusive=(["privatekey_path", "privatekey_content"],),
|
||||
required_one_of=(["privatekey_path", "privatekey_content"],),
|
||||
supports_check_mode=True,
|
||||
|
||||
@@ -123,7 +123,7 @@ from ansible_collections.community.crypto.plugins.module_utils._crypto.support i
|
||||
class SignatureInfoBase(OpenSSLObject):
|
||||
|
||||
def __init__(self, module: AnsibleModule) -> None:
|
||||
super(SignatureInfoBase, self).__init__(
|
||||
super().__init__(
|
||||
path=module.params["path"],
|
||||
state="present",
|
||||
force=False,
|
||||
@@ -152,7 +152,7 @@ class SignatureInfoBase(OpenSSLObject):
|
||||
class SignatureInfoCryptography(SignatureInfoBase):
|
||||
|
||||
def __init__(self, module: AnsibleModule) -> None:
|
||||
super(SignatureInfoCryptography, self).__init__(module)
|
||||
super().__init__(module)
|
||||
|
||||
def run(self) -> dict[str, t.Any]:
|
||||
_padding = cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15()
|
||||
@@ -229,20 +229,22 @@ class SignatureInfoCryptography(SignatureInfoBase):
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
raise OpenSSLObjectError(e)
|
||||
raise OpenSSLObjectError(e) from e
|
||||
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
certificate_path=dict(type="path"),
|
||||
certificate_content=dict(type="str"),
|
||||
path=dict(type="path", required=True),
|
||||
signature=dict(type="str", required=True),
|
||||
select_crypto_backend=dict(
|
||||
type="str", choices=["auto", "cryptography"], default="auto"
|
||||
),
|
||||
),
|
||||
argument_spec={
|
||||
"certificate_path": {"type": "path"},
|
||||
"certificate_content": {"type": "str"},
|
||||
"path": {"type": "path", "required": True},
|
||||
"signature": {"type": "str", "required": True},
|
||||
"select_crypto_backend": {
|
||||
"type": "str",
|
||||
"choices": ["auto", "cryptography"],
|
||||
"default": "auto",
|
||||
},
|
||||
},
|
||||
mutually_exclusive=(["certificate_path", "certificate_content"],),
|
||||
required_one_of=(["certificate_path", "certificate_content"],),
|
||||
supports_check_mode=True,
|
||||
|
||||
@@ -267,7 +267,7 @@ if t.TYPE_CHECKING:
|
||||
|
||||
class CertificateAbsent(OpenSSLObject):
|
||||
def __init__(self, module: AnsibleModule) -> None:
|
||||
super(CertificateAbsent, self).__init__(
|
||||
super().__init__(
|
||||
path=module.params["path"],
|
||||
state=module.params["state"],
|
||||
force=module.params["force"],
|
||||
@@ -284,7 +284,7 @@ class CertificateAbsent(OpenSSLObject):
|
||||
def remove(self, module: AnsibleModule) -> None:
|
||||
if self.backup:
|
||||
self.backup_file = module.backup_local(self.path)
|
||||
super(CertificateAbsent, self).remove(module)
|
||||
super().remove(module)
|
||||
|
||||
def dump(self, check_mode: bool = False) -> dict[str, t.Any]:
|
||||
result = {
|
||||
@@ -305,7 +305,7 @@ class GenericCertificate(OpenSSLObject):
|
||||
"""Retrieve a certificate using the given module backend."""
|
||||
|
||||
def __init__(self, module: AnsibleModule, module_backend: CertificateBackend):
|
||||
super(GenericCertificate, self).__init__(
|
||||
super().__init__(
|
||||
path=module.params["path"],
|
||||
state=module.params["state"],
|
||||
force=module.params["force"],
|
||||
@@ -339,12 +339,10 @@ class GenericCertificate(OpenSSLObject):
|
||||
file_args, self.changed
|
||||
)
|
||||
|
||||
def check(self, module: AnsibleModule, perms_required: bool = True) -> bool:
|
||||
def check(self, module: AnsibleModule, *, perms_required: bool = True) -> bool:
|
||||
"""Ensure the resource is in its desired state."""
|
||||
return (
|
||||
super(GenericCertificate, self).check(
|
||||
module=module, perms_required=perms_required
|
||||
)
|
||||
super().check(module=module, perms_required=perms_required)
|
||||
and not self.module_backend.needs_regeneration()
|
||||
)
|
||||
|
||||
@@ -368,12 +366,16 @@ def main() -> t.NoReturn:
|
||||
add_ownca_provider_to_argument_spec(argument_spec)
|
||||
add_selfsigned_provider_to_argument_spec(argument_spec)
|
||||
argument_spec.argument_spec.update(
|
||||
dict(
|
||||
state=dict(type="str", default="present", choices=["present", "absent"]),
|
||||
path=dict(type="path", required=True),
|
||||
backup=dict(type="bool", default=False),
|
||||
return_content=dict(type="bool", default=False),
|
||||
)
|
||||
{
|
||||
"state": {
|
||||
"type": "str",
|
||||
"default": "present",
|
||||
"choices": ["present", "absent"],
|
||||
},
|
||||
"path": {"type": "path", "required": True},
|
||||
"backup": {"type": "bool", "default": False},
|
||||
"return_content": {"type": "bool", "default": False},
|
||||
}
|
||||
)
|
||||
argument_spec.required_if.append(("state", "present", ["provider"]))
|
||||
module = argument_spec.create_ansible_module(
|
||||
|
||||
@@ -143,13 +143,13 @@ except ImportError:
|
||||
|
||||
|
||||
def parse_certificate(
|
||||
input: bytes, strict: bool = False
|
||||
certificate_content: bytes, strict: bool = False
|
||||
) -> tuple[bytes, t.Literal["pem", "der"], str | None]:
|
||||
input_format: t.Literal["pem", "der"] = (
|
||||
"pem" if identify_pem_format(input) else "der"
|
||||
"pem" if identify_pem_format(certificate_content) else "der"
|
||||
)
|
||||
if input_format == "pem":
|
||||
pems = split_pem_list(to_text(input))
|
||||
pems = split_pem_list(to_text(certificate_content))
|
||||
if len(pems) > 1 and strict:
|
||||
raise ValueError(
|
||||
f"The input contains {len(pems)} PEM objects, expecting only one since strict=true"
|
||||
@@ -159,15 +159,15 @@ def parse_certificate(
|
||||
raise ValueError(
|
||||
f"type is {pem_header_type!r}, expecting CERTIFICATE or X509 CERTIFICATE"
|
||||
)
|
||||
input = base64.b64decode(content)
|
||||
certificate_content = base64.b64decode(content)
|
||||
else:
|
||||
pem_header_type = None
|
||||
return input, input_format, pem_header_type
|
||||
return certificate_content, input_format, pem_header_type
|
||||
|
||||
|
||||
class X509CertificateConvertModule(OpenSSLObject):
|
||||
def __init__(self, module: AnsibleModule) -> None:
|
||||
super(X509CertificateConvertModule, self).__init__(
|
||||
super().__init__(
|
||||
path=module.params["dest_path"],
|
||||
state="present",
|
||||
force=False,
|
||||
@@ -287,16 +287,16 @@ class X509CertificateConvertModule(OpenSSLObject):
|
||||
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
argument_spec = dict(
|
||||
src_path=dict(type="path"),
|
||||
src_content=dict(type="str"),
|
||||
src_content_base64=dict(type="bool", default=False),
|
||||
format=dict(type="str", required=True, choices=["pem", "der"]),
|
||||
strict=dict(type="bool", default=False),
|
||||
dest_path=dict(type="path", required=True),
|
||||
backup=dict(type="bool", default=False),
|
||||
verify_cert_parsable=dict(type="bool", default=False),
|
||||
)
|
||||
argument_spec = {
|
||||
"src_path": {"type": "path"},
|
||||
"src_content": {"type": "str"},
|
||||
"src_content_base64": {"type": "bool", "default": False},
|
||||
"format": {"type": "str", "required": True, "choices": ["pem", "der"]},
|
||||
"strict": {"type": "bool", "default": False},
|
||||
"dest_path": {"type": "path", "required": True},
|
||||
"backup": {"type": "bool", "default": False},
|
||||
"verify_cert_parsable": {"type": "bool", "default": False},
|
||||
}
|
||||
module = AnsibleModule(
|
||||
argument_spec,
|
||||
supports_check_mode=True,
|
||||
|
||||
@@ -410,17 +410,21 @@ from ansible_collections.community.crypto.plugins.module_utils._time import (
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
path=dict(type="path"),
|
||||
content=dict(type="str"),
|
||||
valid_at=dict(type="dict"),
|
||||
name_encoding=dict(
|
||||
type="str", default="ignore", choices=["ignore", "idna", "unicode"]
|
||||
),
|
||||
select_crypto_backend=dict(
|
||||
type="str", default="auto", choices=["auto", "cryptography"]
|
||||
),
|
||||
),
|
||||
argument_spec={
|
||||
"path": {"type": "path"},
|
||||
"content": {"type": "str"},
|
||||
"valid_at": {"type": "dict"},
|
||||
"name_encoding": {
|
||||
"type": "str",
|
||||
"default": "ignore",
|
||||
"choices": ["ignore", "idna", "unicode"],
|
||||
},
|
||||
"select_crypto_backend": {
|
||||
"type": "str",
|
||||
"default": "auto",
|
||||
"choices": ["auto", "cryptography"],
|
||||
},
|
||||
},
|
||||
required_one_of=(["path", "content"],),
|
||||
mutually_exclusive=(["path", "content"],),
|
||||
supports_check_mode=True,
|
||||
@@ -460,7 +464,7 @@ def main() -> t.NoReturn:
|
||||
not_before = module_backend.get_not_before()
|
||||
not_after = module_backend.get_not_after()
|
||||
|
||||
result["valid_at"] = dict()
|
||||
result["valid_at"] = {}
|
||||
if valid_at:
|
||||
for k, v in valid_at.items():
|
||||
result["valid_at"][k] = not_before <= v <= not_after
|
||||
|
||||
@@ -182,9 +182,9 @@ def main() -> t.NoReturn:
|
||||
add_ownca_provider_to_argument_spec(argument_spec)
|
||||
add_selfsigned_provider_to_argument_spec(argument_spec)
|
||||
argument_spec.argument_spec.update(
|
||||
dict(
|
||||
content=dict(type="str"),
|
||||
)
|
||||
{
|
||||
"content": {"type": "str"},
|
||||
}
|
||||
)
|
||||
module = argument_spec.create_ansible_module(
|
||||
supports_check_mode=True,
|
||||
|
||||
@@ -507,7 +507,7 @@ class CRLError(OpenSSLObjectError):
|
||||
class CRL(OpenSSLObject):
|
||||
|
||||
def __init__(self, module: AnsibleModule) -> None:
|
||||
super(CRL, self).__init__(
|
||||
super().__init__(
|
||||
path=module.params["path"],
|
||||
state=module.params["state"],
|
||||
force=module.params["force"],
|
||||
@@ -650,7 +650,7 @@ class CRL(OpenSSLObject):
|
||||
passphrase=self.privatekey_passphrase,
|
||||
)
|
||||
except OpenSSLBadPassphraseError as exc:
|
||||
raise CRLError(exc)
|
||||
raise CRLError(exc) from exc
|
||||
|
||||
self.crl = None
|
||||
try:
|
||||
@@ -704,7 +704,7 @@ class CRL(OpenSSLObject):
|
||||
def remove(self, module: AnsibleModule) -> None:
|
||||
if self.backup:
|
||||
self.backup_file = self.module.backup_local(self.path)
|
||||
super(CRL, self).remove(self.module)
|
||||
super().remove(self.module)
|
||||
|
||||
def _compress_entry(self, entry: dict[str, t.Any]) -> (
|
||||
tuple[
|
||||
@@ -750,27 +750,27 @@ class CRL(OpenSSLObject):
|
||||
entry["invalidity_date"],
|
||||
entry["invalidity_date_critical"],
|
||||
)
|
||||
else:
|
||||
return (
|
||||
entry["serial_number"],
|
||||
entry["revocation_date"],
|
||||
issuer,
|
||||
entry["issuer_critical"],
|
||||
entry["reason"],
|
||||
entry["reason_critical"],
|
||||
entry["invalidity_date"],
|
||||
entry["invalidity_date_critical"],
|
||||
)
|
||||
return (
|
||||
entry["serial_number"],
|
||||
entry["revocation_date"],
|
||||
issuer,
|
||||
entry["issuer_critical"],
|
||||
entry["reason"],
|
||||
entry["reason_critical"],
|
||||
entry["invalidity_date"],
|
||||
entry["invalidity_date_critical"],
|
||||
)
|
||||
|
||||
def check(
|
||||
self,
|
||||
module: AnsibleModule,
|
||||
*,
|
||||
perms_required: bool = True,
|
||||
ignore_conversion: bool = True,
|
||||
) -> bool:
|
||||
"""Ensure the resource is in its desired state."""
|
||||
|
||||
state_and_perms = super(CRL, self).check(
|
||||
state_and_perms = super().check(
|
||||
module=self.module, perms_required=perms_required
|
||||
)
|
||||
|
||||
@@ -843,16 +843,16 @@ class CRL(OpenSSLObject):
|
||||
)
|
||||
)
|
||||
except ValueError as e:
|
||||
raise CRLError(e)
|
||||
raise CRLError(e) from e
|
||||
|
||||
crl = set_last_update(crl, value=self.last_update)
|
||||
if self.next_update is not None:
|
||||
crl = set_next_update(crl, value=self.next_update)
|
||||
|
||||
if self.update and self.crl:
|
||||
new_entries = set(
|
||||
[self._compress_entry(entry) for entry in self.revoked_certificates]
|
||||
)
|
||||
new_entries = {
|
||||
self._compress_entry(entry) for entry in self.revoked_certificates
|
||||
}
|
||||
for entry in self.crl:
|
||||
decoded_entry = self._compress_entry(
|
||||
cryptography_decode_revoked_certificate(entry)
|
||||
@@ -888,8 +888,7 @@ class CRL(OpenSSLObject):
|
||||
self.crl = crl.sign(self.privatekey, digest)
|
||||
if self.format == "pem":
|
||||
return self.crl.public_bytes(Encoding.PEM)
|
||||
else:
|
||||
return self.crl.public_bytes(Encoding.DER)
|
||||
return self.crl.public_bytes(Encoding.DER)
|
||||
|
||||
def generate(self, module: AnsibleModule) -> None:
|
||||
result = None
|
||||
@@ -996,49 +995,53 @@ class CRL(OpenSSLObject):
|
||||
if self.return_content:
|
||||
result["crl"] = self.crl_content
|
||||
|
||||
result["diff"] = dict(
|
||||
before=self.diff_before,
|
||||
after=self.diff_after,
|
||||
)
|
||||
result["diff"] = {
|
||||
"before": self.diff_before,
|
||||
"after": self.diff_after,
|
||||
}
|
||||
return result
|
||||
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
state=dict(type="str", default="present", choices=["present", "absent"]),
|
||||
crl_mode=dict(
|
||||
type="str",
|
||||
default="generate",
|
||||
choices=["generate", "update"],
|
||||
),
|
||||
force=dict(type="bool", default=False),
|
||||
backup=dict(type="bool", default=False),
|
||||
path=dict(type="path", required=True),
|
||||
format=dict(type="str", default="pem", choices=["pem", "der"]),
|
||||
privatekey_path=dict(type="path"),
|
||||
privatekey_content=dict(type="str", no_log=True),
|
||||
privatekey_passphrase=dict(type="str", no_log=True),
|
||||
issuer=dict(type="dict"),
|
||||
issuer_ordered=dict(type="list", elements="dict"),
|
||||
last_update=dict(type="str", default="+0s"),
|
||||
next_update=dict(type="str"),
|
||||
digest=dict(type="str", default="sha256"),
|
||||
ignore_timestamps=dict(type="bool", default=False),
|
||||
return_content=dict(type="bool", default=False),
|
||||
revoked_certificates=dict(
|
||||
type="list",
|
||||
elements="dict",
|
||||
options=dict(
|
||||
path=dict(type="path"),
|
||||
content=dict(type="str"),
|
||||
serial_number=dict(type="raw"),
|
||||
revocation_date=dict(type="str", default="+0s"),
|
||||
issuer=dict(type="list", elements="str"),
|
||||
issuer_critical=dict(type="bool", default=False),
|
||||
reason=dict(
|
||||
type="str",
|
||||
choices=[
|
||||
argument_spec={
|
||||
"state": {
|
||||
"type": "str",
|
||||
"default": "present",
|
||||
"choices": ["present", "absent"],
|
||||
},
|
||||
"crl_mode": {
|
||||
"type": "str",
|
||||
"default": "generate",
|
||||
"choices": ["generate", "update"],
|
||||
},
|
||||
"force": {"type": "bool", "default": False},
|
||||
"backup": {"type": "bool", "default": False},
|
||||
"path": {"type": "path", "required": True},
|
||||
"format": {"type": "str", "default": "pem", "choices": ["pem", "der"]},
|
||||
"privatekey_path": {"type": "path"},
|
||||
"privatekey_content": {"type": "str", "no_log": True},
|
||||
"privatekey_passphrase": {"type": "str", "no_log": True},
|
||||
"issuer": {"type": "dict"},
|
||||
"issuer_ordered": {"type": "list", "elements": "dict"},
|
||||
"last_update": {"type": "str", "default": "+0s"},
|
||||
"next_update": {"type": "str"},
|
||||
"digest": {"type": "str", "default": "sha256"},
|
||||
"ignore_timestamps": {"type": "bool", "default": False},
|
||||
"return_content": {"type": "bool", "default": False},
|
||||
"revoked_certificates": {
|
||||
"type": "list",
|
||||
"elements": "dict",
|
||||
"options": {
|
||||
"path": {"type": "path"},
|
||||
"content": {"type": "str"},
|
||||
"serial_number": {"type": "raw"},
|
||||
"revocation_date": {"type": "str", "default": "+0s"},
|
||||
"issuer": {"type": "list", "elements": "str"},
|
||||
"issuer_critical": {"type": "bool", "default": False},
|
||||
"reason": {
|
||||
"type": "str",
|
||||
"choices": [
|
||||
"unspecified",
|
||||
"key_compromise",
|
||||
"ca_compromise",
|
||||
@@ -1050,21 +1053,25 @@ def main() -> t.NoReturn:
|
||||
"aa_compromise",
|
||||
"remove_from_crl",
|
||||
],
|
||||
),
|
||||
reason_critical=dict(type="bool", default=False),
|
||||
invalidity_date=dict(type="str"),
|
||||
invalidity_date_critical=dict(type="bool", default=False),
|
||||
),
|
||||
required_one_of=[["path", "content", "serial_number"]],
|
||||
mutually_exclusive=[["path", "content", "serial_number"]],
|
||||
),
|
||||
name_encoding=dict(
|
||||
type="str", default="ignore", choices=["ignore", "idna", "unicode"]
|
||||
),
|
||||
serial_numbers=dict(
|
||||
type="str", default="integer", choices=["integer", "hex-octets"]
|
||||
),
|
||||
),
|
||||
},
|
||||
"reason_critical": {"type": "bool", "default": False},
|
||||
"invalidity_date": {"type": "str"},
|
||||
"invalidity_date_critical": {"type": "bool", "default": False},
|
||||
},
|
||||
"required_one_of": [["path", "content", "serial_number"]],
|
||||
"mutually_exclusive": [["path", "content", "serial_number"]],
|
||||
},
|
||||
"name_encoding": {
|
||||
"type": "str",
|
||||
"default": "ignore",
|
||||
"choices": ["ignore", "idna", "unicode"],
|
||||
},
|
||||
"serial_numbers": {
|
||||
"type": "str",
|
||||
"default": "integer",
|
||||
"choices": ["integer", "hex-octets"],
|
||||
},
|
||||
},
|
||||
required_if=[
|
||||
("state", "present", ["privatekey_path", "privatekey_content"], True),
|
||||
("state", "present", ["issuer", "issuer_ordered"], True),
|
||||
|
||||
@@ -190,14 +190,16 @@ from ansible_collections.community.crypto.plugins.module_utils._crypto.pem impor
|
||||
|
||||
def main() -> t.NoReturn:
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
path=dict(type="path"),
|
||||
content=dict(type="str"),
|
||||
list_revoked_certificates=dict(type="bool", default=True),
|
||||
name_encoding=dict(
|
||||
type="str", default="ignore", choices=["ignore", "idna", "unicode"]
|
||||
),
|
||||
),
|
||||
argument_spec={
|
||||
"path": {"type": "path"},
|
||||
"content": {"type": "str"},
|
||||
"list_revoked_certificates": {"type": "bool", "default": True},
|
||||
"name_encoding": {
|
||||
"type": "str",
|
||||
"default": "ignore",
|
||||
"choices": ["ignore", "idna", "unicode"],
|
||||
},
|
||||
},
|
||||
required_one_of=(["path", "content"],),
|
||||
mutually_exclusive=(["path", "content"],),
|
||||
supports_check_mode=True,
|
||||
|
||||
Reference in New Issue
Block a user