UNPKG

k2hr3-app

Version:

K2HR3 Web Application is K2hdkc based Resource and Roles and policy Rules

297 lines (268 loc) 8.43 kB
/* * * K2HR3 Web Application * * 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 Sep 6 2017 * REVISION: * */ 'use strict'; var r3util = require('./libr3util'); var appConfig = require('./libr3appconfig').r3AppConfig; var fs = require('fs'); //--------------------------------------------------------- // User Token Class //--------------------------------------------------------- var R3UserToken = (function() { // // Constructor // var R3UserToken = function(req) { if(!(this instanceof R3UserToken)){ return new R3UserToken(req); } this.appConfig = new appConfig(); if(r3util.isSafeEntity(this.appConfig.getUserValidatorObj().getUserName)){ this.username = this.appConfig.getUserValidatorObj().getUserName(req); if(null === this.username){ console.error('could not get user name, it is not login status.'); } }else{ this.username = null; } if(r3util.isSafeEntity(this.appConfig.getUserValidatorObj().getSignInType)){ this.sinintype = this.appConfig.getUserValidatorObj().getSignInType(); }else{ this.sinintype = null; } if(r3util.isSafeEntity(this.appConfig.getUserValidatorObj().getSignInUri)){ this.signinUrl = this.appConfig.getUserValidatorObj().getSignInUri(req); }else{ this.signinUrl = null; } if(r3util.isSafeEntity(this.appConfig.getUserValidatorObj().getSignOutUri)){ this.signoutUrl = this.appConfig.getUserValidatorObj().getSignOutUri(req); }else{ this.signoutUrl = null; } if(r3util.isSafeEntity(this.appConfig.getUserValidatorObj().getOtherToken)){ this.otherToken = this.appConfig.getUserValidatorObj().getOtherToken(req); }else{ this.otherToken = null; } if(r3util.isSafeEntity(this.appConfig.getUserValidatorObj().getConfigName)){ this.configName = this.appConfig.getUserValidatorObj().getConfigName(req); }else{ this.configName = null; } }; var proto = R3UserToken.prototype; // // Methods // proto.getUserName = function() { return this.username; }; proto.rawExtractUserToken = function(req) { if( !r3util.isSafeEntity(req) || !r3util.isSafeEntity(req.headers) || !r3util.isSafeString(req.headers['x-auth-token']) ) { return null; } var token = req.headers['x-auth-token']; if(-1 !== token.indexOf('R=')){ console.warn('The request object does not have user token header but has role token.'); return null; } if(-1 !== token.indexOf('U=')){ token = token.substr(2); if(!r3util.isSafeString(token)){ console.warn('The request object has empty user token.'); return null; } } return token; }; proto.rawGetUserToken = function(callback, username, token, tenant) { var secure = false; var httpobj = null; var agent = null; // for HTTPS if('https' == this.appConfig.getApiScheme() || 'HTTPS' == this.appConfig.getApiScheme()){ secure = true; httpobj = require('https'); var agentOptions = { host: this.appConfig.getApiHost(), port: this.appConfig.getApiPort(), path: '/', rejectUnauthorized: this.appConfig.getRejectUnauthorized() }; agent = new httpobj.Agent(agentOptions); }else{ httpobj = require('http'); } var _callback = callback; var isscoped = r3util.isSafeString(tenant) && r3util.isSafeString(token); // arguments for the request to API server var urlarg = r3util.isSafeString(username) ? ('?username=' + this.username + (isscoped ? ('&tenantname=' + tenant) : '')) : ''; var headers = { 'Content-Type': 'application/json', 'Content-Length': 0 }; if(isscoped){ headers['x-auth-token'] = 'U=' + token; }else if(r3util.isSafeString(token)){ // token is other token headers['x-auth-token'] = token; } var options = { 'host': this.appConfig.getApiHost(), 'port': this.appConfig.getApiPort(), 'method': 'PUT', 'headers': headers, 'path': ('/v1/user/tokens' + encodeURI(urlarg)) }; if(secure){ options.agent = agent; // Set CA cert file var ca = this.appConfig.getCA(); if(r3util.isSafeString(ca)){ options.ca = [ fs.readFileSync(ca, {encoding: 'utf-8'}) ]; } } console.info('api host = ' + this.appConfig.getApiHost()); console.info('api port = ' + this.appConfig.getApiPort()); console.info('method = PUT'); console.info('headers = ' + headers); console.info('path = /v1/user/tokens' + encodeURI(urlarg)); // send request var request = httpobj.request(options, function(response) { response.setEncoding('utf8'); var resBody = ''; response.on('data', function(chunk) { console.info('RESPONSE CHUNK = ' + chunk); resBody += chunk; }); response.on('end', function(result) // eslint-disable-line no-unused-vars { console.info('RESPONSE CODE = ' + response.statusCode); console.info('RESPONSE HEADER = ' + JSON.stringify(response.headers)); console.info('RESPONSE BODY = ' + r3util.getSafeString(resBody)); var errobj = null; var cvtBody = JSON.parse(r3util.getSafeString(resBody)); if(300 <= response.statusCode){ errobj = new Error('RESPONSE CODE = ' + response.statusCode); }else if( !r3util.isSafeEntity(cvtBody) || !r3util.isSafeBoolean(cvtBody.result) || !r3util.isSafeEntity(cvtBody.message) || !r3util.isSafeBoolean(cvtBody.scoped) || !r3util.isSafeEntity(cvtBody.token) ) { errobj = new Error('Response body is something wrong.'); }else if(!cvtBody.result){ errobj = new Error('Could not get user token by ' + r3util.isSafeString(cvtBody.message)); }else if(isscoped !== cvtBody.scoped){ errobj = new Error('Could not get ' + (isscoped ? 'scoped' : 'unscoped') + ' user token.'); }else if(!r3util.isSafeString(cvtBody.token)){ errobj = new Error('Got token is not strong type.'); } if(null !== errobj){ console.error(errobj.message); _callback(errobj, null); return; } _callback(null, cvtBody.token); }); }); request.on('error', function(error) { // [NOTE] // If fatal error is occurred, the error message must be started with 'K2HR3 API SERVER ERROR'. // This value is checked in caller function. // console.error('ERROR RESPONSE = ' + error.message); _callback(new Error('K2HR3 API SERVER ERROR : ' + error.message), null); }); request.end(); }; proto.hasTokenHeader = function(req) { return (null !== this.rawExtractUserToken(req)); }; proto.getConfigName = function() { return this.configName; }; proto.getUnscopedUserToken = function(callback) { if(!r3util.isSafeString(this.username)){ var errobj = new Error('User name is not specified(not found authentication cookie)'); console.error(errobj.message); callback(errobj, null); return; } return this.rawGetUserToken(callback, null, this.otherToken); }; proto.getScopedUserToken = function(req, tenant, callback) { var errobj; if(!r3util.isSafeString(this.username)){ errobj = new Error('Not find user name.'); console.error(errobj.message); callback(errobj, null); return; } var token = this.rawExtractUserToken(req); if(!r3util.isSafeString(token)){ errobj = new Error('The request does not safe unscoped user token.'); console.error(errobj.message); callback(errobj, null); return; } return this.rawGetUserToken(callback, this.username, token, tenant); }; proto.getSignInType = function() { return this.sinintype; }; proto.getSignInUrl = function() { return this.signinUrl; }; proto.getSignOutUrl = function() { return this.signoutUrl; }; return R3UserToken; })(); //--------------------------------------------------------- // Exports //--------------------------------------------------------- exports.r3UserToken = R3UserToken; /* * 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 */