Skip to content

Commit 7f11a05

Browse files
authored
aligning to npm 2.12.3
aligning to 2.12.3
2 parents effd521 + 7c4627a commit 7f11a05

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1456
-652
lines changed

.version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.12.2
1+
2.12.3

Jenkinsfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ pipeline {
128128
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
129129
}
130130
unstable {
131-
dir(path: 'testing/results') {
131+
dir(path: 'test/results') {
132132
archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml')
133133
}
134134
}
@@ -161,7 +161,7 @@ pipeline {
161161
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
162162
}
163163
unstable {
164-
dir(path: 'testing/results') {
164+
dir(path: 'test/results') {
165165
archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml')
166166
}
167167
}
@@ -199,7 +199,7 @@ pipeline {
199199
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
200200
}
201201
unstable {
202-
dir(path: 'testing/results') {
202+
dir(path: 'test/results') {
203203
archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml')
204204
}
205205
}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# open-appsec NPM Proxy Manager integration (beta)
1+
# open-appsec NPM Proxy Manager integration
22
This is the repository for the beta release of the new integration of open-appsec WAF with NGINX Proxy Manager.
33
This will allow NGINX Proxy Manager (NPM) users to protect their web applications and web APIs exposed by NGINX Proxy Manager by easily activating and configuring open-appsec protection for each of the configured Proxy Host objects in NPM directly from the NPM Web UI and also to monitor security events.
44
This new integration of open-appsec WAF with NGINX Proxy Manager not only closes the security gap caused by the soon end-of-life ModSecurity WAF, but provides a modern, strong protection alternative in form of open-appsec, a preemptive, machine-learning based, fully automatic WAF that does not rely on signatures at all.

backend/internal/access-list.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ const internalAccessList = {
258258
})
259259
.where('access_list.is_deleted', 0)
260260
.andWhere('access_list.id', data.id)
261+
.groupBy('access_list.id')
261262
.allowGraph('[owner,items,clients,proxy_hosts.[certificate,access_list.[clients,items]]]')
262263
.first();
263264

@@ -507,8 +508,13 @@ const internalAccessList = {
507508
if (typeof item.password !== 'undefined' && item.password.length) {
508509
logger.info('Adding: ' + item.username);
509510

510-
utils.execFile('/usr/bin/htpasswd', ['-b', htpasswd_file, item.username, item.password])
511-
.then((/*result*/) => {
511+
utils.execFile('openssl', ['passwd', '-apr1', item.password])
512+
.then((res) => {
513+
try {
514+
fs.appendFileSync(htpasswd_file, item.username + ':' + res + '\n', {encoding: 'utf8'});
515+
} catch (err) {
516+
reject(err);
517+
}
512518
next();
513519
})
514520
.catch((err) => {

backend/internal/certificate.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ const internalCertificate = {
313313
.where('is_deleted', 0)
314314
.andWhere('id', data.id)
315315
.allowGraph('[owner]')
316+
.allowGraph('[proxy_hosts]')
317+
.allowGraph('[redirection_hosts]')
318+
.allowGraph('[dead_hosts]')
316319
.first();
317320

318321
if (access_data.permission_visibility !== 'all') {
@@ -464,6 +467,9 @@ const internalCertificate = {
464467
.where('is_deleted', 0)
465468
.groupBy('id')
466469
.allowGraph('[owner]')
470+
.allowGraph('[proxy_hosts]')
471+
.allowGraph('[redirection_hosts]')
472+
.allowGraph('[dead_hosts]')
467473
.orderBy('nice_name', 'ASC');
468474

469475
if (access_data.permission_visibility !== 'all') {

backend/internal/stream.js

Lines changed: 98 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
const _ = require('lodash');
2-
const error = require('../lib/error');
3-
const utils = require('../lib/utils');
4-
const streamModel = require('../models/stream');
5-
const internalNginx = require('./nginx');
6-
const internalAuditLog = require('./audit-log');
7-
const {castJsonIfNeed} = require('../lib/helpers');
1+
const _ = require('lodash');
2+
const error = require('../lib/error');
3+
const utils = require('../lib/utils');
4+
const streamModel = require('../models/stream');
5+
const internalNginx = require('./nginx');
6+
const internalAuditLog = require('./audit-log');
7+
const internalCertificate = require('./certificate');
8+
const internalHost = require('./host');
9+
const {castJsonIfNeed} = require('../lib/helpers');
810

911
function omissions () {
10-
return ['is_deleted'];
12+
return ['is_deleted', 'owner.is_deleted', 'certificate.is_deleted'];
1113
}
1214

1315
const internalStream = {
@@ -18,6 +20,12 @@ const internalStream = {
1820
* @returns {Promise}
1921
*/
2022
create: (access, data) => {
23+
const create_certificate = data.certificate_id === 'new';
24+
25+
if (create_certificate) {
26+
delete data.certificate_id;
27+
}
28+
2129
return access.can('streams:create', data)
2230
.then((/*access_data*/) => {
2331
// TODO: At this point the existing ports should have been checked
@@ -27,16 +35,44 @@ const internalStream = {
2735
data.meta = {};
2836
}
2937

38+
// streams aren't routed by domain name so don't store domain names in the DB
39+
let data_no_domains = structuredClone(data);
40+
delete data_no_domains.domain_names;
41+
3042
return streamModel
3143
.query()
32-
.insertAndFetch(data)
44+
.insertAndFetch(data_no_domains)
3345
.then(utils.omitRow(omissions()));
3446
})
47+
.then((row) => {
48+
if (create_certificate) {
49+
return internalCertificate.createQuickCertificate(access, data)
50+
.then((cert) => {
51+
// update host with cert id
52+
return internalStream.update(access, {
53+
id: row.id,
54+
certificate_id: cert.id
55+
});
56+
})
57+
.then(() => {
58+
return row;
59+
});
60+
} else {
61+
return row;
62+
}
63+
})
64+
.then((row) => {
65+
// re-fetch with cert
66+
return internalStream.get(access, {
67+
id: row.id,
68+
expand: ['certificate', 'owner']
69+
});
70+
})
3571
.then((row) => {
3672
// Configure nginx
3773
return internalNginx.configure(streamModel, 'stream', row)
3874
.then(() => {
39-
return internalStream.get(access, {id: row.id, expand: ['owner']});
75+
return row;
4076
});
4177
})
4278
.then((row) => {
@@ -60,6 +96,12 @@ const internalStream = {
6096
* @return {Promise}
6197
*/
6298
update: (access, data) => {
99+
const create_certificate = data.certificate_id === 'new';
100+
101+
if (create_certificate) {
102+
delete data.certificate_id;
103+
}
104+
63105
return access.can('streams:update', data.id)
64106
.then((/*access_data*/) => {
65107
// TODO: at this point the existing streams should have been checked
@@ -71,16 +113,32 @@ const internalStream = {
71113
throw new error.InternalValidationError('Stream could not be updated, IDs do not match: ' + row.id + ' !== ' + data.id);
72114
}
73115

116+
if (create_certificate) {
117+
return internalCertificate.createQuickCertificate(access, {
118+
domain_names: data.domain_names || row.domain_names,
119+
meta: _.assign({}, row.meta, data.meta)
120+
})
121+
.then((cert) => {
122+
// update host with cert id
123+
data.certificate_id = cert.id;
124+
})
125+
.then(() => {
126+
return row;
127+
});
128+
} else {
129+
return row;
130+
}
131+
})
132+
.then((row) => {
133+
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
134+
data = _.assign({}, {
135+
domain_names: row.domain_names
136+
}, data);
137+
74138
return streamModel
75139
.query()
76140
.patchAndFetchById(row.id, data)
77141
.then(utils.omitRow(omissions()))
78-
.then((saved_row) => {
79-
return internalNginx.configure(streamModel, 'stream', saved_row)
80-
.then(() => {
81-
return internalStream.get(access, {id: row.id, expand: ['owner']});
82-
});
83-
})
84142
.then((saved_row) => {
85143
// Add to audit log
86144
return internalAuditLog.add(access, {
@@ -93,6 +151,17 @@ const internalStream = {
93151
return saved_row;
94152
});
95153
});
154+
})
155+
.then(() => {
156+
return internalStream.get(access, {id: data.id, expand: ['owner', 'certificate']})
157+
.then((row) => {
158+
return internalNginx.configure(streamModel, 'stream', row)
159+
.then((new_meta) => {
160+
row.meta = new_meta;
161+
row = internalHost.cleanRowCertificateMeta(row);
162+
return _.omit(row, omissions());
163+
});
164+
});
96165
});
97166
},
98167

@@ -115,7 +184,7 @@ const internalStream = {
115184
.query()
116185
.where('is_deleted', 0)
117186
.andWhere('id', data.id)
118-
.allowGraph('[owner]')
187+
.allowGraph('[owner,certificate]')
119188
.first();
120189

121190
if (access_data.permission_visibility !== 'all') {
@@ -132,6 +201,7 @@ const internalStream = {
132201
if (!row || !row.id) {
133202
throw new error.ItemNotFoundError(data.id);
134203
}
204+
row = internalHost.cleanRowCertificateMeta(row);
135205
// Custom omissions
136206
if (typeof data.omit !== 'undefined' && data.omit !== null) {
137207
row = _.omit(row, data.omit);
@@ -197,14 +267,14 @@ const internalStream = {
197267
.then(() => {
198268
return internalStream.get(access, {
199269
id: data.id,
200-
expand: ['owner']
270+
expand: ['certificate', 'owner']
201271
});
202272
})
203273
.then((row) => {
204274
if (!row || !row.id) {
205275
throw new error.ItemNotFoundError(data.id);
206276
} else if (row.enabled) {
207-
throw new error.ValidationError('Host is already enabled');
277+
throw new error.ValidationError('Stream is already enabled');
208278
}
209279

210280
row.enabled = 1;
@@ -250,7 +320,7 @@ const internalStream = {
250320
if (!row || !row.id) {
251321
throw new error.ItemNotFoundError(data.id);
252322
} else if (!row.enabled) {
253-
throw new error.ValidationError('Host is already disabled');
323+
throw new error.ValidationError('Stream is already disabled');
254324
}
255325

256326
row.enabled = 0;
@@ -298,7 +368,7 @@ const internalStream = {
298368
.query()
299369
.where('is_deleted', 0)
300370
.groupBy('id')
301-
.allowGraph('[owner]')
371+
.allowGraph('[owner,certificate]')
302372
.orderByRaw('CAST(incoming_port AS INTEGER) ASC');
303373

304374
if (access_data.permission_visibility !== 'all') {
@@ -317,6 +387,13 @@ const internalStream = {
317387
}
318388

319389
return query.then(utils.omitRows(omissions()));
390+
})
391+
.then((rows) => {
392+
if (typeof expand !== 'undefined' && expand !== null && expand.indexOf('certificate') !== -1) {
393+
return internalHost.cleanAllRowsCertificateMeta(rows);
394+
}
395+
396+
return rows;
320397
});
321398
},
322399

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const migrate_name = 'stream_ssl';
2+
const logger = require('../logger').migrate;
3+
4+
/**
5+
* Migrate
6+
*
7+
* @see http://knexjs.org/#Schema
8+
*
9+
* @param {Object} knex
10+
* @returns {Promise}
11+
*/
12+
exports.up = function (knex) {
13+
logger.info('[' + migrate_name + '] Migrating Up...');
14+
15+
return knex.schema.table('stream', (table) => {
16+
table.integer('certificate_id').notNull().unsigned().defaultTo(0);
17+
})
18+
.then(function () {
19+
logger.info('[' + migrate_name + '] stream Table altered');
20+
});
21+
};
22+
23+
/**
24+
* Undo Migrate
25+
*
26+
* @param {Object} knex
27+
* @returns {Promise}
28+
*/
29+
exports.down = function (knex) {
30+
logger.info('[' + migrate_name + '] Migrating Down...');
31+
32+
return knex.schema.table('stream', (table) => {
33+
table.dropColumn('certificate_id');
34+
})
35+
.then(function () {
36+
logger.info('[' + migrate_name + '] stream Table altered');
37+
});
38+
};

backend/models/certificate.js

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
const db = require('../db');
55
const helpers = require('../lib/helpers');
66
const Model = require('objection').Model;
7-
const User = require('./user');
87
const now = require('./now_helper');
98

109
Model.knex(db);
@@ -68,6 +67,11 @@ class Certificate extends Model {
6867
}
6968

7069
static get relationMappings () {
70+
const ProxyHost = require('./proxy_host');
71+
const DeadHost = require('./dead_host');
72+
const User = require('./user');
73+
const RedirectionHost = require('./redirection_host');
74+
7175
return {
7276
owner: {
7377
relation: Model.HasOneRelation,
@@ -79,6 +83,39 @@ class Certificate extends Model {
7983
modify: function (qb) {
8084
qb.where('user.is_deleted', 0);
8185
}
86+
},
87+
proxy_hosts: {
88+
relation: Model.HasManyRelation,
89+
modelClass: ProxyHost,
90+
join: {
91+
from: 'certificate.id',
92+
to: 'proxy_host.certificate_id'
93+
},
94+
modify: function (qb) {
95+
qb.where('proxy_host.is_deleted', 0);
96+
}
97+
},
98+
dead_hosts: {
99+
relation: Model.HasManyRelation,
100+
modelClass: DeadHost,
101+
join: {
102+
from: 'certificate.id',
103+
to: 'dead_host.certificate_id'
104+
},
105+
modify: function (qb) {
106+
qb.where('dead_host.is_deleted', 0);
107+
}
108+
},
109+
redirection_hosts: {
110+
relation: Model.HasManyRelation,
111+
modelClass: RedirectionHost,
112+
join: {
113+
from: 'certificate.id',
114+
to: 'redirection_host.certificate_id'
115+
},
116+
modify: function (qb) {
117+
qb.where('redirection_host.is_deleted', 0);
118+
}
82119
}
83120
};
84121
}

0 commit comments

Comments
 (0)