summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/vyos/config.py8
-rw-r--r--python/vyos/pki.py45
2 files changed, 34 insertions, 19 deletions
diff --git a/python/vyos/config.py b/python/vyos/config.py
index e79f659b7..113136901 100644
--- a/python/vyos/config.py
+++ b/python/vyos/config.py
@@ -360,7 +360,6 @@ class Config(object):
if pki_dict:
if 'certificate' in pki_dict:
from vyos.defaults import directories
- from vyos.pki import AUTOCHAIN_PREFIX
from vyos.pki import acme_chain_ca_entry
from vyos.pki import acme_chain_redundant
vyos_certbot_dir = directories['certbot']
@@ -385,10 +384,9 @@ class Config(object):
leaf_cert = cert_conf.get('certificate')
if leaf_cert and 'acme' in cert_conf and not acme_chain_redundant(
leaf_cert, real_ca_certs):
- chain_entry = acme_chain_ca_entry(vyos_certbot_dir, certificate)
- if chain_entry:
- ca_dict = pki_dict.setdefault('ca', {})
- autochain_name = f'{AUTOCHAIN_PREFIX}{certificate}'
+ ca_dict = pki_dict.setdefault('ca', {})
+ for autochain_name, chain_entry in acme_chain_ca_entry(
+ vyos_certbot_dir, certificate).items():
# A real, manually-configured CLI CA object
# with this name wins over the synthetic one
if autochain_name not in ca_dict:
diff --git a/python/vyos/pki.py b/python/vyos/pki.py
index 787b3fdbf..af0dee626 100644
--- a/python/vyos/pki.py
+++ b/python/vyos/pki.py
@@ -482,25 +482,42 @@ def find_chain(cert, ca_certs):
# without it ever being a real, settable, or deletable CLI object.
AUTOCHAIN_PREFIX = 'AUTOCHAIN_'
-def acme_chain_ca_entry(vyos_certbot_dir: str, cert_name: str) -> dict | None:
- """Build a synthetic 'pki ca <name>'-shaped dict entry
- (`{'certificate': <base64>}`) for an ACME certificate's intermediate
- CA chain, read live from certbot's own chain.pem.
-
- Returns None if chain.pem is not (yet) present - e.g. the certificate
- has not been issued yet, or a prior request failed - so callers can
- skip this certificate's chain gracefully instead of crashing.
+def acme_chain_ca_entry(vyos_certbot_dir: str, cert_name: str) -> dict:
+ """Build synthetic 'pki ca <name>'-shaped dict entries
+ (`{<name>: {'certificate': <base64>}, ...}`) for every certificate in
+ an ACME certificate's chain, read live from certbot's own chain.pem.
+
+ certbot commonly writes more than just the immediate intermediate to
+ chain.pem (e.g. the intermediate's own issuing root too), and every
+ one of them is needed for find_chain() to walk the full chain - a
+ single 'pki ca' object only ever holds one certificate, so each one
+ gets its own synthetic entry here.
+
+ Returns an empty dict if chain.pem is not (yet) present - e.g. the
+ certificate has not been issued yet, or a prior request failed - so
+ callers can skip this certificate's chain gracefully instead of
+ crashing.
"""
+ import re
from vyos.utils.file import read_file
tmp = read_file(f'{vyos_certbot_dir}/live/{cert_name}/chain.pem',
defaultonfailure=None)
if tmp is None:
- return None
- tmp = load_certificate(tmp, wrap_tags=False)
- if not tmp:
- return None
- chain_base64 = "".join(encode_certificate(tmp).strip().split("\n")[1:-1])
- return {'certificate': chain_base64}
+ return {}
+
+ entries = {}
+ for block in re.findall(
+ r'-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----',
+ tmp, re.DOTALL):
+ cert = load_certificate(block, wrap_tags=False)
+ if not cert:
+ continue
+ index = len(entries) + 1
+ name = f'{AUTOCHAIN_PREFIX}{cert_name}' if index == 1 else \
+ f'{AUTOCHAIN_PREFIX}{cert_name}_{index}'
+ chain_base64 = "".join(encode_certificate(cert).strip().split("\n")[1:-1])
+ entries[name] = {'certificate': chain_base64}
+ return entries
def acme_chain_redundant(leaf_cert_base64: str, ca_certs: dict) -> bool:
"""Return True if one of the already-configured CAs in ca_certs (a