diff options
| author | omnom62 <omnom62@outlook.com> | 2026-08-12 15:22:05 +1000 |
|---|---|---|
| committer | John Estabrook <jestabro@vyos.io> | 2026-08-26 13:33:34 -0500 |
| commit | 1832b2bb3e9948f8bf6dfb3be50fd10363bc3a38 (patch) | |
| tree | f7ffa4ae5bc477d81ab927bc17fc64377c67954f /src/conf_mode/service_https.py | |
| parent | d62e57071f2afb83879f576f6a3af5ecaa21023b (diff) | |
| download | vyos-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-x | src/conf_mode/service_https.py | 23 |
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) |
