| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179 |
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
2×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
152×
1×
1×
1×
1×
1×
1×
| 'use strict';
var express = require('express'),
http = require('http'),
bodyParser = require('body-parser'),
config = require(__dirname + '/config'),
logger = require(__dirname + '/loggers/logger'),
peController = require(__dirname + '/controllers/pe-controller'),
classification = require(__dirname + '/controllers/classification').init(),
_ = require('lodash');
const nonWorkerApp = require(__dirname + '/non-worker-app');
var app = express();
app.set('port', config.networking.pnr_enforcement_port);
app.set('host', config.networking.pnr_enforcement_host);
app.use(bodyParser.json());
app.disable('x-powered-by');
app.disable('etag');
// api routes
app.post('/api/v1/pe/request', peController.requestHandler);
app.post('/api/v1/pe/response', peController.responseHandler);
app.post('/api/v1/pe/avcheck', peController.avCheckHandler);
app.post('/api/v1/pe/avlog', peController.avLogHandler);
app.post('/api/v1/pe/ssl_bump_bypass_check',
peController.sslBumpBypassCheckHandler);
app.post('/api/v1/pe/bounce_all_check', peController.bounceAllCheckHandler);
Iif (classification.error) {
logger.error('pnr-enforcement could not set up URL classifiers',
classification.error);
} else {
app.post('/api/v1/pe/pdp', peController.pdpHandler);
}
app.post('/api/pe/v1/risk_score', peController.riskScoreHandler);
//'is_bypass_allowed' api is deprecated. Use 'user_policy' route instead
app.post('/api/v1/pe/is_bypass_allowed', peController.isBypassAllowed);
app.post('/api/v1/pe/get_bypass_token', peController.getBypassToken);
// DEPRECATED. use /api/pe/v1/user_policy, which follows the correct long-term
// naming convention. Other than that, the API is fully backwards-compatible
app.post('/api/v1/pe/user_policy', peController.getUserPolicy);
app.post('/api/pe/v1/user_policy', peController.getUserPolicy);
app.post('/api/pe/v1/policy_lookup', peController.getPolicyKeys);
app.post('/api/v1/pe/flash_site_list', peController.getFlashSiteListV1);
app.post('/api/v2/pe/flash_site_list', peController.getFlashSiteListV2);
//returns site_flags used by surrogate to make per site customization.
app.get('/api/v1/pe/site_flags', peController.getSiteFlagsV1);
// whitelisting needs this to discover known policies and email domains.
// Then it can use user_policies to retrieve the contents of the policy and
// per-tenant config
app.get('/api/pe/v1/list_policies', peController.listPolicies);
// DEPRECATED. use /api/pe/v1/list_policies
app.get('/api/policy/v1/pe', peController.listPolicies);
// tenant configuration information
app.get('/api/v1/tenants/flash_on', peController.getFlashOnTidList);
// tenant capability information
app.post('/api/v1/tenants/capabilities', peController.getTenantCapabilities);
// map of capabilities to tenants
app.post('/api/v1/capabilities/tenants', peController.getTenantsPerCapability);
// tenant customization information
app.post('/api/v1/pe/customization/web', peController.getTenantCustomization);
//Run multiple processes using cluster
var cluster = require('cluster');
var numWorkers = require('os').cpus().length;
const maxWorkers = parseInt(config.pnr_enforcement.max_workers, 10);
Eif (maxWorkers > 0 && maxWorkers < numWorkers) {
numWorkers = maxWorkers;
}
Eif(process.env.NODE_ENV !== 'production') {
numWorkers = 1;
}
// leave one processor free for system
Iif(numWorkers > 1) {
numWorkers -= 1;
}
//Check if secret key to access policy server is available.
Iif (config.networking.policy_server_enabled && !config.pnr_policy.root_secret) {
const type = cluster.isMaster ? 'master' : 'worker';
logger.error('event=no_root_secret process=' + type);
process.exit(9);
}
// Reserve one more process for the non_pe_worker
numWorkers += 1;
Iif (cluster.isMaster) {
for(var i = 0; i < numWorkers; ++i) {
let env = _.cloneDeep(process.env);
env.WORKER_NAME = (i === 0 ? 'non_pe_worker' : 'pe_worker_' + i);
logger.info("ELIS: " + JSON.stringify(process.env));
if(process.env.running_under_istanbul) {
cluster.setupMaster({
exec: '/usr/bin/istanbul',
args: [
'cover', '--handle-sigint', '--report', 'none', '--print', 'none', '--include-pid',
process.argv[1], '--'].concat(process.argv.slice(2))
});
}
let newWorker = cluster.fork(env);
newWorker.process.env = env;
}
cluster.on('exit', function(worker, code) {
let env = _.cloneDeep(worker.process.env);
logger.error('event="worker died" process_id=' + worker.process.pid +
' error_code=' + code + ' action="restarting worker"' +
' worker_name="' + env.WORKER_NAME + '"');
let newWorker = cluster.fork(env);
newWorker.process.env = env;
});
} else if (process.env.WORKER_NAME === 'non_pe_worker') {
logger.info('Starting Non PE worker app');
nonWorkerApp();
} else {
// In safeview context, PE tries to listen in '10.3.0.1' network
// which may not be available till safeview is started atleast once.
// So, PE should keep trying to connect to network every minute
// if it failed to listen in the previous attempt.
var serverListening = false,
server = null;
var launchServer = function () {
server = http.createServer(app);
server.on('error', function (e) {
serverListening = false;
logger.error('pnr-enforcement server listening error - ' + e);
});
logger.info('Going to launch server listening on ' +
app.get('host') + ':' + app.get('port'));
server.listen(app.get('port'), app.get('host'), function () {
serverListening = true;
//logger.info("ELIS1worker: " + JSON.stringify(process.env));
logger.info(process.env.WORKER_NAME + ' listening on ' +
app.get('host') + ':' + app.get('port'));
});
};
launchServer();
setInterval(function () {
Iif (!serverListening) {
server = null;
launchServer();
}
}, 60 * 1000); //every minute
process.on('uncaughtException', function(err) {
var msg = 'event=UncaughtException error_msg="' + err.message + '"';
Eif (err.stack) {
msg += ' stack="' + err.stack + '"';
}
logger.error(msg);
process.exit(1);
});
}
|