mirror of
https://github.com/ansible-collections/community.crypto.git
synced 2026-05-06 13:22:58 +00:00
ACME: implement dns-account-01 challenge type (#996)
* Implement dns-account-01. * Bump draft versions. * dns-account-01 implementation changed in Pebble; only the one used by ansible-core 2.21/devel's ACME simulator matches the latest draft.
This commit is contained in:
@@ -149,9 +149,23 @@ class ACMECertificateClient:
|
||||
order.load_authorizations(client=self.client)
|
||||
return order
|
||||
|
||||
@staticmethod
|
||||
def _update_dns_data(
|
||||
data_dns: dict[str, list[str]],
|
||||
dns_challenge_type: str,
|
||||
challenge_data: dict[str, t.Any],
|
||||
) -> None:
|
||||
dns_challenge = challenge_data.get(dns_challenge_type)
|
||||
if dns_challenge:
|
||||
values = data_dns.get(dns_challenge["record"])
|
||||
if values is None:
|
||||
values = []
|
||||
data_dns[dns_challenge["record"]] = values
|
||||
values.append(dns_challenge["resource_value"])
|
||||
|
||||
def get_challenges_data(
|
||||
self, order: Order
|
||||
) -> tuple[list[dict[str, t.Any]], dict[str, list[str]]]:
|
||||
) -> tuple[list[dict[str, t.Any]], dict[str, list[str]], dict[str, list[str]]]:
|
||||
"""
|
||||
Get challenge details.
|
||||
|
||||
@@ -159,7 +173,9 @@ class ACMECertificateClient:
|
||||
"""
|
||||
data: list[dict[str, t.Any]] = []
|
||||
data_dns: dict[str, list[str]] = {}
|
||||
data_dns_account: dict[str, list[str]] = {}
|
||||
dns_challenge_type = "dns-01"
|
||||
dns_account_challenge_type = "dns-account-01"
|
||||
for authz in order.authorizations.values():
|
||||
# Skip valid authentications: their challenges are already valid
|
||||
# and do not need to be returned
|
||||
@@ -173,14 +189,11 @@ class ACMECertificateClient:
|
||||
"challenges": challenge_data,
|
||||
}
|
||||
)
|
||||
dns_challenge = challenge_data.get(dns_challenge_type)
|
||||
if dns_challenge:
|
||||
values = data_dns.get(dns_challenge["record"])
|
||||
if values is None:
|
||||
values = []
|
||||
data_dns[dns_challenge["record"]] = values
|
||||
values.append(dns_challenge["resource_value"])
|
||||
return data, data_dns
|
||||
self._update_dns_data(data_dns, dns_challenge_type, challenge_data)
|
||||
self._update_dns_data(
|
||||
data_dns_account, dns_account_challenge_type, challenge_data
|
||||
)
|
||||
return data, data_dns, data_dns_account
|
||||
|
||||
def check_that_authorizations_can_be_used(self, order: Order) -> None:
|
||||
bad_authzs = []
|
||||
|
||||
@@ -130,6 +130,26 @@ class Challenge:
|
||||
"record": record,
|
||||
}
|
||||
|
||||
if self.type == "dns-account-01":
|
||||
if identifier_type != "dns" or client.account_uri is None:
|
||||
return None
|
||||
# https://datatracker.ietf.org/doc/html/draft-ietf-acme-dns-account-label-02#section-3.2
|
||||
prefix = (
|
||||
base64.b32encode(
|
||||
hashlib.sha256(client.account_uri.encode("utf8")).digest()[:10]
|
||||
)
|
||||
.decode("ascii")
|
||||
.lower()
|
||||
)
|
||||
resource = f"_{prefix}._acme-challenge"
|
||||
value = nopad_b64(hashlib.sha256(to_bytes(key_authorization)).digest())
|
||||
record = f"{resource}.{identifier[2:] if identifier.startswith('*.') else identifier}"
|
||||
return {
|
||||
"resource": resource,
|
||||
"resource_value": value,
|
||||
"record": record,
|
||||
}
|
||||
|
||||
if self.type == "tls-alpn-01":
|
||||
# https://www.rfc-editor.org/rfc/rfc8737.html#section-3
|
||||
if identifier_type == "ip":
|
||||
|
||||
Reference in New Issue
Block a user