From 366efc8ac2d446708a24ba61612c5a4849bfd578 Mon Sep 17 00:00:00 2001 From: Will Rouesnel Date: Mon, 29 May 2023 02:29:42 +1000 Subject: [PATCH] Add template support for all host types to do client CA authorization When an access list contains client CAs, the combined CA auth file is added to all location blocks via an `if` statement. This allows LetsEncrypt and other support paths to work, while correctly denying access to the protected resources. --- backend/internal/access-list.js | 2 -- backend/internal/proxy-host.js | 8 ++++---- backend/templates/_access.conf | 6 ++++++ backend/templates/_certificates.conf | 8 +++++++- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/backend/internal/access-list.js b/backend/internal/access-list.js index 74cbbeef..8869e6a8 100644 --- a/backend/internal/access-list.js +++ b/backend/internal/access-list.js @@ -264,7 +264,6 @@ const internalAccessList = { }, true /* <- skip masking */); }) .then((row) => { - console.log(row); return internalAccessList.build(row) .then(() => { if (row.proxy_host_count) { @@ -603,7 +602,6 @@ const internalAccessList = { }); const caCertificateBuild = new Promise((resolve, reject) => { - // TODO: we need to ensure this rebuild is run if any certificates change logger.info('Building Client CA file #' + list.id + ' for: ' + list.name); let clientca_file = internalAccessList.getClientCAFilename(list); diff --git a/backend/internal/proxy-host.js b/backend/internal/proxy-host.js index 02a98da2..284cc708 100644 --- a/backend/internal/proxy-host.js +++ b/backend/internal/proxy-host.js @@ -74,7 +74,7 @@ const internalProxyHost = { // re-fetch with cert return internalProxyHost.get(access, { id: row.id, - expand: ['certificate', 'owner', 'access_list.[clients,items]'] + expand: ['certificate', 'owner', 'access_list.[clientcas.certificate,clients,items]'] }); }) .then((row) => { @@ -188,7 +188,7 @@ const internalProxyHost = { .then(() => { return internalProxyHost.get(access, { id: data.id, - expand: ['owner', 'certificate', 'access_list.[clients,items]'] + expand: ['owner', 'certificate', 'access_list.[clientcas.certificate,clients,items]'] }) .then((row) => { if (!row.enabled) { @@ -225,7 +225,7 @@ const internalProxyHost = { .query() .where('is_deleted', 0) .andWhere('id', data.id) - .allowGraph('[owner,access_list,access_list.[clients,items],certificate]') + .allowGraph('[owner,access_list.[clientcas.certificate,clients,items],certificate]') .first(); if (access_data.permission_visibility !== 'all') { @@ -308,7 +308,7 @@ const internalProxyHost = { .then(() => { return internalProxyHost.get(access, { id: data.id, - expand: ['certificate', 'owner', 'access_list'] + expand: ['certificate', 'owner', 'access_list.[clientcas.certificate]'] }); }) .then((row) => { diff --git a/backend/templates/_access.conf b/backend/templates/_access.conf index 447006c0..cf1950ad 100644 --- a/backend/templates/_access.conf +++ b/backend/templates/_access.conf @@ -1,4 +1,10 @@ {% if access_list_id > 0 %} +{% if access_list.clientcas.size > 0 %} + # TLS Client Certificate Authorization + if ($ssl_client_verify != "SUCCESS") { + return 403; + } +{% endif %} {% if access_list.items.length > 0 %} # Authorization auth_basic "Authorization required"; diff --git a/backend/templates/_certificates.conf b/backend/templates/_certificates.conf index 06ca7bb8..18f0b10c 100644 --- a/backend/templates/_certificates.conf +++ b/backend/templates/_certificates.conf @@ -11,4 +11,10 @@ ssl_certificate_key /data/custom_ssl/npm-{{ certificate_id }}/privkey.pem; {% endif %} {% endif %} - +{% if access_list_id > 0 -%} +{% if access_list.clientcas.size > 0 %} + # Client Certificate Authorization ({{access_list.clientcas.size}} CAs) + ssl_client_certificate /data/clientca/{{ access_list_id }}; + ssl_verify_client optional; +{% endif %} +{% endif %} \ No newline at end of file