UNPKG

k2hr3-api

Version:

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

297 lines (296 loc) 13.3 kB
"use strict"; /* * K2HR3 REST API * * Copyright 2018 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: Tue Oct 2 2018 * REVISION: * */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.userdataProcess = void 0; const k2hr3apiutil_1 = __importDefault(require("./k2hr3apiutil")); const k2hr3cryptutil_1 = __importDefault(require("./k2hr3cryptutil")); const dbglogging_1 = __importDefault(require("./dbglogging")); const k2hr3keys_1 = require("./k2hr3keys"); const k2hr3config_1 = require("./k2hr3config"); const apiConf = new k2hr3config_1.r3ApiConfig(); //--------------------------------------------------------- // Empty script for error //--------------------------------------------------------- const EmptyScriptContents = [ '#!/bin/sh', '#', '# K2HR3 Frontend Web Application', '#', '# Copyright(C) 2018 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: Tue Oct 2 2018', '# REVISION:', '#', '', 'SCRIPTNAME="k2hr3-init"', 'LOGFILE="/var/log/${SCRIPTNAME}.log"', '', 'echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Invalid userdata for creating k2hr3-init script was specified(detail error = {{= %K2HR3_ERROR_MSG% }})" | tee -a ${LOGFILE}', 'exit 1', '', '#', '# VIM modelines', '#', '# vim:set ts=4 fenc=utf-8:', '#' ].join('\n'); //--------------------------------------------------------- // load userdata templates from config directory //--------------------------------------------------------- const LoadedUserdataTemplates = (() => { const templates = { cloud_config: null, init_script: null, init_err_script: null, kw_role_name: /{{= %K2HR3_ROLE_NAME% }}/g, // Role YRN full path kw_role_tenant: /{{= %K2HR3_ROLE_TENANT% }}/g, // Tenant YRN full path kw_role_token: /{{= %K2HR3_ROLE_TOKEN% }}/g, // Role Token kw_api_uri: /{{= %K2HR3_API_HOST_URI% }}/g, // K2HR3 API server URI(ex. https://localhost:3000) kw_err_msg: /{{= %K2HR3_ERROR_MSG% }}/g, // Error message string when something error occured default_script: EmptyScriptContents, }; const userdatacfgobj = apiConf.getUserdataConfig(); if (k2hr3apiutil_1.default.isSafeEntity(userdatacfgobj)) { templates.baseuri = k2hr3apiutil_1.default.getSafeString(userdatacfgobj.baseuri); templates.algorithm = k2hr3apiutil_1.default.getSafeString(userdatacfgobj.algorithm); templates.passphrase = k2hr3apiutil_1.default.getSafeString(userdatacfgobj.passphrase); templates.cloud_config = k2hr3apiutil_1.default.readFileContents(userdatacfgobj.cc_templ); templates.init_script = k2hr3apiutil_1.default.readFileContents(userdatacfgobj.script_templ); templates.init_err_script = k2hr3apiutil_1.default.readFileContents(userdatacfgobj.errscript_templ); } else { templates.baseuri = ''; templates.algorithm = ''; templates.passphrase = ''; templates.cloud_config = null; templates.init_script = null; templates.init_err_script = null; } return templates; })(); //--------------------------------------------------------- // Userdata Processing Class //--------------------------------------------------------- class UserdataProcess { _userdataTemplates; // // Constructor // constructor() { this._userdataTemplates = LoadedUserdataTemplates; } ; // // Methods // encryptRoleInfo = (obj) => { if (!k2hr3apiutil_1.default.isSafeEntity(obj)) { dbglogging_1.default.elog('role information object parameter is empty.'); return null; } return k2hr3cryptutil_1.default.r3EncryptJSON(obj, (k2hr3apiutil_1.default.isSafeString(this._userdataTemplates.passphrase) ? this._userdataTemplates.passphrase : null), (k2hr3apiutil_1.default.isSafeString(this._userdataTemplates.algorithm) ? this._userdataTemplates.algorithm : null)); }; decryptRoleInfo = (str) => { if (!k2hr3apiutil_1.default.isSafeString(str)) { dbglogging_1.default.elog('string parameter is empty.'); return null; } const rawData = k2hr3cryptutil_1.default.r3DecryptJSON(str, this._userdataTemplates.passphrase, this._userdataTemplates.algorithm); if (!k2hr3apiutil_1.default.isValTypeRoleInfo(rawData)) { return null; } return rawData; }; getMultipartUserdata = (roleobj, errorMsg) => { let rolename = ''; let roletenant = ''; let roletoken = ''; if (!k2hr3apiutil_1.default.isSafeString(errorMsg)) { errorMsg = null; } if (!k2hr3apiutil_1.default.isPlainObject(roleobj)) { dbglogging_1.default.elog('role object(role name, role token) parameter is empty.'); if (!errorMsg) { errorMsg = 'k2hr3 role information is wrong'; } } else if (!k2hr3apiutil_1.default.isSafeString(roleobj.role)) { dbglogging_1.default.elog('role name parameter is empty.'); if (!errorMsg) { errorMsg = 'k2hr3 role name is empty'; } } else if (!k2hr3apiutil_1.default.isSafeString(roleobj.token)) { dbglogging_1.default.elog('role token parameter is empty.'); if (!errorMsg) { errorMsg = 'k2hr3 role token is empty'; } } else { rolename = k2hr3apiutil_1.default.getSafeString(roleobj.role); roletoken = k2hr3apiutil_1.default.getSafeString(roleobj.token); // Extract tenant yrn full path from role yrn full path const keys = (0, k2hr3keys_1.getK2hr3Keys)(); const roleptn = new RegExp('^' + keys.MATCH_ANY_TENANT_ROLE); // regex = /^yrn:yahoo:(.*)::(.*):role:(.*)/ const matches = rolename.match(roleptn); if (k2hr3apiutil_1.default.isNotEmptyArray(matches) && 4 <= matches.length && k2hr3apiutil_1.default.isSafeString(matches[2])) { roletenant = keys.NO_SERVICE_KEY + k2hr3apiutil_1.default.getSafeString(matches[1]) + '::' + k2hr3apiutil_1.default.getSafeString(matches[2]); } } //----------------- // expands templates //----------------- const config = this._userdataTemplates.cloud_config; // cloud-config does not have keywords, then no-replacing. let script = null; let errscript = null; let defscript = this._userdataTemplates.default_script; if (this._userdataTemplates.init_script) { script = this._userdataTemplates.init_script.replace(this._userdataTemplates.kw_role_name, rolename); script = script.replace(this._userdataTemplates.kw_role_tenant, roletenant); script = script.replace(this._userdataTemplates.kw_role_token, roletoken); script = script.replace(this._userdataTemplates.kw_api_uri, k2hr3apiutil_1.default.getSafeString(this._userdataTemplates.baseuri)); if (errorMsg) { // [NOTE] // Normally, you'll use a script for error, so this process will be wasted. // However, there are cases where this keyword is specified in the template, // so we will replace it. // script = script.replace(this._userdataTemplates.kw_err_msg, errorMsg); } else { script = script.replace(this._userdataTemplates.kw_err_msg, ''); } } if (this._userdataTemplates.init_err_script) { errscript = this._userdataTemplates.init_err_script.replace(this._userdataTemplates.kw_role_name, rolename); errscript = errscript.replace(this._userdataTemplates.kw_role_token, roletoken); errscript = errscript.replace(this._userdataTemplates.kw_role_tenant, roletenant); errscript = errscript.replace(this._userdataTemplates.kw_api_uri, k2hr3apiutil_1.default.getSafeString(this._userdataTemplates.baseuri)); if (errorMsg) { errscript = errscript.replace(this._userdataTemplates.kw_err_msg, errorMsg); } else { errscript = errscript.replace(this._userdataTemplates.kw_err_msg, ''); } } if (!config && !script) { dbglogging_1.default.wlog('k2hr3-init and error script template is not specified.'); if (!errorMsg) { errorMsg = 'no script is set'; } } if (errorMsg) { defscript = defscript.replace(this._userdataTemplates.kw_err_msg, errorMsg); } //----------------- // make part type array //----------------- const parts = []; // member object is {type: 'contents-type string', filename: 'filename', contents: '...'} if (errorMsg) { if (!errscript) { parts.push({ type: 'text/x-shellscript', filename: 'k2hr3-init-empty.sh', contents: defscript }); } else { parts.push({ type: 'text/x-shellscript', filename: 'k2hr3-init-error.sh', contents: errscript }); } } else if (config && script) { parts.push({ type: 'text/cloud-config', filename: 'k2hr3-cloud-config.txt', contents: config }); parts.push({ type: 'text/x-shellscript', filename: 'k2hr3-init.sh', contents: script }); } else if (config && !script) { parts.push({ type: 'text/cloud-config', filename: 'k2hr3-cloud-config.txt', contents: config }); } else if (!config && script) { parts.push({ type: 'text/x-shellscript', filename: 'k2hr3-init.sh', contents: script }); } else { // !config && !script parts.push({ type: 'text/x-shellscript', filename: 'k2hr3-init-empty.sh', contents: defscript }); } //----------------- // make multipart //----------------- const boundary = '================K2HR3INIT' + Date.now().toString() + '=='; const result = { body: '', type: 'multipart/mixed; boundary="' + boundary + '"', mimeverkey: 'MIME-Version', mimeverval: '1.0', partcntkey: 'Number-Attachments', partcntval: parts.length }; // fill parts for (let cnt = 0; cnt < parts.length; ++cnt) { // part header result.body += '--' + boundary + '\r\n'; result.body += 'MIME-Version: 1.0\r\n'; result.body += 'Content-Type: ' + parts[cnt].type + '; charset="us-ascii"\r\n'; result.body += 'Content-Transfer-Encoding: 7bit\r\n'; result.body += 'Content-Disposition: attachment; filename="' + parts[cnt].filename + '"\r\n\r\n'; // part contents result.body += parts[cnt].contents; result.body += '\r\n'; } // make footer result.body += '--' + boundary + '--\r\n'; return result; }; getGzipMultipartUserdata = (roleobj, errorMsg, callback) => { // get multipart headers and body const multipartobj = this.getMultipartUserdata(roleobj, errorMsg); // make one string let multipart = ''; multipart += 'Content-Type: ' + multipartobj.type + '\r\n'; multipart += multipartobj.mimeverkey + ': ' + multipartobj.mimeverval + '\r\n'; multipart += multipartobj.partcntkey + ': ' + multipartobj.partcntval + '\r\n\r\n'; multipart += multipartobj.body; return k2hr3cryptutil_1.default.r3Gzip(multipart, callback); }; } //--------------------------------------------------------- // Exports //--------------------------------------------------------- // // Class // exports.userdataProcess = UserdataProcess; exports.default = exports.userdataProcess; /* * 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 */