UNPKG

k2hr3-api

Version:

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

263 lines (262 loc) 10.9 kB
"use strict"; /* * 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: * */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); //--------------------------------------------------------- // Imports //--------------------------------------------------------- const path_1 = __importDefault(require("path")); const morgan_1 = __importDefault(require("morgan")); const cookie_parser_1 = __importDefault(require("cookie-parser")); const body_parser_1 = __importDefault(require("body-parser")); const k2hr3apiutil_1 = __importDefault(require("./lib/k2hr3apiutil")); const k2hr3resutil_1 = __importDefault(require("./lib/k2hr3resutil")); const express_1 = __importDefault(require("express")); // // Load Configuration // const k2hr3config_1 = require("./lib/k2hr3config"); const apiConf = new k2hr3config_1.r3ApiConfig(); // // 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. // let is_localtenants = true; const cors_ips = []; (() => { is_localtenants = apiConf.isLocalTenants(); if (k2hr3apiutil_1.default.isSafeEntity(apiConf) && k2hr3apiutil_1.default.isNotEmptyArray(apiConf.getCORSIPs())) { k2hr3apiutil_1.default.mergeArray(cors_ips, apiConf.getCORSIPs()); } })(); //--------------------------------------------------------- // Environments //--------------------------------------------------------- // NODE_ENV(development or production) // NODE_LOGGER(if 'no', not logging by morgan) // const is_product = k2hr3apiutil_1.default.compareCaseString(k2hr3apiutil_1.default.getSafeString(process.env.NODE_ENV), 'production'); const is_logging = !k2hr3apiutil_1.default.compareCaseString(k2hr3apiutil_1.default.getSafeString(process.env.NODE_LOGGER), 'no'); //--------------------------------------------------------- // Routes //--------------------------------------------------------- const version_1 = __importDefault(require("./routes/version")); const userTokens_1 = __importDefault(require("./routes/userTokens")); const policy_1 = __importDefault(require("./routes/policy")); const resource_1 = __importDefault(require("./routes/resource")); const role_1 = __importDefault(require("./routes/role")); const service_1 = __importDefault(require("./routes/service")); const acr_1 = __importDefault(require("./routes/acr")); const list_1 = __importDefault(require("./routes/list")); const userdata_1 = __importDefault(require("./routes/userdata")); const extdata_1 = __importDefault(require("./routes/extdata")); const tenant_1 = __importDefault(require("./routes/tenant")); const debugVerify_1 = __importDefault(require("./routes/debugVerify")); let tenant = null; if (is_localtenants) { tenant = tenant_1.default; } let verify = null; if (!is_product) { verify = debugVerify_1.default; } // // Express objects // const app = (0, express_1.default)(); const userExp = (0, express_1.default)(); const policyExp = (0, express_1.default)(); const resourceExp = (0, express_1.default)(); const roleExp = (0, express_1.default)(); const serviceExp = (0, express_1.default)(); const acrExp = (0, express_1.default)(); const listExp = (0, express_1.default)(); const userdataExp = (0, express_1.default)(); const extdataExp = (0, express_1.default)(); let tenantExp = null; if (is_localtenants) { tenantExp = (0, express_1.default)(); } let verifyExp = null; if (!is_product) { verifyExp = (0, express_1.default)(); } //--------------------------------------------------------- // 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 (tenantExp) { tenantExp.set('trust proxy', 'loopback'); } if (verifyExp) { verifyExp.set('trust proxy', 'loopback'); } // // CORS(Cross-Origin Resource Sharing) Controller // app.use((req, res, next) => { // // Do not allow CORS for userToken without tenant name(=put/post unscoped token) // const userTokenUrlExp = new RegExp('^/v1/user/tokens(.*)'); if (req.socket.localAddress !== req.socket.remoteAddress && k2hr3apiutil_1.default.isNotEmptyArray(k2hr3apiutil_1.default.getSafeString(req.url).match(userTokenUrlExp))) { // // case of POST/PUT userToken // if (!k2hr3apiutil_1.default.findStringInArray(apiConf.getCORSIPs(), req.socket.remoteAddress) && !k2hr3apiutil_1.default.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 ((k2hr3apiutil_1.default.compareCaseString(req.method, 'PUT') && k2hr3apiutil_1.default.isSafeEntity(req.query) && k2hr3apiutil_1.default.isSafeString(req.query.username) && !(apiConf.isAllowedCredentialAccess() && k2hr3apiutil_1.default.isSafeEntity(req.query.password))) || (k2hr3apiutil_1.default.compareCaseString(req.method, 'POST') && k2hr3apiutil_1.default.isSafeEntity(req.body) && k2hr3apiutil_1.default.isSafeEntity(req.body.auth) && k2hr3apiutil_1.default.isSafeEntity(req.body.auth.passwordCredentials))) { // // case of specified user credentials(except specified unscoped token) // const result = { result: false, message: 'not allow CORS(cross-origin resource sharing) to /v1/user/tokens' }; k2hr3resutil_1.default.errResponse(req, res, 405, result, 'application/json; charset=utf-8'); return; } } } // // Origin is specified, allow it. // if (k2hr3apiutil_1.default.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 // const format = apiConf.getAccessLogFormat() ?? 'combined'; const options = apiConf.getMorganLoggerOption(__dirname) ?? undefined; app.use((0, morgan_1.default)(format, options)); } app.use(body_parser_1.default.json()); app.use(body_parser_1.default.urlencoded({ extended: false })); app.use((0, cookie_parser_1.default)()); app.use(express_1.default.static(path_1.default.join(__dirname, 'public'))); app.use('/status.html', express_1.default.static(__dirname + '/public/status.html')); // // Route mapping // app.use('/', version_1.default); // '/' app.use('/v1', version_1.default); // '/v1' userExp.use('/', userTokens_1.default); // '/v1/user/tokens' policyExp.use('/', policy_1.default); // '/v1/policy' resourceExp.use('/', resource_1.default); // '/v1/resource' roleExp.use('/', role_1.default); // '/v1/role' serviceExp.use('/', service_1.default); // '/v1/service' acrExp.use('/', acr_1.default); // '/v1/acr' listExp.use('/', list_1.default); // '/v1/list' userdataExp.use('/', userdata_1.default); // '/v1/userdata' extdataExp.use('/', extdata_1.default); // '/v1/extdata' if (tenantExp && tenant) { tenantExp.use('/', tenant); // '/v1/tenant' } if (verifyExp && verify) { 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 (tenantExp) { app.use(/^\/v1\/tenant(?:\/.*)?$/, tenantExp); // mountpath: '/v1/tenant*' } if (verifyExp) { app.use(/^\/v1\/debug\/verify(?:\/.*)?$/, verifyExp); // mountpath: '/v1/debug/verify*' } app.use((req, res, next) => { const err = new Error('Not Found'); err.status = 404; next(err); }); // // error handler // app.use((err, req, res, _next) => { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; const result = { result: false, message: 'Internal server error' }; k2hr3resutil_1.default.errResponse(req, res, (err.status || 500), result, 'application/json; charset=utf-8'); }); //--------------------------------------------------------- // Exports //--------------------------------------------------------- exports.default = 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 */