Add support for adding Client Certificates to access-lists

Client certificate support is added as a new separate type of option for
access-lists.

This commit is the support code to enable access-lists to contain
Client Certificate references.
This commit is contained in:
Will Rouesnel
2023-05-27 01:43:15 +10:00
parent d5b3e53140
commit e5bb50c164
15 changed files with 374 additions and 41 deletions

View File

@ -1,15 +1,16 @@
const _ = require('lodash');
const fs = require('fs');
const batchflow = require('batchflow');
const logger = require('../logger').access;
const error = require('../lib/error');
const utils = require('../lib/utils');
const accessListModel = require('../models/access_list');
const accessListAuthModel = require('../models/access_list_auth');
const accessListClientModel = require('../models/access_list_client');
const proxyHostModel = require('../models/proxy_host');
const internalAuditLog = require('./audit-log');
const internalNginx = require('./nginx');
const _ = require('lodash');
const fs = require('fs');
const batchflow = require('batchflow');
const logger = require('../logger').access;
const error = require('../lib/error');
const utils = require('../lib/utils');
const accessListModel = require('../models/access_list');
const accessListAuthModel = require('../models/access_list_auth');
const accessListClientModel = require('../models/access_list_client');
const accessListClientCAsModel = require('../models/access_list_clientcas');
const proxyHostModel = require('../models/proxy_host');
const internalAuditLog = require('./audit-log');
const internalNginx = require('./nginx');
function omissions () {
return ['is_deleted'];
@ -66,13 +67,26 @@ const internalAccessList = {
});
}
// Now add the client certificate references
if (typeof data.clientcas !== 'undefined' && data.clientcas) {
data.clientcas.map((certificate_id) => {
promises.push(accessListClientCAsModel
.query()
.insert({
access_list_id: row.id,
certificate_id: certificate_id
})
);
});
}
return Promise.all(promises);
})
.then(() => {
// re-fetch with expansions
return internalAccessList.get(access, {
id: data.id,
expand: ['owner', 'items', 'clients', 'proxy_hosts.access_list.[clients,items]']
expand: ['owner', 'items', 'clients', 'clientcas', 'proxy_hosts.access_list.[clientcas.certificate,clients,items]']
}, true /* <- skip masking */);
})
.then((row) => {
@ -204,6 +218,35 @@ const internalAccessList = {
});
}
})
.then(() => {
// Check for client certificates and add/update/remove them
if (typeof data.clientcas !== 'undefined' && data.clientcas) {
let promises = [];
data.clientcas.map(function (certificate_id) {
promises.push(accessListClientCAsModel
.query()
.insert({
access_list_id: data.id,
certificate_id: certificate_id
})
);
});
let query = accessListClientCAsModel
.query()
.delete()
.where('access_list_id', data.id);
return query
.then(() => {
// Add new items
if (promises.length) {
return Promise.all(promises);
}
});
}
})
.then(internalNginx.reload)
.then(() => {
// Add to audit log
@ -218,7 +261,7 @@ const internalAccessList = {
// re-fetch with expansions
return internalAccessList.get(access, {
id: data.id,
expand: ['owner', 'items', 'clients', 'proxy_hosts.[certificate,access_list.[clients,items]]']
expand: ['owner', 'items', 'clients', 'clientcas', 'proxy_hosts.[certificate,access_list.[clientcas.certificate,clients,items]]']
}, true /* <- skip masking */);
})
.then((row) => {
@ -256,7 +299,7 @@ const internalAccessList = {
.joinRaw('LEFT JOIN `proxy_host` ON `proxy_host`.`access_list_id` = `access_list`.`id` AND `proxy_host`.`is_deleted` = 0')
.where('access_list.is_deleted', 0)
.andWhere('access_list.id', data.id)
.allowGraph('[owner,items,clients,proxy_hosts.[certificate,access_list.[clients,items]]]')
.withGraphFetched('[owner,items,clients,clientcas,proxy_hosts.[certificate,access_list.[clientcas.certificate,clients,items]]]')
.first();
if (access_data.permission_visibility !== 'all') {
@ -294,7 +337,7 @@ const internalAccessList = {
delete: (access, data) => {
return access.can('access_lists:delete', data.id)
.then(() => {
return internalAccessList.get(access, {id: data.id, expand: ['proxy_hosts', 'items', 'clients']});
return internalAccessList.get(access, {id: data.id, expand: ['proxy_hosts', 'items', 'clients', 'clientcas']});
})
.then((row) => {
if (!row) {
@ -377,7 +420,7 @@ const internalAccessList = {
.joinRaw('LEFT JOIN `proxy_host` ON `proxy_host`.`access_list_id` = `access_list`.`id` AND `proxy_host`.`is_deleted` = 0')
.where('access_list.is_deleted', 0)
.groupBy('access_list.id')
.allowGraph('[owner,items,clients]')
.withGraphFetched('[owner,items,clients,clientcas.certificate]')
.orderBy('access_list.name', 'ASC');
if (access_data.permission_visibility !== 'all') {