UNPKG

k2hr3-api

Version:

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

295 lines (294 loc) 12.8 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: Mon Nov 6 2017 * REVISION: * */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const k2hr3apiutil_1 = __importDefault(require("../lib/k2hr3apiutil")); const k2hr3resutil_1 = __importDefault(require("../lib/k2hr3resutil")); const k2hr3tokens_1 = __importDefault(require("../lib/k2hr3tokens")); const dbglogging_1 = __importDefault(require("../lib/dbglogging")); const https = __importStar(require("https")); const http = __importStar(require("http")); const express_1 = __importDefault(require("express")); const cacerts_1 = require("../lib/cacerts"); const router = express_1.default.Router(); // // Debug Verify URL // // This router is for debugging verify url for dummy service. // This is called only on development environment. // // Mountpath : '/v1/debug/verify' // // GET '/v1/debug/verify' : get verify for debug on version 1 // URL argument // service : service name(default testservice) // HEADER : X-Auth-Token => Scoped User token(without 'U=' prefix) // response body = [ : undefined/null or resource array(if one element, allows only it not array) // { // name : resource name which is key name(path) for resource // expire : undefined/null or integer // type : resource data type(string or object), if date is null or '', this value must be string. // data : resource data which must be string or object or null/undefined. // keys = { : resource has keys(associative array), or null/undefined. // 'foo': bar, : any value is allowed // ... : // } : // }, // ] // router.get('/', (req, res, next) => { dbglogging_1.default.dlog('CALL:', req.method, req.url); if ('GET' !== req.method) { // HEAD request comes here, so it should be routed to head function. next(); return; } res.type('application/json; charset=utf-8'); // // Check request // if (!k2hr3apiutil_1.default.isPlainObject(req) || !k2hr3apiutil_1.default.isSafeString(req.baseUrl) || !k2hr3apiutil_1.default.isSafeString(req.method) || !k2hr3apiutil_1.default.isSafeString(req.protocol) || !k2hr3apiutil_1.default.isPlainObject(req.query) || (!k2hr3apiutil_1.default.isSafeString(req.host) && !k2hr3apiutil_1.default.isSafeString(req.hostname)) || !k2hr3apiutil_1.default.isPlainObject(req.headers) || !k2hr3apiutil_1.default.isSafeEntity(req.headers.host)) { dbglogging_1.default.elog('GET request or url or token is wrong'); k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request return; } const _req = req; const _res = res; //------------------------------ // check token //------------------------------ const token_result = k2hr3tokens_1.default.checkToken(req, true, true); // scoped, user token if (!token_result.result) { dbglogging_1.default.elog(k2hr3apiutil_1.default.getSafeString(token_result.message)); const result = { result: token_result.result, message: k2hr3apiutil_1.default.getSafeString(token_result.message), }; k2hr3resutil_1.default.errResponse(req, res, token_result.status, result); return; } const _token_info = token_result.token_info; if (!k2hr3tokens_1.default.isResTypeCheckRoleToken(_token_info)) { const result = { result: false, message: 'specified wrong token or it is not scoped user token' }; dbglogging_1.default.elog(result.message); k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request return; } // // check arguments // let _service_name = 'testservice'; // [NOTE] default service name if (k2hr3apiutil_1.default.isSafeString(req.query.service) && k2hr3apiutil_1.default.isSafeString(req.query.service.trim())) { _service_name = req.query.service.trim(); } // // Check localhost information for ACR API // const urlobj = k2hr3apiutil_1.default.parseUrl(_req.protocol + '://' + _req.headers.host); if (null === urlobj || !urlobj.https) { if (!k2hr3apiutil_1.default.compareCaseString(_req.protocol, 'http')) { dbglogging_1.default.elog('Original request url method is not as same as request method'); k2hr3resutil_1.default.errResponse(_req, _res, 400); // 400: Bad Request return; } } else { if (!k2hr3apiutil_1.default.compareCaseString(_req.protocol, 'https')) { dbglogging_1.default.elog('Original request url method is not as same as request method'); k2hr3resutil_1.default.errResponse(_req, _res, 400); // 400: Bad Request return; } } if (null === urlobj || (urlobj.host !== k2hr3apiutil_1.default.getSafeString(_req.host) && urlobj.host !== k2hr3apiutil_1.default.getSafeString(_req.hostname))) { dbglogging_1.default.elog('Original request url host is not as same as request host'); k2hr3resutil_1.default.errResponse(_req, _res, 400); // 400: Bad Request return; } // // Make request data // const agent = k2hr3apiutil_1.default.compareCaseString('https:', _req.protocol) ? https : http; const headers = { 'Content-Type': 'application/json', 'Content-Length': 0, 'X-Auth-Token': k2hr3apiutil_1.default.getSafeString(_req.headers['x-auth-token']) // Transfer }; const options = { 'host': urlobj.host, 'port': urlobj.port, 'path': '/v1/acr/' + _service_name, 'method': 'GET', 'headers': headers, 'ca': (k2hr3apiutil_1.default.compareCaseString('https:', _req.protocol) && null !== cacerts_1.ca) ? ((0, cacerts_1.ca)() ?? undefined) : undefined }; dbglogging_1.default.dlog('request options = ' + JSON.stringify({ ...options, ca: options.ca ? '[Buffer]' : undefined })); dbglogging_1.default.dlog('request headers = ' + JSON.stringify(headers)); // // Send request to localhost // const subreq = agent.request(options, (subres) => { let _body = ''; const _status = subres.statusCode; const _headers = subres.headers; dbglogging_1.default.dlog('/v1/acr/testservice response status: ' + _status); dbglogging_1.default.dlog('/v1/acr/testservice response header: ' + JSON.stringify(_headers)); subres.setEncoding('utf8'); res.on('data', (chunk) => { //r3logger.dlog('/v1/acr/testservice response chunk: ' + chunk); _body += chunk; }); res.on('end', () => { if (300 <= (_status ?? 500)) { const _error = new Error('got error response for verify request by status=' + String(_status ?? 500)); dbglogging_1.default.elog(_error.message); k2hr3resutil_1.default.errResponse(_req, _res, _status, _error.message); // 4xx, 5xx return; } //r3logger.dlog('/v1/acr/testservice response body: ' + _body); // // Check response body // let res_body = _body; if (k2hr3apiutil_1.default.checkSimpleJSON(_body)) { res_body = JSON.parse(_body); } if (!k2hr3apiutil_1.default.isPlainObject(res_body) || !k2hr3apiutil_1.default.isPlainObject(res_body.tokeninfo) || !k2hr3apiutil_1.default.isSafeString(res_body.tokeninfo.service) || !k2hr3apiutil_1.default.compareCaseString(res_body.tokeninfo.service, _service_name) || !k2hr3apiutil_1.default.isSafeString(res_body.tokeninfo.user) || !k2hr3apiutil_1.default.isSafeString(res_body.tokeninfo.tenant)) { const _error = new Error('/v1/acr/testservice response is something wrong(' + JSON.stringify(res_body) + ').'); dbglogging_1.default.elog(_error.message); k2hr3resutil_1.default.errResponse(_req, _res, 400, _error.message); // 400: Bad Request return; } dbglogging_1.default.dlog('Call Verify URL: verified user(' + k2hr3apiutil_1.default.getSafeString(res_body.user) + ') and tenant(' + k2hr3apiutil_1.default.getSafeString(res_body.tenant) + ')'); // // Make response body for debug // const resobj = [ { name: _service_name + '_resource', // resource name expire: null, // no expire type: 'string', // resource is string type data: _service_name + ' resource data for debug', // resource data(string) keys: { 'creator': k2hr3apiutil_1.default.getSafeString(_token_info.user), 'owner_tenant': k2hr3apiutil_1.default.getSafeString(_token_info.tenant), 'service_name': _service_name, 'token': 'sample_token_value', 'accesskey': 'sample_accesskey_value', 'secretkey': 'sample_secretkey_value', 'anykey': 'sample_value' } } ]; // // Return response // dbglogging_1.default.dlog('succeed : ' + JSON.stringify(resobj)); _res.status(200); // 200: OK _res.send(JSON.stringify(resobj)); }); }); subreq.on('error', (exception) => { dbglogging_1.default.elog(exception.message); const maybeErrno = exception.errno; const maybeCode = exception.code; let status_code = 500; if (k2hr3apiutil_1.default.isSafeNumber(maybeErrno)) { status_code = maybeErrno; } else { let tmpSatus = k2hr3apiutil_1.default.cvtToNumber(maybeErrno); if (!k2hr3apiutil_1.default.isSafeNumber(tmpSatus)) { tmpSatus = k2hr3apiutil_1.default.cvtToNumber(maybeCode); } if (k2hr3apiutil_1.default.isSafeNumber(tmpSatus)) { status_code = tmpSatus; } } k2hr3resutil_1.default.errResponse(_req, _res, status_code, exception.message); return; }); subreq.end(); }); //--------------------------------------------------------- // Exports //--------------------------------------------------------- // // Functions // exports.default = router; /* * 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 */