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); }); } |