k2hr3-api
Version:
K2HR3 REST API is K2hdkc based Resource and Roles and policy Rules
297 lines (296 loc) • 13.3 kB
JavaScript
"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
*/