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:
Felix Fontein
2025-05-18 00:57:28 +02:00
committed by GitHub
parent a3a5284f97
commit 318462fa24
96 changed files with 1748 additions and 1598 deletions

View File

@@ -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,

View File

@@ -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)

View File

@@ -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")],

View File

@@ -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(

View File

@@ -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)

View File

@@ -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()

View File

@@ -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:

View File

@@ -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)

View File

@@ -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
],
)

View File

@@ -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

View File

@@ -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"],

View File

@@ -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,

View File

@@ -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:

View File

@@ -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

View File

@@ -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)

View File

@@ -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:

View File

@@ -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:

View File

@@ -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
]

View File

@@ -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:

View File

@@ -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=[

View File

@@ -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,
)

View File

@@ -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]

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,
)

View File

@@ -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)

View File

@@ -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,

View File

@@ -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,

View File

@@ -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")

View File

@@ -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=[

View File

@@ -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")

View File

@@ -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,

View File

@@ -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,

View File

@@ -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(

View File

@@ -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,

View File

@@ -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

View File

@@ -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,

View File

@@ -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),

View File

@@ -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,