From f990d3f674a661dddd3735d8d794c8bdde26ba29 Mon Sep 17 00:00:00 2001 From: Kyle Klaus Date: Fri, 10 Apr 2020 16:38:54 -0700 Subject: [PATCH 01/11] add access list clients to back-end --- backend/internal/access-list.js | 81 +++++++++++++++---- .../20200410143839_access_list_client.js | 46 +++++++++++ backend/models/access_list.js | 20 ++++- backend/models/access_list_client.js | 54 +++++++++++++ backend/schema/endpoints/access-lists.json | 40 +++++++++ 5 files changed, 220 insertions(+), 21 deletions(-) create mode 100644 backend/migrations/20200410143839_access_list_client.js create mode 100644 backend/models/access_list_client.js diff --git a/backend/internal/access-list.js b/backend/internal/access-list.js index bfecf61..0411b59 100644 --- a/backend/internal/access-list.js +++ b/backend/internal/access-list.js @@ -1,14 +1,15 @@ -const _ = require('lodash'); -const fs = require('fs'); -const batchflow = require('batchflow'); -const logger = require('../logger').access; -const error = require('../lib/error'); -const accessListModel = require('../models/access_list'); -const accessListAuthModel = require('../models/access_list_auth'); -const proxyHostModel = require('../models/proxy_host'); -const internalAuditLog = require('./audit-log'); -const internalNginx = require('./nginx'); -const utils = require('../lib/utils'); +const _ = require('lodash'); +const fs = require('fs'); +const batchflow = require('batchflow'); +const logger = require('../logger').access; +const error = require('../lib/error'); +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 utils = require('../lib/utils'); function omissions () { return ['is_deleted']; @@ -35,8 +36,9 @@ const internalAccessList = { .then((row) => { data.id = row.id; - // Now add the items let promises = []; + + // Now add the items data.items.map((item) => { promises.push(accessListAuthModel .query() @@ -48,13 +50,27 @@ const internalAccessList = { ); }); + // Now add the clients + if (typeof data.clients !== 'undefined' && data.clients) { + data.clients.map((client) => { + promises.push(accessListClientModel + .query() + .insert({ + access_list_id: row.id, + address: client.address, + directive: client.directive + }) + ); + }); + } + return Promise.all(promises); }) .then(() => { // re-fetch with expansions return internalAccessList.get(access, { id: data.id, - expand: ['owner', 'items'] + expand: ['owner', 'items', 'clients'] }, true /* <- skip masking */); }) .then((row) => { @@ -152,6 +168,37 @@ const internalAccessList = { } }); } + + // Check for clients and add/update/remove them + if (typeof data.clients !== 'undefined' && data.clients) { + let promises = []; + + data.clients.map(function (client) { + if (client.address) { + promises.push(accessListAuthModel + .query() + .insert({ + access_list_id: data.id, + address: client.address, + directive: client.directive + }) + ); + } + }); + + let query = accessListClientModel + .query() + .delete() + .where('access_list_id', data.id); + + return query + .then(() => { + // Add new items + if (promises.length) { + return Promise.all(promises); + } + }); + } }) .then(() => { // Add to audit log @@ -166,7 +213,7 @@ const internalAccessList = { // re-fetch with expansions return internalAccessList.get(access, { id: data.id, - expand: ['owner', 'items'] + expand: ['owner', 'items', 'clients'] }, true /* <- skip masking */); }) .then((row) => { @@ -204,7 +251,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) - .allowEager('[owner,items,proxy_hosts]') + .allowEager('[owner,items,clients,proxy_hosts]') .omit(['access_list.is_deleted']) .first(); @@ -246,7 +293,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']}); + return internalAccessList.get(access, {id: data.id, expand: ['proxy_hosts', 'items', 'clients']}); }) .then((row) => { if (!row) { @@ -330,7 +377,7 @@ const internalAccessList = { .where('access_list.is_deleted', 0) .groupBy('access_list.id') .omit(['access_list.is_deleted']) - .allowEager('[owner,items]') + .allowEager('[owner,items,clients]') .orderBy('access_list.name', 'ASC'); if (access_data.permission_visibility !== 'all') { diff --git a/backend/migrations/20200410143839_access_list_client.js b/backend/migrations/20200410143839_access_list_client.js new file mode 100644 index 0000000..2432d77 --- /dev/null +++ b/backend/migrations/20200410143839_access_list_client.js @@ -0,0 +1,46 @@ +const migrate_name = 'access_list_client'; +const logger = require('../logger').migrate; + +/** + * Migrate + * + * @see http://knexjs.org/#Schema + * + * @param {Object} knex + * @param {Promise} Promise + * @returns {Promise} + */ +exports.up = function (knex/*, Promise*/) { + + logger.info('[' + migrate_name + '] Migrating Up...'); + + return knex.schema.createTable('access_list_client', (table) => { + table.increments().primary(); + table.dateTime('created_on').notNull(); + table.dateTime('modified_on').notNull(); + table.integer('access_list_id').notNull().unsigned(); + table.string('address').notNull(); + table.string('directive').notNull(); + table.json('meta').notNull(); + + }) + .then(function () { + logger.info('[' + migrate_name + '] access_list_client Table created'); + }); +}; + +/** + * Undo Migrate + * + * @param {Object} knex + * @param {Promise} Promise + * @returns {Promise} + */ +exports.down = function (knex/*, Promise*/) { + logger.info('[' + migrate_name + '] Migrating Down...'); + + return knex.schema.dropTable('access_list_client') + .then(() => { + logger.info('[' + migrate_name + '] access_list_client Table dropped'); + }); +}; diff --git a/backend/models/access_list.js b/backend/models/access_list.js index 7704893..43a2f12 100644 --- a/backend/models/access_list.js +++ b/backend/models/access_list.js @@ -1,10 +1,11 @@ // Objection Docs: // http://vincit.github.io/objection.js/ -const db = require('../db'); -const Model = require('objection').Model; -const User = require('./user'); -const AccessListAuth = require('./access_list_auth'); +const db = require('../db'); +const Model = require('objection').Model; +const User = require('./user'); +const AccessListAuth = require('./access_list_auth'); +const AccessListClient = require('./access_list_client'); Model.knex(db); @@ -62,6 +63,17 @@ class AccessList extends Model { qb.omit(['id', 'created_on', 'modified_on', 'access_list_id', 'meta']); } }, + clients: { + relation: Model.HasManyRelation, + modelClass: AccessListClient, + join: { + from: 'access_list.id', + to: 'access_list_client.access_list_id' + }, + modify: function (qb) { + qb.omit(['id', 'created_on', 'modified_on', 'access_list_id', 'meta']); + } + }, proxy_hosts: { relation: Model.HasManyRelation, modelClass: ProxyHost, diff --git a/backend/models/access_list_client.js b/backend/models/access_list_client.js new file mode 100644 index 0000000..1bee242 --- /dev/null +++ b/backend/models/access_list_client.js @@ -0,0 +1,54 @@ +// Objection Docs: +// http://vincit.github.io/objection.js/ + +const db = require('../db'); +const Model = require('objection').Model; + +Model.knex(db); + +class AccessListClient extends Model { + $beforeInsert () { + this.created_on = Model.raw('NOW()'); + this.modified_on = Model.raw('NOW()'); + + // Default for meta + if (typeof this.meta === 'undefined') { + this.meta = {}; + } + } + + $beforeUpdate () { + this.modified_on = Model.raw('NOW()'); + } + + static get name () { + return 'AccessListClient'; + } + + static get tableName () { + return 'access_list_client'; + } + + static get jsonAttributes () { + return ['meta']; + } + + static get relationMappings () { + return { + access_list: { + relation: Model.HasOneRelation, + modelClass: require('./access_list'), + join: { + from: 'access_list_client.access_list_id', + to: 'access_list.id' + }, + modify: function (qb) { + qb.where('access_list.is_deleted', 0); + qb.omit(['created_on', 'modified_on', 'is_deleted', 'access_list_id']); + } + } + }; + } +} + +module.exports = AccessListClient; diff --git a/backend/schema/endpoints/access-lists.json b/backend/schema/endpoints/access-lists.json index da90a05..f2ff254 100644 --- a/backend/schema/endpoints/access-lists.json +++ b/backend/schema/endpoints/access-lists.json @@ -19,6 +19,14 @@ "type": "string", "description": "Name of the Access List" }, + "directive": { + "type": "string", + "enum": ["allow", "deny"] + }, + "address": { + "type": "string", + "format": "ipv4" + }, "meta": { "type": "object" } @@ -96,6 +104,22 @@ } } }, + "clients": { + "type": "array", + "minItems": 0, + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "address": { + "$ref": "#/definitions/address" + }, + "directive": { + "$ref": "#/definitions/directive" + } + } + } + }, "meta": { "$ref": "#/definitions/meta" } @@ -141,6 +165,22 @@ } } } + }, + "clients": { + "type": "array", + "minItems": 0, + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "address": { + "$ref": "#/definitions/address" + }, + "directive": { + "$ref": "#/definitions/directive" + } + } + } } } }, From 46a9f5cb965a597c83c648743c6f3e9063d63d96 Mon Sep 17 00:00:00 2001 From: Kyle Klaus Date: Fri, 10 Apr 2020 17:33:14 -0700 Subject: [PATCH 02/11] add basic functionality to front end --- frontend/js/app/nginx/access/form.ejs | 64 ++++++++++++++------ frontend/js/app/nginx/access/form.js | 52 ++++++++++++---- frontend/js/app/nginx/access/form/client.ejs | 13 ++++ frontend/js/app/nginx/access/form/client.js | 7 +++ frontend/js/app/nginx/access/main.js | 2 +- frontend/js/i18n/messages.json | 5 +- frontend/js/models/access-list.js | 1 + 7 files changed, 111 insertions(+), 33 deletions(-) create mode 100644 frontend/js/app/nginx/access/form/client.ejs create mode 100644 frontend/js/app/nginx/access/form/client.js diff --git a/frontend/js/app/nginx/access/form.ejs b/frontend/js/app/nginx/access/form.ejs index a85e396..4866171 100644 --- a/frontend/js/app/nginx/access/form.ejs +++ b/frontend/js/app/nginx/access/form.ejs @@ -3,28 +3,52 @@ - diff --git a/frontend/js/app/nginx/access/form.js b/frontend/js/app/nginx/access/form.js index c932e86..fdfbb65 100644 --- a/frontend/js/app/nginx/access/form.js +++ b/frontend/js/app/nginx/access/form.js @@ -65,17 +65,20 @@ module.exports = Mn.View.extend({ } }); - if (!items_data.length) { - alert('You must specify at least 1 Username and Password combination'); + if (!items_data.length && !clients_data.length) { + alert('You must specify at least 1 Authorization or Access rule'); return; } let data = { - name: form_data.name, - items: items_data, - clients: clients_data + name: form_data.name, + satify_any: !!form_data.satify_any, + items: items_data, + clients: clients_data }; + console.log(data); + let method = App.Api.Nginx.AccessLists.create; let is_new = true; diff --git a/frontend/js/app/nginx/access/list/item.ejs b/frontend/js/app/nginx/access/list/item.ejs index d713259..2979f50 100644 --- a/frontend/js/app/nginx/access/list/item.ejs +++ b/frontend/js/app/nginx/access/list/item.ejs @@ -17,6 +17,13 @@ <%- i18n('access-lists', 'client-count', {count: clients.length || 0}) %> + + <% if (satify_any) { %> + <%- i18n('str', 'any') %> + <%} else { %> + <%- i18n('str', 'all') %> + <% } %> + <%- i18n('access-lists', 'proxy-host-count', {count: proxy_host_count}) %> diff --git a/frontend/js/app/nginx/access/list/main.ejs b/frontend/js/app/nginx/access/list/main.ejs index 1c3b10d..7988e0c 100644 --- a/frontend/js/app/nginx/access/list/main.ejs +++ b/frontend/js/app/nginx/access/list/main.ejs @@ -3,6 +3,7 @@ <%- i18n('str', 'name') %> <%- i18n('access-lists', 'authorization') %> <%- i18n('access-lists', 'access') %> + <%- i18n('access-lists', 'satisfy') %> <%- i18n('proxy-hosts', 'title') %> <% if (canManage) { %>   diff --git a/frontend/js/i18n/messages.json b/frontend/js/i18n/messages.json index ffab7e8..162357d 100644 --- a/frontend/js/i18n/messages.json +++ b/frontend/js/i18n/messages.json @@ -33,7 +33,9 @@ "unknown": "Unknown", "expires": "Expires", "value": "Value", - "please-wait": "Please wait..." + "please-wait": "Please wait...", + "all": "All", + "any": "Any" }, "login": { "title": "Login to your account" @@ -191,7 +193,9 @@ "delete-has-hosts": "This Access List is associated with {count} Proxy Hosts. They will become publicly available upon deletion.", "details": "Details", "authorization": "Authorization", - "access": "Access" + "access": "Access", + "satisfy": "Satisfy", + "satisfy-any": "Satify Any" }, "users": { "title": "Users", From 907e9e182d528039fc8ba448660ae97d85c7b11f Mon Sep 17 00:00:00 2001 From: Kyle Klaus Date: Sat, 11 Apr 2020 00:42:58 -0700 Subject: [PATCH 06/11] remove testing cruft --- backend/internal/access-list.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/backend/internal/access-list.js b/backend/internal/access-list.js index 20c8617..a640c1e 100644 --- a/backend/internal/access-list.js +++ b/backend/internal/access-list.js @@ -480,12 +480,10 @@ const internalAccessList = { return new Promise((resolve, reject) => { let htpasswd_file = internalAccessList.getFilename(list); - let nginx_file = internalAccessList.getFilename(list) + '.conf'; // 1. remove any existing access file try { fs.unlinkSync(htpasswd_file); - fs.unlinkSync(nginx_file); } catch (err) { // do nothing } From e9e5d293cc533b1985058acdd7c81c9214acaa29 Mon Sep 17 00:00:00 2001 From: Kyle Klaus Date: Mon, 13 Apr 2020 19:16:18 -0700 Subject: [PATCH 07/11] expand address format now accepts CIDR notation, IPv6 or the string 'any' --- backend/schema/endpoints/access-lists.json | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/backend/schema/endpoints/access-lists.json b/backend/schema/endpoints/access-lists.json index 18bbf2a..51a07ba 100644 --- a/backend/schema/endpoints/access-lists.json +++ b/backend/schema/endpoints/access-lists.json @@ -24,8 +24,20 @@ "enum": ["allow", "deny"] }, "address": { - "type": "string", - "format": "ipv4" + "oneOf": [ + { + "type": "string", + "pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$" + }, + { + "type": "string", + "pattern": "^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$" + }, + { + "type": "string", + "pattern": "^any$" + } + ] }, "satify_any": { "type": "boolean" From 005e64eb9fcbc7e603dae88a52cd89726794d452 Mon Sep 17 00:00:00 2001 From: Kyle Klaus Date: Mon, 13 Apr 2020 19:23:55 -0700 Subject: [PATCH 08/11] valite auth/access rules in backend --- backend/internal/access-list.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/internal/access-list.js b/backend/internal/access-list.js index a640c1e..69e13f4 100644 --- a/backend/internal/access-list.js +++ b/backend/internal/access-list.js @@ -25,6 +25,10 @@ const internalAccessList = { create: (access, data) => { return access.can('access_lists:create', data) .then((/*access_data*/) => { + if ((typeof data.items === 'undefined' || !data.items.length) && (typeof data.clients === 'undefined' || !data.clients.length)) { + throw new error.InternalValidationError('At leaste one user/pass or address must be defined'); + } + return accessListModel .query() .omit(omissions()) @@ -110,6 +114,10 @@ const internalAccessList = { update: (access, data) => { return access.can('access_lists:update', data.id) .then((/*access_data*/) => { + if ((typeof data.items === 'undefined' || !data.items.length) && (typeof data.clients === 'undefined' || !data.clients.length)) { + throw new error.InternalValidationError('At leaste one user/pass or address must be defined'); + } + return internalAccessList.get(access, {id: data.id}); }) .then((row) => { From e2ee2cbf2db518260a93ac06332b04890b58ad03 Mon Sep 17 00:00:00 2001 From: Kyle Klaus Date: Mon, 13 Apr 2020 19:52:44 -0700 Subject: [PATCH 09/11] enforce a 'deny all' default rule this ensures that an access list is 'secure by default' and requires the user to create exceptions or holes in the proection instead of building the wall entirely. This also means that we no longer require the user to input any username/passwords or client addressses and can avoid internal errors which generate unhelpful user errors. --- backend/internal/access-list.js | 8 -------- frontend/js/app/nginx/access/form.ejs | 12 ++++++++++++ frontend/js/app/nginx/access/form.js | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/backend/internal/access-list.js b/backend/internal/access-list.js index 69e13f4..a640c1e 100644 --- a/backend/internal/access-list.js +++ b/backend/internal/access-list.js @@ -25,10 +25,6 @@ const internalAccessList = { create: (access, data) => { return access.can('access_lists:create', data) .then((/*access_data*/) => { - if ((typeof data.items === 'undefined' || !data.items.length) && (typeof data.clients === 'undefined' || !data.clients.length)) { - throw new error.InternalValidationError('At leaste one user/pass or address must be defined'); - } - return accessListModel .query() .omit(omissions()) @@ -114,10 +110,6 @@ const internalAccessList = { update: (access, data) => { return access.can('access_lists:update', data.id) .then((/*access_data*/) => { - if ((typeof data.items === 'undefined' || !data.items.length) && (typeof data.clients === 'undefined' || !data.clients.length)) { - throw new error.InternalValidationError('At leaste one user/pass or address must be defined'); - } - return internalAccessList.get(access, {id: data.id}); }) .then((row) => { diff --git a/frontend/js/app/nginx/access/form.ejs b/frontend/js/app/nginx/access/form.ejs index 40fe854..3f127cc 100644 --- a/frontend/js/app/nginx/access/form.ejs +++ b/frontend/js/app/nginx/access/form.ejs @@ -55,6 +55,18 @@
+
+
+
+ +
+
+
+
+ +
+
+
Note that the allow and deny directives will be applied in the order they are defined.
diff --git a/frontend/js/app/nginx/access/form.js b/frontend/js/app/nginx/access/form.js index fdfbb65..8efdb72 100644 --- a/frontend/js/app/nginx/access/form.js +++ b/frontend/js/app/nginx/access/form.js @@ -119,7 +119,7 @@ module.exports = Mn.View.extend({ } } - let clients_to_add = 5 - clients.length; + let clients_to_add = 4 - clients.length; if (clients_to_add) { for (let i = 0; i < clients_to_add; i++) { clients.push({}); From f5ee91aeb3756b824aea32db8bfe72f8d4bb8604 Mon Sep 17 00:00:00 2001 From: Kyle Klaus Date: Mon, 13 Apr 2020 23:31:44 -0700 Subject: [PATCH 10/11] write access list to proxy host config --- backend/internal/access-list.js | 10 +++++----- backend/internal/proxy-host.js | 6 +++--- backend/models/access_list.js | 4 ++++ backend/models/access_list_client.js | 4 ++++ backend/templates/proxy_host.conf | 16 +++++++++++++--- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/backend/internal/access-list.js b/backend/internal/access-list.js index a640c1e..6de3310 100644 --- a/backend/internal/access-list.js +++ b/backend/internal/access-list.js @@ -71,7 +71,7 @@ const internalAccessList = { // re-fetch with expansions return internalAccessList.get(access, { id: data.id, - expand: ['owner', 'items', 'clients'] + expand: ['owner', 'items', 'clients', 'proxy_hosts.access_list.clients'] }, true /* <- skip masking */); }) .then((row) => { @@ -81,7 +81,7 @@ const internalAccessList = { return internalAccessList.build(row) .then(() => { if (row.proxy_host_count) { - return internalNginx.reload(); + return internalNginx.bulkGenerateConfigs('proxy_host', row.proxy_hosts); } }) .then(() => { @@ -216,14 +216,14 @@ const internalAccessList = { // re-fetch with expansions return internalAccessList.get(access, { id: data.id, - expand: ['owner', 'items', 'clients'] + expand: ['owner', 'items', 'clients', 'proxy_hosts.access_list.clients'] }, true /* <- skip masking */); }) .then((row) => { return internalAccessList.build(row) .then(() => { if (row.proxy_host_count) { - return internalNginx.reload(); + return internalNginx.bulkGenerateConfigs('proxy_host', row.proxy_hosts); } }) .then(() => { @@ -254,7 +254,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) - .allowEager('[owner,items,clients,proxy_hosts]') + .allowEager('[owner,items,clients,proxy_hosts,proxy_hosts.access_list.clients]') .omit(['access_list.is_deleted']) .first(); diff --git a/backend/internal/proxy-host.js b/backend/internal/proxy-host.js index 0e9ced9..c27d0dd 100644 --- a/backend/internal/proxy-host.js +++ b/backend/internal/proxy-host.js @@ -73,7 +73,7 @@ const internalProxyHost = { // re-fetch with cert return internalProxyHost.get(access, { id: row.id, - expand: ['certificate', 'owner', 'access_list'] + expand: ['certificate', 'owner', 'access_list.clients'] }); }) .then((row) => { @@ -186,7 +186,7 @@ const internalProxyHost = { .then(() => { return internalProxyHost.get(access, { id: data.id, - expand: ['owner', 'certificate', 'access_list'] + expand: ['owner', 'certificate', 'access_list.clients'] }) .then((row) => { // Configure nginx @@ -219,7 +219,7 @@ const internalProxyHost = { .query() .where('is_deleted', 0) .andWhere('id', data.id) - .allowEager('[owner,access_list,certificate]') + .allowEager('[owner,access_list,access_list.clients,certificate]') .first(); if (access_data.permission_visibility !== 'all') { diff --git a/backend/models/access_list.js b/backend/models/access_list.js index 43a2f12..482cfc4 100644 --- a/backend/models/access_list.js +++ b/backend/models/access_list.js @@ -88,6 +88,10 @@ class AccessList extends Model { } }; } + + get satisfy() { + return this.satify_any ? 'satisfy any' : 'satisfy all'; + } } module.exports = AccessList; diff --git a/backend/models/access_list_client.js b/backend/models/access_list_client.js index 1bee242..0386395 100644 --- a/backend/models/access_list_client.js +++ b/backend/models/access_list_client.js @@ -49,6 +49,10 @@ class AccessListClient extends Model { } }; } + + get rule() { + return `${this.directive} ${this.address}`; + } } module.exports = AccessListClient; diff --git a/backend/templates/proxy_host.conf b/backend/templates/proxy_host.conf index 6448dca..0da4bed 100644 --- a/backend/templates/proxy_host.conf +++ b/backend/templates/proxy_host.conf @@ -21,11 +21,21 @@ server { {% if use_default_location %} location / { - {%- if access_list_id > 0 -%} - # Access List + + {% if access_list_id > 0 %} + # Authorization auth_basic "Authorization required"; auth_basic_user_file /data/access/{{ access_list_id }}; - {%- endif %} + + # Access Rules + {% for client in access_list.clients %} + {{- client.rule -}}; + {% endfor %}deny all; + + # Access checks must... + {{ access_list.satisfy }}; + + {% endif %} {% include "_forced_ssl.conf" %} {% include "_hsts.conf" %} From 090b4d0388b5277274d23ffaf262936e8ba3e7d7 Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Wed, 15 Apr 2020 14:18:27 +1000 Subject: [PATCH 11/11] Version bump --- .version | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.version b/.version index b1b25a5..5859406 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.2.2 +2.2.3 diff --git a/README.md b/README.md index 0fbecb4..6099b86 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@



- +