k2hr3-api
Version:
K2HR3 REST API is K2hdkc based Resource and Roles and policy Rules
533 lines (532 loc) • 22.9 kB
JavaScript
;
/*
* 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: Fri Oct 27 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 });
exports.k2hr3acrutil = void 0;
const https = __importStar(require("https"));
const http = __importStar(require("http"));
const k2hr3tokens_1 = __importDefault(require("./k2hr3tokens"));
const k2hr3apiutil_1 = __importDefault(require("./k2hr3apiutil"));
const dbglogging_1 = __importDefault(require("./dbglogging"));
const cacerts_1 = require("./cacerts");
//
// Type chekcer
//
const rawIsResTypeACRVerifyResponseKeys = (val) => {
if (!k2hr3apiutil_1.default.isPlainObject(val)) {
return false;
}
for (const [, value] of Object.entries(val)) {
if (null !== value && !k2hr3apiutil_1.default.isString(value)) {
return false;
}
}
return true;
};
const rawIsDkcTypeACRVerifyOneResponseBodyData = (val) => {
if (!k2hr3apiutil_1.default.isPlainObject(val)) {
return false;
}
const _obj = val;
const _isName = (key) => k2hr3apiutil_1.default.isString(_obj[key]);
const _isExpire = (key) => 'undefined' === typeof _obj[key] || k2hr3apiutil_1.default.isSafeNumber(_obj[key]);
const _isType = (key) => null === _obj[key] || k2hr3apiutil_1.default.isString(_obj[key]);
const _isData = (key) => 'undefined' === typeof _obj[key] || k2hr3apiutil_1.default.isValTypeAll(_obj[key]);
const _isKeys = (key) => 'undefined' === typeof _obj[key] || rawIsResTypeACRVerifyResponseKeys(_obj[key]);
return (_isName('name') &&
_isExpire('expire') &&
_isType('data') &&
_isData('type') &&
_isKeys('keys'));
};
//---------------------------------------------------------
// Common send verify request
//---------------------------------------------------------
//
// Send and Get response from verify URL
//
// Inputs
// scopedtoken : scoped user token
// urlobj : url object built by apiutil.parseUrl()
// callback(error, response) : callback function received response data
//
// Response : following formatted array
//
// Ex.) Response format from verify url
//
// response body = [ : undefined/null or resource array(if one element, allows only it not array)
// dkcTypeACRVerifyOneResponseBodyData = {
// 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
// ... :
// } :
// },
// ...
// ]
//
const rawACRSendVerifyEx = (scopedtoken, urlobj, callback) => {
if (!k2hr3apiutil_1.default.isFunction(callback)) {
dbglogging_1.default.elog('callback parameter is wrong : callback=' + JSON.stringify(callback));
return;
}
const _callback = callback;
if (!k2hr3apiutil_1.default.isSafeString(scopedtoken) || !k2hr3apiutil_1.default.isSafeEntity(urlobj)) {
const error = new Error('some parameters are wrong : scopedtoken=' + JSON.stringify(scopedtoken) + ', urlobj=' + JSON.stringify(urlobj));
dbglogging_1.default.elog(error.message);
_callback(error, null);
return;
}
const headers = {
'Content-Type': 'application/json',
'Content-Length': 0,
'X-Auth-Token': scopedtoken ?? undefined // [NOTE] this token string does not have 'U=' prefix.
};
const caCert = (urlobj && urlobj.https) ? (0, cacerts_1.ca)() : null;
const options = {
'host': k2hr3apiutil_1.default.getSafeString(urlobj.host),
'port': urlobj.port,
'path': k2hr3apiutil_1.default.getSafeString(urlobj.path),
'method': 'GET',
'headers': headers,
'ca': caCert ?? undefined
};
const agent = (urlobj && urlobj.https) ? https : http;
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
const req = agent.request(options, (res) => {
let _body = '';
const _status = res.statusCode;
const _headers = res.headers;
dbglogging_1.default.dlog('verify response status: ' + _status);
dbglogging_1.default.dlog('verify response header: ' + JSON.stringify(_headers));
res.setEncoding('utf8');
res.on('data', (chunk) => {
//r3logger.dlog('verify response chunk: ' + chunk);
_body += chunk;
});
res.on('end', () => {
let _error = null;
let resobj = [];
if (300 <= (_status ?? 500)) {
_error = new Error('got error response for verify request by status=' + String(_status ?? 0));
dbglogging_1.default.elog(_error.message);
_callback(_error, null);
return;
}
//r3logger.dlog('response body: ' + _body);
// check response body
if (!k2hr3apiutil_1.default.isSafeString(_body)) {
_error = new Error('verify resource is not json string : response(json) =' + JSON.stringify(_body));
}
else {
// check response string(json)
if (k2hr3apiutil_1.default.checkSimpleJSON(_body)) {
const tmp_resobj = JSON.parse(_body);
if (k2hr3apiutil_1.default.isArray(tmp_resobj)) {
if (tmp_resobj.every((element) => rawIsDkcTypeACRVerifyOneResponseBodyData(element))) {
resobj = tmp_resobj;
}
}
}
else if (k2hr3apiutil_1.default.isArray(_body)) {
if (_body.every((element) => rawIsDkcTypeACRVerifyOneResponseBodyData(element))) {
resobj = _body;
}
}
else if (rawIsDkcTypeACRVerifyOneResponseBodyData(_body)) { // This format is not officially permitted (maybe it should be removed)
resobj = [_body];
}
if (!k2hr3apiutil_1.default.isArray(resobj)) {
_error = new Error('verify resource is not array : response(object) =' + JSON.stringify(resobj));
}
else {
// check each object in array
const namemap = {};
for (let cnt = 0; cnt < resobj.length; ++cnt) {
// check name field
if (!k2hr3apiutil_1.default.isSafeString(resobj[cnt].name)) {
_error = new Error('empty resource name in verify response is found : response pos=' + cnt);
break;
}
if (k2hr3apiutil_1.default.isSafeEntity(namemap[resobj[cnt].name])) {
_error = new Error('same resource name in verify response is found : response pos=' + cnt + ', name=' + JSON.stringify(resobj[cnt].name));
break;
}
namemap[resobj[cnt].name] = true; // set any value.
// check expire field
if (!k2hr3apiutil_1.default.isSafeEntity(resobj[cnt].expire)) {
resobj[cnt].expire = -1; // set no expire
}
else if (!k2hr3apiutil_1.default.isSafeNumber(resobj[cnt].expire)) {
_error = new Error('wrong expire value in verify response is found : response pos=' + cnt + ', expire=' + JSON.stringify(resobj[cnt].expire));
break;
}
}
}
}
if (null !== _error) {
dbglogging_1.default.elog(_error.message);
_callback(_error, null);
return;
}
// return response
_callback(null, resobj);
return;
});
});
req.on('error', (exception) => {
dbglogging_1.default.elog('problem with verify request: ' + exception.message);
_callback(exception, null);
return;
});
req.end();
};
//---------------------------------------------------------
// Send verify request
//---------------------------------------------------------
//
// Send and Get response from verify URL
//
// Inputs
// user : user name
// passwd : pass phrase for user
// tenant : tenant name for scoped
// verifyurl : verify url(allow not url string, it means static value formatted JSON)
// callback(error, response) : callback function received response data
//
// Response : see rawACRSendVerifyEx()
//
const rawACRSendVerifyByUser = (user, passwd, tenant, verifyurl, callback) => {
if (!k2hr3apiutil_1.default.isFunction(callback)) {
dbglogging_1.default.elog('callback parameter is wrong : callback=' + JSON.stringify(callback));
return;
}
const _callback = callback;
if (!k2hr3apiutil_1.default.isSafeString(verifyurl)) {
const error = new Error('parameter is wrong : verifyurl=' + JSON.stringify(verifyurl));
dbglogging_1.default.elog(error.message);
_callback(error, null);
return;
}
if (k2hr3apiutil_1.default.checkSimpleJSON(verifyurl)) {
// verifyurl is formatted by JSON, it means static value.
_callback(null, JSON.parse(verifyurl));
return;
}
const urlobj = k2hr3apiutil_1.default.parseUrl(verifyurl); // parse verify url string to url obejct.
if (null === urlobj) {
const error = new Error('parameter is wrong : verifyurl=' + JSON.stringify(verifyurl));
dbglogging_1.default.elog(error.message);
_callback(error, null);
return;
}
if (!k2hr3apiutil_1.default.isSafeString(user) || !k2hr3apiutil_1.default.isSafeString(tenant)) {
const error = new Error('some parameters are wrong : user=' + JSON.stringify(user) + ', tenant=' + JSON.stringify(tenant));
dbglogging_1.default.elog(error.message);
_callback(error, null);
return;
}
const _user = user;
const _tenant = tenant;
const _passwd = passwd;
// get scoped token directly.
k2hr3tokens_1.default.getUserToken(_user, _passwd, _tenant, (err, token) => {
if (null !== err) {
const error = new Error('could not get scoped user token for user=' + _user + ', tenant=' + _tenant + ' by ' + k2hr3apiutil_1.default.getSafeString(err.message));
dbglogging_1.default.elog(error.message);
_callback(error, null);
}
dbglogging_1.default.dlog('get user token jsonres = ' + JSON.stringify(token));
// call verify url
rawACRSendVerifyEx(token, urlobj, _callback);
});
};
//---------------------------------------------------------
// Send verify request
//---------------------------------------------------------
//
// Send and Get response from verify URL
//
// Inputs
// unscopedtoken : unscoped user token
// user : user name
// tenant : tenant name for scoped
// verifyurl : verify url(allow not url string, it means static value formatted JSON)
// callback(error, response) : callback function received response data
//
// Response : see rawACRSendVerifyEx()
//
const rawACRSendVerifyByUnscopedToken = (unscopedtoken, user, tenant, verifyurl, callback) => {
if (!k2hr3apiutil_1.default.isFunction(callback)) {
dbglogging_1.default.elog('callback parameter is wrong : callback=' + JSON.stringify(callback));
return;
}
const _callback = callback;
if (!k2hr3apiutil_1.default.isSafeString(verifyurl)) {
const error = new Error('parameter is wrong : verifyurl=' + JSON.stringify(verifyurl));
dbglogging_1.default.elog(error.message);
_callback(error, null);
return;
}
if (k2hr3apiutil_1.default.checkSimpleJSON(verifyurl)) {
// verifyurl is formatted by JSON, it means static value.
_callback(null, JSON.parse(verifyurl));
return;
}
const urlobj = k2hr3apiutil_1.default.parseUrl(verifyurl);
if (null === urlobj) {
const error = new Error('parameter is wrong : verifyurl=' + JSON.stringify(verifyurl));
dbglogging_1.default.elog(error.message);
_callback(error, null);
return;
}
if (!k2hr3apiutil_1.default.isSafeString(unscopedtoken) || !k2hr3apiutil_1.default.isSafeString(user) || !k2hr3apiutil_1.default.isSafeString(tenant)) {
const error = new Error('some parameters are wrong : unscopedtoken=' + JSON.stringify(unscopedtoken) + ', user=' + JSON.stringify(user) + ', tenant=' + JSON.stringify(tenant));
dbglogging_1.default.elog(error.message);
_callback(error, null);
return;
}
const _unscopedtoken = unscopedtoken;
const _user = user;
const _tenant = tenant;
// get scoped token from unscoped token
k2hr3tokens_1.default.getScopedUserToken(_unscopedtoken, _user, _tenant, (err, token) => {
if (null !== err) {
const error = new Error('could not get scoped user token for user=' + _user + ', tenant=' + _tenant + ' by ' + k2hr3apiutil_1.default.getSafeString(err.message));
dbglogging_1.default.elog(error.message);
_callback(error, null);
}
dbglogging_1.default.dlog('get user token jsonres = ' + JSON.stringify(token));
// call verify url
rawACRSendVerifyEx(token, urlobj, _callback);
});
};
//---------------------------------------------------------
// Send verify request
//---------------------------------------------------------
//
// Send and Get response from verify URL
//
// Inputs
// scopedtoken : scoped user token
// verifyurl : verify url(allow not url string, it means static value formatted JSON)
// callback(error, response) : callback function received response data
//
// Response : see rawACRSendVerifyEx()
//
const rawACRSendVerifyByScopedToken = (scopedtoken, verifyurl, callback) => {
if (!k2hr3apiutil_1.default.isFunction(callback)) {
dbglogging_1.default.elog('callback parameter is wrong : callback=' + JSON.stringify(callback));
return;
}
const _callback = callback;
if (!k2hr3apiutil_1.default.isSafeString(verifyurl)) {
const error = new Error('parameter is wrong : verifyurl=' + JSON.stringify(verifyurl));
dbglogging_1.default.elog(error.message);
_callback(error, null);
return;
}
if (k2hr3apiutil_1.default.checkSimpleJSON(verifyurl)) {
// verifyurl is formatted by JSON, it means static value.
_callback(null, JSON.parse(verifyurl));
return;
}
const urlobj = k2hr3apiutil_1.default.parseUrl(verifyurl);
if (null === urlobj) {
const error = new Error('parameter is wrong : verifyurl=' + JSON.stringify(verifyurl));
dbglogging_1.default.elog(error.message);
_callback(error, null);
return;
}
if (!k2hr3apiutil_1.default.isSafeString(scopedtoken)) {
const error = new Error('parameter is wrong : scopedtoken=' + JSON.stringify(scopedtoken));
dbglogging_1.default.elog(error.message);
_callback(error, null);
return;
}
const _scopedtoken = scopedtoken;
// parse token to get user/tenant
const _token_res = k2hr3tokens_1.default.checkUserToken(_scopedtoken);
if (null === _token_res ||
!k2hr3apiutil_1.default.isSafeString(_token_res.user) ||
!k2hr3apiutil_1.default.isSafeString(_token_res.tenant) ||
!k2hr3apiutil_1.default.isSafeEntity(_token_res.scoped) ||
!k2hr3apiutil_1.default.isBoolean(_token_res.scoped) ||
true !== _token_res.scoped) {
const error = new Error('parameter scopedtoken(' + _scopedtoken + ' -> ' + JSON.stringify(_token_res) + ') is something wrong,');
dbglogging_1.default.elog(error.message);
_callback(error, null);
return;
}
// get scoped token from unscoped token
//
// [NOTE]
// getScopedUserToken is allowed scoped token when is has as same as tenant name specified.
//
k2hr3tokens_1.default.getScopedUserToken(_scopedtoken, _token_res.user, _token_res.tenant, (err, token) => {
if (null !== err) {
const error = new Error('could not get scoped user token for user=' + _token_res.user + ', tenant=' + _token_res.tenant + ' by ' + k2hr3apiutil_1.default.getSafeString(err.message));
dbglogging_1.default.elog(error.message);
_callback(error, null);
}
dbglogging_1.default.dlog('get user token jsonres = ' + JSON.stringify(token));
// call verify url
rawACRSendVerifyEx(token, urlobj, _callback);
});
};
//---------------------------------------------------------
// Send verify request for all pattern
//---------------------------------------------------------
//
// Send and Get response from verify URL
//
// Inputs
// unscopedtoken : unscoped user token
// user : user name
// passwd : pass phrase for user
// token : (un)scoped user token
// tenant : tenant name for scoped
// verifyurl : verify url(allow not url string, it means static value formatted JSON)
// callback(error, response) : callback function received response data
//
// Response : see rawACRSendVerifyEx()
//
// [NOTE]
// This function automatically decides raw functions by parameters.
//
// 1) no token
// Both user and passwd parameters must be specified, and token must be null(undefined).
// 2) unscoped token
// Both user and token parameters must be specified, and passwd must be null(undefined).
// The token parameter should be "unscoped" user token.
// 3) scoped token
// token parameter must be specified, and both user and passwd must be null(undefined).
// The token parameter should be "scoped" user token.
//
const rawACRSendVerify = (token, user, passwd, tenant, verifyurl, callback) => {
if (!k2hr3apiutil_1.default.isFunction(callback)) {
dbglogging_1.default.elog('callback parameter is wrong : callback=' + JSON.stringify(callback));
return;
}
const _callback = callback;
let error = null;
// check pattern
if (k2hr3apiutil_1.default.isSafeString(user)) {
if (k2hr3apiutil_1.default.isSafeString(token)) {
if (k2hr3apiutil_1.default.isSafeEntity(passwd)) {
error = new Error('all parameters user(' + JSON.stringify(user) + ') and token(' + JSON.stringify(token) + ') and passwd(xxxxx) are specified.');
}
else {
// case : user + unscoped token
rawACRSendVerifyByUser(user, passwd, tenant, verifyurl, _callback);
}
}
else {
token = null;
if (k2hr3apiutil_1.default.isSafeEntity(passwd)) {
// case : user + passwd
}
else {
// case : user + passwd(null)
//
// [NOTE]
// This case is not error pattern, because empty passwd is allowed by some authorizing system.
}
rawACRSendVerifyByUnscopedToken(token, user, tenant, verifyurl, _callback);
}
}
else {
if (k2hr3apiutil_1.default.isSafeString(token)) {
if (k2hr3apiutil_1.default.isSafeEntity(passwd)) {
error = new Error('user parameter is empty, but passwd(xxxx) is specified.');
}
else {
// case : scoped token
rawACRSendVerifyByScopedToken(token, verifyurl, _callback);
}
}
else {
error = new Error('user parameter is empty, but scoped token is not specified.');
}
}
if (null !== error) {
dbglogging_1.default.elog(error.message);
_callback(error, null);
}
};
//---------------------------------------------------------
// Export types
//---------------------------------------------------------
exports.k2hr3acrutil = {
getACRVerifyByUser: rawACRSendVerifyByUser,
getACRVerifyByUnscopedToken: rawACRSendVerifyByUnscopedToken,
getACRVerifyByScopedToken: rawACRSendVerifyByScopedToken,
getACRSendVerify: rawACRSendVerify
};
exports.default = exports.k2hr3acrutil;
/*
* 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
*/