k2hr3-api 1.0.42 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/k2hr3-init.sh.templ +4 -4
- package/dist/.gitkeep +0 -0
- package/dist/src/app.js +262 -0
- package/{bin → dist/src/bin}/run.sh +1 -1
- package/dist/src/bin/watcher.js +113 -0
- package/dist/src/bin/www.js +217 -0
- package/dist/src/lib/basicipcheck.js +392 -0
- package/dist/src/lib/cacerts.js +106 -0
- package/dist/src/lib/dbglogging.js +190 -0
- package/dist/src/lib/dummyuserapi.js +719 -0
- package/dist/src/lib/ipwatch.js +354 -0
- package/dist/src/lib/k2hr3acrutil.js +532 -0
- package/dist/src/lib/k2hr3apiutil.js +1444 -0
- package/dist/src/lib/k2hr3cliutil.js +183 -0
- package/dist/src/lib/k2hr3config.js +832 -0
- package/dist/src/lib/k2hr3cryptutil.js +258 -0
- package/dist/src/lib/k2hr3dkc.js +12121 -0
- package/dist/src/lib/k2hr3extdata.js +198 -0
- package/dist/src/lib/k2hr3keys.js +207 -0
- package/dist/src/lib/k2hr3resutil.js +111 -0
- package/dist/src/lib/k2hr3template.js +6546 -0
- package/dist/src/lib/k2hr3tokens.js +2643 -0
- package/dist/src/lib/k2hr3userdata.js +296 -0
- package/dist/src/lib/k8soidc.js +1000 -0
- package/dist/src/lib/openstackapiv2.js +695 -0
- package/dist/src/lib/openstackapiv3.js +932 -0
- package/dist/src/lib/openstackep.js +667 -0
- package/{tests/auto_common.js → dist/src/lib/types.js} +4 -38
- package/dist/src/routes/acr.js +704 -0
- package/dist/src/routes/debugVerify.js +294 -0
- package/dist/src/routes/extdata.js +219 -0
- package/dist/src/routes/list.js +264 -0
- package/dist/src/routes/policy.js +840 -0
- package/dist/src/routes/resource.js +1489 -0
- package/dist/src/routes/role.js +2627 -0
- package/dist/src/routes/service.js +908 -0
- package/dist/src/routes/tenant.js +1141 -0
- package/dist/src/routes/userTokens.js +482 -0
- package/dist/src/routes/userdata.js +212 -0
- package/dist/src/routes/version.js +103 -0
- package/package.json +152 -121
- package/ChangeLog +0 -378
- package/app.js +0 -292
- package/bin/watcher +0 -122
- package/bin/www +0 -180
- package/eslint.config.mjs +0 -68
- package/lib/basicipcheck.js +0 -376
- package/lib/cacerts.js +0 -71
- package/lib/dbglogging.js +0 -151
- package/lib/dummyuserapi.js +0 -766
- package/lib/ipwatch.js +0 -379
- package/lib/k2hr3acrutil.js +0 -516
- package/lib/k2hr3apiutil.js +0 -1494
- package/lib/k2hr3cliutil.js +0 -191
- package/lib/k2hr3config.js +0 -826
- package/lib/k2hr3cryptutil.js +0 -254
- package/lib/k2hr3dkc.js +0 -12632
- package/lib/k2hr3extdata.js +0 -198
- package/lib/k2hr3keys.js +0 -234
- package/lib/k2hr3resutil.js +0 -100
- package/lib/k2hr3template.js +0 -6925
- package/lib/k2hr3tokens.js +0 -2799
- package/lib/k2hr3userdata.js +0 -312
- package/lib/k8soidc.js +0 -1012
- package/lib/openstackapiv2.js +0 -764
- package/lib/openstackapiv3.js +0 -1032
- package/lib/openstackep.js +0 -553
- package/routes/acr.js +0 -738
- package/routes/debugVerify.js +0 -263
- package/routes/extdata.js +0 -232
- package/routes/list.js +0 -270
- package/routes/policy.js +0 -869
- package/routes/resource.js +0 -1441
- package/routes/role.js +0 -2664
- package/routes/service.js +0 -894
- package/routes/tenant.js +0 -1095
- package/routes/userTokens.js +0 -511
- package/routes/userdata.js +0 -218
- package/routes/version.js +0 -108
- package/templ/Dockerfile.templ +0 -71
- package/tests/auto_acr.js +0 -1101
- package/tests/auto_acr_spec.js +0 -79
- package/tests/auto_all_spec.js +0 -142
- package/tests/auto_control_subprocess.sh +0 -243
- package/tests/auto_extdata.js +0 -220
- package/tests/auto_extdata_spec.js +0 -79
- package/tests/auto_init_config_json.sh +0 -275
- package/tests/auto_k2hdkc_server.ini +0 -109
- package/tests/auto_k2hdkc_slave.ini +0 -83
- package/tests/auto_list.js +0 -439
- package/tests/auto_list_spec.js +0 -79
- package/tests/auto_policy.js +0 -1579
- package/tests/auto_policy_spec.js +0 -79
- package/tests/auto_resource.js +0 -10956
- package/tests/auto_resource_spec.js +0 -79
- package/tests/auto_role.js +0 -6150
- package/tests/auto_role_spec.js +0 -79
- package/tests/auto_service.js +0 -770
- package/tests/auto_service_spec.js +0 -79
- package/tests/auto_subprocesses.js +0 -114
- package/tests/auto_template.sh +0 -126
- package/tests/auto_tenant.js +0 -1100
- package/tests/auto_tenant_spec.js +0 -79
- package/tests/auto_token_util.js +0 -219
- package/tests/auto_userdata.js +0 -292
- package/tests/auto_userdata_spec.js +0 -79
- package/tests/auto_usertokens.js +0 -565
- package/tests/auto_usertokens_spec.js +0 -79
- package/tests/auto_version.js +0 -127
- package/tests/auto_version_spec.js +0 -79
- package/tests/auto_watcher.js +0 -157
- package/tests/auto_watcher_spec.js +0 -79
- package/tests/k2hdkc_test.data +0 -986
- package/tests/k2hdkc_test_load.sh +0 -255
- package/tests/k2hr3template_test.js +0 -187
- package/tests/k2hr3template_test.sh +0 -339
- package/tests/k2hr3template_test_async.js +0 -216
- package/tests/k2hr3template_test_template.result +0 -7117
- package/tests/k2hr3template_test_template.txt +0 -3608
- package/tests/k2hr3template_test_vars.js +0 -194
- package/tests/manual_acr_delete.js +0 -143
- package/tests/manual_acr_get.js +0 -297
- package/tests/manual_acr_postput.js +0 -215
- package/tests/manual_allusertenant_get.js +0 -113
- package/tests/manual_extdata_get.js +0 -191
- package/tests/manual_k2hr3keys_get.js +0 -84
- package/tests/manual_list_gethead.js +0 -230
- package/tests/manual_policy_delete.js +0 -132
- package/tests/manual_policy_gethead.js +0 -275
- package/tests/manual_policy_postput.js +0 -297
- package/tests/manual_resource_delete.js +0 -433
- package/tests/manual_resource_gethead.js +0 -423
- package/tests/manual_resource_postput.js +0 -487
- package/tests/manual_role_delete.js +0 -404
- package/tests/manual_role_gethead.js +0 -547
- package/tests/manual_role_postput.js +0 -544
- package/tests/manual_service_delete.js +0 -153
- package/tests/manual_service_gethead.js +0 -178
- package/tests/manual_service_postput.js +0 -348
- package/tests/manual_tenant_delete.js +0 -186
- package/tests/manual_tenant_gethead.js +0 -268
- package/tests/manual_tenant_postput.js +0 -293
- package/tests/manual_test.sh +0 -352
- package/tests/manual_userdata_get.js +0 -173
- package/tests/manual_usertoken_gethead.js +0 -136
- package/tests/manual_usertoken_postput.js +0 -310
- package/tests/manual_version_get.js +0 -127
- package/tests/run_local_test_k2hdkc.sh +0 -174
- package/tests/test.sh +0 -333
|
@@ -0,0 +1,2627 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* K2HR3 REST API
|
|
4
|
+
*
|
|
5
|
+
* Copyright 2017 Yahoo Japan Corporation.
|
|
6
|
+
*
|
|
7
|
+
* K2HR3 is K2hdkc based Resource and Roles and policy Rules, gathers
|
|
8
|
+
* common management information for the cloud.
|
|
9
|
+
* K2HR3 can dynamically manage information as "who", "what", "operate".
|
|
10
|
+
* These are stored as roles, resources, policies in K2hdkc, and the
|
|
11
|
+
* client system can dynamically read and modify these information.
|
|
12
|
+
*
|
|
13
|
+
* For the full copyright and license information, please view
|
|
14
|
+
* the license file that was distributed with this source code.
|
|
15
|
+
*
|
|
16
|
+
* AUTHOR: Takeshi Nakatani
|
|
17
|
+
* CREATE: Wed Jun 8 2017
|
|
18
|
+
* REVISION:
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
const k2hr3apiutil_1 = __importDefault(require("../lib/k2hr3apiutil"));
|
|
26
|
+
const k2hr3resutil_1 = __importDefault(require("../lib/k2hr3resutil"));
|
|
27
|
+
const k2hr3tokens_1 = __importDefault(require("../lib/k2hr3tokens"));
|
|
28
|
+
const k2hr3userdata_1 = __importDefault(require("../lib/k2hr3userdata"));
|
|
29
|
+
const k2hr3dkc_1 = __importDefault(require("../lib/k2hr3dkc"));
|
|
30
|
+
const dbglogging_1 = __importDefault(require("../lib/dbglogging"));
|
|
31
|
+
const express_1 = __importDefault(require("express"));
|
|
32
|
+
const k2hr3config_1 = require("../lib/k2hr3config");
|
|
33
|
+
const k2hr3keys_1 = require("../lib/k2hr3keys");
|
|
34
|
+
const apiConf = new k2hr3config_1.r3ApiConfig();
|
|
35
|
+
const r3keys = k2hr3keys_1.getK2hr3Keys;
|
|
36
|
+
const router = express_1.default.Router();
|
|
37
|
+
//
|
|
38
|
+
// check typs
|
|
39
|
+
//
|
|
40
|
+
const rawIsValTypeQueryRoleHostBaseValue = (val) => {
|
|
41
|
+
if (!k2hr3apiutil_1.default.isPlainObject(val)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const _obj = val;
|
|
45
|
+
const _isStringOrNull = (key) => (null === _obj[key] || k2hr3apiutil_1.default.isString(_obj[key]));
|
|
46
|
+
const _isStringOrNullOrUndef = (key) => (undefined === _obj[key] || null === _obj[key] || k2hr3apiutil_1.default.isString(_obj[key]));
|
|
47
|
+
const _isStrNumOrNullOrUndef = (key) => (undefined === _obj[key] || null === _obj[key] || k2hr3apiutil_1.default.isString(_obj[key]) || k2hr3apiutil_1.default.isSafeNumber(_obj[key]));
|
|
48
|
+
return (_isStringOrNull('host') &&
|
|
49
|
+
_isStrNumOrNullOrUndef('port') &&
|
|
50
|
+
_isStringOrNullOrUndef('cuk') &&
|
|
51
|
+
_isStringOrNullOrUndef('extra') &&
|
|
52
|
+
_isStringOrNullOrUndef('tag') &&
|
|
53
|
+
_isStringOrNullOrUndef('inboundip') &&
|
|
54
|
+
_isStringOrNullOrUndef('outboundip'));
|
|
55
|
+
};
|
|
56
|
+
const rawIsValTypeQueryRoleHostBaseValueArray = (arr) => {
|
|
57
|
+
return (Array.isArray(arr) && arr.every((element) => rawIsValTypeQueryRoleHostBaseValue(element)));
|
|
58
|
+
};
|
|
59
|
+
//---------------------------------------------------------
|
|
60
|
+
// Configuration
|
|
61
|
+
// * Get role full path which is allowed to remove ip address
|
|
62
|
+
// * Get expiration for role tokens
|
|
63
|
+
//---------------------------------------------------------
|
|
64
|
+
let delhost_role_yrn = null;
|
|
65
|
+
let expire_rtoken = 0;
|
|
66
|
+
let expire_reg_rtoken = 0;
|
|
67
|
+
(() => {
|
|
68
|
+
const admincfgobj = apiConf.getK2hr3AdminConfig();
|
|
69
|
+
if (k2hr3apiutil_1.default.isPlainObject(admincfgobj) && k2hr3apiutil_1.default.isSafeString(admincfgobj.tenant) && k2hr3apiutil_1.default.isSafeString(admincfgobj.delhostrole)) {
|
|
70
|
+
const keys = r3keys(null, admincfgobj.tenant.trim());
|
|
71
|
+
delhost_role_yrn = keys.ROLE_TOP_KEY + ':' + admincfgobj.delhostrole.trim();
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
dbglogging_1.default.elog('Could not find tenant/role in configuration for deleting host by cuk.');
|
|
75
|
+
delhost_role_yrn = null;
|
|
76
|
+
}
|
|
77
|
+
expire_rtoken = apiConf.getExpireTimeRoleToken();
|
|
78
|
+
expire_reg_rtoken = apiConf.getExpireTimeRegRoleToken();
|
|
79
|
+
})();
|
|
80
|
+
//---------------------------------------------------------
|
|
81
|
+
// Router POST
|
|
82
|
+
//---------------------------------------------------------
|
|
83
|
+
//
|
|
84
|
+
// Mountpath : '/v1/role'
|
|
85
|
+
// POST '/v1/role{/<role{/...}>}' : post role on version 1
|
|
86
|
+
// HEADER : X-Auth-Token => User token or Role token
|
|
87
|
+
// response body : result => true/false
|
|
88
|
+
// message => messages
|
|
89
|
+
//
|
|
90
|
+
// This mount point is for creating(update) role or creating(update) host in role.
|
|
91
|
+
//
|
|
92
|
+
router.post('/', (req, res, next) => {
|
|
93
|
+
dbglogging_1.default.dlog('CALL:', req.method, req.url, req.baseUrl);
|
|
94
|
+
res.type('application/json; charset=utf-8');
|
|
95
|
+
if (!k2hr3apiutil_1.default.isPlainObject(req) ||
|
|
96
|
+
!k2hr3apiutil_1.default.isSafeString(req.baseUrl)) {
|
|
97
|
+
const result = {
|
|
98
|
+
result: false,
|
|
99
|
+
message: 'POST request or url or query is wrong'
|
|
100
|
+
};
|
|
101
|
+
dbglogging_1.default.elog(result.message);
|
|
102
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
// check api type
|
|
106
|
+
if ('/v1/role' === decodeURI(req.baseUrl)) {
|
|
107
|
+
//------------------------------
|
|
108
|
+
// create role type
|
|
109
|
+
//------------------------------
|
|
110
|
+
postRole(req, res, next);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// check host api
|
|
114
|
+
const keys = r3keys();
|
|
115
|
+
const requestptn = new RegExp(keys.MATCH_URI_GET_ROLE_DATA); // regex = /^\/v1\/role\/(.*)/
|
|
116
|
+
const reqmatchs = decodeURI(req.baseUrl).match(requestptn);
|
|
117
|
+
if (!k2hr3apiutil_1.default.isStringArray(reqmatchs) || !k2hr3apiutil_1.default.isNotEmptyArray(reqmatchs) || reqmatchs.length < 2 || '' === k2hr3apiutil_1.default.getSafeString(reqmatchs[1])) {
|
|
118
|
+
const result = {
|
|
119
|
+
result: false,
|
|
120
|
+
message: 'POST request url does not have role name'
|
|
121
|
+
};
|
|
122
|
+
dbglogging_1.default.elog(result.message);
|
|
123
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
// role name
|
|
127
|
+
const name = reqmatchs[1].toLowerCase();
|
|
128
|
+
//------------------------------
|
|
129
|
+
// create host type
|
|
130
|
+
//------------------------------
|
|
131
|
+
postRoleHost(name, req, res, next);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
//---------------------------------------------------------
|
|
135
|
+
// Router PUT
|
|
136
|
+
//---------------------------------------------------------
|
|
137
|
+
// Mountpath : '/v1/role'
|
|
138
|
+
// PUT '/v1/role{/<role{/...}>}': put role on version 1
|
|
139
|
+
// HEADER : X-Auth-Token => User token or Role token
|
|
140
|
+
// response body : result => true/false
|
|
141
|
+
// message => messages
|
|
142
|
+
//
|
|
143
|
+
// This mount point is for creating(update) role and creating(update) host in role.
|
|
144
|
+
//
|
|
145
|
+
router.put('/', (req, res, next) => {
|
|
146
|
+
dbglogging_1.default.dlog('CALL:', req.method, req.url, req.baseUrl);
|
|
147
|
+
res.type('application/json; charset=utf-8');
|
|
148
|
+
if (!k2hr3apiutil_1.default.isPlainObject(req) ||
|
|
149
|
+
!k2hr3apiutil_1.default.isSafeString(req.baseUrl)) {
|
|
150
|
+
const result = {
|
|
151
|
+
result: false,
|
|
152
|
+
message: 'PUT request or url or query is wrong'
|
|
153
|
+
};
|
|
154
|
+
dbglogging_1.default.elog(result.message);
|
|
155
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
// check api type
|
|
159
|
+
if ('/v1/role' === decodeURI(req.baseUrl)) {
|
|
160
|
+
//------------------------------
|
|
161
|
+
// create role type
|
|
162
|
+
//------------------------------
|
|
163
|
+
putRole(req, res, next);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
// check host api
|
|
167
|
+
const keys = r3keys();
|
|
168
|
+
const requestptn = new RegExp(keys.MATCH_URI_GET_ROLE_DATA); // regex = /^\/v1\/role\/(.*)/
|
|
169
|
+
const reqmatchs = decodeURI(req.baseUrl).match(requestptn);
|
|
170
|
+
if (!k2hr3apiutil_1.default.isStringArray(reqmatchs) || !k2hr3apiutil_1.default.isNotEmptyArray(reqmatchs) || reqmatchs.length < 2 || '' === k2hr3apiutil_1.default.getSafeString(reqmatchs[1])) {
|
|
171
|
+
const result = {
|
|
172
|
+
result: false,
|
|
173
|
+
message: 'POST request url does not have role name'
|
|
174
|
+
};
|
|
175
|
+
dbglogging_1.default.elog(result.message);
|
|
176
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
// role name
|
|
180
|
+
const name = reqmatchs[1].toLowerCase();
|
|
181
|
+
//------------------------------
|
|
182
|
+
// create host type
|
|
183
|
+
//------------------------------
|
|
184
|
+
putRoleHost(name, req, res, next);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
//
|
|
188
|
+
// Sub router function for POST CREATE ROLE
|
|
189
|
+
//
|
|
190
|
+
// Mountpath : '/v1/role'
|
|
191
|
+
// POST '/v1/role' : post role on version 1
|
|
192
|
+
// HEADER : X-Auth-Token => User token
|
|
193
|
+
// response body : result => true/false
|
|
194
|
+
// message => messages
|
|
195
|
+
// body :
|
|
196
|
+
// {
|
|
197
|
+
// "role": {
|
|
198
|
+
// "name": <role name> => key is "yrn:yahoo:<service>::<tenant>:role:<role>"
|
|
199
|
+
// <role> can include '/' for hierarchical path
|
|
200
|
+
// "policies": [<policy yrn full path>, ...] => key is "yrn:yahoo:<service>::<tenant>:role:<role>/policies"
|
|
201
|
+
// specify policy as "yrn:yahoo:<service>::<tenant>:policy:<policy>"
|
|
202
|
+
// if null or undefined is specified, not update this member in role when this role exists.
|
|
203
|
+
// if '' or zero array, this member in role is set empty array.
|
|
204
|
+
// "alias": [<role yrn full path>, ...] => key is "yrn:yahoo:<service>::<tenant>:role:<role>/@"
|
|
205
|
+
// specify another role as "yrn:yahoo:<service>::<tenant>:role:<role>"
|
|
206
|
+
// if null or undefined is specified, not update this member in role when this role exists.
|
|
207
|
+
// if '' or zero array, this member in role is set empty array.
|
|
208
|
+
// }
|
|
209
|
+
// }
|
|
210
|
+
//
|
|
211
|
+
// [NOTE]
|
|
212
|
+
// This API does not set host into roles as initial. You can add host to role
|
|
213
|
+
// by another API which is an API dedicated to adding host.
|
|
214
|
+
//
|
|
215
|
+
const postRole = (req, res, _) => {
|
|
216
|
+
if (!k2hr3apiutil_1.default.isPlainObject(req) ||
|
|
217
|
+
!k2hr3apiutil_1.default.isPlainObject(req.body) ||
|
|
218
|
+
!k2hr3apiutil_1.default.isPlainObject(req.body.role)) {
|
|
219
|
+
const result = {
|
|
220
|
+
result: false,
|
|
221
|
+
message: 'POST body does not have role data'
|
|
222
|
+
};
|
|
223
|
+
dbglogging_1.default.elog(result.message);
|
|
224
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
//------------------------------
|
|
228
|
+
// check token
|
|
229
|
+
//------------------------------
|
|
230
|
+
const token_result = k2hr3tokens_1.default.checkToken(req, true, true); // scoped, user token
|
|
231
|
+
if (!token_result.result) {
|
|
232
|
+
const result = {
|
|
233
|
+
result: token_result.result,
|
|
234
|
+
message: k2hr3apiutil_1.default.getSafeString(token_result.message),
|
|
235
|
+
};
|
|
236
|
+
dbglogging_1.default.elog(result.message);
|
|
237
|
+
k2hr3resutil_1.default.errResponse(req, res, token_result.status, result);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const token_info = token_result.token_info;
|
|
241
|
+
if (!k2hr3tokens_1.default.isResTypeCheckRoleToken(token_info)) {
|
|
242
|
+
const result = {
|
|
243
|
+
result: false,
|
|
244
|
+
message: 'specified wrong token or it is not scoped user token'
|
|
245
|
+
};
|
|
246
|
+
dbglogging_1.default.elog(result.message);
|
|
247
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
//------------------------------
|
|
251
|
+
// check arguments
|
|
252
|
+
//------------------------------
|
|
253
|
+
// name
|
|
254
|
+
if (!k2hr3apiutil_1.default.isSafeString(req.body.role.name)) {
|
|
255
|
+
const result = {
|
|
256
|
+
result: false,
|
|
257
|
+
message: 'role:name field is wrong : ' + JSON.stringify(req.body.role.name)
|
|
258
|
+
};
|
|
259
|
+
dbglogging_1.default.elog(result.message);
|
|
260
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const keys = r3keys(token_info.user, token_info.tenant);
|
|
264
|
+
let name = k2hr3apiutil_1.default.getSafeString(req.body.role.name).toLowerCase();
|
|
265
|
+
// role name is only name or full yrn path
|
|
266
|
+
let nameptn = new RegExp('^' + keys.ROLE_TOP_KEY + ':(.*)'); // regex = /^yrn:yahoo:<service>::<tenant>:role:(.*)/
|
|
267
|
+
const namematchs = name.match(nameptn);
|
|
268
|
+
if (k2hr3apiutil_1.default.isStringArray(namematchs) && k2hr3apiutil_1.default.isNotEmptyArray(namematchs) && 2 <= namematchs.length) {
|
|
269
|
+
name = namematchs[1];
|
|
270
|
+
}
|
|
271
|
+
// check name which is not full yrn
|
|
272
|
+
nameptn = new RegExp('^' + keys.NO_TENANT_KEY); // regex = /^yrn:yahoo:/
|
|
273
|
+
if (name.match(nameptn)) {
|
|
274
|
+
const result = {
|
|
275
|
+
result: false,
|
|
276
|
+
message: 'POST request query has wrong yrn full path to role'
|
|
277
|
+
};
|
|
278
|
+
dbglogging_1.default.elog(result.message);
|
|
279
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
// policies
|
|
283
|
+
const policiesptn = new RegExp('^' + keys.POLICY_TOP_KEY + ':(.*)'); // regex = /^yrn:yahoo:<service>::<tenant>:policy:(.*)/
|
|
284
|
+
const policiespram = k2hr3apiutil_1.default.getNormalizeParameter(req.body.role.policies, policiesptn, null);
|
|
285
|
+
if (false === policiespram.result) {
|
|
286
|
+
const result = {
|
|
287
|
+
result: false,
|
|
288
|
+
message: 'role:policies field is wrong : ' + JSON.stringify(req.body.role.policies)
|
|
289
|
+
};
|
|
290
|
+
dbglogging_1.default.elog(result.message);
|
|
291
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
const policies = policiespram.parameter;
|
|
295
|
+
// alias
|
|
296
|
+
const aliasptn = new RegExp('^' + keys.MATCH_ANY_TENANT_ROLE); // regex = /^yrn:yahoo:(.*)::(.*):role:(.*)/
|
|
297
|
+
const aliaspram = k2hr3apiutil_1.default.getNormalizeParameter(req.body.role.alias, aliasptn, null);
|
|
298
|
+
if (false === aliaspram.result) {
|
|
299
|
+
const result = {
|
|
300
|
+
result: false,
|
|
301
|
+
message: 'role:alias field is wrong : ' + JSON.stringify(req.body.role.alias)
|
|
302
|
+
};
|
|
303
|
+
dbglogging_1.default.elog(result.message);
|
|
304
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const aliases = aliaspram.parameter;
|
|
308
|
+
//------------------------------
|
|
309
|
+
// set all field to role
|
|
310
|
+
//------------------------------
|
|
311
|
+
const role_result = k2hr3dkc_1.default.setRoleAll(token_info.user, token_info.tenant, name, policies, aliases, null, false, null, false);
|
|
312
|
+
if (!k2hr3apiutil_1.default.isPlainObject(role_result) || !k2hr3apiutil_1.default.isBoolean(role_result.result) || false === role_result.result) {
|
|
313
|
+
if (!k2hr3apiutil_1.default.isPlainObject(role_result)) {
|
|
314
|
+
const result = {
|
|
315
|
+
result: false,
|
|
316
|
+
message: 'Could not get response from setRoleAll'
|
|
317
|
+
};
|
|
318
|
+
dbglogging_1.default.elog(result.message);
|
|
319
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
const result = {
|
|
323
|
+
result: k2hr3apiutil_1.default.isBoolean(role_result.result) ? role_result.result : false,
|
|
324
|
+
message: k2hr3apiutil_1.default.isString(role_result.message) ? role_result.message : 'Could not get error message in response from setRoleAll'
|
|
325
|
+
};
|
|
326
|
+
dbglogging_1.default.elog(result.message);
|
|
327
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
328
|
+
}
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
dbglogging_1.default.dlog('succeed : ' + k2hr3apiutil_1.default.getSafeString(role_result.message));
|
|
332
|
+
res.status(201); // 201: Created
|
|
333
|
+
res.send(JSON.stringify(role_result));
|
|
334
|
+
};
|
|
335
|
+
//
|
|
336
|
+
// Sub router function for PUT CREATE ROLE
|
|
337
|
+
//
|
|
338
|
+
// Mountpath : '/v1/role'
|
|
339
|
+
// PUT '/v1/role{/<role{/...}>}' : put role on version 1
|
|
340
|
+
// HEADER : X-Auth-Token => User token
|
|
341
|
+
// response body : result => true/false
|
|
342
|
+
// message => messages
|
|
343
|
+
// url argument
|
|
344
|
+
// "name": <role name> => key is "yrn:yahoo:<service>::<tenant>:role:<role>"
|
|
345
|
+
// <role> can include '/' for hierarchical path
|
|
346
|
+
// "policies": [<policy yrn full path>, ...] => key is "yrn:yahoo:<service>::<tenant>:role:<role>/policies"
|
|
347
|
+
// specify policy as "yrn:yahoo:<service>::<tenant>:policy:<policy>", it is formatted by JSON.
|
|
348
|
+
// if null or undefined is specified, not update this member in role when this role exists.
|
|
349
|
+
// if '' or zero array, this member in role is set empty array.
|
|
350
|
+
// "alias": [<role yrn full path>, ...] => key is "yrn:yahoo:<service>::<tenant>:role:<role>/@"
|
|
351
|
+
// specify another role as "yrn:yahoo:<service>::<tenant>:role:<role>", it is formatted by JSON.
|
|
352
|
+
// if null or undefined is specified, not update this member in role when this role exists.
|
|
353
|
+
// if '' or zero array, this member in role is set empty array.
|
|
354
|
+
//
|
|
355
|
+
// [NOTE]
|
|
356
|
+
// This API does not set host into roles as initial. You can add host to role
|
|
357
|
+
// by another API which is an API dedicated to adding host.
|
|
358
|
+
//
|
|
359
|
+
const putRole = (req, res, _) => {
|
|
360
|
+
dbglogging_1.default.dlog('CALL:', req.method, req.url);
|
|
361
|
+
res.type('application/json; charset=utf-8');
|
|
362
|
+
if (!k2hr3apiutil_1.default.isPlainObject(req) ||
|
|
363
|
+
!k2hr3apiutil_1.default.isPlainObject(req.query)) {
|
|
364
|
+
const result = {
|
|
365
|
+
result: false,
|
|
366
|
+
message: 'PUT argument does not have any data'
|
|
367
|
+
};
|
|
368
|
+
dbglogging_1.default.elog(result.message);
|
|
369
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
//------------------------------
|
|
373
|
+
// check token
|
|
374
|
+
//------------------------------
|
|
375
|
+
const token_result = k2hr3tokens_1.default.checkToken(req, true, true); // scoped, user token
|
|
376
|
+
if (!token_result.result) {
|
|
377
|
+
const result = {
|
|
378
|
+
result: token_result.result,
|
|
379
|
+
message: k2hr3apiutil_1.default.getSafeString(token_result.message),
|
|
380
|
+
};
|
|
381
|
+
dbglogging_1.default.elog(result.message);
|
|
382
|
+
k2hr3resutil_1.default.errResponse(req, res, token_result.status, result);
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
const token_info = token_result.token_info;
|
|
386
|
+
if (!k2hr3tokens_1.default.isResTypeCheckRoleToken(token_info)) {
|
|
387
|
+
const result = {
|
|
388
|
+
result: false,
|
|
389
|
+
message: 'specified wrong token or it is not scoped user token'
|
|
390
|
+
};
|
|
391
|
+
dbglogging_1.default.elog(result.message);
|
|
392
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
//------------------------------
|
|
396
|
+
// check arguments
|
|
397
|
+
//------------------------------
|
|
398
|
+
// name
|
|
399
|
+
if (!k2hr3apiutil_1.default.isSafeString(req.query.name)) {
|
|
400
|
+
const result = {
|
|
401
|
+
result: false,
|
|
402
|
+
message: 'role:name field is wrong : ' + JSON.stringify(req.query.name)
|
|
403
|
+
};
|
|
404
|
+
dbglogging_1.default.elog(result.message);
|
|
405
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
const keys = r3keys(token_info.user, token_info.tenant);
|
|
409
|
+
let name = k2hr3apiutil_1.default.getSafeString(req.query.name).toLowerCase();
|
|
410
|
+
// role name is only name or full yrn path
|
|
411
|
+
let nameptn = new RegExp('^' + keys.ROLE_TOP_KEY + ':(.*)'); // regex = /^yrn:yahoo:<service>::<tenant>:role:(.*)/
|
|
412
|
+
const namematchs = name.match(nameptn);
|
|
413
|
+
if (k2hr3apiutil_1.default.isStringArray(namematchs) && k2hr3apiutil_1.default.isNotEmptyArray(namematchs) && 2 <= namematchs.length) {
|
|
414
|
+
name = namematchs[1];
|
|
415
|
+
}
|
|
416
|
+
// check name which is not full yrn
|
|
417
|
+
nameptn = new RegExp('^' + keys.NO_TENANT_KEY); // regex = /^yrn:yahoo:/
|
|
418
|
+
if (name.match(nameptn)) {
|
|
419
|
+
const result = {
|
|
420
|
+
result: false,
|
|
421
|
+
message: 'PUT request query has wrong yrn full path to role'
|
|
422
|
+
};
|
|
423
|
+
dbglogging_1.default.elog(result.message);
|
|
424
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
// policies
|
|
428
|
+
let policies = null;
|
|
429
|
+
if (!k2hr3apiutil_1.default.isString(req.query.policies)) {
|
|
430
|
+
policies = null;
|
|
431
|
+
}
|
|
432
|
+
else if ('' === req.query.policies) {
|
|
433
|
+
policies = '';
|
|
434
|
+
}
|
|
435
|
+
else if (k2hr3apiutil_1.default.isSafeString(req.query.policies)) {
|
|
436
|
+
// policies is encoded by JSON, this value is array.
|
|
437
|
+
//
|
|
438
|
+
let tmp_pol = k2hr3apiutil_1.default.getSafeString(req.query.policies);
|
|
439
|
+
if (k2hr3apiutil_1.default.checkSimpleJSON(tmp_pol)) {
|
|
440
|
+
tmp_pol = JSON.parse(tmp_pol);
|
|
441
|
+
}
|
|
442
|
+
const policiesptn = new RegExp('^' + keys.POLICY_TOP_KEY + ':(.*)'); // regex = /^yrn:yahoo:<service>::<tenant>:policy:(.*)/
|
|
443
|
+
const policiespram = k2hr3apiutil_1.default.getNormalizeParameter(tmp_pol, policiesptn, null);
|
|
444
|
+
if (false === policiespram.result) {
|
|
445
|
+
const result = {
|
|
446
|
+
result: false,
|
|
447
|
+
message: 'role:policies field is wrong : ' + req.query.policies
|
|
448
|
+
};
|
|
449
|
+
dbglogging_1.default.elog(result.message);
|
|
450
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
policies = policiespram.parameter ?? null;
|
|
454
|
+
}
|
|
455
|
+
// alias
|
|
456
|
+
let aliases = null;
|
|
457
|
+
if (!k2hr3apiutil_1.default.isString(req.query.alias)) {
|
|
458
|
+
aliases = null;
|
|
459
|
+
}
|
|
460
|
+
else if ('' === req.query.alias) {
|
|
461
|
+
aliases = '';
|
|
462
|
+
}
|
|
463
|
+
else if (k2hr3apiutil_1.default.isSafeString(req.query.alias)) {
|
|
464
|
+
// alias is encoded by JSON, this value is array.
|
|
465
|
+
//
|
|
466
|
+
let tmp_aliases = k2hr3apiutil_1.default.getSafeString(req.query.alias);
|
|
467
|
+
if (k2hr3apiutil_1.default.checkSimpleJSON(tmp_aliases)) {
|
|
468
|
+
tmp_aliases = JSON.parse(tmp_aliases);
|
|
469
|
+
}
|
|
470
|
+
const aliasptn = new RegExp('^' + keys.MATCH_ANY_TENANT_ROLE); // regex = /^yrn:yahoo:(.*)::(.*):role:(.*)/
|
|
471
|
+
const aliaspram = k2hr3apiutil_1.default.getNormalizeParameter(tmp_aliases, aliasptn, null);
|
|
472
|
+
if (false === aliaspram.result) {
|
|
473
|
+
const result = {
|
|
474
|
+
result: false,
|
|
475
|
+
message: 'role:alias field is wrong : ' + req.query.alias
|
|
476
|
+
};
|
|
477
|
+
dbglogging_1.default.elog(result.message);
|
|
478
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
aliases = aliaspram.parameter ?? null;
|
|
482
|
+
}
|
|
483
|
+
//------------------------------
|
|
484
|
+
// set all field to role
|
|
485
|
+
//------------------------------
|
|
486
|
+
const role_result = k2hr3dkc_1.default.setRoleAll(token_info.user, token_info.tenant, name, policies, aliases, null, false, null, false);
|
|
487
|
+
if (!k2hr3apiutil_1.default.isPlainObject(role_result) || !k2hr3apiutil_1.default.isBoolean(role_result.result) || false === role_result.result) {
|
|
488
|
+
if (!k2hr3apiutil_1.default.isPlainObject(role_result)) {
|
|
489
|
+
const result = {
|
|
490
|
+
result: false,
|
|
491
|
+
message: 'Could not get response from setRoleAll'
|
|
492
|
+
};
|
|
493
|
+
dbglogging_1.default.elog(result.message);
|
|
494
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
495
|
+
}
|
|
496
|
+
else {
|
|
497
|
+
const result = {
|
|
498
|
+
result: k2hr3apiutil_1.default.isBoolean(role_result.result) ? role_result.result : false,
|
|
499
|
+
message: k2hr3apiutil_1.default.isString(role_result.message) ? role_result.message : 'Could not get error message in response from setRoleAll'
|
|
500
|
+
};
|
|
501
|
+
dbglogging_1.default.elog(result.message);
|
|
502
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
503
|
+
}
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
dbglogging_1.default.dlog('succeed : ' + k2hr3apiutil_1.default.getSafeString(role_result.message));
|
|
507
|
+
res.status(201); // 201: Created
|
|
508
|
+
res.send(JSON.stringify(role_result));
|
|
509
|
+
};
|
|
510
|
+
//
|
|
511
|
+
// Sub router function for POST CREATE HOST
|
|
512
|
+
//
|
|
513
|
+
// Mountpath : '/v1/role'
|
|
514
|
+
// POST '/v1/role/<role{/...}>' : post role on version 1
|
|
515
|
+
// HEADER : X-Auth-Token => User token or Role token
|
|
516
|
+
// response body : result => true/false
|
|
517
|
+
// message => messages
|
|
518
|
+
//
|
|
519
|
+
// [UserToken] body :
|
|
520
|
+
// {
|
|
521
|
+
// "host": { => specified single host
|
|
522
|
+
// "host": <hostname / ip address> => key is for "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/{name, ip}/<hostname port cuk>"
|
|
523
|
+
// "port": <port number> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/name/<hostname port cuk>"
|
|
524
|
+
// this value is number string(0-), allowed null and '' for this value.
|
|
525
|
+
// if this value is '0', it means any port.
|
|
526
|
+
// "cuk": <container unique key> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/name/<hostname port cuk>"
|
|
527
|
+
// this value is string. if this value is undefined/null/empty string, it means any.
|
|
528
|
+
// "extra": <extra string data> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
529
|
+
// extra is any string including Control code, allowed null and '' for this value.
|
|
530
|
+
// "tag": <string data> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
531
|
+
// tag is any string including Control code, allowed null and '' for this value.
|
|
532
|
+
// "inboundip": <ip address> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
533
|
+
// inboundip is set ip address string. if you do not use proxy/gateway/bridge/etc, you do not need to set this key.
|
|
534
|
+
// "outboundip": <ip address> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
535
|
+
// outboundip is set ip address string. if you do not use proxy/gateway/bridge/etc, you do not need to set this key.
|
|
536
|
+
// }
|
|
537
|
+
// "clear_hostname": <true/false>
|
|
538
|
+
// "clear_ips": <true/false>
|
|
539
|
+
// }
|
|
540
|
+
// or
|
|
541
|
+
// {
|
|
542
|
+
// "host": [ => specified host as Array(only POST request has this type)
|
|
543
|
+
// {
|
|
544
|
+
// "host": <hostname / ip address>
|
|
545
|
+
// "port": <port number>
|
|
546
|
+
// "cuk": <container unique key>
|
|
547
|
+
// "extra": <extra string data>
|
|
548
|
+
// "tag": <string data>
|
|
549
|
+
// "inboundip": <ip address>
|
|
550
|
+
// "outboundip": <ip address>
|
|
551
|
+
// }
|
|
552
|
+
// ...
|
|
553
|
+
// ]
|
|
554
|
+
// "clear_hostname": <true/false>
|
|
555
|
+
// "clear_ips": <true/false>
|
|
556
|
+
// }
|
|
557
|
+
//
|
|
558
|
+
// [RoleToken] body :
|
|
559
|
+
// {
|
|
560
|
+
// "host": {
|
|
561
|
+
// "port": <port number> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/ip/<ip port cuk>"
|
|
562
|
+
// this value is number string(0-), allowed null and '' for this value.
|
|
563
|
+
// if this value is '0', it means any port.
|
|
564
|
+
// "cuk": <container unique key> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/name/<hostname port cuk>"
|
|
565
|
+
// this value is string. if this value is undefined/null/empty string, it means any.
|
|
566
|
+
// "extra": <extra string data> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
567
|
+
// extra is any string including Control code, allowed null and '' for this value.
|
|
568
|
+
// "tag": <string data> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
569
|
+
// tag is any string including Control code, allowed null and '' for this value.
|
|
570
|
+
// "inboundip": <ip address> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
571
|
+
// inboundip is set ip address string. if you do not use proxy/gateway/bridge/etc, you do not need to set this key.
|
|
572
|
+
// "outboundip": <ip address> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
573
|
+
// outboundip is set ip address string. if you do not use proxy/gateway/bridge/etc, you do not need to set this key.
|
|
574
|
+
// }
|
|
575
|
+
// }
|
|
576
|
+
//
|
|
577
|
+
// [NOTE]
|
|
578
|
+
// This API only set(add/create) host into role. The host is specified hostname.
|
|
579
|
+
// The hostname is any string as like hostname.(ex. "x.yahoo.co.jp", "x[0-9].yahoo.co.jp", "*.yahoo.co.jp", "*", "(.*)", etc)
|
|
580
|
+
// If port number is 0, it means any port.
|
|
581
|
+
// If cuk is undefined/null/empty string, it means any.
|
|
582
|
+
// Extra data can include control-code(CR, etc).
|
|
583
|
+
//
|
|
584
|
+
const postRoleHost = (role, req, res, _) => {
|
|
585
|
+
if (!k2hr3apiutil_1.default.isPlainObject(req) ||
|
|
586
|
+
!k2hr3apiutil_1.default.isPlainObject(req.body) ||
|
|
587
|
+
(!k2hr3apiutil_1.default.isArray(req.body.host) && !k2hr3apiutil_1.default.isPlainObject(req.body.host))) {
|
|
588
|
+
const result = {
|
|
589
|
+
result: false,
|
|
590
|
+
message: 'POST body does not have host data'
|
|
591
|
+
};
|
|
592
|
+
dbglogging_1.default.elog(result.message);
|
|
593
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
//------------------------------
|
|
597
|
+
// check token
|
|
598
|
+
//------------------------------
|
|
599
|
+
const token_result = k2hr3tokens_1.default.checkToken(req, true); // scoped, both token
|
|
600
|
+
if (!token_result.result) {
|
|
601
|
+
const result = {
|
|
602
|
+
result: token_result.result,
|
|
603
|
+
message: k2hr3apiutil_1.default.getSafeString(token_result.message),
|
|
604
|
+
};
|
|
605
|
+
dbglogging_1.default.elog(result.message);
|
|
606
|
+
k2hr3resutil_1.default.errResponse(req, res, token_result.status, result);
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
const token_info = token_result.token_info;
|
|
610
|
+
if (!k2hr3tokens_1.default.isResTypeCheckRoleToken(token_info)) {
|
|
611
|
+
const result = {
|
|
612
|
+
result: false,
|
|
613
|
+
message: 'specified wrong token or it is not scoped user token'
|
|
614
|
+
};
|
|
615
|
+
dbglogging_1.default.elog(result.message);
|
|
616
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
const is_host_req = (!k2hr3apiutil_1.default.isArray(req.body.host) && (!k2hr3apiutil_1.default.isPlainObject(req.body.host) || !k2hr3apiutil_1.default.isSafeString(req.body.host.host)));
|
|
620
|
+
const keys = r3keys(token_info.user, token_info.tenant);
|
|
621
|
+
//------------------------------
|
|
622
|
+
// check arguments
|
|
623
|
+
//------------------------------
|
|
624
|
+
// role name check
|
|
625
|
+
let name = k2hr3apiutil_1.default.getSafeString(role).toLowerCase();
|
|
626
|
+
let nameptn = new RegExp('^' + keys.ROLE_TOP_KEY + ':(.*)'); // regex = /^yrn:yahoo:<service>::<tenant>:role:(.*)/
|
|
627
|
+
const namematchs = name.match(nameptn);
|
|
628
|
+
if (k2hr3apiutil_1.default.isStringArray(namematchs) && k2hr3apiutil_1.default.isNotEmptyArray(namematchs) && 2 <= namematchs.length) {
|
|
629
|
+
// name is full yrn, then reset only name.
|
|
630
|
+
name = namematchs[1];
|
|
631
|
+
}
|
|
632
|
+
else {
|
|
633
|
+
// role name is not full yrn, then check other yrn path
|
|
634
|
+
nameptn = new RegExp('^' + keys.NO_TENANT_KEY); // regex = /^yrn:yahoo:/
|
|
635
|
+
if (name.match(nameptn)) {
|
|
636
|
+
const result = {
|
|
637
|
+
result: false,
|
|
638
|
+
message: 'POST request url has wrong yrn full path to role'
|
|
639
|
+
};
|
|
640
|
+
dbglogging_1.default.elog(result.message);
|
|
641
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
//------------------------------
|
|
646
|
+
// build parameters
|
|
647
|
+
//------------------------------
|
|
648
|
+
let role_result;
|
|
649
|
+
if (!is_host_req) {
|
|
650
|
+
//
|
|
651
|
+
// request from user token
|
|
652
|
+
//
|
|
653
|
+
let hostArray = [];
|
|
654
|
+
if (rawIsValTypeQueryRoleHostBaseValueArray(req.body.host)) {
|
|
655
|
+
hostArray = req.body.host;
|
|
656
|
+
}
|
|
657
|
+
else if (rawIsValTypeQueryRoleHostBaseValue(req.body.host)) {
|
|
658
|
+
hostArray = [req.body.host];
|
|
659
|
+
}
|
|
660
|
+
// check array and make ip array
|
|
661
|
+
let hostnameArray = [];
|
|
662
|
+
let ipArray = [];
|
|
663
|
+
for (let cnt = 0; cnt < hostArray.length; ++cnt) {
|
|
664
|
+
if (!k2hr3apiutil_1.default.isSafeString(hostArray[cnt].host)) {
|
|
665
|
+
const result = {
|
|
666
|
+
result: false,
|
|
667
|
+
message: 'host is not specified.'
|
|
668
|
+
};
|
|
669
|
+
dbglogging_1.default.elog(result.message);
|
|
670
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
// hostname or ip address
|
|
674
|
+
const tmp_host = k2hr3apiutil_1.default.getSafeString(hostArray[cnt].host);
|
|
675
|
+
let tg_host = null;
|
|
676
|
+
let tg_ip = null;
|
|
677
|
+
if (k2hr3apiutil_1.default.isIpAddressString(tmp_host)) {
|
|
678
|
+
tg_ip = tmp_host.toLowerCase();
|
|
679
|
+
tg_host = null;
|
|
680
|
+
}
|
|
681
|
+
else if (k2hr3apiutil_1.default.isSafeString(tmp_host)) {
|
|
682
|
+
tg_host = tmp_host.toLowerCase();
|
|
683
|
+
tg_ip = null;
|
|
684
|
+
}
|
|
685
|
+
// port
|
|
686
|
+
let port = 0;
|
|
687
|
+
if (k2hr3apiutil_1.default.isSafeNumeric(hostArray[cnt].port)) {
|
|
688
|
+
const port_tmp = k2hr3apiutil_1.default.cvtToNumber(hostArray[cnt].port);
|
|
689
|
+
if (!k2hr3apiutil_1.default.isSafeNumber(port_tmp)) {
|
|
690
|
+
const result = {
|
|
691
|
+
result: false,
|
|
692
|
+
message: 'POST request has port which is not number: ' + JSON.stringify(hostArray[cnt].port)
|
|
693
|
+
};
|
|
694
|
+
dbglogging_1.default.elog(result.message);
|
|
695
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
port = port_tmp;
|
|
699
|
+
}
|
|
700
|
+
// cuk
|
|
701
|
+
const tmp_cuk = k2hr3apiutil_1.default.getSafeString(hostArray[cnt].cuk).trim();
|
|
702
|
+
let cuk = null;
|
|
703
|
+
if (k2hr3apiutil_1.default.isSafeString(tmp_cuk)) {
|
|
704
|
+
cuk = tmp_cuk;
|
|
705
|
+
}
|
|
706
|
+
// extra
|
|
707
|
+
const tmp_extra = k2hr3apiutil_1.default.getSafeString(hostArray[cnt].extra);
|
|
708
|
+
let extra = null;
|
|
709
|
+
if (k2hr3apiutil_1.default.isSafeString(tmp_extra)) {
|
|
710
|
+
extra = tmp_extra;
|
|
711
|
+
}
|
|
712
|
+
// tag
|
|
713
|
+
const tmp_tag = k2hr3apiutil_1.default.getSafeString(hostArray[cnt].tag);
|
|
714
|
+
let tag = null;
|
|
715
|
+
if (k2hr3apiutil_1.default.isSafeString(tmp_tag)) {
|
|
716
|
+
tag = tmp_tag;
|
|
717
|
+
}
|
|
718
|
+
// set base host information
|
|
719
|
+
const host_info = {
|
|
720
|
+
hostname: tg_host,
|
|
721
|
+
ip: tg_ip,
|
|
722
|
+
port: port,
|
|
723
|
+
cuk: cuk,
|
|
724
|
+
extra: extra,
|
|
725
|
+
tag: tag,
|
|
726
|
+
inboundip: null,
|
|
727
|
+
outboundip: null
|
|
728
|
+
};
|
|
729
|
+
// set optional keys
|
|
730
|
+
if (k2hr3apiutil_1.default.isSafeString(hostArray[cnt].inboundip)) {
|
|
731
|
+
if (!k2hr3apiutil_1.default.isIpAddressString(hostArray[cnt].inboundip)) {
|
|
732
|
+
const result = {
|
|
733
|
+
result: false,
|
|
734
|
+
message: 'POST request has inbound ip address which is not ignore ip address string: ' + JSON.stringify(hostArray[cnt].inboundip)
|
|
735
|
+
};
|
|
736
|
+
dbglogging_1.default.elog(result.message);
|
|
737
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
host_info.inboundip = k2hr3apiutil_1.default.getSafeString(hostArray[cnt].inboundip);
|
|
741
|
+
}
|
|
742
|
+
if (k2hr3apiutil_1.default.isSafeString(hostArray[cnt].outboundip)) {
|
|
743
|
+
if (!k2hr3apiutil_1.default.isIpAddressString(hostArray[cnt].outboundip)) {
|
|
744
|
+
const result = {
|
|
745
|
+
result: false,
|
|
746
|
+
message: 'POST request has outbound ip address which is not ignore ip address string: ' + JSON.stringify(hostArray[cnt].outboundip)
|
|
747
|
+
};
|
|
748
|
+
dbglogging_1.default.elog(result.message);
|
|
749
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
host_info.outboundip = k2hr3apiutil_1.default.getSafeString(hostArray[cnt].outboundip);
|
|
753
|
+
}
|
|
754
|
+
// push array
|
|
755
|
+
if (null !== tg_host) {
|
|
756
|
+
hostnameArray.push(host_info);
|
|
757
|
+
}
|
|
758
|
+
if (null !== tg_ip) {
|
|
759
|
+
ipArray.push(host_info);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
if (!k2hr3apiutil_1.default.isNotEmptyArray(hostnameArray)) {
|
|
763
|
+
hostnameArray = null;
|
|
764
|
+
}
|
|
765
|
+
if (!k2hr3apiutil_1.default.isNotEmptyArray(ipArray)) {
|
|
766
|
+
ipArray = null;
|
|
767
|
+
}
|
|
768
|
+
// flags
|
|
769
|
+
let clear_hostname = false;
|
|
770
|
+
let clear_ips = false;
|
|
771
|
+
if (k2hr3apiutil_1.default.isBoolean(req.body.clear_hostname)) {
|
|
772
|
+
clear_hostname = req.body.clear_hostname;
|
|
773
|
+
}
|
|
774
|
+
if (k2hr3apiutil_1.default.isBoolean(req.body.clear_ips)) {
|
|
775
|
+
clear_ips = req.body.clear_ips;
|
|
776
|
+
}
|
|
777
|
+
//
|
|
778
|
+
// Add hostnames and ips ---> Need User Token
|
|
779
|
+
//
|
|
780
|
+
role_result = k2hr3dkc_1.default.updateRoleHosts(token_info.user, token_info.tenant, name, hostnameArray, clear_hostname, ipArray, clear_ips);
|
|
781
|
+
}
|
|
782
|
+
else {
|
|
783
|
+
//
|
|
784
|
+
// request from host(token)
|
|
785
|
+
//
|
|
786
|
+
// get ip address
|
|
787
|
+
const ip = k2hr3apiutil_1.default.getClientIpAddress(req);
|
|
788
|
+
if (!k2hr3apiutil_1.default.isSafeString(ip)) {
|
|
789
|
+
const result = {
|
|
790
|
+
result: false,
|
|
791
|
+
message: 'Could not get ip address from request.'
|
|
792
|
+
};
|
|
793
|
+
dbglogging_1.default.elog(result.message);
|
|
794
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
// port
|
|
798
|
+
let port = 0;
|
|
799
|
+
if (k2hr3apiutil_1.default.isPlainObject(req.body.host) && k2hr3apiutil_1.default.isSafeNumeric(req.body.host.port)) {
|
|
800
|
+
const port_tmp = k2hr3apiutil_1.default.cvtToNumber(req.body.host.port);
|
|
801
|
+
if (!k2hr3apiutil_1.default.isSafeNumber(port_tmp)) {
|
|
802
|
+
const result = {
|
|
803
|
+
result: false,
|
|
804
|
+
message: 'POST request has port which is not number: ' + JSON.stringify(req.body.host.port)
|
|
805
|
+
};
|
|
806
|
+
dbglogging_1.default.elog(result.message);
|
|
807
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
port = port_tmp;
|
|
811
|
+
}
|
|
812
|
+
// cuk
|
|
813
|
+
let cuk = null;
|
|
814
|
+
if (k2hr3apiutil_1.default.isPlainObject(req.body.host) && k2hr3apiutil_1.default.isSafeString(req.body.host.cuk) && k2hr3apiutil_1.default.isSafeString(req.body.host.cuk.trim())) {
|
|
815
|
+
cuk = k2hr3apiutil_1.default.getSafeString(req.body.host.cuk).trim();
|
|
816
|
+
}
|
|
817
|
+
// extra
|
|
818
|
+
let extra = null;
|
|
819
|
+
if (k2hr3apiutil_1.default.isPlainObject(req.body.host) && k2hr3apiutil_1.default.isSafeString(req.body.host.extra)) {
|
|
820
|
+
const extra_tmp = k2hr3apiutil_1.default.getSafeString(req.body.host.extra);
|
|
821
|
+
if (k2hr3apiutil_1.default.checkSimpleJSON(extra_tmp)) {
|
|
822
|
+
const extra_parsed_tmp = JSON.parse(extra_tmp);
|
|
823
|
+
if (!k2hr3apiutil_1.default.isSafeString(extra_parsed_tmp)) {
|
|
824
|
+
const result = {
|
|
825
|
+
result: false,
|
|
826
|
+
message: 'POST request has extra which is not string: ' + JSON.stringify(req.body.host.extra)
|
|
827
|
+
};
|
|
828
|
+
dbglogging_1.default.elog(result.message);
|
|
829
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
extra = extra_parsed_tmp;
|
|
833
|
+
}
|
|
834
|
+
else {
|
|
835
|
+
extra = extra_tmp;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
// tag
|
|
839
|
+
let tag = null;
|
|
840
|
+
if (k2hr3apiutil_1.default.isPlainObject(req.body.host) && k2hr3apiutil_1.default.isSafeString(req.body.host.tag)) {
|
|
841
|
+
const tag_tmp = k2hr3apiutil_1.default.getSafeString(req.body.host.tag);
|
|
842
|
+
if (k2hr3apiutil_1.default.checkSimpleJSON(tag_tmp)) {
|
|
843
|
+
const tag_parsed_tmp = JSON.parse(tag_tmp);
|
|
844
|
+
if (!k2hr3apiutil_1.default.isSafeString(tag_parsed_tmp)) {
|
|
845
|
+
const result = {
|
|
846
|
+
result: false,
|
|
847
|
+
message: 'POST request has tag which is not string: ' + JSON.stringify(req.body.host.tag)
|
|
848
|
+
};
|
|
849
|
+
dbglogging_1.default.elog(result.message);
|
|
850
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
tag = tag_parsed_tmp;
|
|
854
|
+
}
|
|
855
|
+
else {
|
|
856
|
+
tag = tag_tmp;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
// inboundip(optional)
|
|
860
|
+
let inboundip = null;
|
|
861
|
+
if (k2hr3apiutil_1.default.isPlainObject(req.body.host) && k2hr3apiutil_1.default.isSafeString(req.body.host.inboundip)) {
|
|
862
|
+
if (!k2hr3apiutil_1.default.isIpAddressString(req.body.host.inboundip)) {
|
|
863
|
+
const result = {
|
|
864
|
+
result: false,
|
|
865
|
+
message: 'POST request has inbound ip address which is not ignore ip address string: ' + JSON.stringify(req.body.host.inboundip)
|
|
866
|
+
};
|
|
867
|
+
dbglogging_1.default.elog(result.message);
|
|
868
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
inboundip = k2hr3apiutil_1.default.getSafeString(req.body.host.inboundip);
|
|
872
|
+
}
|
|
873
|
+
// outboundip(optional)
|
|
874
|
+
let outboundip = null;
|
|
875
|
+
if (k2hr3apiutil_1.default.isPlainObject(req.body.host) && k2hr3apiutil_1.default.isSafeString(req.body.host.outboundip)) {
|
|
876
|
+
if (!k2hr3apiutil_1.default.isIpAddressString(req.body.host.outboundip)) {
|
|
877
|
+
const result = {
|
|
878
|
+
result: false,
|
|
879
|
+
message: 'POST request has outbound ip address which is not ignore ip address string: ' + JSON.stringify(req.body.host.outboundip)
|
|
880
|
+
};
|
|
881
|
+
dbglogging_1.default.elog(result.message);
|
|
882
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
outboundip = k2hr3apiutil_1.default.getSafeString(req.body.host.outboundip);
|
|
886
|
+
}
|
|
887
|
+
//
|
|
888
|
+
// Add ip address ---> Role Token or User Token
|
|
889
|
+
//
|
|
890
|
+
role_result = k2hr3dkc_1.default.addHost(token_info.tenant, name, null, ip, port, cuk, extra, tag, inboundip, outboundip);
|
|
891
|
+
}
|
|
892
|
+
//------------------------------
|
|
893
|
+
// check result
|
|
894
|
+
//------------------------------
|
|
895
|
+
if (!k2hr3apiutil_1.default.isPlainObject(role_result) || !k2hr3apiutil_1.default.isBoolean(role_result.result) || false === role_result.result) {
|
|
896
|
+
const mode_type = (is_host_req ? 'addHost' : 'updateRoleHosts');
|
|
897
|
+
if (!k2hr3apiutil_1.default.isPlainObject(role_result)) {
|
|
898
|
+
const result = {
|
|
899
|
+
result: false,
|
|
900
|
+
message: ('Could not get response from ' + mode_type)
|
|
901
|
+
};
|
|
902
|
+
dbglogging_1.default.elog(result.message);
|
|
903
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
904
|
+
}
|
|
905
|
+
else {
|
|
906
|
+
const result = {
|
|
907
|
+
result: false,
|
|
908
|
+
message: k2hr3apiutil_1.default.isString(role_result.message) ? role_result.message : ('Could not get error message in response from ' + mode_type)
|
|
909
|
+
};
|
|
910
|
+
dbglogging_1.default.elog(result.message);
|
|
911
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
912
|
+
}
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
dbglogging_1.default.dlog('succeed : ' + k2hr3apiutil_1.default.getSafeString(role_result.message));
|
|
916
|
+
res.status(201); // 201: Created
|
|
917
|
+
res.send(JSON.stringify(role_result));
|
|
918
|
+
};
|
|
919
|
+
//
|
|
920
|
+
// Sub router function for PUT CREATE HOST
|
|
921
|
+
//
|
|
922
|
+
// Mountpath : '/v1/role'
|
|
923
|
+
// PUT '/v1/role/<role{/...}>' : put role on version 1
|
|
924
|
+
// HEADER : X-Auth-Token => User token or Role token
|
|
925
|
+
// response body : result => true/false
|
|
926
|
+
// message => messages
|
|
927
|
+
//
|
|
928
|
+
// [UserToken] url argument
|
|
929
|
+
// "host": <hostname or ip address> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/{name, ip}/<hostname port cuk>"
|
|
930
|
+
// "port": <port number> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/name/<hostname port cuk>"
|
|
931
|
+
// this value is number string(0-), allowed null and '' for this value.
|
|
932
|
+
// if this value is '0', it means any port.
|
|
933
|
+
// "cuk": <container unique key> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/name/<hostname port cuk>"
|
|
934
|
+
// this value is string. if this value is undefined/null/empty string, it means any.
|
|
935
|
+
// "extra": <extra string data> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
936
|
+
// This value must be encoded by JSON.
|
|
937
|
+
// extra is any string including Control code, allowed null and '' for this value.
|
|
938
|
+
// "tag": <string data> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
939
|
+
// This value must be encoded by JSON.
|
|
940
|
+
// tag is any string including Control code, allowed null and '' for this value.
|
|
941
|
+
// "inboundip": <ip address> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
942
|
+
// inboundip is set ip address string. if you do not use proxy/gateway/bridge/etc, you do not need to set this key.
|
|
943
|
+
// "outboundip": <ip address> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
944
|
+
// outboundip is set ip address string. if you do not use proxy/gateway/bridge/etc, you do not need to set this key.
|
|
945
|
+
//
|
|
946
|
+
// [RoleToken] url argument
|
|
947
|
+
// "port": <port number> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/ip/<ip port cuk>"
|
|
948
|
+
// this value is number string(0-), allowed null and '' for this value.
|
|
949
|
+
// if this value is '0', it means any port.
|
|
950
|
+
// "cuk": <container unique key> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/name/<hostname port cuk>"
|
|
951
|
+
// this value is string. if this value is undefined/null/empty string, it means any.
|
|
952
|
+
// "extra": <extra string data> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
953
|
+
// This value must be encoded by JSON.
|
|
954
|
+
// extra is any string including Control code, allowed null and '' for this value.
|
|
955
|
+
// "tag": <string data> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
956
|
+
// This value must be encoded by JSON.
|
|
957
|
+
// tag is any string including Control code, allowed null and '' for this value.
|
|
958
|
+
// "inboundip": <ip address> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
959
|
+
// inboundip is set ip address string. if you do not use proxy/gateway/bridge/etc, you do not need to set this key.
|
|
960
|
+
// "outboundip": <ip address> => key is "yrn:yahoo:<service>::<tenant>:role:<role>/hosts/..."
|
|
961
|
+
// outboundip is set ip address string. if you do not use proxy/gateway/bridge/etc, you do not need to set this key.
|
|
962
|
+
//
|
|
963
|
+
// [NOTE]
|
|
964
|
+
// This API only set(add/create) host into role. Ether hostname or ip address must be specified.
|
|
965
|
+
// If port number is 0, it means any port.
|
|
966
|
+
// If cuk is undefined/null/empty string, it means any.
|
|
967
|
+
// Extra data can include control-code(CR, etc).
|
|
968
|
+
//
|
|
969
|
+
const putRoleHost = (role, req, res, _) => {
|
|
970
|
+
dbglogging_1.default.dlog('CALL:', req.method, req.url);
|
|
971
|
+
res.type('application/json; charset=utf-8');
|
|
972
|
+
if (!k2hr3apiutil_1.default.isPlainObject(req) ||
|
|
973
|
+
!k2hr3apiutil_1.default.isPlainObject(req.query)) {
|
|
974
|
+
const result = {
|
|
975
|
+
result: false,
|
|
976
|
+
message: 'PUT argument does not have any data'
|
|
977
|
+
};
|
|
978
|
+
dbglogging_1.default.elog(result.message);
|
|
979
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
//------------------------------
|
|
983
|
+
// check token
|
|
984
|
+
//------------------------------
|
|
985
|
+
const token_result = k2hr3tokens_1.default.checkToken(req, true); // scoped, both token
|
|
986
|
+
if (!token_result.result) {
|
|
987
|
+
const result = {
|
|
988
|
+
result: token_result.result,
|
|
989
|
+
message: k2hr3apiutil_1.default.getSafeString(token_result.message),
|
|
990
|
+
};
|
|
991
|
+
dbglogging_1.default.elog(result.message);
|
|
992
|
+
k2hr3resutil_1.default.errResponse(req, res, token_result.status, result);
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
const token_info = token_result.token_info;
|
|
996
|
+
if (!k2hr3tokens_1.default.isResTypeCheckRoleToken(token_info)) {
|
|
997
|
+
const result = {
|
|
998
|
+
result: false,
|
|
999
|
+
message: 'specified wrong token or it is not scoped user token'
|
|
1000
|
+
};
|
|
1001
|
+
dbglogging_1.default.elog(result.message);
|
|
1002
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
const is_host_req = !k2hr3apiutil_1.default.isSafeString(req.query.host);
|
|
1006
|
+
const keys = r3keys(token_info.user, token_info.tenant);
|
|
1007
|
+
//------------------------------
|
|
1008
|
+
// check arguments
|
|
1009
|
+
//------------------------------
|
|
1010
|
+
// role name check
|
|
1011
|
+
let name = k2hr3apiutil_1.default.getSafeString(role).toLowerCase();
|
|
1012
|
+
let nameptn = new RegExp('^' + keys.ROLE_TOP_KEY + ':(.*)'); // regex = /^yrn:yahoo:<service>::<tenant>:role:(.*)/
|
|
1013
|
+
const namematchs = name.match(nameptn);
|
|
1014
|
+
if (k2hr3apiutil_1.default.isStringArray(namematchs) && k2hr3apiutil_1.default.isNotEmptyArray(namematchs) && 2 <= namematchs.length) {
|
|
1015
|
+
// name is full yrn, then reset only name.
|
|
1016
|
+
name = namematchs[1];
|
|
1017
|
+
}
|
|
1018
|
+
else {
|
|
1019
|
+
// role name is not full yrn, then check other yrn path
|
|
1020
|
+
nameptn = new RegExp('^' + keys.NO_TENANT_KEY); // regex = /^yrn:yahoo:/
|
|
1021
|
+
if (name.match(nameptn)) {
|
|
1022
|
+
const result = {
|
|
1023
|
+
result: false,
|
|
1024
|
+
message: 'POST request url has wrong yrn full path to role'
|
|
1025
|
+
};
|
|
1026
|
+
dbglogging_1.default.elog(result.message);
|
|
1027
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
// hostname
|
|
1032
|
+
let hostname = null;
|
|
1033
|
+
let ip = null;
|
|
1034
|
+
if (!is_host_req) {
|
|
1035
|
+
if (!k2hr3apiutil_1.default.isSafeString(req.query.host)) {
|
|
1036
|
+
const result = {
|
|
1037
|
+
result: false,
|
|
1038
|
+
message: 'host is not specified.'
|
|
1039
|
+
};
|
|
1040
|
+
dbglogging_1.default.elog(result.message);
|
|
1041
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
const tg_host = k2hr3apiutil_1.default.getSafeString(req.query.host);
|
|
1045
|
+
if (k2hr3apiutil_1.default.isIpAddressString(tg_host)) {
|
|
1046
|
+
ip = tg_host.toLowerCase();
|
|
1047
|
+
}
|
|
1048
|
+
else {
|
|
1049
|
+
hostname = tg_host.toLowerCase();
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
else {
|
|
1053
|
+
// get ip address
|
|
1054
|
+
ip = k2hr3apiutil_1.default.getClientIpAddress(req);
|
|
1055
|
+
if (!k2hr3apiutil_1.default.isSafeString(ip)) {
|
|
1056
|
+
const result = {
|
|
1057
|
+
result: false,
|
|
1058
|
+
message: 'Could not get ip address from request.'
|
|
1059
|
+
};
|
|
1060
|
+
dbglogging_1.default.elog(result.message);
|
|
1061
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1062
|
+
return;
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
// port
|
|
1066
|
+
let port;
|
|
1067
|
+
if (k2hr3apiutil_1.default.isSafeNumeric(req.query.port)) {
|
|
1068
|
+
const port_tmp = k2hr3apiutil_1.default.cvtToNumber(req.query.port);
|
|
1069
|
+
if (!k2hr3apiutil_1.default.isSafeNumber(port_tmp)) {
|
|
1070
|
+
const result = {
|
|
1071
|
+
result: false,
|
|
1072
|
+
message: 'PUT request has port which is not number: ' + JSON.stringify(req.query.port)
|
|
1073
|
+
};
|
|
1074
|
+
dbglogging_1.default.elog(result.message);
|
|
1075
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1076
|
+
return;
|
|
1077
|
+
}
|
|
1078
|
+
port = port_tmp;
|
|
1079
|
+
}
|
|
1080
|
+
else {
|
|
1081
|
+
port = 0; // default any
|
|
1082
|
+
}
|
|
1083
|
+
// cuk
|
|
1084
|
+
let cuk = null;
|
|
1085
|
+
if (k2hr3apiutil_1.default.isSafeString(req.query.cuk) && k2hr3apiutil_1.default.isSafeString(req.query.cuk.trim())) {
|
|
1086
|
+
cuk = k2hr3apiutil_1.default.getSafeString(req.query.cuk).trim();
|
|
1087
|
+
}
|
|
1088
|
+
// extra
|
|
1089
|
+
let extra = null;
|
|
1090
|
+
if (k2hr3apiutil_1.default.isSafeString(req.query.extra)) {
|
|
1091
|
+
const extra_tmp = k2hr3apiutil_1.default.getSafeString(req.query.extra);
|
|
1092
|
+
if (k2hr3apiutil_1.default.checkSimpleJSON(extra_tmp)) {
|
|
1093
|
+
const extra_parsed_tmp = JSON.parse(extra_tmp); // extra encoded JSON
|
|
1094
|
+
if (!k2hr3apiutil_1.default.isSafeString(extra_parsed_tmp)) {
|
|
1095
|
+
const result = {
|
|
1096
|
+
result: false,
|
|
1097
|
+
message: 'PUT request has extra which is not string: ' + JSON.stringify(req.query.extra)
|
|
1098
|
+
};
|
|
1099
|
+
dbglogging_1.default.elog(result.message);
|
|
1100
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1103
|
+
extra = extra_parsed_tmp;
|
|
1104
|
+
}
|
|
1105
|
+
else {
|
|
1106
|
+
extra = extra_tmp;
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
// tag
|
|
1110
|
+
let tag = null;
|
|
1111
|
+
if (k2hr3apiutil_1.default.isSafeString(req.query.tag)) {
|
|
1112
|
+
const tag_tmp = k2hr3apiutil_1.default.getSafeString(req.query.tag);
|
|
1113
|
+
if (k2hr3apiutil_1.default.checkSimpleJSON(tag_tmp)) {
|
|
1114
|
+
const tag_parsed_tmp = JSON.parse(tag_tmp); // tag encoded JSON
|
|
1115
|
+
if (!k2hr3apiutil_1.default.isSafeString(tag_parsed_tmp)) {
|
|
1116
|
+
const result = {
|
|
1117
|
+
result: false,
|
|
1118
|
+
message: 'PUT request has tag which is not string: ' + JSON.stringify(req.body.host.tag)
|
|
1119
|
+
};
|
|
1120
|
+
dbglogging_1.default.elog(result.message);
|
|
1121
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
tag = tag_parsed_tmp;
|
|
1125
|
+
}
|
|
1126
|
+
else {
|
|
1127
|
+
tag = tag_tmp;
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
// make base host information
|
|
1131
|
+
const host_info = {
|
|
1132
|
+
hostname: hostname,
|
|
1133
|
+
ip: ip,
|
|
1134
|
+
port: port,
|
|
1135
|
+
cuk: cuk,
|
|
1136
|
+
extra: extra,
|
|
1137
|
+
tag: tag,
|
|
1138
|
+
inboundip: null,
|
|
1139
|
+
outboundip: null
|
|
1140
|
+
};
|
|
1141
|
+
// set inboundip(optional)
|
|
1142
|
+
let inboundip = null;
|
|
1143
|
+
if (k2hr3apiutil_1.default.isSafeString(req.query.inboundip)) {
|
|
1144
|
+
if (!k2hr3apiutil_1.default.isIpAddressString(req.query.inboundip)) {
|
|
1145
|
+
const result = {
|
|
1146
|
+
result: false,
|
|
1147
|
+
message: 'PUT request has inbound ip address which is not ignore ip address string: ' + JSON.stringify(req.query.inboundip)
|
|
1148
|
+
};
|
|
1149
|
+
dbglogging_1.default.elog(result.message);
|
|
1150
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1151
|
+
return;
|
|
1152
|
+
}
|
|
1153
|
+
inboundip = k2hr3apiutil_1.default.getSafeString(req.query.inboundip);
|
|
1154
|
+
host_info.inboundip = inboundip;
|
|
1155
|
+
}
|
|
1156
|
+
// set outboundip(optional)
|
|
1157
|
+
let outboundip = null;
|
|
1158
|
+
if (k2hr3apiutil_1.default.isSafeString(req.query.outboundip)) {
|
|
1159
|
+
if (!k2hr3apiutil_1.default.isIpAddressString(req.query.outboundip)) {
|
|
1160
|
+
const result = {
|
|
1161
|
+
result: false,
|
|
1162
|
+
message: 'PUT request has outbound ip address which is not ignore ip address string: ' + JSON.stringify(req.query.outboundip)
|
|
1163
|
+
};
|
|
1164
|
+
dbglogging_1.default.elog(result.message);
|
|
1165
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
1168
|
+
outboundip = k2hr3apiutil_1.default.getSafeString(req.query.outboundip);
|
|
1169
|
+
host_info.outboundip = outboundip;
|
|
1170
|
+
}
|
|
1171
|
+
//------------------------------
|
|
1172
|
+
// add host to role
|
|
1173
|
+
//------------------------------
|
|
1174
|
+
let role_result;
|
|
1175
|
+
if (!is_host_req) {
|
|
1176
|
+
// Add hostname ---> Need User Token
|
|
1177
|
+
if (null === ip) {
|
|
1178
|
+
role_result = k2hr3dkc_1.default.updateRoleHosts(token_info.user, token_info.tenant, name, host_info);
|
|
1179
|
+
}
|
|
1180
|
+
else {
|
|
1181
|
+
role_result = k2hr3dkc_1.default.updateRoleHosts(token_info.user, token_info.tenant, name, null, false, host_info);
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
else {
|
|
1185
|
+
// Add ip address ---> Role Token or User Token
|
|
1186
|
+
role_result = k2hr3dkc_1.default.addHost(token_info.tenant, name, null, ip, port, cuk, extra, tag, inboundip, outboundip);
|
|
1187
|
+
}
|
|
1188
|
+
if (!k2hr3apiutil_1.default.isPlainObject(role_result) || !k2hr3apiutil_1.default.isBoolean(role_result.result) || false === role_result.result) {
|
|
1189
|
+
const mode_type = (is_host_req ? 'addHost' : 'updateRoleHosts');
|
|
1190
|
+
if (!k2hr3apiutil_1.default.isSafeEntity(role_result)) {
|
|
1191
|
+
const result = {
|
|
1192
|
+
result: false,
|
|
1193
|
+
message: ('Could not get response from ' + mode_type)
|
|
1194
|
+
};
|
|
1195
|
+
dbglogging_1.default.elog(result.message);
|
|
1196
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1197
|
+
}
|
|
1198
|
+
else {
|
|
1199
|
+
const result = {
|
|
1200
|
+
result: false,
|
|
1201
|
+
message: k2hr3apiutil_1.default.isString(role_result.message) ? role_result.message : ('Could not get error message in response from ' + mode_type)
|
|
1202
|
+
};
|
|
1203
|
+
dbglogging_1.default.elog(result.message);
|
|
1204
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1205
|
+
}
|
|
1206
|
+
return;
|
|
1207
|
+
}
|
|
1208
|
+
dbglogging_1.default.dlog('succeed : ' + k2hr3apiutil_1.default.getSafeString(role_result.message));
|
|
1209
|
+
res.status(201); // 201: Created
|
|
1210
|
+
res.send(JSON.stringify(role_result));
|
|
1211
|
+
};
|
|
1212
|
+
//---------------------------------------------------------
|
|
1213
|
+
// Router GET
|
|
1214
|
+
//---------------------------------------------------------
|
|
1215
|
+
//
|
|
1216
|
+
// Mountpath : '/v1/role/<role{/...}>'
|
|
1217
|
+
//
|
|
1218
|
+
// GET '/v1/role/<role{/...}>' : get role on version 1
|
|
1219
|
+
// HEADER : X-Auth-Token => User token
|
|
1220
|
+
// URL arguments : expand => "true"(default) or "false"
|
|
1221
|
+
// response : {
|
|
1222
|
+
// "result": true or false
|
|
1223
|
+
// "message": error message
|
|
1224
|
+
// "role": {
|
|
1225
|
+
// policies: array,
|
|
1226
|
+
// aliases: array <--- only not expand
|
|
1227
|
+
// hosts: { <--- only not expand
|
|
1228
|
+
// 'hostnames': [ hostname array or empty array
|
|
1229
|
+
// <hostname> <port> <cuk> <extra> <tag>, (if any port, port is *)
|
|
1230
|
+
// ...
|
|
1231
|
+
// ],
|
|
1232
|
+
// 'ips': [ ip address array or empty array
|
|
1233
|
+
// <ip address> <port> <cuk> <extra> <tag>,(if any port, port is *)
|
|
1234
|
+
// ...
|
|
1235
|
+
// ]
|
|
1236
|
+
// }
|
|
1237
|
+
// }
|
|
1238
|
+
// }
|
|
1239
|
+
//
|
|
1240
|
+
// GET '/v1/role/token/<role{/...}>' : get role token on version 1
|
|
1241
|
+
// HEADER : X-Auth-Token => User token or Role token
|
|
1242
|
+
// URL arguments : expire => "expire time(unix time value)" or undefined(default 24H)
|
|
1243
|
+
// response : {
|
|
1244
|
+
// "result": true or false
|
|
1245
|
+
// "message": error message
|
|
1246
|
+
// "token": "role token"
|
|
1247
|
+
// "registerpath": "path for registering"
|
|
1248
|
+
// }
|
|
1249
|
+
//
|
|
1250
|
+
// GET '/v1/role/token/list/<role{/...}>': get list of role tokens on version 1
|
|
1251
|
+
// HEADER : X-Auth-Token => User token
|
|
1252
|
+
// URL arguments : expand => "true"(default) or "false"
|
|
1253
|
+
// response : {
|
|
1254
|
+
// result: true/false
|
|
1255
|
+
// message: null or error message string
|
|
1256
|
+
// tokens: {
|
|
1257
|
+
// "token": {
|
|
1258
|
+
// date: create date(UTC ISO 8601)
|
|
1259
|
+
// expire: expire date(UTC ISO 8601)
|
|
1260
|
+
// user: user name if user created this token
|
|
1261
|
+
// hostname: hostname if this token was created by host(name)
|
|
1262
|
+
// ip: ip address if this token was created by ip
|
|
1263
|
+
// port: port number, if specified port when created token
|
|
1264
|
+
// cuk: cuk, if specified cuk when created token
|
|
1265
|
+
// },
|
|
1266
|
+
// ...
|
|
1267
|
+
// }
|
|
1268
|
+
// }
|
|
1269
|
+
// or
|
|
1270
|
+
// {
|
|
1271
|
+
// result: true/false
|
|
1272
|
+
// message: null or error message string
|
|
1273
|
+
// tokens: [
|
|
1274
|
+
// "role token",
|
|
1275
|
+
// ....
|
|
1276
|
+
// ]
|
|
1277
|
+
// }
|
|
1278
|
+
//
|
|
1279
|
+
// This mount point is for creating(update) role or creating(update) host in role.
|
|
1280
|
+
// And get role token by host(ip address) or user(user token), update role token by
|
|
1281
|
+
// role token.
|
|
1282
|
+
//
|
|
1283
|
+
router.get('/', (req, res, next) => {
|
|
1284
|
+
dbglogging_1.default.dlog('CALL:', req.method, req.url, req.baseUrl);
|
|
1285
|
+
if ('GET' !== req.method) {
|
|
1286
|
+
// HEAD request comes here, so it should be routed to head function.
|
|
1287
|
+
next();
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1290
|
+
res.type('application/json; charset=utf-8');
|
|
1291
|
+
if (!k2hr3apiutil_1.default.isPlainObject(req) ||
|
|
1292
|
+
!k2hr3apiutil_1.default.isSafeString(req.baseUrl)) {
|
|
1293
|
+
const result = {
|
|
1294
|
+
result: false,
|
|
1295
|
+
message: 'GET request or url is wrong'
|
|
1296
|
+
};
|
|
1297
|
+
dbglogging_1.default.elog(result.message);
|
|
1298
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1299
|
+
return;
|
|
1300
|
+
}
|
|
1301
|
+
//------------------------------
|
|
1302
|
+
// check token for API mode
|
|
1303
|
+
//------------------------------
|
|
1304
|
+
let token_str = null;
|
|
1305
|
+
let token_type = null;
|
|
1306
|
+
let token_info = null;
|
|
1307
|
+
let keys = r3keys();
|
|
1308
|
+
if (k2hr3tokens_1.default.hasAuthTokenHeader(req)) {
|
|
1309
|
+
const token_result = k2hr3tokens_1.default.checkToken(req, true); // scoped, both token
|
|
1310
|
+
if (!token_result.result) {
|
|
1311
|
+
const result = {
|
|
1312
|
+
result: token_result.result,
|
|
1313
|
+
message: k2hr3apiutil_1.default.getSafeString(token_result.message),
|
|
1314
|
+
};
|
|
1315
|
+
dbglogging_1.default.elog(result.message);
|
|
1316
|
+
k2hr3resutil_1.default.errResponse(req, res, token_result.status, result);
|
|
1317
|
+
return;
|
|
1318
|
+
}
|
|
1319
|
+
if (!k2hr3tokens_1.default.isResTypeCheckRoleToken(token_result.token_info)) {
|
|
1320
|
+
const result = {
|
|
1321
|
+
result: false,
|
|
1322
|
+
message: 'specified wrong token or it is not scoped user token'
|
|
1323
|
+
};
|
|
1324
|
+
dbglogging_1.default.elog(result.message);
|
|
1325
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1326
|
+
return;
|
|
1327
|
+
}
|
|
1328
|
+
token_info = token_result.token_info;
|
|
1329
|
+
token_str = token_result.token ?? null;
|
|
1330
|
+
token_type = token_result.token_type ?? null;
|
|
1331
|
+
keys = r3keys(token_info.user, token_info.tenant);
|
|
1332
|
+
}
|
|
1333
|
+
//------------------------------
|
|
1334
|
+
// get role name
|
|
1335
|
+
//------------------------------
|
|
1336
|
+
// check get token type and parse role name
|
|
1337
|
+
let is_get_token = false;
|
|
1338
|
+
let is_get_list = false;
|
|
1339
|
+
let requestptn = new RegExp(keys.MATCH_URI_GET_RTOKEN_LIST); // regex = /^\/v1\/role\/token\/list\/(.*)/
|
|
1340
|
+
let reqmatchs = decodeURI(req.baseUrl).match(requestptn);
|
|
1341
|
+
if (k2hr3apiutil_1.default.isStringArray(reqmatchs) && k2hr3apiutil_1.default.isNotEmptyArray(reqmatchs) && 2 <= reqmatchs.length && '' !== k2hr3apiutil_1.default.getSafeString(reqmatchs[1])) {
|
|
1342
|
+
// get list of tokens
|
|
1343
|
+
is_get_list = true;
|
|
1344
|
+
}
|
|
1345
|
+
else {
|
|
1346
|
+
// recheck
|
|
1347
|
+
requestptn = new RegExp(keys.MATCH_URI_GET_RTOKEN); // regex = /^\/v1\/role\/token\/(.*)/
|
|
1348
|
+
reqmatchs = decodeURI(req.baseUrl).match(requestptn);
|
|
1349
|
+
if (k2hr3apiutil_1.default.isStringArray(reqmatchs) && k2hr3apiutil_1.default.isNotEmptyArray(reqmatchs) && 2 <= reqmatchs.length && '' !== k2hr3apiutil_1.default.getSafeString(reqmatchs[1])) {
|
|
1350
|
+
// get token
|
|
1351
|
+
is_get_token = true;
|
|
1352
|
+
}
|
|
1353
|
+
else {
|
|
1354
|
+
// retry parse role name
|
|
1355
|
+
requestptn = new RegExp(keys.MATCH_URI_GET_ROLE_DATA); // regex = /^\/v1\/role\/(.*)/
|
|
1356
|
+
reqmatchs = decodeURI(req.baseUrl).match(requestptn);
|
|
1357
|
+
if (!k2hr3apiutil_1.default.isStringArray(reqmatchs) || !k2hr3apiutil_1.default.isNotEmptyArray(reqmatchs) || reqmatchs.length < 2 || '' === k2hr3apiutil_1.default.getSafeString(reqmatchs[1])) {
|
|
1358
|
+
const result = {
|
|
1359
|
+
result: false,
|
|
1360
|
+
message: 'GET request url does not have role name'
|
|
1361
|
+
};
|
|
1362
|
+
dbglogging_1.default.elog(result.message);
|
|
1363
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
// check role name is only name or full yrn path
|
|
1369
|
+
let name = reqmatchs[1].toLowerCase();
|
|
1370
|
+
let nameptn = new RegExp('^' + keys.MATCH_ANY_TENANT_ROLE); // regex = /^yrn:yahoo:(.*)::(.*):role:(.*)/
|
|
1371
|
+
const namematchs = name.match(nameptn);
|
|
1372
|
+
if (!k2hr3apiutil_1.default.isStringArray(namematchs) || !k2hr3apiutil_1.default.isNotEmptyArray(namematchs) || namematchs.length < 4) {
|
|
1373
|
+
//
|
|
1374
|
+
// name is not full yrn to role, then check wrong role name
|
|
1375
|
+
//
|
|
1376
|
+
nameptn = new RegExp('^' + keys.NO_TENANT_KEY); // regex = /^yrn:yahoo:/
|
|
1377
|
+
if (name.match(nameptn)) {
|
|
1378
|
+
const result = {
|
|
1379
|
+
result: false,
|
|
1380
|
+
message: 'GET request query has wrong yrn full path to role'
|
|
1381
|
+
};
|
|
1382
|
+
dbglogging_1.default.elog(result.message);
|
|
1383
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
// role name is not full yrn, we need tenant name
|
|
1387
|
+
if (!k2hr3apiutil_1.default.isSafeString(keys.ROLE_TOP_KEY)) {
|
|
1388
|
+
const result = {
|
|
1389
|
+
result: false,
|
|
1390
|
+
message: 'GET request role name which is not full yrn, and not token. role name must be full yrn, if token is not specified.'
|
|
1391
|
+
};
|
|
1392
|
+
dbglogging_1.default.elog(result.message);
|
|
1393
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1394
|
+
return;
|
|
1395
|
+
}
|
|
1396
|
+
// make full yrn for role name
|
|
1397
|
+
name = keys.ROLE_TOP_KEY + ':' + name;
|
|
1398
|
+
}
|
|
1399
|
+
else {
|
|
1400
|
+
//
|
|
1401
|
+
// name is full yrn to role.
|
|
1402
|
+
// need to check tenant name when token is specified.
|
|
1403
|
+
//
|
|
1404
|
+
if (k2hr3apiutil_1.default.isSafeString(token_type) && (!k2hr3apiutil_1.default.isPlainObject(token_info) || !k2hr3apiutil_1.default.isSafeString(token_info.tenant) || !k2hr3apiutil_1.default.compareCaseString(namematchs[2], token_info.tenant))) {
|
|
1405
|
+
const result = {
|
|
1406
|
+
result: false,
|
|
1407
|
+
message: 'GET request query has wrong tenant yrn full path(tenant=' + namematchs[2] + ') or not specify tenant.'
|
|
1408
|
+
};
|
|
1409
|
+
dbglogging_1.default.elog(result.message);
|
|
1410
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1411
|
+
return;
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
// Run
|
|
1415
|
+
if (is_get_token) {
|
|
1416
|
+
//------------------------------
|
|
1417
|
+
// GET ROLE TOKEN
|
|
1418
|
+
//------------------------------
|
|
1419
|
+
// token_info: null(undefined) => not specify token, put token by host ip address
|
|
1420
|
+
// user token => put token by user
|
|
1421
|
+
// role token => update token by role
|
|
1422
|
+
//
|
|
1423
|
+
getRoleToken(name, token_info, token_type, token_str, req, res);
|
|
1424
|
+
}
|
|
1425
|
+
else if (is_get_list) {
|
|
1426
|
+
//------------------------------
|
|
1427
|
+
// GET LIST OF ROLE TOKENS
|
|
1428
|
+
//------------------------------
|
|
1429
|
+
if ('user' === k2hr3apiutil_1.default.getSafeString(token_type)) {
|
|
1430
|
+
getListRoleTokens(name, token_info, req, res);
|
|
1431
|
+
}
|
|
1432
|
+
else {
|
|
1433
|
+
const result = {
|
|
1434
|
+
result: false,
|
|
1435
|
+
message: 'GET request without UserToken for getting list of role(' + name + ') tokens, need User Token.'
|
|
1436
|
+
};
|
|
1437
|
+
dbglogging_1.default.elog(result.message);
|
|
1438
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1439
|
+
return;
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
else {
|
|
1443
|
+
//------------------------------
|
|
1444
|
+
// GET ROLE DATA
|
|
1445
|
+
//------------------------------
|
|
1446
|
+
if ('user' === k2hr3apiutil_1.default.getSafeString(token_type) && k2hr3apiutil_1.default.isPlainObject(token_info)) {
|
|
1447
|
+
getRole(name, token_info, req, res);
|
|
1448
|
+
}
|
|
1449
|
+
else {
|
|
1450
|
+
const result = {
|
|
1451
|
+
result: false,
|
|
1452
|
+
message: 'GET request without UserToken for getting role(' + name + '), need User Token.'
|
|
1453
|
+
};
|
|
1454
|
+
dbglogging_1.default.elog(result.message);
|
|
1455
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1456
|
+
return;
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
});
|
|
1460
|
+
//
|
|
1461
|
+
// Sub router function for GET ROLE DATA
|
|
1462
|
+
//
|
|
1463
|
+
// Mountpath : '/v1/role/<role{/...}>'
|
|
1464
|
+
//
|
|
1465
|
+
// GET '/v1/role/<role{/...}>' : get role on version 1
|
|
1466
|
+
// HEADER : X-Auth-Token => User token
|
|
1467
|
+
// URL arguments : expand => "true"(default) or "false"
|
|
1468
|
+
// response : {
|
|
1469
|
+
// "result": true or false
|
|
1470
|
+
// "message": error message
|
|
1471
|
+
// "role": {
|
|
1472
|
+
// policies: array,
|
|
1473
|
+
// aliases: array <--- only not expand
|
|
1474
|
+
// hosts: { <--- only not expand
|
|
1475
|
+
// 'hostnames': [ hostname array or empty array
|
|
1476
|
+
// <hostname> <port> <cuk> <extra> <tag>, (if any port, port is *)
|
|
1477
|
+
// ...
|
|
1478
|
+
// ],
|
|
1479
|
+
// 'ips': [ ip address array or empty array
|
|
1480
|
+
// <ip address> <port> <cuk> <extra> <tag>,(if any port, port is *)
|
|
1481
|
+
// ...
|
|
1482
|
+
// ]
|
|
1483
|
+
// }
|
|
1484
|
+
// }
|
|
1485
|
+
// }
|
|
1486
|
+
//
|
|
1487
|
+
// This mount point is for creating(update) role or creating(update) host in role.
|
|
1488
|
+
//
|
|
1489
|
+
const getRole = (role, token_info, req, res) => {
|
|
1490
|
+
dbglogging_1.default.dlog('CALL:', req.method, req.url);
|
|
1491
|
+
res.type('application/json; charset=utf-8');
|
|
1492
|
+
if (!k2hr3apiutil_1.default.isPlainObject(req) ||
|
|
1493
|
+
!k2hr3apiutil_1.default.isPlainObject(req.query)) {
|
|
1494
|
+
const result = {
|
|
1495
|
+
result: false,
|
|
1496
|
+
message: 'GET request query is wrong'
|
|
1497
|
+
};
|
|
1498
|
+
dbglogging_1.default.elog(result.message);
|
|
1499
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
if (!k2hr3apiutil_1.default.isSafeString(role) ||
|
|
1503
|
+
!k2hr3tokens_1.default.isResTypeCheckRoleToken(token_info) ||
|
|
1504
|
+
!k2hr3apiutil_1.default.isSafeString(token_info.user) ||
|
|
1505
|
+
!k2hr3apiutil_1.default.isSafeString(token_info.tenant)) {
|
|
1506
|
+
const result = {
|
|
1507
|
+
result: false,
|
|
1508
|
+
message: 'GET request is failure by internal error.'
|
|
1509
|
+
};
|
|
1510
|
+
dbglogging_1.default.elog(result.message);
|
|
1511
|
+
k2hr3resutil_1.default.errResponse(req, res, 500, result); // 500: Internal Error
|
|
1512
|
+
return;
|
|
1513
|
+
}
|
|
1514
|
+
//------------------------------
|
|
1515
|
+
// check arguments
|
|
1516
|
+
//------------------------------
|
|
1517
|
+
const keys = r3keys(token_info.user, token_info.tenant);
|
|
1518
|
+
// expand type
|
|
1519
|
+
let is_expand = true;
|
|
1520
|
+
if (k2hr3apiutil_1.default.isSafeString(req.query.expand)) {
|
|
1521
|
+
if (k2hr3apiutil_1.default.compareCaseString(keys.VALUE_TRUE, req.query.expand)) {
|
|
1522
|
+
is_expand = true;
|
|
1523
|
+
}
|
|
1524
|
+
else if (k2hr3apiutil_1.default.compareCaseString(keys.VALUE_FALSE, req.query.expand)) {
|
|
1525
|
+
is_expand = false;
|
|
1526
|
+
}
|
|
1527
|
+
else {
|
|
1528
|
+
const result = {
|
|
1529
|
+
result: false,
|
|
1530
|
+
message: 'GET expand url argument parameter(' + JSON.stringify(req.query.expand) + ') is wrong, it must be ' + keys.VALUE_TRUE + ' or ' + keys.VALUE_FALSE + '.'
|
|
1531
|
+
};
|
|
1532
|
+
dbglogging_1.default.elog(result.message);
|
|
1533
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1534
|
+
return;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
//------------------------------
|
|
1538
|
+
// get role
|
|
1539
|
+
//------------------------------
|
|
1540
|
+
const role_result = k2hr3dkc_1.default.getRole(role, is_expand);
|
|
1541
|
+
if (!k2hr3apiutil_1.default.isPlainObject(role_result) || !k2hr3apiutil_1.default.isBoolean(role_result.result) || false === role_result.result) {
|
|
1542
|
+
if (!k2hr3apiutil_1.default.isPlainObject(role_result)) {
|
|
1543
|
+
const result = {
|
|
1544
|
+
result: false,
|
|
1545
|
+
message: 'Could not get response from getRole'
|
|
1546
|
+
};
|
|
1547
|
+
dbglogging_1.default.elog(result.message);
|
|
1548
|
+
k2hr3resutil_1.default.errResponse(req, res, 404, result); // 404: Not Found
|
|
1549
|
+
}
|
|
1550
|
+
else {
|
|
1551
|
+
const result = {
|
|
1552
|
+
result: false,
|
|
1553
|
+
message: k2hr3apiutil_1.default.isString(role_result.message) ? role_result.message : 'Could not get error message in response from getRole'
|
|
1554
|
+
};
|
|
1555
|
+
dbglogging_1.default.elog(result.message);
|
|
1556
|
+
k2hr3resutil_1.default.errResponse(req, res, 404, result); // 404: Not Found
|
|
1557
|
+
}
|
|
1558
|
+
return;
|
|
1559
|
+
}
|
|
1560
|
+
dbglogging_1.default.dlog('succeed : ' + k2hr3apiutil_1.default.getSafeString(role_result.message));
|
|
1561
|
+
res.status(200); // 200: OK
|
|
1562
|
+
res.send(JSON.stringify(role_result));
|
|
1563
|
+
};
|
|
1564
|
+
//
|
|
1565
|
+
// Sub router function for GET ROLE TOKEN
|
|
1566
|
+
//
|
|
1567
|
+
// Mountpath : '/v1/role/<role{/...}>'
|
|
1568
|
+
//
|
|
1569
|
+
// GET '/v1/role/token/<role{/...}>' : get role on version 1
|
|
1570
|
+
// HEADER : X-Auth-Token => undefined User token or Role token
|
|
1571
|
+
// URL arguments : expire => "expire time(unix time value)" or undefined(default 24H)
|
|
1572
|
+
// if 0 is specified, no expire.
|
|
1573
|
+
// response : {
|
|
1574
|
+
// "result": true or false
|
|
1575
|
+
// "message": error message
|
|
1576
|
+
// "token": "role token"
|
|
1577
|
+
// "registerpath": "path for registering"
|
|
1578
|
+
// }
|
|
1579
|
+
//
|
|
1580
|
+
// This mount point is for creating(update) role or creating(update) host in role.
|
|
1581
|
+
//
|
|
1582
|
+
const getRoleToken = (role, token_info, token_type, token_str, req, res) => {
|
|
1583
|
+
dbglogging_1.default.dlog('CALL:', req.method, req.url);
|
|
1584
|
+
res.type('application/json; charset=utf-8');
|
|
1585
|
+
if (!k2hr3apiutil_1.default.isSafeString(role)) {
|
|
1586
|
+
const result = {
|
|
1587
|
+
result: false,
|
|
1588
|
+
message: 'GET request is failure by internal error.'
|
|
1589
|
+
};
|
|
1590
|
+
dbglogging_1.default.elog(result.message);
|
|
1591
|
+
k2hr3resutil_1.default.errResponse(req, res, 500, result); // 500: Internal Error
|
|
1592
|
+
return;
|
|
1593
|
+
}
|
|
1594
|
+
//------------------------------
|
|
1595
|
+
// tenant/role name/client ip
|
|
1596
|
+
//------------------------------
|
|
1597
|
+
let tenant;
|
|
1598
|
+
if (!k2hr3tokens_1.default.isResTypeCheckRoleToken(token_info) || !k2hr3apiutil_1.default.isSafeString(token_info.tenant)) {
|
|
1599
|
+
// parse role yrn path to tenant and role name
|
|
1600
|
+
const keys = r3keys();
|
|
1601
|
+
const nameptn = new RegExp('^' + keys.MATCH_ANY_TENANT_ROLE); // regex = /^yrn:yahoo:(.*)::(.*):role:(.*)/
|
|
1602
|
+
const namematchs = role.match(nameptn);
|
|
1603
|
+
if (!k2hr3apiutil_1.default.isStringArray(namematchs) || !k2hr3apiutil_1.default.isNotEmptyArray(namematchs) || namematchs.length < 4) {
|
|
1604
|
+
// role is not full yrn
|
|
1605
|
+
const result = {
|
|
1606
|
+
result: false,
|
|
1607
|
+
message: 'GET request is failure by internal error(role yrn path is broken).'
|
|
1608
|
+
};
|
|
1609
|
+
dbglogging_1.default.elog(result.message);
|
|
1610
|
+
k2hr3resutil_1.default.errResponse(req, res, 500, result); // 500: Internal Error
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
tenant = namematchs[2];
|
|
1614
|
+
}
|
|
1615
|
+
else {
|
|
1616
|
+
tenant = token_info.tenant;
|
|
1617
|
+
}
|
|
1618
|
+
// client ip
|
|
1619
|
+
const clientip = k2hr3apiutil_1.default.getClientIpAddress(req);
|
|
1620
|
+
if (!k2hr3apiutil_1.default.isSafeString(clientip)) {
|
|
1621
|
+
const result = {
|
|
1622
|
+
result: false,
|
|
1623
|
+
message: 'GET request does not have ip address for client.'
|
|
1624
|
+
};
|
|
1625
|
+
dbglogging_1.default.elog(result.message);
|
|
1626
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1627
|
+
return;
|
|
1628
|
+
}
|
|
1629
|
+
// date/expire
|
|
1630
|
+
let token_date = '';
|
|
1631
|
+
if (k2hr3tokens_1.default.isResTypeCheckRoleToken(token_info) && k2hr3apiutil_1.default.isSafeString(token_info.date)) {
|
|
1632
|
+
token_date = token_info.date;
|
|
1633
|
+
}
|
|
1634
|
+
let token_expire = '';
|
|
1635
|
+
if (k2hr3tokens_1.default.isResTypeCheckRoleToken(token_info) && k2hr3apiutil_1.default.isSafeString(token_info.expire)) {
|
|
1636
|
+
token_expire = token_info.expire;
|
|
1637
|
+
}
|
|
1638
|
+
//------------------------------
|
|
1639
|
+
// get role token
|
|
1640
|
+
//------------------------------
|
|
1641
|
+
let rtoken_result;
|
|
1642
|
+
if (!k2hr3apiutil_1.default.isSafeString(token_type)) {
|
|
1643
|
+
// no token
|
|
1644
|
+
let port = 0;
|
|
1645
|
+
if (k2hr3apiutil_1.default.isSafeNumeric(req.query.port)) {
|
|
1646
|
+
const port_tmp = k2hr3apiutil_1.default.cvtToNumber(req.query.port);
|
|
1647
|
+
if (!k2hr3apiutil_1.default.isSafeNumber(port_tmp)) {
|
|
1648
|
+
const result = {
|
|
1649
|
+
result: false,
|
|
1650
|
+
message: 'GET request has port which is not number: ' + JSON.stringify(req.query.port)
|
|
1651
|
+
};
|
|
1652
|
+
dbglogging_1.default.elog(result.message);
|
|
1653
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1654
|
+
return;
|
|
1655
|
+
}
|
|
1656
|
+
port = port_tmp;
|
|
1657
|
+
}
|
|
1658
|
+
// check cuk parameter
|
|
1659
|
+
let cuk = null;
|
|
1660
|
+
if (k2hr3apiutil_1.default.isSafeString(req.query.cuk) && k2hr3apiutil_1.default.isSafeString(req.query.cuk.trim())) {
|
|
1661
|
+
cuk = k2hr3apiutil_1.default.getSafeString(req.query.cuk).trim();
|
|
1662
|
+
}
|
|
1663
|
+
rtoken_result = k2hr3tokens_1.default.getRoleTokenByIP(clientip, port, cuk, tenant, role, expire_rtoken); // strict checking port/cuk
|
|
1664
|
+
}
|
|
1665
|
+
else if ('role' === k2hr3apiutil_1.default.getSafeString(token_type)) {
|
|
1666
|
+
// role token
|
|
1667
|
+
if (!k2hr3apiutil_1.default.compareRequestIpAddress(req, (null !== token_info ? k2hr3apiutil_1.default.getSafeString(token_info.ip) : ''))) {
|
|
1668
|
+
// wrong ip address in token
|
|
1669
|
+
const result = {
|
|
1670
|
+
result: false,
|
|
1671
|
+
message: 'GET request ip address and role token are not same.'
|
|
1672
|
+
};
|
|
1673
|
+
dbglogging_1.default.elog(result.message);
|
|
1674
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1675
|
+
return;
|
|
1676
|
+
}
|
|
1677
|
+
// set expire time as same as old token
|
|
1678
|
+
let expire = k2hr3apiutil_1.default.getExpireUnixtimeFromISOStrings(token_date, token_expire);
|
|
1679
|
+
if (0 >= expire) {
|
|
1680
|
+
expire = expire_rtoken;
|
|
1681
|
+
}
|
|
1682
|
+
// using port/cuk from token inforamtion
|
|
1683
|
+
rtoken_result = k2hr3tokens_1.default.getRoleTokenByIP(clientip, (null !== token_info ? token_info.port : null), (null !== token_info ? token_info.cuk : null), tenant, role, expire); // strict checking port/cuk
|
|
1684
|
+
// if succeed to get new role token, remove old token
|
|
1685
|
+
if (k2hr3apiutil_1.default.isPlainObject(rtoken_result) && k2hr3apiutil_1.default.isBoolean(rtoken_result.result) && rtoken_result.result) {
|
|
1686
|
+
const rm_result = k2hr3tokens_1.default.removeRoleTokenByIP(token_str, clientip, (null !== token_info ? token_info.port : null), (null !== token_info ? token_info.cuk : null));
|
|
1687
|
+
if (!k2hr3apiutil_1.default.isPlainObject(rm_result) || !k2hr3apiutil_1.default.isBoolean(rm_result.result) || false === rm_result.result) {
|
|
1688
|
+
dbglogging_1.default.wlog('could not remove old role token(' + token_str + '), but continue...');
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
else if ('user' === k2hr3apiutil_1.default.getSafeString(token_type)) {
|
|
1693
|
+
// user token
|
|
1694
|
+
// expire
|
|
1695
|
+
let expire = expire_rtoken; // expire default is 24H
|
|
1696
|
+
if (k2hr3apiutil_1.default.isSafeNumeric(req.query.expire)) {
|
|
1697
|
+
const tmpExp = k2hr3apiutil_1.default.cvtToNumber(req.query.expire);
|
|
1698
|
+
if (!k2hr3apiutil_1.default.isSafeNumber(tmpExp)) {
|
|
1699
|
+
const result = {
|
|
1700
|
+
result: false,
|
|
1701
|
+
message: 'GET request has expire which is not number: ' + JSON.stringify(req.query.expire)
|
|
1702
|
+
};
|
|
1703
|
+
dbglogging_1.default.elog(result.message);
|
|
1704
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1705
|
+
return;
|
|
1706
|
+
}
|
|
1707
|
+
if (0 == tmpExp) {
|
|
1708
|
+
expire = expire_reg_rtoken; // If 0 is specified, it means no expire
|
|
1709
|
+
}
|
|
1710
|
+
else {
|
|
1711
|
+
expire = tmpExp;
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
rtoken_result = k2hr3tokens_1.default.getRoleTokenByUser((null !== token_info ? token_info.user : null), tenant, role, expire);
|
|
1715
|
+
}
|
|
1716
|
+
else {
|
|
1717
|
+
// broken token
|
|
1718
|
+
const result = {
|
|
1719
|
+
result: false,
|
|
1720
|
+
message: 'GET request is failure by internal error(token data broken).'
|
|
1721
|
+
};
|
|
1722
|
+
dbglogging_1.default.elog(result.message);
|
|
1723
|
+
k2hr3resutil_1.default.errResponse(req, res, 500, result); // 500: Internal Error
|
|
1724
|
+
return;
|
|
1725
|
+
}
|
|
1726
|
+
// check result
|
|
1727
|
+
if (!k2hr3apiutil_1.default.isPlainObject(rtoken_result) || !k2hr3apiutil_1.default.isBoolean(rtoken_result.result) || false === rtoken_result.result) {
|
|
1728
|
+
if (!k2hr3apiutil_1.default.isPlainObject(rtoken_result)) {
|
|
1729
|
+
const result = {
|
|
1730
|
+
result: false,
|
|
1731
|
+
message: 'Could not get role token.'
|
|
1732
|
+
};
|
|
1733
|
+
dbglogging_1.default.elog(result.message);
|
|
1734
|
+
k2hr3resutil_1.default.errResponse(req, res, 404, result); // 404: Not Found
|
|
1735
|
+
}
|
|
1736
|
+
else {
|
|
1737
|
+
const result = {
|
|
1738
|
+
result: false,
|
|
1739
|
+
message: k2hr3apiutil_1.default.isString(rtoken_result.message) ? rtoken_result.message : 'Could not get error message in response from get role token'
|
|
1740
|
+
};
|
|
1741
|
+
dbglogging_1.default.elog(result.message);
|
|
1742
|
+
k2hr3resutil_1.default.errResponse(req, res, 404, result); // 404: Not Found
|
|
1743
|
+
}
|
|
1744
|
+
return;
|
|
1745
|
+
}
|
|
1746
|
+
// create url parameter(path) for registering role member
|
|
1747
|
+
//
|
|
1748
|
+
const regparamobj = {
|
|
1749
|
+
role: role,
|
|
1750
|
+
token: rtoken_result.token
|
|
1751
|
+
};
|
|
1752
|
+
const udproc = new k2hr3userdata_1.default();
|
|
1753
|
+
const regparamstr = udproc.encryptRoleInfo(regparamobj);
|
|
1754
|
+
if (!k2hr3apiutil_1.default.isSafeString(regparamstr)) {
|
|
1755
|
+
const result = {
|
|
1756
|
+
result: false,
|
|
1757
|
+
message: 'Could not create register url parameter with role token.'
|
|
1758
|
+
};
|
|
1759
|
+
dbglogging_1.default.elog(result.message);
|
|
1760
|
+
k2hr3resutil_1.default.errResponse(req, res, 404, result); // 404: Not Found
|
|
1761
|
+
return;
|
|
1762
|
+
}
|
|
1763
|
+
const res_result = {
|
|
1764
|
+
result: rtoken_result.result,
|
|
1765
|
+
message: rtoken_result.message,
|
|
1766
|
+
token: rtoken_result.token,
|
|
1767
|
+
registerpath: regparamstr
|
|
1768
|
+
};
|
|
1769
|
+
dbglogging_1.default.dlog('succeed : ' + k2hr3apiutil_1.default.getSafeString(res_result.message));
|
|
1770
|
+
res.status(200); // 200: OK
|
|
1771
|
+
res.send(JSON.stringify(res_result));
|
|
1772
|
+
};
|
|
1773
|
+
//
|
|
1774
|
+
// Sub router function for GET LIST OF ROLE TOKENS
|
|
1775
|
+
//
|
|
1776
|
+
// Mountpath : '/v1/role/list/token/<role{/...}>'
|
|
1777
|
+
//
|
|
1778
|
+
// GET '/v1/role/token/list/<role{/...}>' : get list of role tokens on version 1
|
|
1779
|
+
// HEADER : X-Auth-Token => User token
|
|
1780
|
+
// URL arguments : expand => "true"(default) or "false"
|
|
1781
|
+
//
|
|
1782
|
+
// response : {
|
|
1783
|
+
// result: true/false
|
|
1784
|
+
// message: null or error message string
|
|
1785
|
+
// tokens: {
|
|
1786
|
+
// "token": {
|
|
1787
|
+
// date: create date(UTC ISO 8601)
|
|
1788
|
+
// expire: expire date(UTC ISO 8601)
|
|
1789
|
+
// user: user name if user created this token
|
|
1790
|
+
// hostname: hostname if this token was created by host(name)
|
|
1791
|
+
// ip: ip address if this token was created by ip
|
|
1792
|
+
// port: port number, if specified port when created token
|
|
1793
|
+
// cuk: cuk, if specified cuk when created token
|
|
1794
|
+
// registerpath: register path in user data script
|
|
1795
|
+
// },
|
|
1796
|
+
// ...
|
|
1797
|
+
// }
|
|
1798
|
+
// }
|
|
1799
|
+
// or
|
|
1800
|
+
// {
|
|
1801
|
+
// result: true/false
|
|
1802
|
+
// message: null or error message string
|
|
1803
|
+
// tokens: [
|
|
1804
|
+
// "role token",
|
|
1805
|
+
// ....
|
|
1806
|
+
// ]
|
|
1807
|
+
// }
|
|
1808
|
+
//
|
|
1809
|
+
// This mount point is for listing of all role tokens in role.
|
|
1810
|
+
//
|
|
1811
|
+
const getListRoleTokens = (role, token_info, req, res) => {
|
|
1812
|
+
dbglogging_1.default.dlog('CALL:', req.method, req.url, req.baseUrl);
|
|
1813
|
+
res.type('application/json; charset=utf-8');
|
|
1814
|
+
if (!k2hr3apiutil_1.default.isPlainObject(req) ||
|
|
1815
|
+
!k2hr3apiutil_1.default.isPlainObject(req.query)) {
|
|
1816
|
+
const result = {
|
|
1817
|
+
result: false,
|
|
1818
|
+
message: 'GET request query is wrong'
|
|
1819
|
+
};
|
|
1820
|
+
dbglogging_1.default.elog(result.message);
|
|
1821
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1822
|
+
return;
|
|
1823
|
+
}
|
|
1824
|
+
//------------------------------
|
|
1825
|
+
// check arguments
|
|
1826
|
+
//------------------------------
|
|
1827
|
+
const keys = r3keys();
|
|
1828
|
+
let expand = true;
|
|
1829
|
+
if (k2hr3apiutil_1.default.isSafeString(req.query.expand)) {
|
|
1830
|
+
if (k2hr3apiutil_1.default.compareCaseString(keys.VALUE_TRUE, req.query.expand)) {
|
|
1831
|
+
expand = true;
|
|
1832
|
+
}
|
|
1833
|
+
else if (k2hr3apiutil_1.default.compareCaseString(keys.VALUE_FALSE, req.query.expand)) {
|
|
1834
|
+
expand = false;
|
|
1835
|
+
}
|
|
1836
|
+
else {
|
|
1837
|
+
const result = {
|
|
1838
|
+
result: false,
|
|
1839
|
+
message: 'GET expand url argument parameter(' + JSON.stringify(req.query.expand) + ') is wrong, it must be ' + keys.VALUE_TRUE + ' or ' + keys.VALUE_FALSE + '.'
|
|
1840
|
+
};
|
|
1841
|
+
dbglogging_1.default.elog(result.message);
|
|
1842
|
+
k2hr3resutil_1.default.errResponse(req, res, 400, result); // 400: Bad Request
|
|
1843
|
+
return;
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
// check token
|
|
1847
|
+
if (!k2hr3apiutil_1.default.isSafeString(role) ||
|
|
1848
|
+
!k2hr3tokens_1.default.isResTypeCheckRoleToken(token_info) ||
|
|
1849
|
+
!k2hr3apiutil_1.default.isSafeString(token_info.user) ||
|
|
1850
|
+
!k2hr3apiutil_1.default.isSafeString(token_info.tenant)) {
|
|
1851
|
+
const result = {
|
|
1852
|
+
result: false,
|
|
1853
|
+
message: 'GET request is failure by internal error.'
|
|
1854
|
+
};
|
|
1855
|
+
dbglogging_1.default.elog(result.message);
|
|
1856
|
+
k2hr3resutil_1.default.errResponse(req, res, 500, result); // 500: Internal Error
|
|
1857
|
+
return;
|
|
1858
|
+
}
|
|
1859
|
+
//------------------------------
|
|
1860
|
+
// get list of role tokens
|
|
1861
|
+
//------------------------------
|
|
1862
|
+
const role_result = k2hr3tokens_1.default.getListRoleTokens(role, token_info.tenant, expand);
|
|
1863
|
+
// check result
|
|
1864
|
+
if (!k2hr3apiutil_1.default.isPlainObject(role_result) || !k2hr3apiutil_1.default.isBoolean(role_result.result) || false === role_result.result) {
|
|
1865
|
+
if (!k2hr3apiutil_1.default.isPlainObject(role_result)) {
|
|
1866
|
+
const result = {
|
|
1867
|
+
result: false,
|
|
1868
|
+
message: 'Could not get role token list.'
|
|
1869
|
+
};
|
|
1870
|
+
dbglogging_1.default.elog(result.message);
|
|
1871
|
+
k2hr3resutil_1.default.errResponse(req, res, 404, result); // 404: Not Found
|
|
1872
|
+
}
|
|
1873
|
+
else {
|
|
1874
|
+
const result = {
|
|
1875
|
+
result: false,
|
|
1876
|
+
message: k2hr3apiutil_1.default.isString(role_result.message) ? role_result.message : 'Could not get error message in response from get role token list'
|
|
1877
|
+
};
|
|
1878
|
+
dbglogging_1.default.elog(result.message);
|
|
1879
|
+
k2hr3resutil_1.default.errResponse(req, res, 404, result); // 404: Not Found
|
|
1880
|
+
}
|
|
1881
|
+
return;
|
|
1882
|
+
}
|
|
1883
|
+
// add register path into each role token elements
|
|
1884
|
+
if (expand && k2hr3tokens_1.default.isResTypeObjRoleTokens(role_result.tokens)) {
|
|
1885
|
+
Object.keys(role_result.tokens).forEach((oneToken) => {
|
|
1886
|
+
const regparamobj = {
|
|
1887
|
+
role: role,
|
|
1888
|
+
token: oneToken
|
|
1889
|
+
};
|
|
1890
|
+
const udproc = new k2hr3userdata_1.default();
|
|
1891
|
+
const regparamstr = udproc.encryptRoleInfo(regparamobj);
|
|
1892
|
+
if (!k2hr3apiutil_1.default.isSafeString(regparamstr) || !k2hr3tokens_1.default.isResTypeObjRoleTokens(role_result.tokens)) { // need to check type again(because scope is not same)
|
|
1893
|
+
dbglogging_1.default.elog('Could not create register url parameter with role token(' + JSON.stringify(oneToken) + '), but continue...');
|
|
1894
|
+
}
|
|
1895
|
+
else {
|
|
1896
|
+
role_result.tokens[oneToken].registerpath = regparamstr;
|
|
1897
|
+
}
|
|
1898
|
+
});
|
|
1899
|
+
}
|
|
1900
|
+
dbglogging_1.default.dlog('succeed : ' + k2hr3apiutil_1.default.getSafeString(role_result.message));
|
|
1901
|
+
res.status(200); // 200: OK
|
|
1902
|
+
res.send(JSON.stringify(role_result));
|
|
1903
|
+
};
|
|
1904
|
+
//---------------------------------------------------------
|
|
1905
|
+
// Router HEAD
|
|
1906
|
+
//---------------------------------------------------------
|
|
1907
|
+
//
|
|
1908
|
+
// Mountpath : '/v1/role/<role{/...}>'
|
|
1909
|
+
//
|
|
1910
|
+
// HEAD '/v1/role/<role{/...}>' : head role on version 1
|
|
1911
|
+
// HEADER : X-Auth-Token => User token or Role token or undefined
|
|
1912
|
+
// response : nothing
|
|
1913
|
+
// response status code : 204 or 4xx/5xx
|
|
1914
|
+
//
|
|
1915
|
+
// This mount point is for checking role existing or validation for role token/host ip address in role.
|
|
1916
|
+
//
|
|
1917
|
+
router.head('/', (req, res, next) => {
|
|
1918
|
+
dbglogging_1.default.dlog('CALL:', req.method, req.url, req.baseUrl);
|
|
1919
|
+
if ('HEAD' !== req.method) {
|
|
1920
|
+
// If other method request comes here, so it should be routed another function.
|
|
1921
|
+
next();
|
|
1922
|
+
return;
|
|
1923
|
+
}
|
|
1924
|
+
res.type('application/json; charset=utf-8');
|
|
1925
|
+
if (!k2hr3apiutil_1.default.isPlainObject(req) ||
|
|
1926
|
+
!k2hr3apiutil_1.default.isSafeString(req.baseUrl)) {
|
|
1927
|
+
dbglogging_1.default.elog('HEAD request or url or query is wrong');
|
|
1928
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
1929
|
+
return;
|
|
1930
|
+
}
|
|
1931
|
+
//------------------------------
|
|
1932
|
+
// check token for API mode
|
|
1933
|
+
//------------------------------
|
|
1934
|
+
let token_str = null;
|
|
1935
|
+
let token_type = null;
|
|
1936
|
+
let token_info = null;
|
|
1937
|
+
let keys = r3keys();
|
|
1938
|
+
if (k2hr3tokens_1.default.hasAuthTokenHeader(req)) {
|
|
1939
|
+
const token_result = k2hr3tokens_1.default.checkToken(req, true); // scoped, both token
|
|
1940
|
+
if (!token_result.result) {
|
|
1941
|
+
dbglogging_1.default.elog(token_result.message);
|
|
1942
|
+
k2hr3resutil_1.default.errResponse(req, res, token_result.status);
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1945
|
+
if (!k2hr3tokens_1.default.isResTypeCheckRoleToken(token_result.token_info)) {
|
|
1946
|
+
dbglogging_1.default.elog('specified wrong token or it is not scoped user token');
|
|
1947
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
1948
|
+
return;
|
|
1949
|
+
}
|
|
1950
|
+
token_info = token_result.token_info;
|
|
1951
|
+
token_str = token_result.token ?? null;
|
|
1952
|
+
token_type = token_result.token_type ?? null;
|
|
1953
|
+
keys = r3keys(token_info.user, token_info.tenant);
|
|
1954
|
+
}
|
|
1955
|
+
//------------------------------
|
|
1956
|
+
// get role name
|
|
1957
|
+
//------------------------------
|
|
1958
|
+
// check get token type and parse role name
|
|
1959
|
+
const requestptn = new RegExp(keys.MATCH_URI_GET_ROLE_DATA); // regex = /^\/v1\/role\/(.*)/
|
|
1960
|
+
const reqmatchs = decodeURI(req.baseUrl).match(requestptn);
|
|
1961
|
+
if (!k2hr3apiutil_1.default.isStringArray(reqmatchs) || !k2hr3apiutil_1.default.isNotEmptyArray(reqmatchs) || reqmatchs.length < 2 || '' === k2hr3apiutil_1.default.getSafeString(reqmatchs[1])) {
|
|
1962
|
+
dbglogging_1.default.elog('HEAD request url does not have role name');
|
|
1963
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
1964
|
+
return;
|
|
1965
|
+
}
|
|
1966
|
+
// check role name is only name or full yrn path and tenant name
|
|
1967
|
+
let tenantname;
|
|
1968
|
+
let rolename;
|
|
1969
|
+
let roleyrn = reqmatchs[1].toLowerCase();
|
|
1970
|
+
let roleyrnptn = new RegExp('^' + keys.MATCH_ANY_TENANT_ROLE); // regex = /^yrn:yahoo:(.*)::(.*):role:(.*)/
|
|
1971
|
+
const roleyrnmatchs = roleyrn.match(roleyrnptn);
|
|
1972
|
+
if (!k2hr3apiutil_1.default.isStringArray(roleyrnmatchs) || !k2hr3apiutil_1.default.isNotEmptyArray(roleyrnmatchs) || roleyrnmatchs.length < 4) {
|
|
1973
|
+
//
|
|
1974
|
+
// roleyrn is not full yrn to role, then check wrong role name
|
|
1975
|
+
//
|
|
1976
|
+
roleyrnptn = new RegExp('^' + keys.NO_TENANT_KEY); // regex = /^yrn:yahoo:/
|
|
1977
|
+
if (roleyrn.match(roleyrnptn)) {
|
|
1978
|
+
dbglogging_1.default.elog('HEAD request query has wrong yrn full path to role');
|
|
1979
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
1980
|
+
return;
|
|
1981
|
+
}
|
|
1982
|
+
// roleyrn is not full yrn, we need tenant name
|
|
1983
|
+
if (!k2hr3apiutil_1.default.isSafeString(keys.ROLE_TOP_KEY)) {
|
|
1984
|
+
dbglogging_1.default.elog('HEAD request role name which is not full yrn, and not token. role name must be full yrn, if token is not specified.');
|
|
1985
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
1986
|
+
return;
|
|
1987
|
+
}
|
|
1988
|
+
// make full yrn for role, and set tenant name/role name.
|
|
1989
|
+
tenantname = (k2hr3apiutil_1.default.isPlainObject(token_info) && k2hr3apiutil_1.default.isSafeString(token_info.tenant)) ? token_info.tenant : null;
|
|
1990
|
+
rolename = roleyrn;
|
|
1991
|
+
roleyrn = keys.ROLE_TOP_KEY + ':' + roleyrn;
|
|
1992
|
+
}
|
|
1993
|
+
else {
|
|
1994
|
+
//
|
|
1995
|
+
// roleyrn is full yrn to role.
|
|
1996
|
+
// need to check tenant name when token is specified.
|
|
1997
|
+
//
|
|
1998
|
+
if (null !== token_type && (!k2hr3apiutil_1.default.isPlainObject(token_info) || !k2hr3apiutil_1.default.isSafeString(token_info.tenant) || !k2hr3apiutil_1.default.compareCaseString(roleyrnmatchs[2], token_info.tenant))) {
|
|
1999
|
+
dbglogging_1.default.elog('HEAD request query has wrong tenant yrn full path(tenant=' + roleyrnmatchs[2] + ') or not specify tenant.');
|
|
2000
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2001
|
+
return;
|
|
2002
|
+
}
|
|
2003
|
+
// set tenant name/role name.
|
|
2004
|
+
tenantname = roleyrnmatchs[2];
|
|
2005
|
+
rolename = roleyrnmatchs[3];
|
|
2006
|
+
}
|
|
2007
|
+
//------------------------------
|
|
2008
|
+
// Run
|
|
2009
|
+
//------------------------------
|
|
2010
|
+
if (!k2hr3apiutil_1.default.isSafeString(token_type)) {
|
|
2011
|
+
// check host ip address in role
|
|
2012
|
+
const clientip = k2hr3apiutil_1.default.getClientIpAddress(req);
|
|
2013
|
+
if (!k2hr3apiutil_1.default.isSafeString(clientip)) {
|
|
2014
|
+
dbglogging_1.default.elog('HEAD request does not have ip address for client.');
|
|
2015
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2016
|
+
return;
|
|
2017
|
+
}
|
|
2018
|
+
// port
|
|
2019
|
+
let tg_port = 0;
|
|
2020
|
+
if (k2hr3apiutil_1.default.isSafeNumeric(req.query.port)) {
|
|
2021
|
+
const port_tmp = k2hr3apiutil_1.default.cvtToNumber(req.query.port);
|
|
2022
|
+
if (!k2hr3apiutil_1.default.isSafeNumber(port_tmp)) {
|
|
2023
|
+
dbglogging_1.default.elog('HEAD request has port which is not number: ' + JSON.stringify(req.query.port));
|
|
2024
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2025
|
+
return;
|
|
2026
|
+
}
|
|
2027
|
+
tg_port = port_tmp;
|
|
2028
|
+
}
|
|
2029
|
+
// cuk
|
|
2030
|
+
let tg_cuk = null;
|
|
2031
|
+
if (k2hr3apiutil_1.default.isPlainObject(req.query) && k2hr3apiutil_1.default.isSafeString(req.query.cuk) && k2hr3apiutil_1.default.isSafeString(req.query.cuk.trim())) {
|
|
2032
|
+
tg_cuk = req.query.cuk.trim();
|
|
2033
|
+
}
|
|
2034
|
+
// find host
|
|
2035
|
+
const find_result = k2hr3dkc_1.default.findHost(tenantname, rolename, null, clientip, tg_port, tg_cuk, false); // not strictly checking
|
|
2036
|
+
// result
|
|
2037
|
+
if (!find_result.result) {
|
|
2038
|
+
dbglogging_1.default.elog('HEAD request failure - check host ip(' + clientip + ') address in role(tenant=' + tenantname + ', role=' + rolename + ') host');
|
|
2039
|
+
k2hr3resutil_1.default.errResponse(req, res, 403); // 403: Forbidden
|
|
2040
|
+
return;
|
|
2041
|
+
}
|
|
2042
|
+
else {
|
|
2043
|
+
dbglogging_1.default.dlog('HEAD request succeed - check host ip(' + clientip + ') address in role(tenant=' + tenantname + ', role=' + rolename + ') host');
|
|
2044
|
+
res.status(204); // 204: No Content
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
else if ('role' === k2hr3apiutil_1.default.getSafeString(token_type)) {
|
|
2048
|
+
// check role token
|
|
2049
|
+
const check_result = k2hr3tokens_1.default.checkToken(req, true, false); // recheck - scoped, both token
|
|
2050
|
+
// result
|
|
2051
|
+
if (!check_result.result) {
|
|
2052
|
+
dbglogging_1.default.elog('HEAD request failure - check role token(' + JSON.stringify(token_str) + ') : ' + k2hr3apiutil_1.default.getSafeString(check_result.message));
|
|
2053
|
+
k2hr3resutil_1.default.errResponse(req, res, 403); // 403: Forbidden
|
|
2054
|
+
return;
|
|
2055
|
+
}
|
|
2056
|
+
else {
|
|
2057
|
+
dbglogging_1.default.dlog('HEAD request succeed - check role token(' + JSON.stringify(token_str) + ')');
|
|
2058
|
+
res.status(204); // 204: No Content
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
else if ('user' === k2hr3apiutil_1.default.getSafeString(token_type)) {
|
|
2062
|
+
// check role exist
|
|
2063
|
+
const role_result = k2hr3dkc_1.default.getRole(roleyrn, true);
|
|
2064
|
+
// result
|
|
2065
|
+
if (!role_result.result) {
|
|
2066
|
+
dbglogging_1.default.elog('HEAD request failure - check role(' + roleyrn + ') exist');
|
|
2067
|
+
k2hr3resutil_1.default.errResponse(req, res, 403); // 403: Forbidden
|
|
2068
|
+
return;
|
|
2069
|
+
}
|
|
2070
|
+
else {
|
|
2071
|
+
dbglogging_1.default.dlog('HEAD request succeed - check role(' + roleyrn + ') exists');
|
|
2072
|
+
res.status(204); // 204: No Content
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
else {
|
|
2076
|
+
// broken token
|
|
2077
|
+
dbglogging_1.default.elog('HEAD request is failure by internal error(token data broken).');
|
|
2078
|
+
k2hr3resutil_1.default.errResponse(req, res, 500); // 500: Internal Error
|
|
2079
|
+
return;
|
|
2080
|
+
}
|
|
2081
|
+
res.send();
|
|
2082
|
+
});
|
|
2083
|
+
//---------------------------------------------------------
|
|
2084
|
+
// Router DELETE
|
|
2085
|
+
//---------------------------------------------------------
|
|
2086
|
+
//
|
|
2087
|
+
// Mountpath : '/v1/role/<role{/...}>'
|
|
2088
|
+
//
|
|
2089
|
+
// DELETE '/v1/role/<role{/...}>' : delete role member host on version 1
|
|
2090
|
+
// HEADER : X-Auth-Token => undefined
|
|
2091
|
+
// URL arguments
|
|
2092
|
+
// "port": <port number> : this value is number string(0-), allowed null and '' for this value.
|
|
2093
|
+
// "cuk": <container unique key> : this value is string. if this value is undefined/null/empty string, it means any.
|
|
2094
|
+
// response : nothing
|
|
2095
|
+
// response status code : 204 or 4xx/5xx
|
|
2096
|
+
//
|
|
2097
|
+
// The role's host member removes itself from the role without any token.
|
|
2098
|
+
// Whether a role member is a host is automatically determined by client ip, port, and cuk.
|
|
2099
|
+
//
|
|
2100
|
+
//
|
|
2101
|
+
// DELETE '/v1/role/<role{/...}>' : delete role token on version 1
|
|
2102
|
+
// HEADER : X-Auth-Token => Role token
|
|
2103
|
+
// URL arguments : n/a
|
|
2104
|
+
// response : nothing
|
|
2105
|
+
// response status code : 204 or 4xx/5xx
|
|
2106
|
+
//
|
|
2107
|
+
// Delete the role token by role token.
|
|
2108
|
+
//
|
|
2109
|
+
//
|
|
2110
|
+
// DELETE '/v1/role/<role{/...}>' : delete role member hosts or ip addresses on version 1
|
|
2111
|
+
// HEADER : X-Auth-Token => User Scoped token
|
|
2112
|
+
// URL arguments
|
|
2113
|
+
// "host": <string, JSON string array> : this value is string for one IP address, or string array encoded JSON string
|
|
2114
|
+
// for IP addresses.
|
|
2115
|
+
// "port": <port number> : this value is number string(0-), allowed null and '' for this value.
|
|
2116
|
+
// "cuk": <container unique key> : this value is string. if this value is undefined/null/empty string, it means any.
|
|
2117
|
+
// response : nothing
|
|
2118
|
+
// response status code : 204 or 4xx/5xx
|
|
2119
|
+
//
|
|
2120
|
+
// Delete the role host(ip address)s member.
|
|
2121
|
+
//
|
|
2122
|
+
//
|
|
2123
|
+
// DELETE '/v1/role/<role{/...}>' : delete role member hosts or ip addresses on version 1
|
|
2124
|
+
// HEADER : X-Auth-Token => User Scoped token
|
|
2125
|
+
// URL arguments : n/a
|
|
2126
|
+
// response : nothing
|
|
2127
|
+
// response status code : 204 or 4xx/5xx
|
|
2128
|
+
//
|
|
2129
|
+
// Delete the role.
|
|
2130
|
+
//
|
|
2131
|
+
//---------------------------------------------------------
|
|
2132
|
+
//
|
|
2133
|
+
// Mountpath : '/v1/role/token/<role token>'
|
|
2134
|
+
//
|
|
2135
|
+
// DELETE '/v1/role/token/<role token>' : delete role token on version 1
|
|
2136
|
+
// HEADER : X-Auth-Token => User Scoped token
|
|
2137
|
+
// URL arguments : undefined
|
|
2138
|
+
// response : nothing
|
|
2139
|
+
// response status code : 204 or 4xx/5xx
|
|
2140
|
+
//
|
|
2141
|
+
// Delete the role token by user.
|
|
2142
|
+
//
|
|
2143
|
+
//---------------------------------------------------------
|
|
2144
|
+
//
|
|
2145
|
+
// Mountpath : '/v1/role'
|
|
2146
|
+
//
|
|
2147
|
+
// DELETE '/v1/role' : delete role member by cuk on version 1
|
|
2148
|
+
// URL arguments
|
|
2149
|
+
// "cuk": <container unique key> : this value is string.
|
|
2150
|
+
// Specify the Container Unique Id to be deleted.
|
|
2151
|
+
// Role members associated with this Id will be deleted.
|
|
2152
|
+
// "host": <string, JSON string array> : this value is string for one IP address, or string array encoded JSON string
|
|
2153
|
+
// for IP addresses.
|
|
2154
|
+
// response : nothing
|
|
2155
|
+
// response status code : 204 or 4xx/5xx
|
|
2156
|
+
//
|
|
2157
|
+
//
|
|
2158
|
+
// This mount point is for deleting ip addresses from roles by container unique key which includes ip addresses.
|
|
2159
|
+
// The requester must be role member which is allowed to access this mount point for removing IP address by cuk.
|
|
2160
|
+
//
|
|
2161
|
+
router.delete('/', (req, res, _) => {
|
|
2162
|
+
dbglogging_1.default.dlog('CALL:', req.method, req.url, req.baseUrl);
|
|
2163
|
+
res.type('application/json; charset=utf-8');
|
|
2164
|
+
if (!k2hr3apiutil_1.default.isPlainObject(req) ||
|
|
2165
|
+
!k2hr3apiutil_1.default.isSafeString(req.baseUrl)) {
|
|
2166
|
+
dbglogging_1.default.elog('DELETE request or url or query is wrong');
|
|
2167
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2168
|
+
return;
|
|
2169
|
+
}
|
|
2170
|
+
//
|
|
2171
|
+
// Check Path type and branch
|
|
2172
|
+
//
|
|
2173
|
+
const keys = r3keys();
|
|
2174
|
+
let is_delete_token = false;
|
|
2175
|
+
let is_delete_ip = false;
|
|
2176
|
+
const urlpath = decodeURI(req.baseUrl);
|
|
2177
|
+
const requestptn = new RegExp(keys.MATCH_URI_GET_RTOKEN); // regex = /^\/v1\/role\/token\/(.*)/
|
|
2178
|
+
const reqmatchs = urlpath.match(requestptn);
|
|
2179
|
+
if (k2hr3apiutil_1.default.isStringArray(reqmatchs) && k2hr3apiutil_1.default.isNotEmptyArray(reqmatchs) && 2 <= reqmatchs.length && '' !== k2hr3apiutil_1.default.getSafeString(reqmatchs[1])) {
|
|
2180
|
+
// get token
|
|
2181
|
+
is_delete_token = true;
|
|
2182
|
+
}
|
|
2183
|
+
else {
|
|
2184
|
+
// recheck simply
|
|
2185
|
+
if (k2hr3apiutil_1.default.isSafeString(urlpath) && (urlpath == '/v1/role' || urlpath == '/v1/role/')) {
|
|
2186
|
+
// urlpath is /v1/role, this is to delete ip address by cuk
|
|
2187
|
+
is_delete_ip = true;
|
|
2188
|
+
}
|
|
2189
|
+
else {
|
|
2190
|
+
// urlpath is not /v1/role, expected /v1/role/<role>, this is to delete role.
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
// Run
|
|
2194
|
+
if (is_delete_token) {
|
|
2195
|
+
// delete role token.
|
|
2196
|
+
if (!rawDeleteRoleToken(req, res)) {
|
|
2197
|
+
dbglogging_1.default.elog('failed to delete role token.');
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
else if (is_delete_ip) {
|
|
2201
|
+
// delete ip address by cuk
|
|
2202
|
+
if (!rawDeleteIpsByCuk(req, res)) {
|
|
2203
|
+
dbglogging_1.default.elog('failed to delete ip address by cuk.');
|
|
2204
|
+
}
|
|
2205
|
+
}
|
|
2206
|
+
else {
|
|
2207
|
+
// delete role / role token.
|
|
2208
|
+
if (!rawDeleteRoleByPath(req, res)) {
|
|
2209
|
+
dbglogging_1.default.elog('failed to delete role.');
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
res.send();
|
|
2213
|
+
});
|
|
2214
|
+
//
|
|
2215
|
+
// Utility for deleting role / role token
|
|
2216
|
+
//
|
|
2217
|
+
const rawDeleteRoleByPath = (req, res) => {
|
|
2218
|
+
//------------------------------
|
|
2219
|
+
// check token for API mode
|
|
2220
|
+
//------------------------------
|
|
2221
|
+
let token_str = null;
|
|
2222
|
+
let token_type = null;
|
|
2223
|
+
let token_info = null;
|
|
2224
|
+
let keys = r3keys();
|
|
2225
|
+
if (k2hr3tokens_1.default.hasAuthTokenHeader(req)) {
|
|
2226
|
+
const token_result = k2hr3tokens_1.default.checkToken(req, true); // scoped, both token
|
|
2227
|
+
if (!token_result.result) {
|
|
2228
|
+
dbglogging_1.default.elog(token_result.message);
|
|
2229
|
+
k2hr3resutil_1.default.errResponse(req, res, token_result.status);
|
|
2230
|
+
return false;
|
|
2231
|
+
}
|
|
2232
|
+
if (!k2hr3tokens_1.default.isResTypeCheckRoleToken(token_result.token_info)) {
|
|
2233
|
+
dbglogging_1.default.elog('specified wrong token or it is not scoped user token');
|
|
2234
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2235
|
+
return false;
|
|
2236
|
+
}
|
|
2237
|
+
token_info = token_result.token_info;
|
|
2238
|
+
token_str = token_result.token ?? null;
|
|
2239
|
+
token_type = token_result.token_type ?? null;
|
|
2240
|
+
keys = r3keys(token_info.user, token_info.tenant);
|
|
2241
|
+
}
|
|
2242
|
+
//------------------------------
|
|
2243
|
+
// get role name
|
|
2244
|
+
//------------------------------
|
|
2245
|
+
// check get token type and parse role name
|
|
2246
|
+
const requestptn = new RegExp(keys.MATCH_URI_GET_ROLE_DATA); // regex = /^\/v1\/role\/(.*)/
|
|
2247
|
+
const reqmatchs = decodeURI(req.baseUrl).match(requestptn);
|
|
2248
|
+
if (!k2hr3apiutil_1.default.isStringArray(reqmatchs) || !k2hr3apiutil_1.default.isNotEmptyArray(reqmatchs) || reqmatchs.length < 2 || '' === k2hr3apiutil_1.default.getSafeString(reqmatchs[1])) {
|
|
2249
|
+
dbglogging_1.default.elog('DELETE request url does not have role name');
|
|
2250
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2251
|
+
return false;
|
|
2252
|
+
}
|
|
2253
|
+
// check role name is only name or full yrn path and tenant name
|
|
2254
|
+
let tenantname;
|
|
2255
|
+
let rolename;
|
|
2256
|
+
let roleyrn = reqmatchs[1].toLowerCase();
|
|
2257
|
+
let roleyrnptn = new RegExp('^' + keys.MATCH_ANY_TENANT_ROLE); // regex = /^yrn:yahoo:(.*)::(.*):role:(.*)/
|
|
2258
|
+
const roleyrnmatchs = roleyrn.match(roleyrnptn);
|
|
2259
|
+
if (!k2hr3apiutil_1.default.isStringArray(roleyrnmatchs) || !k2hr3apiutil_1.default.isNotEmptyArray(roleyrnmatchs) || roleyrnmatchs.length < 4) {
|
|
2260
|
+
//
|
|
2261
|
+
// roleyrn is not full yrn to role, then check wrong role name
|
|
2262
|
+
//
|
|
2263
|
+
roleyrnptn = new RegExp('^' + keys.NO_TENANT_KEY); // regex = /^yrn:yahoo:/
|
|
2264
|
+
if (roleyrn.match(roleyrnptn)) {
|
|
2265
|
+
dbglogging_1.default.elog('DELETE request query has wrong yrn full path to role');
|
|
2266
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2267
|
+
return false;
|
|
2268
|
+
}
|
|
2269
|
+
// roleyrn is not full yrn, we need tenant name
|
|
2270
|
+
if (!k2hr3apiutil_1.default.isSafeString(keys.ROLE_TOP_KEY)) {
|
|
2271
|
+
dbglogging_1.default.elog('DELETE request role name which is not full yrn, and not token. role name must be full yrn, if token is not specified.');
|
|
2272
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2273
|
+
return false;
|
|
2274
|
+
}
|
|
2275
|
+
// make full yrn for role, and set tenant name/role name.
|
|
2276
|
+
tenantname = (k2hr3apiutil_1.default.isPlainObject(token_info) && k2hr3apiutil_1.default.isSafeString(token_info.tenant)) ? token_info.tenant : null;
|
|
2277
|
+
rolename = roleyrn;
|
|
2278
|
+
roleyrn = keys.ROLE_TOP_KEY + ':' + roleyrn;
|
|
2279
|
+
}
|
|
2280
|
+
else {
|
|
2281
|
+
//
|
|
2282
|
+
// roleyrn is full yrn to role.
|
|
2283
|
+
// need to check tenant name when token is specified.
|
|
2284
|
+
//
|
|
2285
|
+
if (null !== token_type && (!k2hr3apiutil_1.default.isPlainObject(token_info) || !k2hr3apiutil_1.default.isSafeString(token_info.tenant) || !k2hr3apiutil_1.default.compareCaseString(roleyrnmatchs[2], token_info.tenant))) {
|
|
2286
|
+
dbglogging_1.default.elog('DELETE request query has wrong tenant yrn full path(tenant=' + roleyrnmatchs[2] + ') or not specify tenant.');
|
|
2287
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2288
|
+
return false;
|
|
2289
|
+
}
|
|
2290
|
+
// set tenant name/role name.
|
|
2291
|
+
tenantname = roleyrnmatchs[2];
|
|
2292
|
+
rolename = roleyrnmatchs[3];
|
|
2293
|
+
}
|
|
2294
|
+
//------------------------------
|
|
2295
|
+
// Run
|
|
2296
|
+
//------------------------------
|
|
2297
|
+
if (!k2hr3apiutil_1.default.isSafeString(token_type)) {
|
|
2298
|
+
// remove host ip address in role
|
|
2299
|
+
const clientip = k2hr3apiutil_1.default.getClientIpAddress(req);
|
|
2300
|
+
if (!k2hr3apiutil_1.default.isSafeString(clientip)) {
|
|
2301
|
+
dbglogging_1.default.elog('DELETE request does not have ip address for client.');
|
|
2302
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2303
|
+
return false;
|
|
2304
|
+
}
|
|
2305
|
+
// check port
|
|
2306
|
+
let port = 0;
|
|
2307
|
+
if (k2hr3apiutil_1.default.isSafeNumeric(req.query.port)) {
|
|
2308
|
+
const port_tmp = k2hr3apiutil_1.default.cvtToNumber(req.query.port);
|
|
2309
|
+
if (!k2hr3apiutil_1.default.isSafeNumber(port_tmp)) {
|
|
2310
|
+
dbglogging_1.default.elog('DELETE request has port which is not number: ' + JSON.stringify(req.query.port));
|
|
2311
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2312
|
+
return false;
|
|
2313
|
+
}
|
|
2314
|
+
port = port_tmp;
|
|
2315
|
+
}
|
|
2316
|
+
// check cuk parameter
|
|
2317
|
+
let cuk = null;
|
|
2318
|
+
if (k2hr3apiutil_1.default.isPlainObject(req.query) && k2hr3apiutil_1.default.isSafeString(req.query.cuk) && k2hr3apiutil_1.default.isSafeString(req.query.cuk.trim())) {
|
|
2319
|
+
cuk = k2hr3apiutil_1.default.getSafeString(req.query.cuk).trim();
|
|
2320
|
+
}
|
|
2321
|
+
// remove host(check requester and requester is target)
|
|
2322
|
+
const rm_result = k2hr3dkc_1.default.removeHost(tenantname, rolename, clientip, port, cuk, clientip, port, cuk);
|
|
2323
|
+
// result
|
|
2324
|
+
if (!rm_result.result) {
|
|
2325
|
+
dbglogging_1.default.elog('DELETE request failure - remove host by ip(' + clientip + ':' + String(port) + ') address, cuk(' + JSON.stringify(cuk) + ') in role(tenant=' + tenantname + ', role=' + rolename + ') host');
|
|
2326
|
+
k2hr3resutil_1.default.errResponse(req, res, 403); // 403: Forbidden
|
|
2327
|
+
return false;
|
|
2328
|
+
}
|
|
2329
|
+
else {
|
|
2330
|
+
dbglogging_1.default.dlog('DELETE request succeed - remove host by ip(' + clientip + ':' + String(port) + ') address, cuk(' + JSON.stringify(cuk) + ') in role(tenant=' + tenantname + ', role=' + rolename + ') host');
|
|
2331
|
+
res.status(204); // 204: No Content
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
else if ('role' === k2hr3apiutil_1.default.getSafeString(token_type) && k2hr3apiutil_1.default.isPlainObject(token_info)) {
|
|
2335
|
+
// remove role token
|
|
2336
|
+
const clientip = k2hr3apiutil_1.default.getClientIpAddress(req);
|
|
2337
|
+
if (!k2hr3apiutil_1.default.isSafeString(clientip)) {
|
|
2338
|
+
dbglogging_1.default.elog('DELETE request does not have ip address for client.');
|
|
2339
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2340
|
+
return false;
|
|
2341
|
+
}
|
|
2342
|
+
// check full role yrn path in token and path
|
|
2343
|
+
if (!k2hr3apiutil_1.default.isSafeString(token_info.role) || token_info.role != roleyrn) {
|
|
2344
|
+
dbglogging_1.default.elog('DELETE request is something wrong, the role token(' + JSON.stringify(token_info.role) + ') and role path(' + JSON.stringify(roleyrn) + ') do not match.');
|
|
2345
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2346
|
+
return false;
|
|
2347
|
+
}
|
|
2348
|
+
// check for k8s cuk/port
|
|
2349
|
+
let port = 0;
|
|
2350
|
+
let cuk;
|
|
2351
|
+
if (k2hr3apiutil_1.default.isSafeString(token_info.extra) && token_info.extra === keys.VALUE_K8S_V1) {
|
|
2352
|
+
// cuk
|
|
2353
|
+
if (!k2hr3apiutil_1.default.isPlainObject(req.query) || !k2hr3apiutil_1.default.isSafeString(req.query.cuk) || !k2hr3apiutil_1.default.isSafeString(req.query.cuk.trim())) {
|
|
2354
|
+
dbglogging_1.default.elog('DELETE request need cuk parameter for deleting role token which is made for k8s.');
|
|
2355
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2356
|
+
return false;
|
|
2357
|
+
}
|
|
2358
|
+
cuk = k2hr3apiutil_1.default.getSafeString(req.query.cuk).trim();
|
|
2359
|
+
if (!k2hr3apiutil_1.default.isSafeString(token_info.cuk) || token_info.cuk != cuk) {
|
|
2360
|
+
dbglogging_1.default.elog('DELETE request cuk(' + JSON.stringify(cuk) + ') parameter is invalid.');
|
|
2361
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2362
|
+
return false;
|
|
2363
|
+
}
|
|
2364
|
+
// port
|
|
2365
|
+
if (k2hr3apiutil_1.default.isPlainObject(req.query) && k2hr3apiutil_1.default.isSafeNumeric(req.query.port)) {
|
|
2366
|
+
const port_tmp = k2hr3apiutil_1.default.cvtToNumber(req.query.port);
|
|
2367
|
+
if (!k2hr3apiutil_1.default.isSafeNumber(port_tmp)) {
|
|
2368
|
+
dbglogging_1.default.elog('DELETE request has port which is not number: ' + JSON.stringify(req.query.port));
|
|
2369
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2370
|
+
return false;
|
|
2371
|
+
}
|
|
2372
|
+
port = port_tmp;
|
|
2373
|
+
}
|
|
2374
|
+
if (!k2hr3apiutil_1.default.isSafeNumber(token_info.port) || token_info.port != port) {
|
|
2375
|
+
dbglogging_1.default.elog('DELETE request port(' + JSON.stringify(port) + ') parameter is invalid.');
|
|
2376
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2377
|
+
return false;
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2380
|
+
// remove role token
|
|
2381
|
+
const rm_result = k2hr3tokens_1.default.removeRoleTokenByIP(token_str, clientip, token_info.port, token_info.cuk);
|
|
2382
|
+
// result
|
|
2383
|
+
if (!rm_result.result) {
|
|
2384
|
+
dbglogging_1.default.elog('DELETE request failure - remove role token(' + JSON.stringify(token_str) + ')');
|
|
2385
|
+
k2hr3resutil_1.default.errResponse(req, res, 403); // 403: Forbidden
|
|
2386
|
+
return false;
|
|
2387
|
+
}
|
|
2388
|
+
else {
|
|
2389
|
+
dbglogging_1.default.dlog('DELETE request succeed - remove role token(' + JSON.stringify(token_str) + ')');
|
|
2390
|
+
res.status(204); // 204: No Content
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2393
|
+
else if ('user' === k2hr3apiutil_1.default.getSafeString(token_type) && k2hr3apiutil_1.default.isPlainObject(token_info)) {
|
|
2394
|
+
if (k2hr3apiutil_1.default.isPlainObject(req.query) && k2hr3apiutil_1.default.isSafeString(req.query.host)) {
|
|
2395
|
+
// remove host(hostname or ip address) in role
|
|
2396
|
+
let tg_host;
|
|
2397
|
+
const tmp_str_host = k2hr3apiutil_1.default.getSafeString(req.query.host);
|
|
2398
|
+
const tmp_arr_host = k2hr3apiutil_1.default.parseJSON(req.query.host);
|
|
2399
|
+
if (k2hr3apiutil_1.default.isStringArray(tmp_arr_host) && k2hr3apiutil_1.default.isNotEmptyArray(tmp_arr_host)) {
|
|
2400
|
+
tg_host = tmp_arr_host;
|
|
2401
|
+
}
|
|
2402
|
+
else {
|
|
2403
|
+
tg_host = [tmp_str_host];
|
|
2404
|
+
}
|
|
2405
|
+
// check port
|
|
2406
|
+
let port = 0;
|
|
2407
|
+
if (k2hr3apiutil_1.default.isSafeNumeric(req.query.port)) {
|
|
2408
|
+
const port_tmp = k2hr3apiutil_1.default.cvtToNumber(req.query.port);
|
|
2409
|
+
if (!k2hr3apiutil_1.default.isSafeNumber(port_tmp)) {
|
|
2410
|
+
dbglogging_1.default.elog('GET request has port which is not number: ' + JSON.stringify(req.query.port));
|
|
2411
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2412
|
+
return false;
|
|
2413
|
+
}
|
|
2414
|
+
port = port_tmp;
|
|
2415
|
+
}
|
|
2416
|
+
// check cuk parameter
|
|
2417
|
+
let cuk = null;
|
|
2418
|
+
if (k2hr3apiutil_1.default.isSafeString(req.query.cuk) && k2hr3apiutil_1.default.isSafeString(req.query.cuk.trim())) {
|
|
2419
|
+
cuk = k2hr3apiutil_1.default.getSafeString(req.query.cuk).trim();
|
|
2420
|
+
}
|
|
2421
|
+
// remove host(not check requester)
|
|
2422
|
+
const rm_result = k2hr3dkc_1.default.removeHost(tenantname, rolename, tg_host, port, cuk);
|
|
2423
|
+
// result
|
|
2424
|
+
if (!rm_result.result) {
|
|
2425
|
+
dbglogging_1.default.elog('DELETE request failure - remove host(' + k2hr3apiutil_1.default.getSafeString(tg_host) + ':' + String(port) + ') address, cuk(' + JSON.stringify(cuk) + ') in role(tenant=' + tenantname + ', role=' + rolename + ') host');
|
|
2426
|
+
k2hr3resutil_1.default.errResponse(req, res, 403); // 403: Forbidden
|
|
2427
|
+
return false;
|
|
2428
|
+
}
|
|
2429
|
+
else {
|
|
2430
|
+
dbglogging_1.default.dlog('DELETE request succeed - remove host(' + k2hr3apiutil_1.default.getSafeString(tg_host) + ':' + String(port) + ') address, cuk(' + JSON.stringify(cuk) + ') in role(tenant=' + tenantname + ', role=' + rolename + ') host');
|
|
2431
|
+
res.status(204); // 204: No Content
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
else {
|
|
2435
|
+
// remove role
|
|
2436
|
+
const rm_result = k2hr3dkc_1.default.removeRole(token_info.user, tenantname, rolename);
|
|
2437
|
+
// result
|
|
2438
|
+
if (!rm_result.result) {
|
|
2439
|
+
dbglogging_1.default.elog('DELETE request failure - remove role(' + rolename + ') exist');
|
|
2440
|
+
k2hr3resutil_1.default.errResponse(req, res, 403); // 403: Forbidden
|
|
2441
|
+
return false;
|
|
2442
|
+
}
|
|
2443
|
+
else {
|
|
2444
|
+
dbglogging_1.default.dlog('DELETE request succeed - remove role(' + rolename + ') exists');
|
|
2445
|
+
res.status(204); // 204: No Content
|
|
2446
|
+
}
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
else {
|
|
2450
|
+
// broken token
|
|
2451
|
+
dbglogging_1.default.elog('DELETE request is failure by internal error(token data broken).');
|
|
2452
|
+
k2hr3resutil_1.default.errResponse(req, res, 500); // 500: Internal Error
|
|
2453
|
+
return false;
|
|
2454
|
+
}
|
|
2455
|
+
return true;
|
|
2456
|
+
};
|
|
2457
|
+
//
|
|
2458
|
+
// Utility for deleting ip address by cuk
|
|
2459
|
+
//
|
|
2460
|
+
const rawDeleteIpsByCuk = (req, res) => {
|
|
2461
|
+
const keys = r3keys();
|
|
2462
|
+
const clientip = k2hr3apiutil_1.default.getClientIpAddress(req);
|
|
2463
|
+
if (!k2hr3apiutil_1.default.isSafeString(clientip)) {
|
|
2464
|
+
dbglogging_1.default.elog('DELETE request does not have ip address for client');
|
|
2465
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2466
|
+
return false;
|
|
2467
|
+
}
|
|
2468
|
+
//------------------------------
|
|
2469
|
+
// check arguments
|
|
2470
|
+
//------------------------------
|
|
2471
|
+
if (!k2hr3apiutil_1.default.isPlainObject(req.query)) {
|
|
2472
|
+
dbglogging_1.default.elog('DELETE request has no query parameter');
|
|
2473
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2474
|
+
return false;
|
|
2475
|
+
}
|
|
2476
|
+
let tg_host = [];
|
|
2477
|
+
if (k2hr3apiutil_1.default.isSafeEntity(req.query.host)) {
|
|
2478
|
+
const tmp_str_host = k2hr3apiutil_1.default.getSafeString(req.query.host).trim();
|
|
2479
|
+
const tmp_arr_host = k2hr3apiutil_1.default.parseJSON(tmp_str_host);
|
|
2480
|
+
if (k2hr3apiutil_1.default.isStringArray(tmp_arr_host) && k2hr3apiutil_1.default.isNotEmptyArray(tmp_arr_host)) {
|
|
2481
|
+
tg_host = tmp_arr_host.slice(0, tmp_arr_host.length);
|
|
2482
|
+
}
|
|
2483
|
+
else if (k2hr3apiutil_1.default.isSafeString(tmp_str_host)) {
|
|
2484
|
+
tg_host.push(tmp_str_host);
|
|
2485
|
+
}
|
|
2486
|
+
else {
|
|
2487
|
+
dbglogging_1.default.dlog('DELETE request has no host parameter, it means removing all host in cuk: ' + JSON.stringify(req.query.cuk));
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
// cuk parameter
|
|
2491
|
+
if (!k2hr3apiutil_1.default.isSafeString(req.query.cuk) || !k2hr3apiutil_1.default.isSafeString(req.query.cuk.trim())) {
|
|
2492
|
+
dbglogging_1.default.elog('DELETE request has invalid cuk parameter: ' + JSON.stringify(req.query.cuk));
|
|
2493
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2494
|
+
return false;
|
|
2495
|
+
}
|
|
2496
|
+
const tg_cuk = req.query.cuk.trim();
|
|
2497
|
+
const tg_extra = k2hr3dkc_1.default.getExtraFromCuk(tg_cuk);
|
|
2498
|
+
// Check client ip address
|
|
2499
|
+
if (tg_extra == keys.VALUE_K8S_V1) {
|
|
2500
|
+
// for kubernetes
|
|
2501
|
+
// check client ip address is the host itself to be removed
|
|
2502
|
+
//
|
|
2503
|
+
// [NOTE]
|
|
2504
|
+
// if result is true, it means client ip address is cuk's node ip address.
|
|
2505
|
+
// after that, the comparison between the cuk object data contents and the cuk data
|
|
2506
|
+
// in k2hdkc linked to the this ip address is done in removeIpsByCuk() function.
|
|
2507
|
+
//
|
|
2508
|
+
if (!k2hr3dkc_1.default.compareIpAndKubernetesCuk(clientip, tg_cuk)) {
|
|
2509
|
+
// client ip is not as same as cuk's node ip address,
|
|
2510
|
+
// then retry to compare delhost ip in config and it.
|
|
2511
|
+
const adminips = k2hr3dkc_1.default.findRoleHost(null, delhost_role_yrn, null, clientip, 0, null); // not strict checking for admin delhost host
|
|
2512
|
+
if (!k2hr3apiutil_1.default.isArray(adminips)) {
|
|
2513
|
+
dbglogging_1.default.elog('DELETE request from ip address(' + JSON.stringify(clientip) + ') is not role(' + JSON.stringify(delhost_role_yrn) + ') member.');
|
|
2514
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2515
|
+
return false;
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
else if (tg_extra == keys.VALUE_OPENSTACK_V1) {
|
|
2520
|
+
// for openstack
|
|
2521
|
+
// In case of openstack, when deleting without token, it can be deleted only from
|
|
2522
|
+
// the IP address registered as delhost ip in config.
|
|
2523
|
+
//
|
|
2524
|
+
// Check client ip address is in role admin member ip address.
|
|
2525
|
+
const adminips = k2hr3dkc_1.default.findRoleHost(null, delhost_role_yrn, null, clientip, 0, null); // not strict checking for admin delhost host
|
|
2526
|
+
if (!k2hr3apiutil_1.default.isArray(adminips)) {
|
|
2527
|
+
dbglogging_1.default.elog('DELETE request from ip address(' + JSON.stringify(clientip) + ') is not role(' + JSON.stringify(delhost_role_yrn) + ') member.');
|
|
2528
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2529
|
+
return false;
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
else {
|
|
2533
|
+
// Currently supports only openstack and kubernetes
|
|
2534
|
+
dbglogging_1.default.elog('DELETE request has unknown extra type in cuk parameter: ' + JSON.stringify(req.query.cuk));
|
|
2535
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2536
|
+
return false;
|
|
2537
|
+
}
|
|
2538
|
+
//------------------------------
|
|
2539
|
+
// Run
|
|
2540
|
+
//------------------------------
|
|
2541
|
+
const resobj = k2hr3dkc_1.default.removeIpsByCuk(tg_cuk, tg_host, true);
|
|
2542
|
+
if (!k2hr3apiutil_1.default.isPlainObject(resobj) || !k2hr3apiutil_1.default.isBoolean(resobj.result) || false === resobj.result) {
|
|
2543
|
+
if (k2hr3apiutil_1.default.isPlainObject(resobj) && k2hr3apiutil_1.default.isString(resobj.message)) {
|
|
2544
|
+
dbglogging_1.default.elog('DELETE request failed by ' + resobj.message);
|
|
2545
|
+
}
|
|
2546
|
+
else {
|
|
2547
|
+
dbglogging_1.default.elog('DELETE request failed by unknown reason.');
|
|
2548
|
+
}
|
|
2549
|
+
k2hr3resutil_1.default.errResponse(req, res, 403); // 403: Forbidden(is this status OK?)
|
|
2550
|
+
return false;
|
|
2551
|
+
}
|
|
2552
|
+
dbglogging_1.default.dlog('succeed : ' + k2hr3apiutil_1.default.getSafeString(resobj.message));
|
|
2553
|
+
res.status(204); // 204: No Content
|
|
2554
|
+
return true;
|
|
2555
|
+
};
|
|
2556
|
+
//
|
|
2557
|
+
// Utility for deleting role token
|
|
2558
|
+
//
|
|
2559
|
+
const rawDeleteRoleToken = (req, res) => {
|
|
2560
|
+
if (!k2hr3apiutil_1.default.isPlainObject(req) ||
|
|
2561
|
+
!k2hr3apiutil_1.default.isSafeString(req.baseUrl)) {
|
|
2562
|
+
dbglogging_1.default.elog('DELETE request or url or query is wrong');
|
|
2563
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2564
|
+
return false;
|
|
2565
|
+
}
|
|
2566
|
+
//------------------------------
|
|
2567
|
+
// check token
|
|
2568
|
+
//------------------------------
|
|
2569
|
+
if (!k2hr3tokens_1.default.hasAuthTokenHeader(req)) {
|
|
2570
|
+
dbglogging_1.default.elog('DELETE request does not have any auth token.');
|
|
2571
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2572
|
+
return false;
|
|
2573
|
+
}
|
|
2574
|
+
const token_result = k2hr3tokens_1.default.checkToken(req, true, true); // scoped, user token
|
|
2575
|
+
if (!token_result.result) {
|
|
2576
|
+
dbglogging_1.default.elog(token_result.message);
|
|
2577
|
+
k2hr3resutil_1.default.errResponse(req, res, token_result.status);
|
|
2578
|
+
return false;
|
|
2579
|
+
}
|
|
2580
|
+
const token_info = token_result.token_info;
|
|
2581
|
+
if (!k2hr3tokens_1.default.isResTypeCheckRoleToken(token_info)) {
|
|
2582
|
+
dbglogging_1.default.elog('specified wrong token or it is not scoped user token');
|
|
2583
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2584
|
+
return false;
|
|
2585
|
+
}
|
|
2586
|
+
const keys = r3keys(token_info.user, token_info.tenant);
|
|
2587
|
+
//------------------------------
|
|
2588
|
+
// get role token from uri
|
|
2589
|
+
//------------------------------
|
|
2590
|
+
// check get token type and parse role name
|
|
2591
|
+
const requestptn = new RegExp(keys.MATCH_URI_GET_RTOKEN); // regex = /^\/v1\/role\/token\/(.*)/
|
|
2592
|
+
const reqmatchs = decodeURI(req.baseUrl).match(requestptn);
|
|
2593
|
+
if (!k2hr3apiutil_1.default.isStringArray(reqmatchs) || !k2hr3apiutil_1.default.isNotEmptyArray(reqmatchs) || reqmatchs.length < 2 || '' === k2hr3apiutil_1.default.getSafeString(reqmatchs[1])) {
|
|
2594
|
+
dbglogging_1.default.elog('DELETE request url does not have token string nor yrn path');
|
|
2595
|
+
k2hr3resutil_1.default.errResponse(req, res, 400); // 400: Bad Request
|
|
2596
|
+
return false;
|
|
2597
|
+
}
|
|
2598
|
+
const token_string = k2hr3apiutil_1.default.getSafeString(reqmatchs[1]);
|
|
2599
|
+
//------------------------------
|
|
2600
|
+
// Run
|
|
2601
|
+
//------------------------------
|
|
2602
|
+
if (!k2hr3tokens_1.default.removeRoleTokenByPath(token_string, (k2hr3apiutil_1.default.isSafeString(token_info.tenant) ? token_info.tenant : null))) {
|
|
2603
|
+
dbglogging_1.default.elog('DELETE request failure - remove role token(' + token_string + ')');
|
|
2604
|
+
k2hr3resutil_1.default.errResponse(req, res, 403); // 403: Forbidden
|
|
2605
|
+
return false;
|
|
2606
|
+
}
|
|
2607
|
+
else {
|
|
2608
|
+
dbglogging_1.default.dlog('DELETE request succeed - remove role token(' + token_string + ')');
|
|
2609
|
+
res.status(204); // 204: No Content
|
|
2610
|
+
}
|
|
2611
|
+
return true;
|
|
2612
|
+
};
|
|
2613
|
+
//---------------------------------------------------------
|
|
2614
|
+
// Exports
|
|
2615
|
+
//---------------------------------------------------------
|
|
2616
|
+
//
|
|
2617
|
+
// Functions
|
|
2618
|
+
//
|
|
2619
|
+
exports.default = router;
|
|
2620
|
+
/*
|
|
2621
|
+
* Local variables:
|
|
2622
|
+
* tab-width: 4
|
|
2623
|
+
* c-basic-offset: 4
|
|
2624
|
+
* End:
|
|
2625
|
+
* vim600: noexpandtab sw=4 ts=4 fdm=marker
|
|
2626
|
+
* vim<600: noexpandtab sw=4 ts=4
|
|
2627
|
+
*/
|