mirror of
https://github.com/ansible-collections/community.crypto.git
synced 2026-05-07 13:53:06 +00:00
Add type hints and type checking (#885)
* Enable basic type checking. * Fix first errors. * Add changelog fragment. * Add types to module_utils and plugin_utils (without module backends). * Add typing hints for acme_* modules. * Add typing to X.509 certificate modules, and add more helpers. * Add typing to remaining module backends. * Add typing for action, filter, and lookup plugins. * Bump ansible-core 2.19 beta requirement for typing. * Add more typing definitions. * Add typing to some unit tests.
This commit is contained in:
@@ -39,6 +39,8 @@ _value:
|
||||
type: string
|
||||
"""
|
||||
|
||||
import typing as t
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.common.text.converters import to_bytes
|
||||
from ansible_collections.community.crypto.plugins.module_utils.gnupg.cli import (
|
||||
@@ -50,7 +52,7 @@ from ansible_collections.community.crypto.plugins.plugin_utils.gnupg import (
|
||||
)
|
||||
|
||||
|
||||
def gpg_fingerprint(input):
|
||||
def gpg_fingerprint(input: str | bytes) -> str:
|
||||
if not isinstance(input, (str, bytes)):
|
||||
raise AnsibleFilterError(
|
||||
f"The input for the community.crypto.gpg_fingerprint filter must be a string; got {type(input)} instead"
|
||||
@@ -65,7 +67,7 @@ def gpg_fingerprint(input):
|
||||
class FilterModule:
|
||||
"""Ansible jinja2 filters"""
|
||||
|
||||
def filters(self):
|
||||
def filters(self) -> dict[str, t.Callable]:
|
||||
return {
|
||||
"gpg_fingerprint": gpg_fingerprint,
|
||||
}
|
||||
|
||||
@@ -274,6 +274,8 @@ _value:
|
||||
sample: 12345
|
||||
"""
|
||||
|
||||
import typing as t
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_native
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
|
||||
@@ -287,7 +289,9 @@ from ansible_collections.community.crypto.plugins.plugin_utils.filter_module imp
|
||||
)
|
||||
|
||||
|
||||
def openssl_csr_info_filter(data, name_encoding="ignore"):
|
||||
def openssl_csr_info_filter(
|
||||
data: str | bytes, name_encoding: t.Literal["ignore", "idna", "unicode"] = "ignore"
|
||||
) -> dict[str, t.Any]:
|
||||
"""Extract information from X.509 PEM certificate."""
|
||||
if not isinstance(data, (str, bytes)):
|
||||
raise AnsibleFilterError(
|
||||
@@ -313,7 +317,7 @@ def openssl_csr_info_filter(data, name_encoding="ignore"):
|
||||
class FilterModule:
|
||||
"""Ansible jinja2 filters"""
|
||||
|
||||
def filters(self):
|
||||
def filters(self) -> dict[str, t.Callable]:
|
||||
return {
|
||||
"openssl_csr_info": openssl_csr_info_filter,
|
||||
}
|
||||
|
||||
@@ -146,8 +146,10 @@ _value:
|
||||
type: dict
|
||||
"""
|
||||
|
||||
import typing as t
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.common.text.converters import to_bytes
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_text
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
|
||||
OpenSSLObjectError,
|
||||
)
|
||||
@@ -161,8 +163,10 @@ from ansible_collections.community.crypto.plugins.plugin_utils.filter_module imp
|
||||
|
||||
|
||||
def openssl_privatekey_info_filter(
|
||||
data, passphrase=None, return_private_key_data=False
|
||||
):
|
||||
data: str | bytes,
|
||||
passphrase: str | bytes | None = None,
|
||||
return_private_key_data: bool = False,
|
||||
) -> dict[str, t.Any]:
|
||||
"""Extract information from X.509 PEM certificate."""
|
||||
if not isinstance(data, (str, bytes)):
|
||||
raise AnsibleFilterError(
|
||||
@@ -182,7 +186,7 @@ def openssl_privatekey_info_filter(
|
||||
result = get_privatekey_info(
|
||||
module,
|
||||
content=to_bytes(data),
|
||||
passphrase=passphrase,
|
||||
passphrase=to_text(passphrase) if passphrase is not None else None,
|
||||
return_private_key_data=return_private_key_data,
|
||||
)
|
||||
result.pop("can_parse_key", None)
|
||||
@@ -197,7 +201,7 @@ def openssl_privatekey_info_filter(
|
||||
class FilterModule:
|
||||
"""Ansible jinja2 filters"""
|
||||
|
||||
def filters(self):
|
||||
def filters(self) -> dict[str, t.Callable]:
|
||||
return {
|
||||
"openssl_privatekey_info": openssl_privatekey_info_filter,
|
||||
}
|
||||
|
||||
@@ -123,6 +123,8 @@ _value:
|
||||
returned: When RV(_value.type=DSA) or RV(_value.type=ECC)
|
||||
"""
|
||||
|
||||
import typing as t
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.common.text.converters import to_bytes
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
|
||||
@@ -137,7 +139,7 @@ from ansible_collections.community.crypto.plugins.plugin_utils.filter_module imp
|
||||
)
|
||||
|
||||
|
||||
def openssl_publickey_info_filter(data):
|
||||
def openssl_publickey_info_filter(data: str | bytes) -> dict[str, t.Any]:
|
||||
"""Extract information from OpenSSL PEM public key."""
|
||||
if not isinstance(data, (str, bytes)):
|
||||
raise AnsibleFilterError(
|
||||
@@ -156,7 +158,7 @@ def openssl_publickey_info_filter(data):
|
||||
class FilterModule:
|
||||
"""Ansible jinja2 filters"""
|
||||
|
||||
def filters(self):
|
||||
def filters(self) -> dict[str, t.Callable]:
|
||||
return {
|
||||
"openssl_publickey_info": openssl_publickey_info_filter,
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ _value:
|
||||
type: int
|
||||
"""
|
||||
|
||||
import typing as t
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible_collections.community.crypto.plugins.module_utils.serial import (
|
||||
@@ -46,7 +48,7 @@ from ansible_collections.community.crypto.plugins.module_utils.serial import (
|
||||
)
|
||||
|
||||
|
||||
def parse_serial_filter(input):
|
||||
def parse_serial_filter(input: str | bytes) -> int:
|
||||
if not isinstance(input, (str, bytes)):
|
||||
raise AnsibleFilterError(
|
||||
f"The input for the community.crypto.parse_serial filter must be a string; got {type(input)} instead"
|
||||
@@ -60,7 +62,7 @@ def parse_serial_filter(input):
|
||||
class FilterModule:
|
||||
"""Ansible jinja2 filters"""
|
||||
|
||||
def filters(self):
|
||||
def filters(self) -> dict[str, t.Callable]:
|
||||
return {
|
||||
"parse_serial": parse_serial_filter,
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ _value:
|
||||
elements: string
|
||||
"""
|
||||
|
||||
import typing as t
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.common.text.converters import to_text
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.pem import (
|
||||
@@ -45,21 +47,20 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.pem import
|
||||
)
|
||||
|
||||
|
||||
def split_pem_filter(data):
|
||||
def split_pem_filter(data: str | bytes) -> list[str]:
|
||||
"""Split PEM file."""
|
||||
if not isinstance(data, (str, bytes)):
|
||||
raise AnsibleFilterError(
|
||||
f"The community.crypto.split_pem input must be a text type, not {type(data)}"
|
||||
)
|
||||
|
||||
data = to_text(data)
|
||||
return split_pem_list(data)
|
||||
return split_pem_list(to_text(data))
|
||||
|
||||
|
||||
class FilterModule:
|
||||
"""Ansible jinja2 filters"""
|
||||
|
||||
def filters(self):
|
||||
def filters(self) -> dict[str, t.Callable]:
|
||||
return {
|
||||
"split_pem": split_pem_filter,
|
||||
}
|
||||
|
||||
@@ -39,11 +39,13 @@ _value:
|
||||
type: string
|
||||
"""
|
||||
|
||||
import typing as t
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible_collections.community.crypto.plugins.module_utils.serial import to_serial
|
||||
|
||||
|
||||
def to_serial_filter(input):
|
||||
def to_serial_filter(input: int) -> str:
|
||||
if not isinstance(input, int):
|
||||
raise AnsibleFilterError(
|
||||
f"The input for the community.crypto.to_serial filter must be an integer; got {type(input)} instead"
|
||||
@@ -61,7 +63,7 @@ def to_serial_filter(input):
|
||||
class FilterModule:
|
||||
"""Ansible jinja2 filters"""
|
||||
|
||||
def filters(self):
|
||||
def filters(self) -> dict[str, t.Callable]:
|
||||
return {
|
||||
"to_serial": to_serial_filter,
|
||||
}
|
||||
|
||||
@@ -308,6 +308,8 @@ _value:
|
||||
type: str
|
||||
"""
|
||||
|
||||
import typing as t
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_native
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
|
||||
@@ -321,7 +323,9 @@ from ansible_collections.community.crypto.plugins.plugin_utils.filter_module imp
|
||||
)
|
||||
|
||||
|
||||
def x509_certificate_info_filter(data, name_encoding="ignore"):
|
||||
def x509_certificate_info_filter(
|
||||
data: str | bytes, name_encoding: t.Literal["ignore", "idna", "unicode"] = "ignore"
|
||||
) -> dict[str, t.Any]:
|
||||
"""Extract information from X.509 PEM certificate."""
|
||||
if not isinstance(data, (str, bytes)):
|
||||
raise AnsibleFilterError(
|
||||
@@ -347,7 +351,7 @@ def x509_certificate_info_filter(data, name_encoding="ignore"):
|
||||
class FilterModule:
|
||||
"""Ansible jinja2 filters"""
|
||||
|
||||
def filters(self):
|
||||
def filters(self) -> dict[str, t.Callable]:
|
||||
return {
|
||||
"x509_certificate_info": x509_certificate_info_filter,
|
||||
}
|
||||
|
||||
@@ -155,6 +155,7 @@ _value:
|
||||
|
||||
import base64
|
||||
import binascii
|
||||
import typing as t
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_native
|
||||
@@ -172,7 +173,11 @@ from ansible_collections.community.crypto.plugins.plugin_utils.filter_module imp
|
||||
)
|
||||
|
||||
|
||||
def x509_crl_info_filter(data, name_encoding="ignore", list_revoked_certificates=True):
|
||||
def x509_crl_info_filter(
|
||||
data: str | bytes,
|
||||
name_encoding: t.Literal["ignore", "idna", "unicode"] = "ignore",
|
||||
list_revoked_certificates: bool = True,
|
||||
) -> dict[str, t.Any]:
|
||||
"""Extract information from X.509 PEM certificate."""
|
||||
if not isinstance(data, (str, bytes)):
|
||||
raise AnsibleFilterError(
|
||||
@@ -192,17 +197,19 @@ def x509_crl_info_filter(data, name_encoding="ignore", list_revoked_certificates
|
||||
f'The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "{name_encoding}"'
|
||||
)
|
||||
|
||||
data = to_bytes(data)
|
||||
if not identify_pem_format(data):
|
||||
data_bytes = to_bytes(data)
|
||||
if not identify_pem_format(data_bytes):
|
||||
try:
|
||||
data = base64.b64decode(to_native(data))
|
||||
data_bytes = base64.b64decode(to_native(data_bytes))
|
||||
except (binascii.Error, TypeError, ValueError, UnicodeEncodeError):
|
||||
pass
|
||||
|
||||
module = FilterModuleMock({"name_encoding": name_encoding})
|
||||
try:
|
||||
return get_crl_info(
|
||||
module, content=data, list_revoked_certificates=list_revoked_certificates
|
||||
module,
|
||||
content=data_bytes,
|
||||
list_revoked_certificates=list_revoked_certificates,
|
||||
)
|
||||
except OpenSSLObjectError as exc:
|
||||
raise AnsibleFilterError(str(exc))
|
||||
@@ -211,7 +218,7 @@ def x509_crl_info_filter(data, name_encoding="ignore", list_revoked_certificates
|
||||
class FilterModule:
|
||||
"""Ansible jinja2 filters"""
|
||||
|
||||
def filters(self):
|
||||
def filters(self) -> dict[str, t.Callable]:
|
||||
return {
|
||||
"x509_crl_info": x509_crl_info_filter,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user