mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-08-07 18:03:33 +00:00
Notify policy updates to open-appsec container.
UI labels in log.
This commit is contained in:
@@ -1,3 +1,6 @@
|
|||||||
|
const util = require('util');
|
||||||
|
const execPromise = util.promisify(require('child_process').exec);
|
||||||
|
const { exec } = require('child_process');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const logger = require('../logger').nginx;
|
const logger = require('../logger').nginx;
|
||||||
@@ -100,7 +103,24 @@ const internalNginxOpenappsec = {
|
|||||||
(err) => {
|
(err) => {
|
||||||
logger.error('Error generating openappsec config:', err);
|
logger.error('Error generating openappsec config:', err);
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Return the notifyPolicyUpdate promise chain
|
||||||
|
// notify openappsec to apply the policy
|
||||||
|
return internalNginxOpenappsec.notifyPolicyUpdate().catch((errorMessage) => {
|
||||||
|
console.error('Error:', errorMessage);
|
||||||
|
const errorMessageForUI = `Error: Policy couldn’t be applied, open-appsec-agent container is not responding.
|
||||||
|
Check if open-appec-agent container is running, then apply open-appsec Configuration
|
||||||
|
again by clicking here:
|
||||||
|
<br>Settings -> open-appsec Advanced -> Save Settings`;
|
||||||
|
|
||||||
|
return Promise.reject(new Error(errorMessageForUI));
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
logger.error('Error generating openappsec config:', err);
|
||||||
|
throw err; // Propagate the error to the caller
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -122,9 +142,22 @@ const internalNginxOpenappsec = {
|
|||||||
internalNginxOpenappsec.removeMatchingNodes(openappsecConfig, pattern);
|
internalNginxOpenappsec.removeMatchingNodes(openappsecConfig, pattern);
|
||||||
fs.writeFileSync(configFilePath, yaml.dump(openappsecConfig));
|
fs.writeFileSync(configFilePath, yaml.dump(openappsecConfig));
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.then(() => {
|
||||||
|
// Return the notifyPolicyUpdate promise chain
|
||||||
|
// notify openappsec to apply the policy
|
||||||
|
return internalNginxOpenappsec.notifyPolicyUpdate().catch((errorMessage) => {
|
||||||
|
console.error('---Error:', errorMessage);
|
||||||
|
const errorMessageForUI = `Error: Policy couldn’t be applied, open-appsec-agent container is not responding.
|
||||||
|
Check if open-appec-agent container is running, then apply open-appsec Configuration
|
||||||
|
again by clicking here:
|
||||||
|
<br>Settings -> open-appsec Advanced -> Save Settings`;
|
||||||
|
|
||||||
|
return Promise.reject(new Error(errorMessageForUI));
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
logger.error('Error deleting openappsec config:', err);
|
logger.error('Error deleting openappsec config:', err);
|
||||||
return Promise.reject(err);
|
throw err; // Propagate the error to the caller
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -180,6 +213,38 @@ const internalNginxOpenappsec = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
notifyPolicyUpdate: async function() {
|
||||||
|
if (!constants.USE_NOTIFY_POLICY) {
|
||||||
|
console.log('USE_NOTIFY_POLICY is false');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let ports = constants.PORTS;
|
||||||
|
console.log(`Notifying openappsec to apply the policy on ports ${ports}`);
|
||||||
|
let lastError = null;
|
||||||
|
|
||||||
|
for (let port of ports) {
|
||||||
|
try {
|
||||||
|
const command = `curl -s -o /dev/null -w "%{http_code}" ${constants.HOSTURL}:${port}/openappsec/apply-policy`;
|
||||||
|
console.log(`command: ${command}`);
|
||||||
|
let { stdout } = await execPromise(command);
|
||||||
|
if (stdout === '200') {
|
||||||
|
console.log(`Policy applied successfully on port ${port}`);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
console.log(`Policy Unexpected response code: ${stdout}`);
|
||||||
|
lastError = new Error(`Unexpected response code: ${stdout}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Error notifying openappsec to apply the policy on port ${port}: ${error.message}`);
|
||||||
|
lastError = error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastError) {
|
||||||
|
throw lastError;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively removes nodes from a JavaScript object based on a pattern.
|
* Recursively removes nodes from a JavaScript object based on a pattern.
|
||||||
*
|
*
|
||||||
|
@@ -100,7 +100,6 @@ const internalOpenappsecLog = {
|
|||||||
.then(async () => {
|
.then(async () => {
|
||||||
const directoryPath = APPSEC_LOG_DIR;
|
const directoryPath = APPSEC_LOG_DIR;
|
||||||
let totalDataLines = await this.countTotalLines(directoryPath);
|
let totalDataLines = await this.countTotalLines(directoryPath);
|
||||||
console.log("totalLineCount: " + totalDataLines);
|
|
||||||
|
|
||||||
const files = await fs.promises.readdir(directoryPath);
|
const files = await fs.promises.readdir(directoryPath);
|
||||||
const logFiles = files.filter(file => path.extname(file).startsWith('.log'));
|
const logFiles = files.filter(file => path.extname(file).startsWith('.log'));
|
||||||
|
@@ -95,9 +95,14 @@ const internalProxyHost = {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(row => {
|
.then(row => {
|
||||||
internalNginxOpenappsec.generateConfig(access, row, data)
|
return internalNginxOpenappsec.generateConfig(access, row, data)
|
||||||
return row;
|
.then(() => {
|
||||||
})
|
return row;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new error.ConfigurationError(err.message);
|
||||||
|
});
|
||||||
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Audit log
|
// Audit log
|
||||||
data.meta = _.assign({}, data.meta || {}, row.meta);
|
data.meta = _.assign({}, data.meta || {}, row.meta);
|
||||||
@@ -174,10 +179,14 @@ const internalProxyHost = {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(row => {
|
.then(row => {
|
||||||
internalNginxOpenappsec.generateConfig(access, row, data);
|
return internalNginxOpenappsec.generateConfig(access, row, data)
|
||||||
// internalNginxOpenappsec.updateConfig(row, data)
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
})
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new error.ConfigurationError(err.message);
|
||||||
|
});
|
||||||
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
||||||
data = _.assign({}, {
|
data = _.assign({}, {
|
||||||
@@ -316,7 +325,11 @@ const internalProxyHost = {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Delete openappsec config
|
// Delete openappsec config
|
||||||
internalNginxOpenappsec.deleteConfig(access, row);
|
return internalNginxOpenappsec.deleteConfig(access, row)
|
||||||
|
.catch((err) => {
|
||||||
|
throw new error.ConfigurationError(err.message);
|
||||||
|
});
|
||||||
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Delete Nginx Config
|
// Delete Nginx Config
|
||||||
|
@@ -2,4 +2,8 @@ module.exports = {
|
|||||||
APPSEC_CONFIG_FILE_NAME: 'local_policy.yaml',
|
APPSEC_CONFIG_FILE_NAME: 'local_policy.yaml',
|
||||||
APPSEC_EXT_DIR: '/ext/appsec',
|
APPSEC_EXT_DIR: '/ext/appsec',
|
||||||
APPSEC_LOG_DIR: '/ext/appsec-logs',
|
APPSEC_LOG_DIR: '/ext/appsec-logs',
|
||||||
|
USE_NOTIFY_POLICY: true,
|
||||||
|
PORTS: [7777, 7778],
|
||||||
|
HOSTURL: 'http://127.0.0.1',
|
||||||
|
POLICY_PATH: '/etc/cp/conf/local_policy.yaml',
|
||||||
};
|
};
|
@@ -1,29 +1,6 @@
|
|||||||
|
|
||||||
<td>
|
<td><%- formatDbDate(eventTime, 'D-M-YY, H:mm') %></td>
|
||||||
<%- formatDbDate(eventTime, 'D-M-YYYY, H:mm') %>
|
<td><%- eventSeverity %></td>
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div class="text-nowrap">
|
|
||||||
<% var sevirityClass = 'bg-success';
|
|
||||||
switch (eventSeverity) {
|
|
||||||
case 'Critical':
|
|
||||||
sevirityClass = 'bg-danger';
|
|
||||||
break;
|
|
||||||
case 'Warning':
|
|
||||||
sevirityClass = 'bg-warning';
|
|
||||||
break;
|
|
||||||
case 'Info':
|
|
||||||
sevirityClass = 'bg-success';
|
|
||||||
//sevirityClass = 'bg-info';
|
|
||||||
break;
|
|
||||||
case 'Debug':
|
|
||||||
sevirityClass = 'bg-success';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
%>
|
|
||||||
<span class="status-icon <%- sevirityClass %>"></span> <%- eventSeverity %>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td><%- assetName %></td>
|
<td><%- assetName %></td>
|
||||||
<td><%- securityAction %></td>
|
<td><%- securityAction %></td>
|
||||||
<td><%- waapIncidentType %></td>
|
<td><%- waapIncidentType %></td>
|
||||||
@@ -34,10 +11,10 @@
|
|||||||
<td><%- httpMethod %></td>
|
<td><%- httpMethod %></td>
|
||||||
<td><%- httpResponseCode %></td>
|
<td><%- httpResponseCode %></td>
|
||||||
<td><%- httpUriPath %></td>
|
<td><%- httpUriPath %></td>
|
||||||
<td><%- protectionName %></td>
|
<td><%- eventTopic %></td>
|
||||||
<td><%- matchedLocation %></td>
|
<td><%- matchedLocation %></td>
|
||||||
<td><%- matchedParameter %></td>
|
<td><%- matchedParameter %></td>
|
||||||
<td><%- matchedSample %></td>
|
<td><%- matchedSample %></td>
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
<a href="#" class="meta btn btn-secondary btn-sm">open</a>
|
<a href="#" class="meta btn btn-secondary btn-sm">open</a>
|
||||||
</td>
|
</td>
|
@@ -11,7 +11,7 @@
|
|||||||
<th>HTTP Method</th>
|
<th>HTTP Method</th>
|
||||||
<th>HTTP Response Code</th>
|
<th>HTTP Response Code</th>
|
||||||
<th>HTTP URI Path</th>
|
<th>HTTP URI Path</th>
|
||||||
<th>Protection Name</th>
|
<th>Event Topic</th>
|
||||||
<th>Matched Location</th>
|
<th>Matched Location</th>
|
||||||
<th>Matched Parameter</th>
|
<th>Matched Parameter</th>
|
||||||
<th>Matched Sample</th>
|
<th>Matched Sample</th>
|
||||||
|
@@ -8,7 +8,6 @@ let TableBody = Mn.CollectionView.extend({
|
|||||||
|
|
||||||
initialize: function (options) {
|
initialize: function (options) {
|
||||||
this.options = new Backbone.Model(options);
|
this.options = new Backbone.Model(options);
|
||||||
console.log("options: ", options);
|
|
||||||
// this.page = options.page;
|
// this.page = options.page;
|
||||||
// this.perPage = options.perPage;
|
// this.perPage = options.perPage;
|
||||||
this.updatePage();
|
this.updatePage();
|
||||||
@@ -20,22 +19,12 @@ let TableBody = Mn.CollectionView.extend({
|
|||||||
let page = this.page || 1;
|
let page = this.page || 1;
|
||||||
let models;
|
let models;
|
||||||
if (this.perPage && this.page) {
|
if (this.perPage && this.page) {
|
||||||
console.log('updatePage2');
|
|
||||||
models = this.collection.models.slice((page - 1) * perPage, page * perPage);
|
models = this.collection.models.slice((page - 1) * perPage, page * perPage);
|
||||||
} else {
|
} else {
|
||||||
console.log('updatePage3');
|
|
||||||
|
|
||||||
models = this.collection.models;
|
models = this.collection.models;
|
||||||
}
|
}
|
||||||
this.collection.reset(models);
|
this.collection.reset(models);
|
||||||
}
|
}
|
||||||
|
|
||||||
// updatePage: function () {
|
|
||||||
// let perPage = this.perPage || this.collection.length;
|
|
||||||
// let page = this.page || 1;
|
|
||||||
// let models = this.collection.models.slice((page - 1) * perPage, page * perPage);
|
|
||||||
// this.collection.reset(models);
|
|
||||||
// }
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = Mn.View.extend({
|
module.exports = Mn.View.extend({
|
||||||
|
@@ -1,29 +1,6 @@
|
|||||||
|
|
||||||
<td>
|
<td><%- formatDbDate(eventTime, 'D-M-YY, H:mm') %></td>
|
||||||
<%- formatDbDate(eventTime, 'D-M-YY, H:mm') %>
|
<td><%- eventSeverity %></td>
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div class="text-nowrap">
|
|
||||||
<% var sevirityClass = 'bg-success';
|
|
||||||
switch (eventSeverity) {
|
|
||||||
case 'Critical':
|
|
||||||
sevirityClass = 'bg-danger';
|
|
||||||
break;
|
|
||||||
case 'Warning':
|
|
||||||
sevirityClass = 'bg-warning';
|
|
||||||
break;
|
|
||||||
case 'Info':
|
|
||||||
sevirityClass = 'bg-success';
|
|
||||||
//sevirityClass = 'bg-info';
|
|
||||||
break;
|
|
||||||
case 'Debug':
|
|
||||||
sevirityClass = 'bg-success';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
%>
|
|
||||||
<span class="status-icon <%- sevirityClass %>"></span> <%- eventSeverity %>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td><%- assetName %></td>
|
<td><%- assetName %></td>
|
||||||
<td><%- securityAction %></td>
|
<td><%- securityAction %></td>
|
||||||
<td><%- waapIncidentType %></td>
|
<td><%- waapIncidentType %></td>
|
||||||
@@ -34,7 +11,7 @@
|
|||||||
<td><%- httpMethod %></td>
|
<td><%- httpMethod %></td>
|
||||||
<td><%- httpResponseCode %></td>
|
<td><%- httpResponseCode %></td>
|
||||||
<td><%- httpUriPath %></td>
|
<td><%- httpUriPath %></td>
|
||||||
<td><%- protectionName %></td>
|
<td><%- eventTopic %></td>
|
||||||
<td><%- matchedLocation %></td>
|
<td><%- matchedLocation %></td>
|
||||||
<td><%- matchedParameter %></td>
|
<td><%- matchedParameter %></td>
|
||||||
<td><%- matchedSample %></td>
|
<td><%- matchedSample %></td>
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
<th>HTTP Method</th>
|
<th>HTTP Method</th>
|
||||||
<th>HTTP Response Code</th>
|
<th>HTTP Response Code</th>
|
||||||
<th>HTTP URI Path</th>
|
<th>HTTP URI Path</th>
|
||||||
<th>Protection Name</th>
|
<th>Event Topic</th>
|
||||||
<th>Matched Location</th>
|
<th>Matched Location</th>
|
||||||
<th>Matched Parameter</th>
|
<th>Matched Parameter</th>
|
||||||
<th>Matched Sample</th>
|
<th>Matched Sample</th>
|
||||||
|
@@ -15,7 +15,6 @@ let TableBody = Mn.CollectionView.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
updatePage: function () {
|
updatePage: function () {
|
||||||
console.log('updatePage');
|
|
||||||
let models = this.collection.models.slice((this.page - 1) * this.perPage, this.page * this.perPage);
|
let models = this.collection.models.slice((this.page - 1) * this.perPage, this.page * this.perPage);
|
||||||
this.collection.reset(models);
|
this.collection.reset(models);
|
||||||
}
|
}
|
||||||
|
@@ -1,27 +1,5 @@
|
|||||||
|
|
||||||
<td><%- formatDbDate(eventTime, 'D-M-YY, H:mm') %></td>
|
<td><%- formatDbDate(eventTime, 'D-M-YY, H:mm') %></td>
|
||||||
<td>
|
<td><%- eventSeverity %></td>
|
||||||
<div class="text-nowrap">
|
|
||||||
<% var sevirityClass = 'bg-success';
|
|
||||||
switch (eventSeverity) {
|
|
||||||
case 'Critical':
|
|
||||||
sevirityClass = 'bg-danger';
|
|
||||||
break;
|
|
||||||
case 'Warning':
|
|
||||||
sevirityClass = 'bg-warning';
|
|
||||||
break;
|
|
||||||
case 'Info':
|
|
||||||
sevirityClass = 'bg-success';
|
|
||||||
//sevirityClass = 'bg-info';
|
|
||||||
break;
|
|
||||||
case 'Debug':
|
|
||||||
sevirityClass = 'bg-success';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
%>
|
|
||||||
<span class="status-icon <%- sevirityClass %>"></span> <%- eventSeverity %>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td><%- eventPriority %></td>
|
<td><%- eventPriority %></td>
|
||||||
<td><%- eventTopic %></td>
|
<td><%- eventTopic %></td>
|
||||||
<td><%- eventName %></td>
|
<td><%- eventName %></td>
|
||||||
|
@@ -15,7 +15,6 @@ let TableBody = Mn.CollectionView.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
updatePage: function () {
|
updatePage: function () {
|
||||||
console.log('updatePage');
|
|
||||||
let models = this.collection.models.slice((this.page - 1) * this.perPage, this.page * this.perPage);
|
let models = this.collection.models.slice((this.page - 1) * this.perPage, this.page * this.perPage);
|
||||||
this.collection.reset(models);
|
this.collection.reset(models);
|
||||||
}
|
}
|
||||||
|
@@ -182,24 +182,6 @@ module.exports = Mn.View.extend({
|
|||||||
onTabClick: function(event) {
|
onTabClick: function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const selectedTab = event.target.id;
|
const selectedTab = event.target.id;
|
||||||
|
|
||||||
console.log("selectedTab: ", selectedTab);
|
|
||||||
|
|
||||||
// let ListView;
|
|
||||||
// switch (selectedTab) {
|
|
||||||
// case 'tab1':
|
|
||||||
// ListView = ListViewTab1;
|
|
||||||
// break;
|
|
||||||
// case 'tab2':
|
|
||||||
// ListView = ListViewTab2;
|
|
||||||
// break;
|
|
||||||
// case 'tab3':
|
|
||||||
// ListView = ListViewTab3;
|
|
||||||
// break;
|
|
||||||
// default:
|
|
||||||
// ListView = ListViewTab1;
|
|
||||||
// }
|
|
||||||
|
|
||||||
let view = this;
|
let view = this;
|
||||||
let query = this.ui.query.val() || '';
|
let query = this.ui.query.val() || '';
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user