certificate_complete_chain: avoid infinite loops, and double roots when root certificate was already part of chain (#360)

* Avoid infinite loops, and double roots when root certificate was already part of chain.

* Refactor tests for readability.
This commit is contained in:
Felix Fontein
2022-01-04 07:00:09 +01:00
committed by GitHub
parent f3e431912d
commit 6ee238d961
3 changed files with 146 additions and 54 deletions

View File

@@ -238,12 +238,14 @@ class CertificateSet(object):
self.module = module
self.certificates = set()
self.certificate_by_issuer = dict()
self.certificate_by_cert = dict()
def _load_file(self, path):
certs = load_PEM_list(self.module, path, fail_on_error=False)
for cert in certs:
self.certificates.add(cert)
self.certificate_by_issuer[cert.cert.subject] = cert
self.certificate_by_cert[cert.cert] = cert
def load(self, path):
'''
@@ -275,6 +277,16 @@ def format_cert(cert):
return str(cert.cert)
def check_cycle(module, occured_certificates, next):
'''
Make sure that next is not in occured_certificates so far, and add it.
'''
next_cert = next.cert
if next_cert in occured_certificates:
module.fail_json(msg='Found cycle while building certificate chain')
occured_certificates.add(next_cert)
def main():
module = AnsibleModule(
argument_spec=dict(
@@ -313,13 +325,19 @@ def main():
# Try to complete chain
current = chain[-1]
completed = []
occured_certificates = set([cert.cert for cert in chain])
if current.cert in roots.certificate_by_cert:
# Don't try to complete the chain when it's already ending with a root certificate
current = None
while current:
root = roots.find_parent(current)
if root:
check_cycle(module, occured_certificates, root)
completed.append(root)
break
intermediate = intermediates.find_parent(current)
if intermediate:
check_cycle(module, occured_certificates, intermediate)
completed.append(intermediate)
current = intermediate
else: