UNPKG

k2hr3-api

Version:

K2HR3 REST API is K2hdkc based Resource and Roles and policy Rules

293 lines (267 loc) 9.47 kB
/* * K2HR3 REST API * * Copyright 2017 Yahoo Japan Corporation. * * K2HR3 is K2hdkc based Resource and Roles and policy Rules, gathers * common management information for the cloud. * K2HR3 can dynamically manage information as "who", "what", "operate". * These are stored as roles, resources, policies in K2hdkc, and the * client system can dynamically read and modify these information. * * For the full copyright and license information, please view * the license file that was distributed with this source code. * * AUTHOR: Takeshi Nakatani * CREATE: Wed Jun 8 2017 * REVISION: * */ 'use strict'; var express = require('express'); var path = require('path'); var logger = require('morgan'); var cookieParser= require('cookie-parser'); var bodyParser = require('body-parser'); //--------------------------------------------------------- // Utilities //--------------------------------------------------------- var apiutil = require('./lib/k2hr3apiutil'); var resutil = require('./lib/k2hr3resutil'); //--------------------------------------------------------- // Load Configuration //--------------------------------------------------------- var r3Conf = require('./lib/k2hr3config').r3ApiConfig; var apiConf = new r3Conf(); // // Load variables // // - Local Tenants // - Load CORS(Cross-Origin Resource Sharing) Setting // // [NOTE][TODO] // It specifies a web development machine for temporary debugging. // In future we plan to specify with K2HR3 role. // var is_localtenants = true; var cors_ips = []; (function() { var k2hr3config = require('config'); is_localtenants = apiConf.isLocalTenants(); if(apiutil.isSafeEntity(k2hr3config) && !apiutil.isEmptyArray(k2hr3config.corsips)){ apiutil.mergeArray(cors_ips, k2hr3config.corsips); } }()); //--------------------------------------------------------- // Debug logging objects //--------------------------------------------------------- var r3logger = require('./lib/dbglogging'); // eslint-disable-line no-unused-vars //--------------------------------------------------------- // Environments //--------------------------------------------------------- // NODE_ENV(development or production) // NODE_LOGGER(if 'no', not logging by morgan) // var is_product = apiutil.compareCaseString(apiutil.getSafeString(process.env.NODE_ENV), 'production'); var is_logging = !apiutil.compareCaseString(apiutil.getSafeString(process.env.NODE_LOGGER), 'no'); //--------------------------------------------------------- // Routes //--------------------------------------------------------- var version = require('./routes/version'); var userTokens = require('./routes/userTokens'); var policy = require('./routes/policy'); var resource = require('./routes/resource'); var role = require('./routes/role'); var service = require('./routes/service'); var acr = require('./routes/acr'); var list = require('./routes/list'); var userdata = require('./routes/userdata'); var extdata = require('./routes/extdata'); var tenant = null; if(is_localtenants){ tenant = require('./routes/tenant'); } var verify = null; if(!is_product){ verify = require('./routes/debugVerify'); } // // Express objects // var app = express(); var userExp = express(); var policyExp = express(); var resourceExp = express(); var roleExp = express(); var serviceExp = express(); var acrExp = express(); var listExp = express(); var userdataExp = express(); var extdataExp = express(); var tenantExp = null; if(is_localtenants){ tenantExp = express(); } var verifyExp = null; if(!is_product){ verifyExp = express(); } //--------------------------------------------------------- // Trusted proxy //--------------------------------------------------------- // [NOTE][TODO] // We set trusted proxy as only loopback now. // Here, we need to add CDN/Proxy for our NW, but pending now. // app.set('trust proxy', 'loopback'); userExp.set('trust proxy', 'loopback'); policyExp.set('trust proxy', 'loopback'); resourceExp.set('trust proxy', 'loopback'); roleExp.set('trust proxy', 'loopback'); serviceExp.set('trust proxy', 'loopback'); acrExp.set('trust proxy', 'loopback'); listExp.set('trust proxy', 'loopback'); userdataExp.set('trust proxy', 'loopback'); extdataExp.set('trust proxy', 'loopback'); if(is_localtenants){ tenantExp.set('trust proxy','loopback'); } if(!is_product){ verifyExp.set('trust proxy','loopback'); } // // CORS(Cross-Origin Resource Sharing) Controller // app.use(function(req, res, next) { // // Do not allow CORS for userToken without tenant name(=put/post unscoped token) // var userTokenUrlExp = new RegExp('^/v1/user/tokens(.*)'); if(req.client.localAddress !== req.client.remoteAddress && !apiutil.isEmptyArray(apiutil.getSafeString(req.url).match(userTokenUrlExp))){ // // case of POST/PUT userToken // if(!apiutil.findStringInArray(apiConf.getCORSIPs(), req.client.remoteAddress) && !apiutil.findStringInArray(apiConf.getCORSIPs(), '*')){ // [NOTE] // If allowcredauth is true in configuration and password is specified on PUT method, // it allows authorization by credential(username/password). // This case is used for accessing keystone directly. // (The password is empty is allowed.) // if( (apiutil.compareCaseString(req.method, 'PUT') && apiutil.isSafeEntity(req.query) && apiutil.isSafeString(req.query.username) && !(apiConf.isAllowedCredentialAccess() && apiutil.isSafeEntity(req.query.password))) || (apiutil.compareCaseString(req.method, 'POST') && apiutil.isSafeEntity(req.body) && apiutil.isSafeEntity(req.body.auth) && apiutil.isSafeEntity(req.body.auth.passwordCredentials)) ) { // // case of specified user credentials(except specified unscoped token) // var result = { result: false, message: 'not allow CORS(cross-origin resource sharing) to /v1/user/tokens' }; resutil.errResponse(req, res, 405, result, 'application/json; charset=utf-8'); return; } } } // // Origin is specified, allow it. // if(apiutil.isSafeString(req.headers.origin)){ res.header('Access-Control-Allow-Origin', req.headers.origin); res.header('Access-Control-Allow-Headers', 'Origin,X-Requested-With,X-HTTP-Method-Override,Content-Type,Accept,X-Auth-Token,x-k2hr3-debug'); res.header('Access-Control-Allow-Methods', 'HEAD,POST,GET,PUT,DELETE,OPTIONS'); res.header('Access-Control-Expose-Headers', 'X-Auth-Token,x-k2hr3-error'); res.header('Access-Control-Allow-Credentials', true); res.header('Access-Control-Max-Age', '86400'); } next(); }); //--------------------------------------------------------- // Express //--------------------------------------------------------- // // Setting for express // if(is_logging){ // // Setup Log // app.use(logger(apiConf.getAccessLogFormat(), apiConf.getMorganLoggerOption(__dirname))); } app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use('/status.html', express.static(__dirname + '/public/status.html')); // // Route mapping // app.use('/', version); // '/' app.use('/v1', version); // '/v1' userExp.use('/', userTokens); // '/v1/user/tokens' policyExp.use('/*', policy); // '/v1/policy' resourceExp.use('/*', resource); // '/v1/resource' roleExp.use('/*', role); // '/v1/role' serviceExp.use('/*', service); // '/v1/service' acrExp.use('/*', acr); // '/v1/acr' listExp.use('/*', list); // '/v1/list' userdataExp.use('/*', userdata); // '/v1/userdata' extdataExp.use('/*', extdata); // '/v1/extdata' if(is_localtenants){ tenantExp.use('/*', tenant); // '/v1/tenant' } if(!is_product){ verifyExp.use('/*', verify); // '/v1/debug/verify*' } app.use('/v1/user/tokens', userExp); // mountpath: '/v1/user/tokens*' app.use('/v1/policy', policyExp); // mountpath: '/v1/policy*' app.use('/v1/resource', resourceExp); // mountpath: '/v1/resource*' app.use('/v1/role', roleExp); // mountpath: '/v1/role*' app.use('/v1/service', serviceExp); // mountpath: '/v1/service*' app.use('/v1/acr', acrExp); // mountpath: '/v1/acr*' app.use('/v1/list', listExp); // mountpath: '/v1/list*' app.use('/v1/userdata', userdataExp); // mountpath: '/v1/userdata*' app.use('/v1/extdata', extdataExp); // mountpath: '/v1/extdata*' if(is_localtenants){ app.use('/v1/tenant', tenantExp); // mountpath: '/v1/tenant*' } if(!is_product){ app.use('/v1/debug/verify', verifyExp); // mountpath: '/v1/debug/verify*' } //--------------------------------------------------------- // Error handler //--------------------------------------------------------- // // catch 404 and forward to error handler // app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // // error handler // app.use(function(err, req, res, next) // eslint-disable-line no-unused-vars { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; var result = { result: false, message: 'Internal server error' }; resutil.errResponse(req, res, (err.status || 500), result, 'application/json; charset=utf-8'); }); module.exports = app; /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noexpandtab sw=4 ts=4 fdm=marker * vim<600: noexpandtab sw=4 ts=4 */