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.
pull/43695/merge
Felix Fontein 6 years ago committed by René Moser
parent 5fecf8baab
commit fadf8a2d09

@ -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…
Cancel
Save