UNPKG

k2hr3-api

Version:

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

870 lines (790 loc) 31.6 kB
/* * 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: Wed Jun 8 2017 * REVISION: * */ 'use strict'; var express = require('express'); var router = express.Router(); var r3token = require('../lib/k2hr3tokens'); var apiutil = require('../lib/k2hr3apiutil'); var resutil = require('../lib/k2hr3resutil'); var k2hr3 = require('../lib/k2hr3dkc'); var r3keys = require('../lib/k2hr3keys').getK2hr3Keys; // Debug logging objects var r3logger = require('../lib/dbglogging'); // Mountpath : '/v1/policy' // POST '/v1/policy' : post policy on version 1 // response body : result => true/false // message => messages // body : // { // "policy": { // "name": <policy name> => key is "yrn:yahoo:<service>::<tenant>:policy:<policy>" // "effect": "allow" or "deny" => key is "yrn:yahoo:<service>::<tenant>:policy:<policy>/effect" // if null or undefined is specified, not update this member in policy when this policy exists. // if '' or zero array, this member in policy is set default(default deny).. // "action": [<action yrn full path>, ...] => key is "yrn:yahoo:<service>::<tenant>:policy:<policy>/action" // specify "yrn:yahoo::::action:read" or "yrn:yahoo::::action:write" // if null or undefined is specified, not update this member in policy when this policy exists. // if '' or zero array, this member in policy is set empty array. // "resource": [<resource yrn full path>, ...] => key is "yrn:yahoo:<service>::<tenant>:policy:<policy>/resource" // specify "yrn:yahoo:<service>::<tenant>:resource:<resource>{/<resource>{...}}" // if null or undefined is specified, not update this member in policy when this policy exists. // if '' or zero array, this member in policy is set empty array. // "condition": null or undefined => this member is reserved on v1, must be null or undefined. // "alias": [<policy yrn full path>, ...] => key is "yrn:yahoo:<service>::<tenant>:policy:<policy>/@" // specify another policy as "yrn:yahoo:<service>::<tenant>:policy:<policy>" // if null or undefined is specified, not update this member in policy when this policy exists. // if '' or zero array, this member in policy is set empty array. // } // } // router.post('/', function(req, res, next) // eslint-disable-line no-unused-vars { r3logger.dlog('CALL:', req.method, req.url); res.type('application/json; charset=utf-8'); var result; if( !apiutil.isSafeEntity(req) || !apiutil.isSafeEntity(req.body) || !apiutil.isSafeEntity(req.body.policy) ) { result = { result: false, message: 'POST body does not have policy data' }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } //------------------------------ // check token //------------------------------ var token_result = r3token.checkToken(req, true, true); // scoped, user token if(!token_result.result){ r3logger.elog(token_result.message); var _status = token_result.status; delete token_result.status; resutil.errResponse(req, res, _status, token_result); return; } var token_info = token_result.token_info; //------------------------------ // check arguments //------------------------------ if(!apiutil.isSafeString(req.body.policy.name)){ result = { result: false, message: 'policy:name field is wrong : ' + JSON.stringify(req.body.policy.name) }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var keys = r3keys(token_info.user, token_info.tenant); var name = apiutil.getSafeString(req.body.policy.name); name = name.toLowerCase(); // policy name is only name or full yrn path var nameptn = new RegExp('^' + keys.POLICY_TOP_KEY + ':(.*)'); // regex = /^yrn:yahoo:<service>::<tenant>:policy:(.*)/ var namematchs = name.match(nameptn); if(!apiutil.isEmptyArray(namematchs) && 2 <= namematchs.length){ name = namematchs[1]; } // check token's tenant(if same tenant, name is not full yrn) nameptn = new RegExp('^' + keys.NO_TENANT_KEY); // regex = /^yrn:yahoo:/ if(name.match(nameptn)){ result = { result: false, message: 'POST request url has wrong yrn full path to policy' }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var effect; if(!apiutil.isSafeEntity(req.body.policy.effect)){ effect = null; // = not update if policy exists }else if('' === req.body.policy.effect){ effect = false; // = deny }else if(apiutil.compareCaseString(req.body.policy.effect, keys.VALUE_ALLOW)){ effect = true; // = allow }else if(apiutil.compareCaseString(req.body.policy.effect, keys.VALUE_DENY)){ effect = false; // = deny }else{ result = { result: false, message: 'policy:effect field is wrong : ' + JSON.stringify(req.body.policy.effect) }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var actptns = [keys.ACTION_READ_KEY, keys.ACTION_WRITE_KEY]; // allow string as read/write yrn full path var actpram = apiutil.getNormalizeParameter(req.body.policy.action, null, actptns); if(false === actpram.result){ result = { result: false, message: 'policy:action field is wrong : ' + JSON.stringify(req.body.policy.action) }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var actions = actpram.parameter; var resptn = new RegExp('^' + keys.RESOURCE_TOP_KEY + ':(.*)'); // regex = /^yrn:yahoo:<service>::<tenant>:resource:(.*)/ var respram = apiutil.getNormalizeParameter(req.body.policy.resource, resptn, null); if(false === respram.result){ result = { result: false, message: 'policy:resource field is wrong : ' + JSON.stringify(req.body.policy.resource) }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var resources = respram.parameter; var condition; if(!apiutil.isSafeEntity(req.body.policy.condition) || '' === req.body.policy.condition){ condition = null; // now reserved this field }else{ result = { result: false, message: 'policy:condition field is wrong : ' + JSON.stringify(req.body.policy.condition) }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var aliasptn = new RegExp('^' + keys.POLICY_TOP_KEY + ':(.*)'); // regex = /^yrn:yahoo:<service>::<tenant>:policy:(.*)/ var aliaspram = apiutil.getNormalizeParameter(req.body.policy.alias, aliasptn, null); if(false === aliaspram.result){ result = { result: false, message: 'policy:alias field is wrong : ' + JSON.stringify(req.body.policy.alias) }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var aliases = aliaspram.parameter; //------------------------------ // set all field to policy //------------------------------ result = k2hr3.setPolicyAll(token_info.user, token_info.tenant, name, effect, actions, resources, condition, aliases); if(!apiutil.isSafeEntity(result) || !apiutil.isSafeEntity(result.result) || false === result.result){ if(!apiutil.isSafeEntity(result)){ result = { result: false, message: 'Could not get response from setPolicyAll' }; }else{ if(!apiutil.isSafeEntity(result.result)){ result.result = false; } if(!apiutil.isSafeEntity(result.message)){ result.message = 'Could not get error message in response from setPolicyAll'; } } r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } r3logger.dlog('succeed : ' + result.message); res.status(201); // 201: Created res.send(JSON.stringify(result)); }); // Mountpath : '/v1/policy' // PUT '/v1/policy' : put policy on version 1 // response body : result => true/false // message => messages // url argument // "name" : <policy name> => key is "yrn:yahoo:<service>::<tenant>:policy:<policy>" // "effect" : "allow" or "deny" => key is "yrn:yahoo:<service>::<tenant>:policy:<policy>/effect" // if null or undefined is specified, not update this member in policy when this policy exists. // if '' or zero array, this member in policy is set default(default deny).. // "action" : [<action yrn full path>, ...] => key is "yrn:yahoo:<service>::<tenant>:policy:<policy>/action" // specify "yrn:yahoo::::action:read" or "yrn:yahoo::::action:write" // if null or undefined is specified, not update this member in policy when this policy exists. // if '' or zero array, this member in policy is set empty array. // "resource" : [<resource yrn full path>, ...] => key is "yrn:yahoo:<service>::<tenant>:policy:<policy>/resource" // specify "yrn:yahoo:<service>::<tenant>:resource:<resource>{/<resource>{...}}" // if null or undefined is specified, not update this member in policy when this policy exists. // if '' or zero array, this member in policy is set empty array. // "condition" : null or undefined => this member is reserved on v1, must be null or undefined. // "alias" : [<policy yrn full path>, ...] => key is "yrn:yahoo:<service>::<tenant>:policy:<policy>/@" // specify another policy as "yrn:yahoo:<service>::<tenant>:policy:<policy>" // if null or undefined is specified, not update this member in policy when this policy exists. // if '' or zero array, this member in policy is set empty array. // router.put('/', function(req, res, next) // eslint-disable-line no-unused-vars { r3logger.dlog('CALL:', req.method, req.url); res.type('application/json; charset=utf-8'); var result; if( !apiutil.isSafeEntity(req) || !apiutil.isSafeEntity(req.query) ) { result = { result: false, message: 'PUT argument does not have any data' }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } //------------------------------ // check token //------------------------------ var token_result = r3token.checkToken(req, true, true); // scoped, user token if(!token_result.result){ r3logger.elog(token_result.message); var _status = token_result.status; delete token_result.status; resutil.errResponse(req, res, _status, token_result); return; } var token_info = token_result.token_info; //------------------------------ // check arguments //------------------------------ if(!apiutil.isSafeString(req.query.name)){ result = { result: false, message: 'policy:name field is wrong : ' + JSON.stringify(req.query.name) }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var keys = r3keys(token_info.user, token_info.tenant); var name = apiutil.getSafeString(req.query.name); name = name.toLowerCase(); // policy name is only name or full yrn path var nameptn = new RegExp('^' + keys.POLICY_TOP_KEY + ':(.*)'); // regex = /^yrn:yahoo:<service>::<tenant>:policy:(.*)/ var namematchs = name.match(nameptn); if(!apiutil.isEmptyArray(namematchs) && 2 <= namematchs.length){ name = namematchs[1]; } // check token's tenant(if same tenant, name is not full yrn) nameptn = new RegExp('^' + keys.NO_TENANT_KEY); // regex = /^yrn:yahoo:/ if(name.match(nameptn)){ result = { result: false, message: 'PUT request url has wrong yrn full path to policy' }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var effect; if(!apiutil.isSafeEntity(req.query.effect)){ effect = null; // = not update if policy exists }else if('' === req.query.effect){ effect = false; // = deny }else if(apiutil.compareCaseString(req.query.effect, keys.VALUE_ALLOW)){ effect = true; // = allow }else if(apiutil.compareCaseString(req.query.effect, keys.VALUE_DENY)){ effect = false; // = deny }else{ result = { result: false, message: 'policy:effect field is wrong : ' + JSON.stringify(req.query.effect) }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var actptns = [keys.ACTION_READ_KEY, keys.ACTION_WRITE_KEY]; // allow string as read/write yrn full path var actpram = apiutil.getNormalizeParameter(req.query.action, null, actptns); if(false === actpram.result){ result = { result: false, message: 'policy:action field is wrong : ' + JSON.stringify(req.query.action) }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var actions = actpram.parameter; var resptn = new RegExp('^' + keys.RESOURCE_TOP_KEY + ':(.*)'); // regex = /^yrn:yahoo:<service>::<tenant>:resource:(.*)/ var respram = apiutil.getNormalizeParameter(req.query.resource, resptn, null); if(false === respram.result){ result = { result: false, message: 'policy:resource field is wrong : ' + JSON.stringify(req.query.resource) }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var resources = respram.parameter; var condition; if(!apiutil.isSafeEntity(req.query.condition) || '' === req.query.condition){ condition = null; // now reserved this field }else{ result = { result: false, message: 'policy:condition field is wrong : ' + JSON.stringify(req.query.condition) }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var aliasptn = new RegExp('^' + keys.POLICY_TOP_KEY + ':(.*)'); // regex = /^yrn:yahoo:<service>::<tenant>:policy:(.*)/ var aliaspram = apiutil.getNormalizeParameter(req.query.alias, aliasptn, null); if(false === aliaspram.result){ result = { result: false, message: 'policy:alias field is wrong : ' + JSON.stringify(req.query.alias) }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var aliases = aliaspram.parameter; //------------------------------ // set all field to policy //------------------------------ result = k2hr3.setPolicyAll(token_info.user, token_info.tenant, name, effect, actions, resources, condition, aliases); if(!apiutil.isSafeEntity(result) || !apiutil.isSafeEntity(result.result) || false === result.result){ if(!apiutil.isSafeEntity(result)){ result = { result: false, message: 'Could not get response from setPolicyAll' }; }else{ if(!apiutil.isSafeEntity(result.result)){ result.result = false; } if(!apiutil.isSafeEntity(result.message)){ result.message = 'Could not get error message in response from setPolicyAll'; } } r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } r3logger.dlog('succeed : ' + result.message); res.status(201); // 201: Created res.send(JSON.stringify(result)); }); // Mountpath : '/v1/policy/*' // GET '/v1/policy/name' : get policy on version 1(name is allowed full yrn path) // URL arguments : service => undefined or service name // response body : result => true/false // message => error message // policy => object // policy object // { // "name": <policy name> // "effect": "allow" or "deny" // "action": [<action yrn full path>, ...] // "resource": [<resource yrn full path>, ...] // "condition": null or undefined // "alias": [<policy yrn full path>, ...] // } // router.get('/', function(req, res, next) { r3logger.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'); var result; if( !apiutil.isSafeEntity(req) || !apiutil.isSafeEntity(req.baseUrl) ) { result = { result: false, message: 'GET request or url is wrong' }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } //------------------------------ // service name //------------------------------ var service = null; if(apiutil.isSafeEntity(req.query) && apiutil.isSafeString(req.query.service)){ service = apiutil.getSafeString(req.query.service).toLowerCase(); } //------------------------------ // check token //------------------------------ var token_result = r3token.checkToken(req, true, true); // scoped, user token if(!token_result.result){ r3logger.elog(token_result.message); var _status = token_result.status; delete token_result.status; resutil.errResponse(req, res, _status, token_result); return; } var token_info = token_result.token_info; var keys = r3keys(token_info.user, token_info.tenant, service); //------------------------------ // check policy name //------------------------------ var requestptn = new RegExp('^/v1/policy/(.*)'); // regex = /^\/v1\/policy\/(.*)/ var reqmatchs = decodeURI(req.baseUrl).match(requestptn); if(apiutil.isEmptyArray(reqmatchs) || reqmatchs.length < 2 || '' === apiutil.getSafeString(reqmatchs[1])){ result = { result: false, message: 'GET request url does not have policy name' }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var name = reqmatchs[1]; name = name.toLowerCase(); // // make policy name from policy yrn // var nameptn = new RegExp('^' + keys.MATCH_ANY_TENANT_POLICY); // regex = /^yrn:yahoo:(.*)::(.*):policy:(.*)/ var namematchs = name.match(nameptn); if(apiutil.isEmptyArray(namematchs) || namematchs.length < 4){ // name is not full yrn to policy, then check wrong policy name nameptn = new RegExp('^' + keys.NO_TENANT_KEY); // regex = /^yrn:yahoo:/ if(name.match(nameptn)){ result.res_obj.result = false; result.res_obj.message = 'Request query has wrong yrn full path to policy'; result.res_code = 400; // 400: Bad Request r3logger.elog(result.res_obj.message); return result; } // no token need full yrn to policy(other token has tenant name) if(null === token_result.token_type){ result.res_obj.result = false; result.res_obj.message = 'Request query does not have yrn full path to policy'; result.res_code = 400; // 400: Bad Request r3logger.elog(result.res_obj.message); return result; } // no problem, name is policy name }else{ // name is full yrn to policy, then need to check tenant name if(null !== token_result.token_type && !apiutil.compareCaseString(namematchs[2], token_info.tenant)){ result.res_obj.result = false; result.res_obj.message = 'Request query has wrong yrn full path(tenant=' + namematchs[2] + ') to policy(tenant=' + token_info.tenant + ')'; result.res_code = 400; // 400: Bad Request r3logger.elog(result.res_obj.message); return result; } // check service name if(apiutil.isSafeString(service)){ if(!apiutil.compareCaseString(service, namematchs[1])){ result.res_obj.result = false; result.res_obj.message = 'Request query has service name(' + service + ') and path has service name(' + namematchs[1] + '), but both are not same service name.'; result.res_code = 400; // 400: Bad Request r3logger.elog(result.res_obj.message); return result; } }else if(apiutil.isSafeString(namematchs[1])){ // set service name service = apiutil.getSafeString(namematchs[1]).trim().toLowerCase(); keys = r3keys(token_info.user, token_info.tenant, service); } // set name name = namematchs[3].toLowerCase(); } //------------------------------ // get all policy //------------------------------ result = k2hr3.getPolicyAll(token_info.user, token_info.tenant, service, name); if(!apiutil.isSafeEntity(result) || !apiutil.isSafeEntity(result.result) || false === result.result){ if(!apiutil.isSafeEntity(result)){ result = { result: false, message: 'Could not get response from getPolicyAll' }; }else{ if(!apiutil.isSafeEntity(result.result)){ result.result = false; } if(!apiutil.isSafeEntity(result.message)){ result.message = 'Could not get error message in response from getPolicyAll'; } } r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } r3logger.dlog('succeed : ' + result.message); res.status(200); // 200: OK res.send(JSON.stringify(result)); }); // Mountpath : '/v1/policy/*' // HEAD '/v1/policy/name' : head policy on version 1(name is allowed full yrn path) // Url arguments // tenant : optional for policy/resource not full yrn // resource : resource to full yrn(or name) // action : action(read/write) // service : undefined or service name // router.head('/', function(req, res, next) { r3logger.dlog('CALL:', req.method, req.url); if('HEAD' !== req.method){ // If other method request comes here, so it should be routed another function. next(); return; } res.type('application/json; charset=utf-8'); if( !apiutil.isSafeEntity(req) || !apiutil.isSafeEntity(req.baseUrl) || !apiutil.isSafeEntity(req.query) ) { r3logger.elog('HEAD request or url or query is wrong'); resutil.errResponse(req, res, 400); // 400: Bad Request return; } //------------------------------ // check arguments //------------------------------ // first tenant name var tenant = null; if(apiutil.isSafeString(req.query.tenant)){ tenant = apiutil.getSafeString(req.query.tenant).trim().toLowerCase(); } // service name var service = null; if(apiutil.isSafeEntity(req.query) && apiutil.isSafeString(req.query.service)){ service = apiutil.getSafeString(req.query.service).trim().toLowerCase(); } // keys var keys = r3keys(null, tenant, service); // policy name from path var requestptn = new RegExp('^/v1/policy/(.*)'); // regex = /^\/v1\/policy\/(.*)/ var reqmatchs = decodeURI(req.baseUrl).match(requestptn); if(apiutil.isEmptyArray(reqmatchs) || reqmatchs.length < 2 || '' === apiutil.getSafeString(reqmatchs[1])){ r3logger.elog('HEAD request url does not have policy name'); resutil.errResponse(req, res, 400); // 400: Bad Request return; } // check policy name is only name or full yrn path var name = reqmatchs[1]; name = name.toLowerCase(); // // make policy name and full yrn path // var policy_yrn = null; var nameptn = new RegExp('^' + keys.MATCH_ANY_TENANT_POLICY); // regex = /^yrn:yahoo:(.*)::(.*):policy:(.*)/ var namematchs = name.match(nameptn); if(apiutil.isEmptyArray(namematchs) || namematchs.length < 4){ // name is not full yrn to policy, then check wrong policy name nameptn = new RegExp('^' + keys.NO_TENANT_KEY); // regex = /^yrn:yahoo:/ if(name.match(nameptn)){ result.res_obj.result = false; result.res_obj.message = 'Request query has wrong yrn full path to policy'; result.res_code = 400; // 400: Bad Request r3logger.elog(result.res_obj.message); return result; } // no token need full yrn to policy(other token has tenant name) if(!apiutil.isSafeString(tenant)){ result.res_obj.result = false; result.res_obj.message = 'Request query does not have yrn full path to policy'; result.res_code = 400; // 400: Bad Request r3logger.elog(result.res_obj.message); return result; } // no problem, name is policy name policy_yrn = keys.POLICY_TOP_KEY + ':' + name; }else{ // name is full yrn to policy, then need to check tenant name if(apiutil.isSafeString(tenant) && !apiutil.compareCaseString(namematchs[2], tenant)){ result.res_obj.result = false; result.res_obj.message = 'Request query has wrong yrn full path(tenant=' + namematchs[2] + ') to policy(tenant=' + tenant + ')'; result.res_code = 400; // 400: Bad Request r3logger.elog(result.res_obj.message); return result; } // check service name if(apiutil.isSafeString(service)){ if(!apiutil.compareCaseString(service, namematchs[1])){ result.res_obj.result = false; result.res_obj.message = 'Request query has service name(' + service + ') and path has service name(' + namematchs[1] + '), but both are not same service name.'; result.res_code = 400; // 400: Bad Request r3logger.elog(result.res_obj.message); return result; } }else if(apiutil.isSafeString(namematchs[1])){ // set service name service = apiutil.getSafeString(namematchs[1]).trim().toLowerCase(); keys = r3keys(null, tenant, service); } // set name name = namematchs[3].toLowerCase(); policy_yrn = keys.POLICY_TOP_KEY + ':' + name; } // resource if(!apiutil.isSafeString(req.query.resource)){ r3logger.elog('HEAD request argument does not have resource parameter'); resutil.errResponse(req, res, 400); // 400: Bad Request return; } // check resource is only resource name or full yrn path var resource = apiutil.getSafeString(req.query.resource); var resourceptn = new RegExp('^' + keys.MATCH_ANY_TENANT_RESOURCE); // regex = /^yrn:yahoo:(.*)::(.*):resource:(.*)/ var resourcematchs = resource.match(resourceptn); if(apiutil.isEmptyArray(resourcematchs) || resourcematchs.length < 4){ // resource is not matched resource(maybe not full yrn), thus we need tenant parameter if(!apiutil.isSafeString(tenant)){ r3logger.elog('HEAD request query does not have resource by full yrn(if you want to set only resource name, you must specify tenant url argument)'); resutil.errResponse(req, res, 400); // 400: Bad Request return; } // if resource is yrn full path, then it is wrong policy resource resourceptn = new RegExp('^' + keys.NO_TENANT_KEY); // regex = /^yrn:yahoo:/ if(resource.match(resourceptn)){ r3logger.elog('HEAD request query has wrong yrn full path to resource'); resutil.errResponse(req, res, 400); // 400: Bad Request return; } // make full yrn for policy resource resource = keys.RESOURCE_TOP_KEY + ':' + resource; } // action if(!apiutil.isSafeString(req.query.action)){ r3logger.elog('HEAD request argument does not have action parameter'); resutil.errResponse(req, res, 400); // 400: Bad Request return; } // check action is only action name or full yrn path var action = apiutil.getSafeString(req.query.action); if(keys.VALUE_READ === action){ action = keys.ACTION_READ_KEY; }else if(keys.VALUE_WRITE === action){ action = keys.ACTION_WRITE_KEY; }else if(keys.ACTION_READ_KEY !== action && keys.ACTION_WRITE_KEY !== action){ r3logger.elog('HEAD request query has wrong action value'); resutil.errResponse(req, res, 400); // 400: Bad Request return; } //------------------------------ // check policy //------------------------------ var result = k2hr3.checkPolicy(policy_yrn, resource, action); if(!result.result){ r3logger.dlog('action(' + action + ') to resource(' + resource + ') is not allowed by policy(' + name + ') : message=' + apiutil.getSafeString(result.message)); resutil.errResponse(req, res, 403); // 403: Forbidden return; } r3logger.dlog('action(' + action + ') to resource(' + resource + ') is allowed by policy(' + name + ')'); res.status(204); // 204: No Content res.send(); }); // Mountpath : '/v1/policy/*' // DELETE '/v1/policy/name' : delete policy on version 1 // router.delete('/', function(req, res, next) // eslint-disable-line no-unused-vars { r3logger.dlog('CALL:', req.method, req.url); res.type('application/json; charset=utf-8'); if( !apiutil.isSafeEntity(req) || !apiutil.isSafeEntity(req.baseUrl) ) { r3logger.elog('DELETE request or url or query is wrong'); resutil.errResponse(req, res, 400); // 400: Bad Request return; } var result; //------------------------------ // check token //------------------------------ var token_result = r3token.checkToken(req, true, true); // scoped, user token if(!token_result.result){ r3logger.elog(token_result.message); var _status = token_result.status; delete token_result.status; resutil.errResponse(req, res, _status, token_result); return; } var token_info = token_result.token_info; var keys = r3keys(token_info.user, token_info.tenant); //------------------------------ // check policy name //------------------------------ var requestptn = new RegExp('^/v1/policy/(.*)'); // regex = /^\/v1\/policy\/(.*)/ var reqmatchs = decodeURI(req.baseUrl).match(requestptn); if(apiutil.isEmptyArray(reqmatchs) || reqmatchs.length < 2 || '' === apiutil.getSafeString(reqmatchs[1])){ result = { result: false, message: 'GET request url does not have policy name' }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } var name = reqmatchs[1]; name = name.toLowerCase(); // policy name is only name or full yrn path var nameptn = new RegExp('^' + keys.POLICY_TOP_KEY + ':(.*)'); // regex = /^yrn:yahoo:<service>::<tenant>:policy:(.*)/ var namematchs = name.match(nameptn); if(!apiutil.isEmptyArray(namematchs) && 2 <= namematchs.length){ name = namematchs[1]; } // check yrn full path(it is NG) nameptn = new RegExp('^' + keys.NO_TENANT_KEY); // regex = /^yrn:yahoo:/ if(name.match(nameptn)){ result = { result: false, message: 'DELETE request url has wrong yrn full path to policy' }; r3logger.elog(result.message); resutil.errResponse(req, res, 400, result); // 400: Bad Request return; } //------------------------------ // delete policy //------------------------------ result = k2hr3.removePolicy(token_info.user, token_info.tenant, name); if(!apiutil.isSafeEntity(result) || !apiutil.isSafeEntity(result.result) || false === result.result){ if(!apiutil.isSafeEntity(result)){ result = { result: false, message: 'Could not get response from removePolicy' }; }else{ if(!apiutil.isSafeEntity(result.result)){ result.result = false; } if(!apiutil.isSafeEntity(result.message)){ result.message = 'Could not get error message in response from removePolicy'; } } r3logger.elog(result.message); resutil.errResponse(req, res, 403); // 403: Forbidden(is this status OK?) return; } r3logger.dlog('succeed : ' + result.message); res.status(204); // 204: No Content res.send(); }); module.exports = 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 */