mirror of
https://github.com/ansible-collections/community.crypto.git
synced 2026-05-07 05:43:06 +00:00
ACME modules refactor (#187)
* Move acme.py to acme/__init__.py to prepare splitup. * Began moving generic code out. * Creating backends. * Update unit tests. * Move remaining new code out. * Use new interface. * Rewrite module init code. * Add changelog. * Add BackendException for crypto backend errors. * Improve / uniformize ACME error reporting. * Create ACMELegacyAccount for backwards compatibility. * Split up ACMEAccount into ACMEClient and ACMEAccount. * Move get_keyauthorization into module_utils.acme.challenges. * Improve error handling. * Move challenge and authorization handling code into module_utils. * Add split_identifier helper. * Move order code into module_utils. * Move ACME v2 certificate handling code to module_utils. * Fix/move ACME v1 certificate retrieval to module_utils as well. * Refactor alternate chain handling code by splitting it up into simpler functions. * Make chain matcher creation part of backend.
This commit is contained in:
71
plugins/module_utils/acme/utils.py
Normal file
71
plugins/module_utils/acme/utils.py
Normal file
@@ -0,0 +1,71 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2016 Michael Gruener <michael.gruener@chaosmoon.net>
|
||||
# Copyright: (c) 2021 Felix Fontein <felix@fontein.de>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
import base64
|
||||
import re
|
||||
import textwrap
|
||||
import traceback
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.six.moves.urllib.parse import unquote
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.acme.errors import ModuleFailException
|
||||
|
||||
|
||||
def nopad_b64(data):
|
||||
return base64.urlsafe_b64encode(data).decode('utf8').replace("=", "")
|
||||
|
||||
|
||||
def der_to_pem(der_cert):
|
||||
'''
|
||||
Convert the DER format certificate in der_cert to a PEM format certificate and return it.
|
||||
'''
|
||||
return """-----BEGIN CERTIFICATE-----\n{0}\n-----END CERTIFICATE-----\n""".format(
|
||||
"\n".join(textwrap.wrap(base64.b64encode(der_cert).decode('utf8'), 64)))
|
||||
|
||||
|
||||
def pem_to_der(pem_filename=None, pem_content=None):
|
||||
'''
|
||||
Load PEM file, or use PEM file's content, and convert to DER.
|
||||
|
||||
If PEM contains multiple entities, the first entity will be used.
|
||||
'''
|
||||
certificate_lines = []
|
||||
if pem_content is not None:
|
||||
lines = pem_content.splitlines()
|
||||
elif pem_filename is not None:
|
||||
try:
|
||||
with open(pem_filename, "rt") as f:
|
||||
lines = list(f)
|
||||
except Exception as err:
|
||||
raise ModuleFailException("cannot load PEM file {0}: {1}".format(pem_filename, to_native(err)), exception=traceback.format_exc())
|
||||
else:
|
||||
raise ModuleFailException('One of pem_filename and pem_content must be provided')
|
||||
header_line_count = 0
|
||||
for line in lines:
|
||||
if line.startswith('-----'):
|
||||
header_line_count += 1
|
||||
if header_line_count == 2:
|
||||
# If certificate file contains other certs appended
|
||||
# (like intermediate certificates), ignore these.
|
||||
break
|
||||
continue
|
||||
certificate_lines.append(line.strip())
|
||||
return base64.b64decode(''.join(certificate_lines))
|
||||
|
||||
|
||||
def process_links(info, callback):
|
||||
'''
|
||||
Process link header, calls callback for every link header with the URL and relation as options.
|
||||
'''
|
||||
if 'link' in info:
|
||||
link = info['link']
|
||||
for url, relation in re.findall(r'<([^>]+)>;\s*rel="(\w+)"', link):
|
||||
callback(unquote(url), relation)
|
||||
Reference in New Issue
Block a user