ACME modules: documentation improvements (#42165)
* Always using current draft when referring to ACME v2. * Adding URL for ACME v1 protocol. * Improve cross-referencing of acme_* modules. * General improvements. * Fixing syntax error.
This commit is contained in:
parent
6412cbf84b
commit
6b6c017dd1
5 changed files with 44 additions and 29 deletions
|
@ -147,7 +147,7 @@ class ACMEDirectory(object):
|
||||||
and allows to obtain a Replay-Nonce. The acme_directory URL
|
and allows to obtain a Replay-Nonce. The acme_directory URL
|
||||||
needs to support unauthenticated GET requests; ACME endpoints
|
needs to support unauthenticated GET requests; ACME endpoints
|
||||||
requiring authentication are not supported.
|
requiring authentication are not supported.
|
||||||
https://tools.ietf.org/html/draft-ietf-acme-acme-09#section-7.1.1
|
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.1.1
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, module):
|
def __init__(self, module):
|
||||||
|
@ -228,7 +228,7 @@ class ACMEAccount(object):
|
||||||
def get_keyauthorization(self, token):
|
def get_keyauthorization(self, token):
|
||||||
'''
|
'''
|
||||||
Returns the key authorization for the given token
|
Returns the key authorization for the given token
|
||||||
https://tools.ietf.org/html/draft-ietf-acme-acme-09#section-8.1
|
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-8.1
|
||||||
'''
|
'''
|
||||||
accountkey_json = json.dumps(self.jwk, sort_keys=True, separators=(',', ':'))
|
accountkey_json = json.dumps(self.jwk, sort_keys=True, separators=(',', ':'))
|
||||||
thumbprint = nopad_b64(hashlib.sha256(accountkey_json.encode('utf8')).digest())
|
thumbprint = nopad_b64(hashlib.sha256(accountkey_json.encode('utf8')).digest())
|
||||||
|
@ -360,7 +360,7 @@ class ACMEAccount(object):
|
||||||
'''
|
'''
|
||||||
Sends a JWS signed HTTP POST request to the ACME server and returns
|
Sends a JWS signed HTTP POST request to the ACME server and returns
|
||||||
the response as dictionary
|
the response as dictionary
|
||||||
https://tools.ietf.org/html/draft-ietf-acme-acme-10#section-6.2
|
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-6.2
|
||||||
'''
|
'''
|
||||||
key_data = key_data or self.key_data
|
key_data = key_data or self.key_data
|
||||||
key = key or self.key
|
key = key or self.key
|
||||||
|
@ -392,7 +392,7 @@ class ACMEAccount(object):
|
||||||
try:
|
try:
|
||||||
result = self.module.from_json(content.decode('utf8'))
|
result = self.module.from_json(content.decode('utf8'))
|
||||||
# In case of badNonce error, try again (up to 5 times)
|
# In case of badNonce error, try again (up to 5 times)
|
||||||
# (https://tools.ietf.org/html/draft-ietf-acme-acme-09#section-6.6)
|
# (https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-6.6)
|
||||||
if (400 <= info['status'] < 600 and
|
if (400 <= info['status'] < 600 and
|
||||||
result.get('type') == 'urn:ietf:params:acme:error:badNonce' and
|
result.get('type') == 'urn:ietf:params:acme:error:badNonce' and
|
||||||
failed_tries <= 5):
|
failed_tries <= 5):
|
||||||
|
@ -420,7 +420,7 @@ class ACMEAccount(object):
|
||||||
Registers a new ACME account. Returns True if the account was
|
Registers a new ACME account. Returns True if the account was
|
||||||
created and False if it already existed (e.g. it was not newly
|
created and False if it already existed (e.g. it was not newly
|
||||||
created).
|
created).
|
||||||
https://tools.ietf.org/html/draft-ietf-acme-acme-10#section-7.3
|
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.3
|
||||||
'''
|
'''
|
||||||
contact = [] if contact is None else contact
|
contact = [] if contact is None else contact
|
||||||
|
|
||||||
|
@ -498,7 +498,7 @@ class ACMEAccount(object):
|
||||||
will be stored in self.uri; if it is None, the account does not
|
will be stored in self.uri; if it is None, the account does not
|
||||||
exist.
|
exist.
|
||||||
|
|
||||||
https://tools.ietf.org/html/draft-ietf-acme-acme-10#section-7.3
|
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.3
|
||||||
'''
|
'''
|
||||||
|
|
||||||
new_account = True
|
new_account = True
|
||||||
|
|
|
@ -23,6 +23,10 @@ description:
|
||||||
- "Allows to create, modify or delete accounts with Let's Encrypt.
|
- "Allows to create, modify or delete accounts with Let's Encrypt.
|
||||||
Let's Encrypt is a free, automated, and open certificate authority
|
Let's Encrypt is a free, automated, and open certificate authority
|
||||||
(CA), run for the public's benefit. For details see U(https://letsencrypt.org)."
|
(CA), run for the public's benefit. For details see U(https://letsencrypt.org)."
|
||||||
|
- "The M(acme_certificate) module also allows to do basic account management.
|
||||||
|
When using both modules, it is recommended to disable account management
|
||||||
|
for M(acme_certificate). For that, use the C(modify_account) option of
|
||||||
|
M(acme_certificate)."
|
||||||
- "This module only works with the ACME v2 protocol."
|
- "This module only works with the ACME v2 protocol."
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- acme
|
- acme
|
||||||
|
@ -48,7 +52,7 @@ options:
|
||||||
description:
|
description:
|
||||||
- "A list of contact URLs."
|
- "A list of contact URLs."
|
||||||
- "Email addresses must be prefixed with C(mailto:)."
|
- "Email addresses must be prefixed with C(mailto:)."
|
||||||
- "See https://tools.ietf.org/html/draft-ietf-acme-acme-10#section-7.1.2
|
- "See https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.1.2
|
||||||
for what is allowed."
|
for what is allowed."
|
||||||
- "Must be specified when state is C(present). Will be ignored
|
- "Must be specified when state is C(present). Will be ignored
|
||||||
if state is C(absent) or C(changed_key)."
|
if state is C(absent) or C(changed_key)."
|
||||||
|
|
|
@ -20,10 +20,10 @@ author: "Michael Gruener (@mgruener)"
|
||||||
version_added: "2.2"
|
version_added: "2.2"
|
||||||
short_description: Create SSL certificates with an ACME protocol endpoint
|
short_description: Create SSL certificates with an ACME protocol endpoint
|
||||||
description:
|
description:
|
||||||
- "Create and renew SSL certificates with a CA supporting the ACME protocol,
|
- "Create and renew SSL certificates with a CA supporting the
|
||||||
such as Let's Encrypt (U(https://letsencrypt.org)). For details see
|
L(ACME protocol,https://tools.ietf.org/html/draft-ietf-acme-acme-12),
|
||||||
U(https://letsencrypt.org). The current implementation supports the
|
such as L(Let's Encrypt,https://letsencrypt.org/). The current
|
||||||
C(http-01) and C(dns-01) challenges."
|
implementation supports the C(http-01) and C(dns-01) challenges."
|
||||||
- "To use this module, it has to be executed twice. Either as two
|
- "To use this module, it has to be executed twice. Either as two
|
||||||
different tasks in the same run or during two runs. Note that the output
|
different tasks in the same run or during two runs. Note that the output
|
||||||
of the first run needs to be recorded and passed to the second run as the
|
of the first run needs to be recorded and passed to the second run as the
|
||||||
|
@ -34,12 +34,16 @@ description:
|
||||||
C(dns-01) the necessary dns record has to be created.
|
C(dns-01) the necessary dns record has to be created.
|
||||||
It is I(not) the responsibility of this module to perform these steps."
|
It is I(not) the responsibility of this module to perform these steps."
|
||||||
- "For details on how to fulfill these challenges, you might have to read through
|
- "For details on how to fulfill these challenges, you might have to read through
|
||||||
U(https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-8).
|
L(the specification,https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-8).
|
||||||
Also, consider the examples provided for this module."
|
Also, consider the examples provided for this module."
|
||||||
- "Although the defaults are chosen so that the module can be used with
|
- "Although the defaults are chosen so that the module can be used with
|
||||||
the Let's Encrypt CA, the module can be used with any service using the ACME
|
the Let's Encrypt CA, the module can be used with any service using the ACME
|
||||||
v1 or v2 protocol."
|
v1 or v2 protocol."
|
||||||
- "At least one of C(dest) and C(fullchain_dest) must be specified."
|
- "At least one of C(dest) and C(fullchain_dest) must be specified."
|
||||||
|
- "Note that this module includes basic account management functionality.
|
||||||
|
If you want to have more control over your ACME account, use the M(acme_account)
|
||||||
|
module and disable account management for this module using the C(modify_account)
|
||||||
|
option."
|
||||||
- "Note: this module was called C(letsencrypt) before Ansible 2.6. The usage
|
- "Note: this module was called C(letsencrypt) before Ansible 2.6. The usage
|
||||||
did not change."
|
did not change."
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
|
@ -49,6 +53,10 @@ options:
|
||||||
description:
|
description:
|
||||||
- "The email address associated with this account."
|
- "The email address associated with this account."
|
||||||
- "It will be used for certificate expiration warnings."
|
- "It will be used for certificate expiration warnings."
|
||||||
|
- "Note that when C(modify_account) is not set to C(no) and you also
|
||||||
|
used the M(acme_account) module to specify more than one contact
|
||||||
|
for your account, this module will update your account and restrict
|
||||||
|
it to the (at most one) contact email address specified here."
|
||||||
agreement:
|
agreement:
|
||||||
description:
|
description:
|
||||||
- "URI to a terms of service document you agree to when using the
|
- "URI to a terms of service document you agree to when using the
|
||||||
|
@ -67,9 +75,9 @@ options:
|
||||||
description:
|
description:
|
||||||
- "Boolean indicating whether the module should create the account if
|
- "Boolean indicating whether the module should create the account if
|
||||||
necessary, and update its contact data."
|
necessary, and update its contact data."
|
||||||
- "Set to C(no) if you want to use C(acme_account) to manage your
|
- "Set to C(no) if you want to use the M(acme_account) module to manage
|
||||||
account instead, and to avoid accidental creation of a new account
|
your account instead, and to avoid accidental creation of a new account
|
||||||
using an old key if you changed the account key with C(acme_account)."
|
using an old key if you changed the account key with M(acme_account)."
|
||||||
- "If set to C(no), C(terms_agreed) and C(account_email) are ignored."
|
- "If set to C(no), C(terms_agreed) and C(account_email) are ignored."
|
||||||
type: bool
|
type: bool
|
||||||
default: 'yes'
|
default: 'yes'
|
||||||
|
@ -465,11 +473,11 @@ class ACMEClient(object):
|
||||||
keyauthorization = self.account.get_keyauthorization(token)
|
keyauthorization = self.account.get_keyauthorization(token)
|
||||||
|
|
||||||
if type == 'http-01':
|
if type == 'http-01':
|
||||||
# https://tools.ietf.org/html/draft-ietf-acme-acme-09#section-8.3
|
# https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-8.3
|
||||||
resource = '.well-known/acme-challenge/' + token
|
resource = '.well-known/acme-challenge/' + token
|
||||||
data[type] = {'resource': resource, 'resource_value': keyauthorization}
|
data[type] = {'resource': resource, 'resource_value': keyauthorization}
|
||||||
elif type == 'dns-01':
|
elif type == 'dns-01':
|
||||||
# https://tools.ietf.org/html/draft-ietf-acme-acme-09#section-8.5
|
# https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-8.4
|
||||||
resource = '_acme-challenge'
|
resource = '_acme-challenge'
|
||||||
value = nopad_b64(hashlib.sha256(to_bytes(keyauthorization)).digest())
|
value = nopad_b64(hashlib.sha256(to_bytes(keyauthorization)).digest())
|
||||||
record = (resource + domain[1:]) if domain.startswith('*.') else (resource + '.' + domain)
|
record = (resource + domain[1:]) if domain.startswith('*.') else (resource + '.' + domain)
|
||||||
|
@ -523,7 +531,7 @@ class ACMEClient(object):
|
||||||
result['uri'] = auth['uri']
|
result['uri'] = auth['uri']
|
||||||
if self._add_or_update_auth(domain, result):
|
if self._add_or_update_auth(domain, result):
|
||||||
self.changed = True
|
self.changed = True
|
||||||
# draft-ietf-acme-acme-02
|
# https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-6.1.2
|
||||||
# "status (required, string): ...
|
# "status (required, string): ...
|
||||||
# If this field is missing, then the default value is "pending"."
|
# If this field is missing, then the default value is "pending"."
|
||||||
if self.version == 1 and 'status' not in result:
|
if self.version == 1 and 'status' not in result:
|
||||||
|
@ -541,7 +549,7 @@ class ACMEClient(object):
|
||||||
'''
|
'''
|
||||||
Create a new certificate based on the csr.
|
Create a new certificate based on the csr.
|
||||||
Return the certificate object as dict
|
Return the certificate object as dict
|
||||||
https://tools.ietf.org/html/draft-ietf-acme-acme-09#section-7.4
|
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.4
|
||||||
'''
|
'''
|
||||||
openssl_csr_cmd = [self._openssl_bin, "req", "-in", self.csr, "-outform", "DER"]
|
openssl_csr_cmd = [self._openssl_bin, "req", "-in", self.csr, "-outform", "DER"]
|
||||||
dummy, out, dummy = self.module.run_command(openssl_csr_cmd, check_rc=True)
|
dummy, out, dummy = self.module.run_command(openssl_csr_cmd, check_rc=True)
|
||||||
|
@ -577,7 +585,7 @@ class ACMEClient(object):
|
||||||
def _download_cert(self, url):
|
def _download_cert(self, url):
|
||||||
'''
|
'''
|
||||||
Download and parse the certificate chain.
|
Download and parse the certificate chain.
|
||||||
https://tools.ietf.org/html/draft-ietf-acme-acme-09#section-7.4.2
|
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.4.2
|
||||||
'''
|
'''
|
||||||
resp, info = fetch_url(self.module, url, headers={'Accept': 'application/pem-certificate-chain'})
|
resp, info = fetch_url(self.module, url, headers={'Accept': 'application/pem-certificate-chain'})
|
||||||
try:
|
try:
|
||||||
|
@ -651,7 +659,7 @@ class ACMEClient(object):
|
||||||
def _new_order_v2(self):
|
def _new_order_v2(self):
|
||||||
'''
|
'''
|
||||||
Start a new certificate order (ACME v2 protocol).
|
Start a new certificate order (ACME v2 protocol).
|
||||||
https://tools.ietf.org/html/draft-ietf-acme-acme-09#section-7.4
|
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.4
|
||||||
'''
|
'''
|
||||||
identifiers = []
|
identifiers = []
|
||||||
for domain in self.domains:
|
for domain in self.domains:
|
||||||
|
@ -813,7 +821,7 @@ class ACMEClient(object):
|
||||||
'''
|
'''
|
||||||
Deactivates all valid authz's. Does not raise exceptions.
|
Deactivates all valid authz's. Does not raise exceptions.
|
||||||
https://community.letsencrypt.org/t/authorization-deactivation/19860/2
|
https://community.letsencrypt.org/t/authorization-deactivation/19860/2
|
||||||
https://tools.ietf.org/html/draft-ietf-acme-acme-09#section-7.5.2
|
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.5.2
|
||||||
'''
|
'''
|
||||||
authz_deactivate = {
|
authz_deactivate = {
|
||||||
'status': 'deactivated'
|
'status': 'deactivated'
|
||||||
|
|
|
@ -20,8 +20,10 @@ author: "Felix Fontein (@felixfontein)"
|
||||||
version_added: "2.7"
|
version_added: "2.7"
|
||||||
short_description: Revoke certificates with the ACME protocol.
|
short_description: Revoke certificates with the ACME protocol.
|
||||||
description:
|
description:
|
||||||
- "Allows to revoke certificates with the ACME protocol. This protocol
|
- "Allows to revoke certificates with the ACME protocol, for example
|
||||||
is, for example, used by Let's Encrypt."
|
for certificates obtained by the M(acme_certificate) module. The
|
||||||
|
ACME protocol is used by some Certificate Authorities such as
|
||||||
|
L(Let's Encrypt,https://letsencrypt.org/)."
|
||||||
- "Note that exactly one of C(account_key_src), C(account_key_content),
|
- "Note that exactly one of C(account_key_src), C(account_key_content),
|
||||||
C(private_key_src) or C(private_key_content) must be specified."
|
C(private_key_src) or C(private_key_content) must be specified."
|
||||||
- "Also note that in general, trying to revoke an already revoked
|
- "Also note that in general, trying to revoke an already revoked
|
||||||
|
@ -48,7 +50,7 @@ options:
|
||||||
- "Content of the certificate's private key."
|
- "Content of the certificate's private key."
|
||||||
- "Note that exactly one of C(account_key_src), C(account_key_content),
|
- "Note that exactly one of C(account_key_src), C(account_key_content),
|
||||||
C(private_key_src) or C(private_key_content) must be specified."
|
C(private_key_src) or C(private_key_content) must be specified."
|
||||||
- "Warning: the content will be written into a temporary file, which will
|
- "I(Warning): the content will be written into a temporary file, which will
|
||||||
be deleted by Ansible when the module completes. Since this is an
|
be deleted by Ansible when the module completes. Since this is an
|
||||||
important private key — it can be used to change the account key,
|
important private key — it can be used to change the account key,
|
||||||
or to revoke your certificates without knowing their private keys
|
or to revoke your certificates without knowing their private keys
|
||||||
|
|
|
@ -17,7 +17,8 @@ options:
|
||||||
- "Path to a file containing the ACME account RSA or Elliptic Curve
|
- "Path to a file containing the ACME account RSA or Elliptic Curve
|
||||||
key."
|
key."
|
||||||
- "RSA keys can be created with C(openssl rsa ...). Elliptic curve keys can
|
- "RSA keys can be created with C(openssl rsa ...). Elliptic curve keys can
|
||||||
be created with C(openssl ecparam -genkey ...)."
|
be created with C(openssl ecparam -genkey ...). Any other tool creating
|
||||||
|
private keys in PEM format can be used as well."
|
||||||
- "Mutually exclusive with C(account_key_content)."
|
- "Mutually exclusive with C(account_key_content)."
|
||||||
- "Required if C(account_key_content) is not used."
|
- "Required if C(account_key_content) is not used."
|
||||||
aliases: [ account_key ]
|
aliases: [ account_key ]
|
||||||
|
@ -26,7 +27,7 @@ options:
|
||||||
- "Content of the ACME account RSA or Elliptic Curve key."
|
- "Content of the ACME account RSA or Elliptic Curve key."
|
||||||
- "Mutually exclusive with C(account_key_src)."
|
- "Mutually exclusive with C(account_key_src)."
|
||||||
- "Required if C(account_key_src) is not used."
|
- "Required if C(account_key_src) is not used."
|
||||||
- "Warning: the content will be written into a temporary file, which will
|
- "I(Warning): the content will be written into a temporary file, which will
|
||||||
be deleted by Ansible when the module completes. Since this is an
|
be deleted by Ansible when the module completes. Since this is an
|
||||||
important private key — it can be used to change the account key,
|
important private key — it can be used to change the account key,
|
||||||
or to revoke your certificates without knowing their private keys
|
or to revoke your certificates without knowing their private keys
|
||||||
|
@ -59,8 +60,8 @@ options:
|
||||||
validate_certs:
|
validate_certs:
|
||||||
description:
|
description:
|
||||||
- Whether calls to the ACME directory will validate TLS certificates.
|
- Whether calls to the ACME directory will validate TLS certificates.
|
||||||
- I(Warning:) Should I(only ever) be set to C(no) for testing purposes,
|
- "I(Warning): Should I(only ever) be set to C(no) for testing purposes,
|
||||||
for example when testing against a local Pebble server.
|
for example when testing against a local Pebble server."
|
||||||
type: bool
|
type: bool
|
||||||
default: 'yes'
|
default: 'yes'
|
||||||
version_added: 2.5
|
version_added: 2.5
|
||||||
|
|
Loading…
Reference in a new issue