ACME: improve documentation (#44691)
* Override description for account_key_src and account_key_content to also mention private_key_*. * Convert generic OpenSSL/cryptography remark from description to note. This avoids the whole description list to be sorted alphabetically, which will be done by plugin_docs.py in case description is mentioned in both module fragment and module itself. * Moving more notes to the notes: section. * Uniformization of first paragraph. Mainly mention ACME supporting CAs, and only then mention Let's Encrypt as one of them. * Adjusting to current drafts. * Adjusting to updated drafts. * Harmonizing short module descriptions. * Referencing helper modules. * Move general Let's Encrypt remark to doc fragment. * Changing some Let's Encrypt references to more generic statements.
This commit is contained in:
parent
5fecf8baab
commit
fadf8a2d09
6 changed files with 86 additions and 56 deletions
|
@ -466,7 +466,7 @@ class ACMEDirectory(object):
|
|||
and allows to obtain a Replay-Nonce. The acme_directory URL
|
||||
needs to support unauthenticated GET requests; ACME endpoints
|
||||
requiring authentication are not supported.
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.1.1
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-7.1.1
|
||||
'''
|
||||
|
||||
def __init__(self, module):
|
||||
|
@ -536,7 +536,7 @@ class ACMEAccount(object):
|
|||
def get_keyauthorization(self, token):
|
||||
'''
|
||||
Returns the key authorization for the given token
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-8.1
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-8.1
|
||||
'''
|
||||
accountkey_json = json.dumps(self.jwk, sort_keys=True, separators=(',', ':'))
|
||||
thumbprint = nopad_b64(hashlib.sha256(accountkey_json.encode('utf8')).digest())
|
||||
|
@ -570,7 +570,7 @@ class ACMEAccount(object):
|
|||
'''
|
||||
Sends a JWS signed HTTP POST request to the ACME server and returns
|
||||
the response as dictionary
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-6.2
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-6.2
|
||||
'''
|
||||
key_data = key_data or self.key_data
|
||||
jws_header = jws_header or self.jws_header
|
||||
|
@ -601,7 +601,7 @@ class ACMEAccount(object):
|
|||
try:
|
||||
result = self.module.from_json(content.decode('utf8'))
|
||||
# In case of badNonce error, try again (up to 5 times)
|
||||
# (https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-6.6)
|
||||
# (https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-6.6)
|
||||
if (400 <= info['status'] < 600 and
|
||||
result.get('type') == 'urn:ietf:params:acme:error:badNonce' and
|
||||
failed_tries <= 5):
|
||||
|
@ -629,7 +629,7 @@ class ACMEAccount(object):
|
|||
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).
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.3
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-7.3
|
||||
'''
|
||||
contact = [] if contact is None else contact
|
||||
|
||||
|
@ -711,7 +711,7 @@ class ACMEAccount(object):
|
|||
will be stored in self.uri; if it is None, the account does not
|
||||
exist.
|
||||
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.3
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-7.3
|
||||
'''
|
||||
|
||||
new_account = True
|
||||
|
|
|
@ -18,16 +18,19 @@ DOCUMENTATION = '''
|
|||
module: acme_account
|
||||
author: "Felix Fontein (@felixfontein)"
|
||||
version_added: "2.6"
|
||||
short_description: Create, modify or delete accounts with Let's Encrypt
|
||||
short_description: Create, modify or delete ACME accounts
|
||||
description:
|
||||
- "Allows to create, modify or delete accounts with Let's Encrypt.
|
||||
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)."
|
||||
- "Allows to create, modify or delete accounts with a CA supporting the
|
||||
L(ACME protocol,https://tools.ietf.org/html/draft-ietf-acme-acme-14),
|
||||
such as L(Let's Encrypt,https://letsencrypt.org/)."
|
||||
- "This module only works with the ACME v2 protocol."
|
||||
notes:
|
||||
- "Facts about an ACME account can be retrieved with the M(acme_account_facts)
|
||||
module."
|
||||
- "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."
|
||||
extends_documentation_fragment:
|
||||
- acme
|
||||
options:
|
||||
|
@ -52,7 +55,7 @@ options:
|
|||
description:
|
||||
- "A list of contact URLs."
|
||||
- "Email addresses must be prefixed with C(mailto:)."
|
||||
- "See https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.1.2
|
||||
- "See https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-7.1.2
|
||||
for what is allowed."
|
||||
- "Must be specified when state is C(present). Will be ignored
|
||||
if state is C(absent) or C(changed_key)."
|
||||
|
@ -65,14 +68,13 @@ options:
|
|||
type: bool
|
||||
new_account_key_src:
|
||||
description:
|
||||
- "Path to a file containing the Let's Encrypt account RSA or Elliptic Curve
|
||||
key to change to."
|
||||
- "Path to a file containing the ACME account RSA or Elliptic Curve key to change to."
|
||||
- "Same restrictions apply as to C(account_key_src)."
|
||||
- "Mutually exclusive with C(new_account_key_content)."
|
||||
- "Required if C(new_account_key_content) is not used and state is C(changed_key)."
|
||||
new_account_key_content:
|
||||
description:
|
||||
- "Content of the Let's Encrypt account RSA or Elliptic Curve key to change to."
|
||||
- "Content of the ACME account RSA or Elliptic Curve key to change to."
|
||||
- "Same restrictions apply as to C(account_key_content)."
|
||||
- "Mutually exclusive with C(new_account_key_src)."
|
||||
- "Required if C(new_account_key_src) is not used and state is C(changed_key)."
|
||||
|
@ -221,7 +223,7 @@ def main():
|
|||
# Now we can start the account key rollover
|
||||
if not module.check_mode:
|
||||
# Compose inner signed message
|
||||
# https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.3.6
|
||||
# https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-7.3.6
|
||||
url = account.directory['keyChange']
|
||||
protected = {
|
||||
"alg": new_key_data['alg'],
|
||||
|
@ -230,9 +232,8 @@ def main():
|
|||
}
|
||||
payload = {
|
||||
"account": account.uri,
|
||||
"newKey": new_key_data['jwk'], # specified in draft 12
|
||||
"oldKey": account.jwk, # discussed in https://github.com/ietf-wg-acme/acme/pull/425,
|
||||
# might be required in draft 13
|
||||
"newKey": new_key_data['jwk'], # specified in draft 12 and older
|
||||
"oldKey": account.jwk, # specified in draft 13 and newer
|
||||
}
|
||||
data = account.sign_request(protected, payload, new_key_data)
|
||||
# Send request and verify result
|
||||
|
|
|
@ -18,13 +18,14 @@ DOCUMENTATION = '''
|
|||
module: acme_account_facts
|
||||
author: "Felix Fontein (@felixfontein)"
|
||||
version_added: "2.7"
|
||||
short_description: Retrieves information on ACME accounts.
|
||||
short_description: Retrieves information on ACME accounts
|
||||
description:
|
||||
- "Allows to retrieve information on accounts with Let's Encrypt.
|
||||
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)."
|
||||
- "The M(acme_account) module allows to modify, create and delete ACME accounts."
|
||||
- "Allows to retrieve information on accounts a CA supporting the
|
||||
L(ACME protocol,https://tools.ietf.org/html/draft-ietf-acme-acme-14),
|
||||
such as L(Let's Encrypt,https://letsencrypt.org/)."
|
||||
- "This module only works with the ACME v2 protocol."
|
||||
notes:
|
||||
- "The M(acme_account) module allows to modify, create and delete ACME accounts."
|
||||
extends_documentation_fragment:
|
||||
- acme
|
||||
'''
|
||||
|
|
|
@ -18,10 +18,10 @@ DOCUMENTATION = '''
|
|||
module: acme_certificate
|
||||
author: "Michael Gruener (@mgruener)"
|
||||
version_added: "2.2"
|
||||
short_description: Create SSL certificates with an ACME protocol endpoint
|
||||
short_description: Create SSL/TLS certificates with the ACME protocol
|
||||
description:
|
||||
- "Create and renew SSL certificates with a CA supporting the
|
||||
L(ACME protocol,https://tools.ietf.org/html/draft-ietf-acme-acme-12),
|
||||
- "Create and renew SSL/TLS certificates with a CA supporting the
|
||||
L(ACME protocol,https://tools.ietf.org/html/draft-ietf-acme-acme-14),
|
||||
such as L(Let's Encrypt,https://letsencrypt.org/). The current
|
||||
implementation supports the C(http-01), C(dns-01) and C(tls-alpn-01)
|
||||
challenges."
|
||||
|
@ -36,19 +36,21 @@ description:
|
|||
the necessary certificate has to be created and served.
|
||||
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
|
||||
L(the main ACME specification,https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-8)
|
||||
and the L(TLS-ALPN-01 specification,U(https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-01#section-3).
|
||||
L(the main ACME specification,https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-8)
|
||||
and the L(TLS-ALPN-01 specification,https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05#section-3).
|
||||
Also, consider the examples provided for this module."
|
||||
- "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
|
||||
v1 or v2 protocol."
|
||||
notes:
|
||||
- "At least one of C(dest) and C(fullchain_dest) must be specified."
|
||||
- "Note that this module includes basic account management functionality.
|
||||
- "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
|
||||
- "This module was called C(letsencrypt) before Ansible 2.6. The usage
|
||||
did not change."
|
||||
- "If you want to use the C(tls-alpn-01) challenge, you can use the
|
||||
M(acme_challenge_cert_helper) module to prepare the challenge certificate."
|
||||
- "You can use the M(certificate_complet_chain) module to find the root certificate
|
||||
for the returned fullchain."
|
||||
extends_documentation_fragment:
|
||||
- acme
|
||||
options:
|
||||
|
@ -98,8 +100,8 @@ options:
|
|||
CSR to be signed."
|
||||
- "I(Note): the private key used to create the CSR I(must not) be the
|
||||
account key. This is a bad idea from a security point of view, and
|
||||
the CA should not accept the CSR. Let's Encrypt will return an error
|
||||
in this case."
|
||||
the CA should not accept the CSR. The ACME server should return an
|
||||
error in this case."
|
||||
required: true
|
||||
aliases: ['src']
|
||||
data:
|
||||
|
@ -284,7 +286,7 @@ challenge_data:
|
|||
- "For C(tls-alpn-01) challenges, note that this return value contains a
|
||||
Base64 encoded version of the correct binary blob which has to be put
|
||||
into the acmeValidation x509 extension; see
|
||||
U(https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-01#section-3)
|
||||
U(https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05#section-3)
|
||||
for details. To do this, you might need the C(b64decode) Jinja filter
|
||||
to extract the binary blob from this return value."
|
||||
returned: changed
|
||||
|
@ -307,7 +309,7 @@ authorizations:
|
|||
type: complex
|
||||
contains:
|
||||
authorization:
|
||||
description: ACME authorization object. See U(https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.1.4)
|
||||
description: ACME authorization object. See U(https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-7.1.4)
|
||||
returned: success
|
||||
type: dict
|
||||
order_uri:
|
||||
|
@ -492,17 +494,17 @@ class ACMEClient(object):
|
|||
keyauthorization = self.account.get_keyauthorization(token)
|
||||
|
||||
if type == 'http-01':
|
||||
# https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-8.3
|
||||
# https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-8.3
|
||||
resource = '.well-known/acme-challenge/' + token
|
||||
data[type] = {'resource': resource, 'resource_value': keyauthorization}
|
||||
elif type == 'dns-01':
|
||||
# https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-8.4
|
||||
# https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-8.4
|
||||
resource = '_acme-challenge'
|
||||
value = nopad_b64(hashlib.sha256(to_bytes(keyauthorization)).digest())
|
||||
record = (resource + domain[1:]) if domain.startswith('*.') else (resource + '.' + domain)
|
||||
data[type] = {'resource': resource, 'resource_value': value, 'record': record}
|
||||
elif type == 'tls-alpn-01':
|
||||
# https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-01#section-3
|
||||
# https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05#section-3
|
||||
resource = domain
|
||||
value = base64.b64encode(hashlib.sha256(to_bytes(keyauthorization)).digest())
|
||||
data[type] = {'resource': resource, 'resource_value': value}
|
||||
|
@ -573,7 +575,7 @@ class ACMEClient(object):
|
|||
'''
|
||||
Create a new certificate based on the csr.
|
||||
Return the certificate object as dict
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.4
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-7.4
|
||||
'''
|
||||
csr = pem_to_der(self.csr)
|
||||
new_cert = {
|
||||
|
@ -607,7 +609,7 @@ class ACMEClient(object):
|
|||
def _download_cert(self, url):
|
||||
'''
|
||||
Download and parse the certificate chain.
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.4.2
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-7.4.2
|
||||
'''
|
||||
resp, info = fetch_url(self.module, url, headers={'Accept': 'application/pem-certificate-chain'})
|
||||
try:
|
||||
|
@ -679,7 +681,7 @@ class ACMEClient(object):
|
|||
def _new_order_v2(self):
|
||||
'''
|
||||
Start a new certificate order (ACME v2 protocol).
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.4
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-7.4
|
||||
'''
|
||||
identifiers = []
|
||||
for domain in self.domains:
|
||||
|
@ -841,7 +843,7 @@ class ACMEClient(object):
|
|||
'''
|
||||
Deactivates all valid authz's. Does not raise exceptions.
|
||||
https://community.letsencrypt.org/t/authorization-deactivation/19860/2
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.5.2
|
||||
https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-7.5.2
|
||||
'''
|
||||
authz_deactivate = {
|
||||
'status': 'deactivated'
|
||||
|
|
|
@ -18,15 +18,15 @@ DOCUMENTATION = '''
|
|||
module: acme_certificate_revoke
|
||||
author: "Felix Fontein (@felixfontein)"
|
||||
version_added: "2.7"
|
||||
short_description: Revoke certificates with the ACME protocol.
|
||||
short_description: Revoke certificates with the ACME protocol
|
||||
description:
|
||||
- "Allows to revoke certificates with the ACME protocol, for example
|
||||
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),
|
||||
- "Allows to revoke certificates issued by a CA supporting the
|
||||
L(ACME protocol,https://tools.ietf.org/html/draft-ietf-acme-acme-14),
|
||||
such as L(Let's Encrypt,https://letsencrypt.org/)."
|
||||
notes:
|
||||
- "Exactly one of C(account_key_src), C(account_key_content),
|
||||
C(private_key_src) or C(private_key_content) must be specified."
|
||||
- "Also note that trying to revoke an already revoked certificate
|
||||
- "Trying to revoke an already revoked certificate
|
||||
should result in an unchanged status, even if the revocation reason
|
||||
was different than the one specified here. Also, depending on the
|
||||
server, it can happen that some other error is returned if the
|
||||
|
@ -38,6 +38,29 @@ options:
|
|||
description:
|
||||
- "Path to the certificate to revoke."
|
||||
required: yes
|
||||
account_key_src:
|
||||
description:
|
||||
- "Path to a file containing the ACME account RSA or Elliptic Curve
|
||||
key."
|
||||
- "RSA keys can be created with C(openssl rsa ...). Elliptic curve keys can
|
||||
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)."
|
||||
- "Required if C(account_key_content) is not used."
|
||||
account_key_content:
|
||||
description:
|
||||
- "Content of the ACME account RSA or Elliptic Curve key."
|
||||
- "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."
|
||||
- "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
|
||||
important private key — it can be used to change the account key,
|
||||
or to revoke your certificates without knowing their private keys
|
||||
—, this might not be acceptable."
|
||||
- "In case C(cryptography) is used, the content is not written into a
|
||||
temporary file. It can still happen that it is written to disk by
|
||||
Ansible in the process of moving the module with its argument to
|
||||
the node where it is executed."
|
||||
private_key_src:
|
||||
description:
|
||||
- "Path to the certificate's private key."
|
||||
|
|
|
@ -8,14 +8,17 @@ class ModuleDocFragment(object):
|
|||
|
||||
# Standard files documentation fragment
|
||||
DOCUMENTATION = """
|
||||
description:
|
||||
- "Note that if a new enough version of the C(cryptography) library
|
||||
notes:
|
||||
- "If a new enough version of the C(cryptography) library
|
||||
is available (see Requirements for details), it will be used
|
||||
instead of the C(openssl) binary. This can be explicitly disabled
|
||||
or enabled with the C(select_crypto_backend) option. Note that using
|
||||
the C(openssl) binary will be slower and less secure, as private key
|
||||
contents always have to be stored on disk (see
|
||||
C(account_key_content))."
|
||||
- "Although the defaults are chosen so that the module can be used with
|
||||
the L(Let's Encrypt,https://letsencrypt.org/) CA, the module can in
|
||||
principle be used with any CA providing an ACME endpoint."
|
||||
requirements:
|
||||
- "python >= 2.6"
|
||||
- "either openssl, ..."
|
||||
|
@ -73,8 +76,8 @@ options:
|
|||
U(https://acme-v01.api.letsencrypt.org/directory), and the production
|
||||
directory URL for ACME v2 is U(https://acme-v02.api.letsencrypt.org/directory)."
|
||||
- "I(Warning): So far, the module has only been tested against Let's Encrypt
|
||||
(staging and production) and against the Pebble testing server
|
||||
(U(https://github.com/letsencrypt/Pebble))."
|
||||
(staging and production) and against the
|
||||
L(Pebble testing server,https://github.com/letsencrypt/Pebble)."
|
||||
default: https://acme-staging.api.letsencrypt.org/directory
|
||||
validate_certs:
|
||||
description:
|
||||
|
|
Loading…
Reference in a new issue