Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

acme_* modules: deprecate acme_version default, announce that ACME v1 support will be deprecated eventually #61667

Merged
merged 7 commits into from
Sep 21, 2019
Merged
45 changes: 45 additions & 0 deletions lib/ansible/module_utils/acme.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import datetime
import hashlib
import json
import locale
import os
import re
import shutil
Expand Down Expand Up @@ -941,3 +942,47 @@ def process_links(info, callback):
link = info['link']
for url, relation in re.findall(r'<([^>]+)>;rel="(\w+)"', link):
callback(unquote(url), relation)


def get_default_argspec():
'''
Provides default argument spec for the options documented in the acme doc fragment.
'''
return dict(
account_key_src=dict(type='path', aliases=['account_key']),
account_key_content=dict(type='str', no_log=True),
account_uri=dict(type='str'),
acme_directory=dict(type='str'),
acme_version=dict(type='int', choices=[1, 2]),
validate_certs=dict(type='bool', default=True),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'openssl', 'cryptography']),
)


def handle_standard_module_arguments(module, needs_acme_v2=False):
'''
Do standard module setup, argument handling and warning emitting.
'''
set_crypto_backend(module)

if not module.params['validate_certs']:
module.warn(
'Disabling certificate validation for communications with ACME endpoint. '
'This should only be done for testing against a local ACME server for '
'development purposes, but *never* for production purposes.'
)

if module.params['acme_version'] is None:
module.params['acme_version'] = 1
module.deprecate("The option 'acme_version' will be required from Ansible 2.14 on", version='2.14')

if module.params['acme_directory'] is None:
module.params['acme_directory'] = 'https://acme-staging.api.letsencrypt.org/directory'
module.deprecate("The option 'acme_directory' will be required from Ansible 2.14 on", version='2.14')

if needs_acme_v2 and module.params['acme_version'] < 2:
module.fail_json(msg='The {0} module requires the ACME v2 protocol!'.format(module._name))

# AnsibleModule() changes the locale, so change it back to C because we rely on time.strptime() when parsing certificate dates.
module.run_command_environ_update = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C', LC_CTYPE='C')
locale.setlocale(locale.LC_ALL, 'C')
39 changes: 15 additions & 24 deletions lib/ansible/modules/crypto/acme/acme_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,29 +130,27 @@
'''

from ansible.module_utils.acme import (
ModuleFailException, ACMEAccount, set_crypto_backend,
ModuleFailException,
ACMEAccount,
handle_standard_module_arguments,
get_default_argspec,
)

from ansible.module_utils.basic import AnsibleModule


def main():
argument_spec = get_default_argspec()
argument_spec.update(dict(
terms_agreed=dict(type='bool', default=False),
state=dict(type='str', required=True, choices=['absent', 'present', 'changed_key']),
allow_creation=dict(type='bool', default=True),
contact=dict(type='list', elements='str', default=[]),
new_account_key_src=dict(type='path'),
new_account_key_content=dict(type='str', no_log=True),
))
module = AnsibleModule(
argument_spec=dict(
account_key_src=dict(type='path', aliases=['account_key']),
account_key_content=dict(type='str', no_log=True),
account_uri=dict(type='str'),
acme_directory=dict(type='str', default='https://acme-staging.api.letsencrypt.org/directory'),
acme_version=dict(type='int', default=1, choices=[1, 2]),
validate_certs=dict(type='bool', default=True),
terms_agreed=dict(type='bool', default=False),
state=dict(type='str', required=True, choices=['absent', 'present', 'changed_key']),
allow_creation=dict(type='bool', default=True),
contact=dict(type='list', elements='str', default=[]),
new_account_key_src=dict(type='path'),
new_account_key_content=dict(type='str', no_log=True),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'openssl', 'cryptography']),
),
argument_spec=argument_spec,
required_one_of=(
['account_key_src', 'account_key_content'],
),
Expand All @@ -167,14 +165,7 @@ def main():
),
supports_check_mode=True,
)
set_crypto_backend(module)

if not module.params.get('validate_certs'):
module.warn(warning='Disabling certificate validation for communications with ACME endpoint. ' +
'This should only be done for testing against a local ACME server for ' +
'development purposes, but *never* for production purposes.')
if module.params.get('acme_version') < 2:
module.fail_json(msg='The acme_account module requires the ACME v2 protocol!')
handle_standard_module_arguments(module, needs_acme_v2=True)

try:
account = ACMEAccount(module)
Expand Down
30 changes: 11 additions & 19 deletions lib/ansible/modules/crypto/acme/acme_account_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,11 @@
'''

from ansible.module_utils.acme import (
ModuleFailException, ACMEAccount, set_crypto_backend, process_links,
ModuleFailException,
ACMEAccount,
handle_standard_module_arguments,
process_links,
get_default_argspec,
)

from ansible.module_utils.basic import AnsibleModule
Expand Down Expand Up @@ -238,17 +242,12 @@ def get_order(account, order_url):


def main():
argument_spec = get_default_argspec()
argument_spec.update(dict(
retrieve_orders=dict(type='str', default='ignore', choices=['ignore', 'url_list', 'object_list']),
))
module = AnsibleModule(
argument_spec=dict(
account_key_src=dict(type='path', aliases=['account_key']),
account_key_content=dict(type='str', no_log=True),
account_uri=dict(type='str'),
acme_directory=dict(type='str', default='https://acme-staging.api.letsencrypt.org/directory'),
acme_version=dict(type='int', default=1, choices=[1, 2]),
validate_certs=dict(type='bool', default=True),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'openssl', 'cryptography']),
retrieve_orders=dict(type='str', default='ignore', choices=['ignore', 'url_list', 'object_list']),
),
argument_spec=argument_spec,
required_one_of=(
['account_key_src', 'account_key_content'],
),
Expand All @@ -259,14 +258,7 @@ def main():
)
if module._name == 'acme_account_facts':
module.deprecate("The 'acme_account_facts' module has been renamed to 'acme_account_info'", version='2.12')
set_crypto_backend(module)

if not module.params.get('validate_certs'):
module.warn(warning='Disabling certificate validation for communications with ACME endpoint. ' +
'This should only be done for testing against a local ACME server for ' +
'development purposes, but *never* for production purposes.')
if module.params.get('acme_version') < 2:
module.fail_json(msg='The acme_account module requires the ACME v2 protocol!')
handle_standard_module_arguments(module, needs_acme_v2=True)

try:
account = ACMEAccount(module)
Expand Down
61 changes: 24 additions & 37 deletions lib/ansible/modules/crypto/acme/acme_certificate.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,24 +414,25 @@

from ansible.module_utils.acme import (
ModuleFailException,
write_file, nopad_b64, pem_to_der,
write_file,
nopad_b64,
pem_to_der,
ACMEAccount,
HAS_CURRENT_CRYPTOGRAPHY,
cryptography_get_csr_identifiers,
openssl_get_csr_identifiers,
cryptography_get_cert_days,
set_crypto_backend,
handle_standard_module_arguments,
process_links,
get_default_argspec,
)

import base64
import hashlib
import locale
import os
import re
import textwrap
import time
import urllib
from datetime import datetime

from ansible.module_utils.basic import AnsibleModule
Expand Down Expand Up @@ -987,30 +988,25 @@ def deactivate_authzs(self):


def main():
argument_spec = get_default_argspec()
argument_spec.update(dict(
modify_account=dict(type='bool', default=True),
account_email=dict(type='str'),
agreement=dict(type='str'),
terms_agreed=dict(type='bool', default=False),
challenge=dict(type='str', default='http-01', choices=['http-01', 'dns-01', 'tls-alpn-01']),
csr=dict(type='path', required=True, aliases=['src']),
data=dict(type='dict'),
dest=dict(type='path', aliases=['cert']),
fullchain_dest=dict(type='path', aliases=['fullchain']),
chain_dest=dict(type='path', aliases=['chain']),
remaining_days=dict(type='int', default=10),
deactivate_authzs=dict(type='bool', default=False),
force=dict(type='bool', default=False),
retrieve_all_alternates=dict(type='bool', default=False),
))
module = AnsibleModule(
argument_spec=dict(
account_key_src=dict(type='path', aliases=['account_key']),
account_key_content=dict(type='str', no_log=True),
account_uri=dict(type='str'),
modify_account=dict(type='bool', default=True),
acme_directory=dict(type='str', default='https://acme-staging.api.letsencrypt.org/directory'),
acme_version=dict(type='int', default=1, choices=[1, 2]),
validate_certs=dict(default=True, type='bool'),
account_email=dict(type='str'),
agreement=dict(type='str'),
terms_agreed=dict(type='bool', default=False),
challenge=dict(type='str', default='http-01', choices=['http-01', 'dns-01', 'tls-alpn-01']),
csr=dict(type='path', required=True, aliases=['src']),
data=dict(type='dict'),
dest=dict(type='path', aliases=['cert']),
fullchain_dest=dict(type='path', aliases=['fullchain']),
chain_dest=dict(type='path', aliases=['chain']),
remaining_days=dict(type='int', default=10),
deactivate_authzs=dict(type='bool', default=False),
force=dict(type='bool', default=False),
retrieve_all_alternates=dict(type='bool', default=False),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'openssl', 'cryptography']),
),
argument_spec=argument_spec,
required_one_of=(
['account_key_src', 'account_key_content'],
['dest', 'fullchain_dest'],
Expand All @@ -1020,16 +1016,7 @@ def main():
),
supports_check_mode=True,
)
set_crypto_backend(module)

# AnsibleModule() changes the locale, so change it back to C because we rely on time.strptime() when parsing certificate dates.
module.run_command_environ_update = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C', LC_CTYPE='C')
locale.setlocale(locale.LC_ALL, 'C')

if not module.params.get('validate_certs'):
module.warn(warning='Disabling certificate validation for communications with ACME endpoint. ' +
'This should only be done for testing against a local ACME server for ' +
'development purposes, but *never* for production purposes.')
handle_standard_module_arguments(module)

try:
if module.params.get('dest'):
Expand Down
35 changes: 15 additions & 20 deletions lib/ansible/modules/crypto/acme/acme_certificate_revoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,27 +123,27 @@
'''

from ansible.module_utils.acme import (
ModuleFailException, ACMEAccount, nopad_b64, pem_to_der, set_crypto_backend,
ModuleFailException,
ACMEAccount,
nopad_b64,
pem_to_der,
handle_standard_module_arguments,
get_default_argspec,
)

from ansible.module_utils.basic import AnsibleModule


def main():
argument_spec = get_default_argspec()
argument_spec.update(dict(
private_key_src=dict(type='path'),
private_key_content=dict(type='str', no_log=True),
certificate=dict(type='path', required=True),
revoke_reason=dict(type='int'),
))
module = AnsibleModule(
argument_spec=dict(
account_key_src=dict(type='path', aliases=['account_key']),
account_key_content=dict(type='str', no_log=True),
account_uri=dict(type='str'),
acme_directory=dict(type='str', default='https://acme-staging.api.letsencrypt.org/directory'),
acme_version=dict(type='int', default=1, choices=[1, 2]),
validate_certs=dict(type='bool', default=True),
private_key_src=dict(type='path'),
private_key_content=dict(type='str', no_log=True),
certificate=dict(type='path', required=True),
revoke_reason=dict(type='int'),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'openssl', 'cryptography']),
),
argument_spec=argument_spec,
required_one_of=(
['account_key_src', 'account_key_content', 'private_key_src', 'private_key_content'],
),
Expand All @@ -152,12 +152,7 @@ def main():
),
supports_check_mode=False,
)
set_crypto_backend(module)

if not module.params.get('validate_certs'):
module.warn(warning='Disabling certificate validation for communications with ACME endpoint. ' +
'This should only be done for testing against a local ACME server for ' +
'development purposes, but *never* for production purposes.')
handle_standard_module_arguments(module)

try:
account = ACMEAccount(module)
Expand Down
33 changes: 13 additions & 20 deletions lib/ansible/modules/crypto/acme/acme_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,10 @@
'''

from ansible.module_utils.acme import (
ModuleFailException, ACMEAccount, set_crypto_backend,
ModuleFailException,
ACMEAccount,
handle_standard_module_arguments,
get_default_argspec,
)

from ansible.module_utils.basic import AnsibleModule
Expand All @@ -256,20 +259,15 @@


def main():
argument_spec = get_default_argspec()
argument_spec.update(dict(
url=dict(type='str'),
method=dict(type='str', choices=['get', 'post', 'directory-only'], default='get'),
content=dict(type='str'),
fail_on_acme_error=dict(type='bool', default=True),
))
module = AnsibleModule(
argument_spec=dict(
account_key_src=dict(type='path', aliases=['account_key']),
account_key_content=dict(type='str', no_log=True),
account_uri=dict(type='str'),
acme_directory=dict(type='str', default='https://acme-staging.api.letsencrypt.org/directory'),
acme_version=dict(type='int', default=1, choices=[1, 2]),
validate_certs=dict(type='bool', default=True),
url=dict(type='str'),
method=dict(type='str', choices=['get', 'post', 'directory-only'], default='get'),
content=dict(type='str'),
fail_on_acme_error=dict(type='bool', default=True),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'openssl', 'cryptography']),
),
argument_spec=argument_spec,
mutually_exclusive=(
['account_key_src', 'account_key_content'],
),
Expand All @@ -280,12 +278,7 @@ def main():
['method', 'post', ['account_key_src', 'account_key_content'], True],
),
)
set_crypto_backend(module)

if not module.params.get('validate_certs'):
module.warn(warning='Disabling certificate validation for communications with ACME endpoint. ' +
'This should only be done for testing against a local ACME server for ' +
'development purposes, but *never* for production purposes.')
handle_standard_module_arguments(module)

result = dict()
changed = False
Expand Down
Loading