summaryrefslogtreecommitdiff
path: root/src/conf_mode/service_https.py
diff options
context:
space:
mode:
authoromnom62 <omnom62@outlook.com>2026-08-12 15:22:05 +1000
committerJohn Estabrook <jestabro@vyos.io>2026-08-26 13:33:34 -0500
commit1832b2bb3e9948f8bf6dfb3be50fd10363bc3a38 (patch)
treef7ffa4ae5bc477d81ab927bc17fc64377c67954f /src/conf_mode/service_https.py
parentd62e57071f2afb83879f576f6a3af5ecaa21023b (diff)
downloadvyos-1x-1832b2bb3e9948f8bf6dfb3be50fd10363bc3a38.tar.gz
vyos-1x-1832b2bb3e9948f8bf6dfb3be50fd10363bc3a38.zip
http-api: T8989: address further review comments
- Scope mTLS CA chain to selected CA only (not all configured CAs) - Pass verify-client value to nginx template instead of hardcoding optional - Allow mTLS-only REST configuration without API keys - Add mTLS warning when no API keys are configured
Diffstat (limited to 'src/conf_mode/service_https.py')
-rwxr-xr-xsrc/conf_mode/service_https.py23
1 files changed, 18 insertions, 5 deletions
diff --git a/src/conf_mode/service_https.py b/src/conf_mode/service_https.py
index b1381eca5..093209304 100755
--- a/src/conf_mode/service_https.py
+++ b/src/conf_mode/service_https.py
@@ -156,11 +156,18 @@ def verify(https):
# If only key-based methods are enabled,
# fail the commit if no valid key configurations are found
- if (not valid_keys_exist) and (not jwt_auth):
- raise ConfigError('At least one HTTPS API key is required unless GraphQL token authentication is enabled!')
+ mtls_auth = dict_search('certificates.verify_client', https) is not None
+ if (not valid_keys_exist) and (not jwt_auth) and (not mtls_auth):
+ raise ConfigError(
+ 'At least one HTTPS API key is required unless GraphQL token or mTLS authentication is enabled!'
+ )
if (not valid_keys_exist) and jwt_auth:
Warning(f'API keys are not configured: classic (non-GraphQL) API will be unavailable!')
+ if (not valid_keys_exist) and mtls_auth and not jwt_auth:
+ Warning(
+ 'API keys are not configured: only mTLS client certificate authentication will be available for the REST API!'
+ )
return None
@@ -224,15 +231,21 @@ def generate(https):
ca_name = https['certificates']['ca_certificate']
pki_ca = dict_search(f'pki.ca.{ca_name}', https)
if pki_ca:
- # Build full chain: intermediate + root CAs for client cert verification
- loaded_ca_certs = {
+ # Build chain for the selected CA only (not all configured CAs)
+ # to prevent any other CA from authenticating REST API clients
+ all_ca_certs = {
load_certificate(cert_data['certificate'])
for cert_data in dict_search('pki.ca', https, default={}).values()
}
+ selected_ca = load_certificate(pki_ca['certificate'])
+ ca_chain_certs = find_chain(selected_ca, all_ca_certs)
mtls_ca_path = os.path.join(cert_dir, f'{ca_name}_mtls_ca.pem')
- ca_chain = '\n'.join(encode_certificate(c) for c in loaded_ca_certs)
+ ca_chain = '\n'.join(encode_certificate(c) for c in ca_chain_certs)
write_file(mtls_ca_path, ca_chain, user=user, group=group, mode=0o644)
https['certificates']['mtls_ca_path'] = mtls_ca_path
+ https['certificates']['verify_client'] = dict_search(
+ 'certificates.verify_client', https
+ )
render(config_file, 'https/nginx.default.j2', https)
render(systemd_override, 'https/override.conf.j2', https)