Pep8 fixes for letsencrypt module (#24144)

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
This commit is contained in:
Abhijeet Kasurde 2017-05-02 22:05:06 +05:30 committed by Matt Martz
parent df5be2b8ea
commit fbb924ff24
2 changed files with 90 additions and 87 deletions

View file

@ -174,7 +174,8 @@ from datetime import datetime
def nopad_b64(data): def nopad_b64(data):
return base64.urlsafe_b64encode(data).decode('utf8').replace("=", "") return base64.urlsafe_b64encode(data).decode('utf8').replace("=", "")
def simple_get(module,url):
def simple_get(module, url):
resp, info = fetch_url(module, url, method='GET') resp, info = fetch_url(module, url, method='GET')
result = None result = None
@ -189,15 +190,16 @@ def simple_get(module,url):
try: try:
result = module.from_json(content.decode('utf8')) result = module.from_json(content.decode('utf8'))
except ValueError: except ValueError:
module.fail_json(msg="Failed to parse the ACME response: {0} {1}".format(url,content)) module.fail_json(msg="Failed to parse the ACME response: {0} {1}".format(url, content))
else: else:
result = content result = content
if info['status'] >= 400: if info['status'] >= 400:
module.fail_json(msg="ACME request failed: CODE: {0} RESULT:{1}".format(info['status'],result)) module.fail_json(msg="ACME request failed: CODE: {0} RESULT: {1}".format(info['status'], result))
return result return result
def get_cert_days(module,cert_file):
def get_cert_days(module, cert_file):
''' '''
Return the days the certificate in cert_file remains valid and -1 Return the days the certificate in cert_file remains valid and -1
if the file was not found. if the file was not found.
@ -207,10 +209,10 @@ def get_cert_days(module,cert_file):
openssl_bin = module.get_bin_path('openssl', True) openssl_bin = module.get_bin_path('openssl', True)
openssl_cert_cmd = [openssl_bin, "x509", "-in", cert_file, "-noout", "-text"] openssl_cert_cmd = [openssl_bin, "x509", "-in", cert_file, "-noout", "-text"]
_, out, _ = module.run_command(openssl_cert_cmd,check_rc=True) _, out, _ = module.run_command(openssl_cert_cmd, check_rc=True)
try: try:
not_after_str = re.search(r"\s+Not After\s*:\s+(.*)",out.decode('utf8')).group(1) not_after_str = re.search(r"\s+Not After\s*:\s+(.*)", out.decode('utf8')).group(1)
not_after = datetime.datetime.fromtimestamp(time.mktime(time.strptime(not_after_str,'%b %d %H:%M:%S %Y %Z'))) not_after = datetime.datetime.fromtimestamp(time.mktime(time.strptime(not_after_str, '%b %d %H:%M:%S %Y %Z')))
except AttributeError: except AttributeError:
module.fail_json(msg="No 'Not after' date found in {0}".format(cert_file)) module.fail_json(msg="No 'Not after' date found in {0}".format(cert_file))
except ValueError: except ValueError:
@ -218,6 +220,7 @@ def get_cert_days(module,cert_file):
now = datetime.datetime.utcnow() now = datetime.datetime.utcnow()
return (not_after - now).days return (not_after - now).days
# function source: network/basics/uri.py # function source: network/basics/uri.py
def write_file(module, dest, content): def write_file(module, dest, content):
''' '''
@ -234,15 +237,15 @@ def write_file(module, dest, content):
os.remove(tmpsrc) os.remove(tmpsrc)
module.fail_json(msg="failed to create temporary content file: %s" % str(err)) module.fail_json(msg="failed to create temporary content file: %s" % str(err))
f.close() f.close()
checksum_src = None checksum_src = None
checksum_dest = None checksum_dest = None
# raise an error if there is no tmpsrc file # raise an error if there is no tmpsrc file
if not os.path.exists(tmpsrc): if not os.path.exists(tmpsrc):
os.remove(tmpsrc) os.remove(tmpsrc)
module.fail_json(msg="Source %s does not exist" % (tmpsrc)) module.fail_json(msg="Source %s does not exist" % (tmpsrc))
if not os.access(tmpsrc, os.R_OK): if not os.access(tmpsrc, os.R_OK):
os.remove(tmpsrc) os.remove(tmpsrc)
module.fail_json( msg="Source %s not readable" % (tmpsrc)) module.fail_json(msg="Source %s not readable" % (tmpsrc))
checksum_src = module.sha1(tmpsrc) checksum_src = module.sha1(tmpsrc)
# check if there is no dest file # check if there is no dest file
if os.path.exists(dest): if os.path.exists(dest):
@ -268,6 +271,7 @@ def write_file(module, dest, content):
os.remove(tmpsrc) os.remove(tmpsrc)
return changed return changed
class ACMEDirectory(object): class ACMEDirectory(object):
''' '''
The ACME server directory. Gives access to the available resources The ACME server directory. Gives access to the available resources
@ -277,15 +281,15 @@ class ACMEDirectory(object):
https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-6.2 https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-6.2
''' '''
def __init__(self, module): def __init__(self, module):
self.module = module self.module = module
self.directory_root = module.params['acme_directory'] self.directory_root = module.params['acme_directory']
self.directory = simple_get(self.module,self.directory_root) self.directory = simple_get(self.module, self.directory_root)
def __getitem__(self, key): def __getitem__(self, key):
return self.directory[key] return self.directory[key]
def get_nonce(self,resource=None): def get_nonce(self, resource=None):
url = self.directory_root url = self.directory_root
if resource is not None: if resource is not None:
url = resource url = resource
@ -294,21 +298,22 @@ class ACMEDirectory(object):
self.module.fail_json(msg="Failed to get replay-nonce, got status {0}".format(info['status'])) self.module.fail_json(msg="Failed to get replay-nonce, got status {0}".format(info['status']))
return info['replay-nonce'] return info['replay-nonce']
class ACMEAccount(object): class ACMEAccount(object):
''' '''
ACME account object. Handles the authorized communication with the ACME account object. Handles the authorized communication with the
ACME server. Provides access to account bound information like ACME server. Provides access to account bound information like
the currently active authorizations and valid certificates the currently active authorizations and valid certificates
''' '''
def __init__(self,module): def __init__(self, module):
self.module = module self.module = module
self.agreement = module.params['agreement'] self.agreement = module.params['agreement']
self.key = module.params['account_key'] self.key = module.params['account_key']
self.email = module.params['account_email'] self.email = module.params['account_email']
self.data = module.params['data'] self.data = module.params['data']
self.directory = ACMEDirectory(module) self.directory = ACMEDirectory(module)
self.uri = None self.uri = None
self.changed = False self.changed = False
self._authz_list_uri = None self._authz_list_uri = None
self._certs_list_uri = None self._certs_list_uri = None
@ -319,7 +324,7 @@ class ACMEAccount(object):
self._openssl_bin = module.get_bin_path('openssl', True) self._openssl_bin = module.get_bin_path('openssl', True)
pub_hex, pub_exp = self._parse_account_key(self.key) pub_hex, pub_exp = self._parse_account_key(self.key)
self.jws_header = { self.jws_header = {
"alg": "RS256", "alg": "RS256",
"jwk": { "jwk": {
"e": nopad_b64(binascii.unhexlify(pub_exp.encode("utf-8"))), "e": nopad_b64(binascii.unhexlify(pub_exp.encode("utf-8"))),
@ -329,7 +334,7 @@ class ACMEAccount(object):
} }
self.init_account() self.init_account()
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-02#section-7.1 https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-7.1
@ -338,17 +343,17 @@ class ACMEAccount(object):
thumbprint = nopad_b64(hashlib.sha256(accountkey_json.encode('utf8')).digest()) thumbprint = nopad_b64(hashlib.sha256(accountkey_json.encode('utf8')).digest())
return "{0}.{1}".format(token, thumbprint) return "{0}.{1}".format(token, thumbprint)
def _parse_account_key(self,key): def _parse_account_key(self, key):
''' '''
Parses an RSA key file in PEM format and returns the modulus Parses an RSA key file in PEM format and returns the modulus
and public exponent of the key and public exponent of the key
''' '''
openssl_keydump_cmd = [self._openssl_bin, "rsa", "-in", key, "-noout", "-text"] openssl_keydump_cmd = [self._openssl_bin, "rsa", "-in", key, "-noout", "-text"]
_, out, _ = self.module.run_command(openssl_keydump_cmd,check_rc=True) _, out, _ = self.module.run_command(openssl_keydump_cmd, check_rc=True)
pub_hex, pub_exp = re.search( pub_hex, pub_exp = re.search(
r"modulus:\n\s+00:([a-f0-9\:\s]+?)\npublicExponent: ([0-9]+)", r"modulus:\n\s+00:([a-f0-9\:\s]+?)\npublicExponent: ([0-9]+)",
out.decode('utf8'), re.MULTILINE|re.DOTALL).groups() out.decode('utf8'), re.MULTILINE | re.DOTALL).groups()
pub_exp = "{0:x}".format(int(pub_exp)) pub_exp = "{0:x}".format(int(pub_exp))
if len(pub_exp) % 2: if len(pub_exp) % 2:
pub_exp = "0{0}".format(pub_exp) pub_exp = "0{0}".format(pub_exp)
@ -372,7 +377,7 @@ class ACMEAccount(object):
openssl_sign_cmd = [self._openssl_bin, "dgst", "-sha256", "-sign", self.key] openssl_sign_cmd = [self._openssl_bin, "dgst", "-sha256", "-sign", self.key]
sign_payload = "{0}.{1}".format(protected64, payload64).encode('utf8') sign_payload = "{0}.{1}".format(protected64, payload64).encode('utf8')
_, out, _ = self.module.run_command(openssl_sign_cmd,data=sign_payload,check_rc=True, binary_data=True) _, out, _ = self.module.run_command(openssl_sign_cmd, data=sign_payload, check_rc=True, binary_data=True)
data = self.module.jsonify({ data = self.module.jsonify({
"header": self.jws_header, "header": self.jws_header,
@ -394,13 +399,13 @@ class ACMEAccount(object):
try: try:
result = self.module.from_json(content.decode('utf8')) result = self.module.from_json(content.decode('utf8'))
except ValueError: except ValueError:
self.module.fail_json(msg="Failed to parse the ACME response: {0} {1}".format(url,content)) self.module.fail_json(msg="Failed to parse the ACME response: {0} {1}".format(url, content))
else: else:
result = content result = content
return result,info return result, info
def _new_reg(self,contact=[]): def _new_reg(self, contact=[]):
''' '''
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
@ -420,7 +425,7 @@ class ACMEAccount(object):
if 'location' in info: if 'location' in info:
self.uri = info['location'] self.uri = info['location']
if info['status'] in [200,201]: if info['status'] in [200, 201]:
# Account did not exist # Account did not exist
self.changed = True self.changed = True
return True return True
@ -448,7 +453,7 @@ class ACMEAccount(object):
# if this is not a new registration (e.g. existing account) # if this is not a new registration (e.g. existing account)
if not self._new_reg(contact): if not self._new_reg(contact):
# pre-existing account, get account data... # pre-existing account, get account data...
result, _ = self.send_signed_request(self.uri, {'resource':'reg'}) result, _ = self.send_signed_request(self.uri, {'resource': 'reg'})
# XXX: letsencrypt/boulder#1435 # XXX: letsencrypt/boulder#1435
if 'authorizations' in result: if 'authorizations' in result:
@ -459,7 +464,7 @@ class ACMEAccount(object):
# ...and check if update is necessary # ...and check if update is necessary
do_update = False do_update = False
if 'contact' in result: if 'contact' in result:
if cmp(contact,result['contact']) != 0: if cmp(contact, result['contact']) != 0:
do_update = True do_update = True
elif len(contact) > 0: elif len(contact) > 0:
do_update = True do_update = True
@ -493,55 +498,55 @@ class ACMEAccount(object):
authz = [] authz = []
for auth_uri in authz_list['authorizations']: for auth_uri in authz_list['authorizations']:
auth = simple_get(self.module,auth_uri) auth = simple_get(self.module, auth_uri)
auth['uri'] = auth_uri auth['uri'] = auth_uri
authz.append(auth) authz.append(auth)
return authz return authz
class ACMEClient(object): class ACMEClient(object):
''' '''
ACME client class. Uses an ACME account object and a CSR to ACME client class. Uses an ACME account object and a CSR to
start and validate ACME challenges and download the respective start and validate ACME challenges and download the respective
certificates. certificates.
''' '''
def __init__(self,module): def __init__(self, module):
self.module = module self.module = module
self.challenge = module.params['challenge'] self.challenge = module.params['challenge']
self.csr = module.params['csr'] self.csr = module.params['csr']
self.dest = module.params['dest'] self.dest = module.params['dest']
self.account = ACMEAccount(module) self.account = ACMEAccount(module)
self.directory = self.account.directory self.directory = self.account.directory
self.authorizations = self.account.get_authorizations() self.authorizations = self.account.get_authorizations()
self.cert_days = -1 self.cert_days = -1
self.changed = self.account.changed self.changed = self.account.changed
if not os.path.exists(self.csr): if not os.path.exists(self.csr):
module.fail_json(msg="CSR %s not found" % (self.csr)) module.fail_json(msg="CSR %s not found" % (self.csr))
self._openssl_bin = module.get_bin_path('openssl', True) self._openssl_bin = module.get_bin_path('openssl', True)
self.domains = self._get_csr_domains() self.domains = self._get_csr_domains()
def _get_csr_domains(self): def _get_csr_domains(self):
''' '''
Parse the CSR and return the list of requested domains Parse the CSR and return the list of requested domains
''' '''
openssl_csr_cmd = [self._openssl_bin, "req", "-in", self.csr, "-noout", "-text"] openssl_csr_cmd = [self._openssl_bin, "req", "-in", self.csr, "-noout", "-text"]
_, out, _ = self.module.run_command(openssl_csr_cmd,check_rc=True) _, out, _ = self.module.run_command(openssl_csr_cmd, check_rc=True)
domains = set([]) domains = set([])
common_name = re.search(r"Subject:.*? CN=([^\s,;/]+)", out.decode('utf8')) common_name = re.search(r"Subject:.*? CN=([^\s,;/]+)", out.decode('utf8'))
if common_name is not None: if common_name is not None:
domains.add(common_name.group(1)) domains.add(common_name.group(1))
subject_alt_names = re.search(r"X509v3 Subject Alternative Name: \n +([^\n]+)\n", out.decode('utf8'), re.MULTILINE|re.DOTALL) subject_alt_names = re.search(r"X509v3 Subject Alternative Name: \n +([^\n]+)\n", out.decode('utf8'), re.MULTILINE | re.DOTALL)
if subject_alt_names is not None: if subject_alt_names is not None:
for san in subject_alt_names.group(1).split(", "): for san in subject_alt_names.group(1).split(", "):
if san.startswith("DNS:"): if san.startswith("DNS:"):
domains.add(san[4:]) domains.add(san[4:])
return domains return domains
def _get_domain_auth(self, domain):
def _get_domain_auth(self,domain):
''' '''
Get the status string of the first authorization for the given domain. Get the status string of the first authorization for the given domain.
Return None if no active authorization for the given domain was found. Return None if no active authorization for the given domain was found.
@ -554,16 +559,16 @@ class ACMEClient(object):
return auth return auth
return None return None
def _add_or_update_auth(self,auth): def _add_or_update_auth(self, auth):
''' '''
Add or update the given authroization in the global authorizations list. Add or update the given authroization in the global authorizations list.
Return True if the auth was updated/added and False if no change was Return True if the auth was updated/added and False if no change was
necessary. necessary.
''' '''
for index,cur_auth in enumerate(self.authorizations): for index, cur_auth in enumerate(self.authorizations):
if (cur_auth['uri'] == auth['uri']): if (cur_auth['uri'] == auth['uri']):
# does the auth parameter contain updated data? # does the auth parameter contain updated data?
if cmp(cur_auth,auth) != 0: if cmp(cur_auth, auth) != 0:
# yes, update our current authorization list # yes, update our current authorization list
self.authorizations[index] = auth self.authorizations[index] = auth
return True return True
@ -574,7 +579,7 @@ class ACMEClient(object):
self.authorizations.append(auth) self.authorizations.append(auth)
return True return True
def _new_authz(self,domain): def _new_authz(self, domain):
''' '''
Create a new authorization for the given domain. Create a new authorization for the given domain.
Return the authorization object of the new authorization Return the authorization object of the new authorization
@ -589,13 +594,13 @@ class ACMEClient(object):
} }
result, info = self.account.send_signed_request(self.directory['new-authz'], new_authz) result, info = self.account.send_signed_request(self.directory['new-authz'], new_authz)
if info['status'] not in [200,201]: if info['status'] not in [200, 201]:
self.module.fail_json(msg="Error requesting challenges: CODE: {0} RESULT: {1}".format(info['status'], result)) self.module.fail_json(msg="Error requesting challenges: CODE: {0} RESULT: {1}".format(info['status'], result))
else: else:
result['uri'] = info['location'] result['uri'] = info['location']
return result return result
def _get_challenge_data(self,auth): def _get_challenge_data(self, auth):
''' '''
Returns a dict with the data for all proposed (and supported) challenges Returns a dict with the data for all proposed (and supported) challenges
of the given authorization. of the given authorization.
@ -625,8 +630,8 @@ class ACMEClient(object):
len_ka_digest = len(ka_digest) len_ka_digest = len(ka_digest)
resource = 'subjectAlternativeNames' resource = 'subjectAlternativeNames'
value = [ value = [
"{0}.{1}.token.acme.invalid".format(token_digest[:len_token_digest/2],token_digest[len_token_digest/2:]), "{0}.{1}.token.acme.invalid".format(token_digest[:len_token_digest / 2], token_digest[len_token_digest / 2:]),
"{0}.{1}.ka.acme.invalid".format(ka_digest[:len_ka_digest/2],ka_digest[len_ka_digest/2:]), "{0}.{1}.ka.acme.invalid".format(ka_digest[:len_ka_digest / 2], ka_digest[len_ka_digest / 2:]),
] ]
elif type == 'dns-01': elif type == 'dns-01':
# https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-7.4 # https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-7.4
@ -635,10 +640,10 @@ class ACMEClient(object):
else: else:
continue continue
data[type] = { 'resource': resource, 'resource_value': value } data[type] = {'resource': resource, 'resource_value': value}
return data return data
def _validate_challenges(self,auth): def _validate_challenges(self, auth):
''' '''
Validate the authorization provided in the auth dict. Returns True Validate the authorization provided in the auth dict. Returns True
when the validation was successful and False when it was not. when the validation was successful and False when it was not.
@ -656,13 +661,13 @@ class ACMEClient(object):
"keyAuthorization": keyauthorization, "keyAuthorization": keyauthorization,
} }
result, info = self.account.send_signed_request(uri, challenge_response) result, info = self.account.send_signed_request(uri, challenge_response)
if info['status'] not in [200,202]: if info['status'] not in [200, 202]:
self.module.fail_json(msg="Error validating challenge: CODE: {0} RESULT: {1}".format(info['status'], result)) self.module.fail_json(msg="Error validating challenge: CODE: {0} RESULT: {1}".format(info['status'], result))
status = '' status = ''
while status not in ['valid','invalid','revoked']: while status not in ['valid', 'invalid', 'revoked']:
result = simple_get(self.module,auth['uri']) result = simple_get(self.module, auth['uri'])
result['uri'] = auth['uri'] result['uri'] = auth['uri']
if self._add_or_update_auth(result): if self._add_or_update_auth(result):
self.changed = True self.changed = True
@ -686,7 +691,7 @@ class ACMEClient(object):
error_details += ' DETAILS: {0};'.format(challenge['error']['detail']) error_details += ' DETAILS: {0};'.format(challenge['error']['detail'])
else: else:
error_details += ';' error_details += ';'
self.module.fail_json(msg="Authorization for {0} returned invalid: {1}".format(result['identifier']['value'],error_details)) self.module.fail_json(msg="Authorization for {0} returned invalid: {1}".format(result['identifier']['value'], error_details))
return status == 'valid' return status == 'valid'
@ -697,19 +702,19 @@ class ACMEClient(object):
https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-6.5 https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-6.5
''' '''
openssl_csr_cmd = [self._openssl_bin, "req", "-in", self.csr, "-outform", "DER"] openssl_csr_cmd = [self._openssl_bin, "req", "-in", self.csr, "-outform", "DER"]
_, out, _ = self.module.run_command(openssl_csr_cmd,check_rc=True) _, out, _ = self.module.run_command(openssl_csr_cmd, check_rc=True)
new_cert = { new_cert = {
"resource": "new-cert", "resource": "new-cert",
"csr": nopad_b64(out), "csr": nopad_b64(out),
} }
result, info = self.account.send_signed_request(self.directory['new-cert'], new_cert) result, info = self.account.send_signed_request(self.directory['new-cert'], new_cert)
if info['status'] not in [200,201]: if info['status'] not in [200, 201]:
self.module.fail_json(msg="Error new cert: CODE: {0} RESULT: {1}".format(info['status'], result)) self.module.fail_json(msg="Error new cert: CODE: {0} RESULT: {1}".format(info['status'], result))
else: else:
return {'cert': result, 'uri': info['location']} return {'cert': result, 'uri': info['location']}
def _der_to_pem(self,der_cert): def _der_to_pem(self, der_cert):
''' '''
Convert the DER format certificate in der_cert to a PEM format Convert the DER format certificate in der_cert to a PEM format
certificate and return it. certificate and return it.
@ -759,47 +764,46 @@ class ACMEClient(object):
cert = self._new_cert() cert = self._new_cert()
if cert['cert'] is not None: if cert['cert'] is not None:
pem_cert = self._der_to_pem(cert['cert']) pem_cert = self._der_to_pem(cert['cert'])
if write_file(self.module,self.dest,pem_cert): if write_file(self.module, self.dest, pem_cert):
self.cert_days = get_cert_days(self.module,self.dest) self.cert_days = get_cert_days(self.module, self.dest)
self.changed = True self.changed = True
def main(): def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec = dict( argument_spec=dict(
account_key = dict(required=True, type='path'), account_key=dict(required=True, type='path'),
account_email = dict(required=False, default=None, type='str'), account_email=dict(required=False, default=None, type='str'),
acme_directory = dict(required=False, default='https://acme-staging.api.letsencrypt.org/directory', type='str'), acme_directory=dict(required=False, default='https://acme-staging.api.letsencrypt.org/directory', type='str'),
agreement = dict(required=False, default='https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf', type='str'), agreement=dict(required=False, default='https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf', type='str'),
challenge = dict(required=False, default='http-01', choices=['http-01', 'dns-01', 'tls-sni-02'], type='str'), challenge=dict(required=False, default='http-01', choices=['http-01', 'dns-01', 'tls-sni-02'], type='str'),
csr = dict(required=True, aliases=['src'], type='path'), csr=dict(required=True, aliases=['src'], type='path'),
data = dict(required=False, no_log=True, default=None, type='dict'), data=dict(required=False, no_log=True, default=None, type='dict'),
dest = dict(required=True, aliases=['cert'], type='path'), dest=dict(required=True, aliases=['cert'], type='path'),
remaining_days = dict(required=False, default=10, type='int'), remaining_days=dict(required=False, default=10, type='int'),
), ),
supports_check_mode = True, supports_check_mode=True,
) )
# AnsibleModule() changes the locale, so change it back to C because we rely on time.strptime() when parsing certificate dates. # AnsibleModule() changes the locale, so change it back to C because we rely on time.strptime() when parsing certificate dates.
locale.setlocale(locale.LC_ALL, "C") locale.setlocale(locale.LC_ALL, "C")
cert_days = get_cert_days(module,module.params['dest']) cert_days = get_cert_days(module, module.params['dest'])
if cert_days < module.params['remaining_days']: if cert_days < module.params['remaining_days']:
# If checkmode is active, base the changed state solely on the status # If checkmode is active, base the changed state solely on the status
# of the certificate file as all other actions (accessing an account, checking # of the certificate file as all other actions (accessing an account, checking
# the authorization status...) would lead to potential changes of the current # the authorization status...) would lead to potential changes of the current
# state # state
if module.check_mode: if module.check_mode:
module.exit_json(changed=True,authorizations={}, module.exit_json(changed=True, authorizations={}, challenge_data={}, cert_days=cert_days)
challenge_data={},cert_days=cert_days)
else: else:
client = ACMEClient(module) client = ACMEClient(module)
client.cert_days = cert_days client.cert_days = cert_days
data = client.do_challenges() data = client.do_challenges()
client.get_certificate() client.get_certificate()
module.exit_json(changed=client.changed,authorizations=client.authorizations, module.exit_json(changed=client.changed, authorizations=client.authorizations, challenge_data=data, cert_days=client.cert_days)
challenge_data=data,cert_days=client.cert_days)
else: else:
module.exit_json(changed=False,cert_days=cert_days) module.exit_json(changed=False, cert_days=cert_days)
# import module snippets # import module snippets
from ansible.module_utils.basic import * from ansible.module_utils.basic import *

View file

@ -772,7 +772,6 @@ lib/ansible/modules/web_infrastructure/ejabberd_user.py
lib/ansible/modules/web_infrastructure/htpasswd.py lib/ansible/modules/web_infrastructure/htpasswd.py
lib/ansible/modules/web_infrastructure/jboss.py lib/ansible/modules/web_infrastructure/jboss.py
lib/ansible/modules/web_infrastructure/jira.py lib/ansible/modules/web_infrastructure/jira.py
lib/ansible/modules/web_infrastructure/letsencrypt.py
lib/ansible/modules/windows/win_disk_image.py lib/ansible/modules/windows/win_disk_image.py
lib/ansible/modules/windows/win_dns_client.py lib/ansible/modules/windows/win_dns_client.py
lib/ansible/modules/windows/win_domain.py lib/ansible/modules/windows/win_domain.py