k2hr3-api 1.0.41 → 2.0.0

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.
Files changed (149) hide show
  1. package/config/k2hr3-init.sh.templ +2 -2
  2. package/dist/.gitkeep +0 -0
  3. package/dist/src/app.js +262 -0
  4. package/{bin → dist/src/bin}/run.sh +1 -1
  5. package/dist/src/bin/watcher.js +113 -0
  6. package/dist/src/bin/www.js +217 -0
  7. package/dist/src/lib/basicipcheck.js +392 -0
  8. package/dist/src/lib/cacerts.js +106 -0
  9. package/dist/src/lib/dbglogging.js +190 -0
  10. package/dist/src/lib/dummyuserapi.js +719 -0
  11. package/dist/src/lib/ipwatch.js +354 -0
  12. package/dist/src/lib/k2hr3acrutil.js +532 -0
  13. package/dist/src/lib/k2hr3apiutil.js +1444 -0
  14. package/dist/src/lib/k2hr3cliutil.js +183 -0
  15. package/dist/src/lib/k2hr3config.js +832 -0
  16. package/dist/src/lib/k2hr3cryptutil.js +258 -0
  17. package/dist/src/lib/k2hr3dkc.js +12121 -0
  18. package/dist/src/lib/k2hr3extdata.js +198 -0
  19. package/dist/src/lib/k2hr3keys.js +207 -0
  20. package/dist/src/lib/k2hr3resutil.js +111 -0
  21. package/dist/src/lib/k2hr3template.js +6546 -0
  22. package/dist/src/lib/k2hr3tokens.js +2643 -0
  23. package/dist/src/lib/k2hr3userdata.js +296 -0
  24. package/dist/src/lib/k8soidc.js +1000 -0
  25. package/dist/src/lib/openstackapiv2.js +695 -0
  26. package/dist/src/lib/openstackapiv3.js +932 -0
  27. package/dist/src/lib/openstackep.js +667 -0
  28. package/{tests/auto_common.js → dist/src/lib/types.js} +4 -38
  29. package/dist/src/routes/acr.js +704 -0
  30. package/dist/src/routes/debugVerify.js +294 -0
  31. package/dist/src/routes/extdata.js +219 -0
  32. package/dist/src/routes/list.js +264 -0
  33. package/dist/src/routes/policy.js +840 -0
  34. package/dist/src/routes/resource.js +1489 -0
  35. package/dist/src/routes/role.js +2627 -0
  36. package/dist/src/routes/service.js +908 -0
  37. package/dist/src/routes/tenant.js +1141 -0
  38. package/dist/src/routes/userTokens.js +482 -0
  39. package/dist/src/routes/userdata.js +212 -0
  40. package/dist/src/routes/version.js +103 -0
  41. package/package.json +152 -121
  42. package/ChangeLog +0 -372
  43. package/app.js +0 -292
  44. package/bin/watcher +0 -122
  45. package/bin/www +0 -180
  46. package/eslint.config.mjs +0 -68
  47. package/lib/basicipcheck.js +0 -376
  48. package/lib/cacerts.js +0 -71
  49. package/lib/dbglogging.js +0 -151
  50. package/lib/dummyuserapi.js +0 -766
  51. package/lib/ipwatch.js +0 -379
  52. package/lib/k2hr3acrutil.js +0 -516
  53. package/lib/k2hr3apiutil.js +0 -1494
  54. package/lib/k2hr3cliutil.js +0 -191
  55. package/lib/k2hr3config.js +0 -826
  56. package/lib/k2hr3cryptutil.js +0 -254
  57. package/lib/k2hr3dkc.js +0 -12632
  58. package/lib/k2hr3extdata.js +0 -198
  59. package/lib/k2hr3keys.js +0 -234
  60. package/lib/k2hr3resutil.js +0 -100
  61. package/lib/k2hr3template.js +0 -6925
  62. package/lib/k2hr3tokens.js +0 -2799
  63. package/lib/k2hr3userdata.js +0 -312
  64. package/lib/k8soidc.js +0 -1012
  65. package/lib/openstackapiv2.js +0 -764
  66. package/lib/openstackapiv3.js +0 -1032
  67. package/lib/openstackep.js +0 -553
  68. package/routes/acr.js +0 -738
  69. package/routes/debugVerify.js +0 -263
  70. package/routes/extdata.js +0 -232
  71. package/routes/list.js +0 -270
  72. package/routes/policy.js +0 -869
  73. package/routes/resource.js +0 -1441
  74. package/routes/role.js +0 -2664
  75. package/routes/service.js +0 -894
  76. package/routes/tenant.js +0 -1095
  77. package/routes/userTokens.js +0 -511
  78. package/routes/userdata.js +0 -218
  79. package/routes/version.js +0 -108
  80. package/templ/Dockerfile.templ +0 -71
  81. package/tests/auto_acr.js +0 -1101
  82. package/tests/auto_acr_spec.js +0 -79
  83. package/tests/auto_all_spec.js +0 -142
  84. package/tests/auto_control_subprocess.sh +0 -243
  85. package/tests/auto_extdata.js +0 -220
  86. package/tests/auto_extdata_spec.js +0 -79
  87. package/tests/auto_init_config_json.sh +0 -275
  88. package/tests/auto_k2hdkc_server.ini +0 -109
  89. package/tests/auto_k2hdkc_slave.ini +0 -83
  90. package/tests/auto_list.js +0 -439
  91. package/tests/auto_list_spec.js +0 -79
  92. package/tests/auto_policy.js +0 -1579
  93. package/tests/auto_policy_spec.js +0 -79
  94. package/tests/auto_resource.js +0 -10956
  95. package/tests/auto_resource_spec.js +0 -79
  96. package/tests/auto_role.js +0 -6150
  97. package/tests/auto_role_spec.js +0 -79
  98. package/tests/auto_service.js +0 -770
  99. package/tests/auto_service_spec.js +0 -79
  100. package/tests/auto_subprocesses.js +0 -114
  101. package/tests/auto_template.sh +0 -126
  102. package/tests/auto_tenant.js +0 -1100
  103. package/tests/auto_tenant_spec.js +0 -79
  104. package/tests/auto_token_util.js +0 -219
  105. package/tests/auto_userdata.js +0 -292
  106. package/tests/auto_userdata_spec.js +0 -79
  107. package/tests/auto_usertokens.js +0 -565
  108. package/tests/auto_usertokens_spec.js +0 -79
  109. package/tests/auto_version.js +0 -127
  110. package/tests/auto_version_spec.js +0 -79
  111. package/tests/auto_watcher.js +0 -157
  112. package/tests/auto_watcher_spec.js +0 -79
  113. package/tests/k2hdkc_test.data +0 -986
  114. package/tests/k2hdkc_test_load.sh +0 -255
  115. package/tests/k2hr3template_test.js +0 -187
  116. package/tests/k2hr3template_test.sh +0 -339
  117. package/tests/k2hr3template_test_async.js +0 -216
  118. package/tests/k2hr3template_test_template.result +0 -7117
  119. package/tests/k2hr3template_test_template.txt +0 -3608
  120. package/tests/k2hr3template_test_vars.js +0 -194
  121. package/tests/manual_acr_delete.js +0 -143
  122. package/tests/manual_acr_get.js +0 -297
  123. package/tests/manual_acr_postput.js +0 -215
  124. package/tests/manual_allusertenant_get.js +0 -113
  125. package/tests/manual_extdata_get.js +0 -191
  126. package/tests/manual_k2hr3keys_get.js +0 -84
  127. package/tests/manual_list_gethead.js +0 -230
  128. package/tests/manual_policy_delete.js +0 -132
  129. package/tests/manual_policy_gethead.js +0 -275
  130. package/tests/manual_policy_postput.js +0 -297
  131. package/tests/manual_resource_delete.js +0 -433
  132. package/tests/manual_resource_gethead.js +0 -423
  133. package/tests/manual_resource_postput.js +0 -487
  134. package/tests/manual_role_delete.js +0 -404
  135. package/tests/manual_role_gethead.js +0 -547
  136. package/tests/manual_role_postput.js +0 -544
  137. package/tests/manual_service_delete.js +0 -153
  138. package/tests/manual_service_gethead.js +0 -178
  139. package/tests/manual_service_postput.js +0 -348
  140. package/tests/manual_tenant_delete.js +0 -186
  141. package/tests/manual_tenant_gethead.js +0 -268
  142. package/tests/manual_tenant_postput.js +0 -293
  143. package/tests/manual_test.sh +0 -352
  144. package/tests/manual_userdata_get.js +0 -173
  145. package/tests/manual_usertoken_gethead.js +0 -136
  146. package/tests/manual_usertoken_postput.js +0 -310
  147. package/tests/manual_version_get.js +0 -127
  148. package/tests/run_local_test_k2hdkc.sh +0 -174
  149. package/tests/test.sh +0 -333
@@ -1,2799 +0,0 @@
1
- /*
2
- * K2HR3 REST API
3
- *
4
- * Copyright 2017 Yahoo Japan Corporation.
5
- *
6
- * K2HR3 is K2hdkc based Resource and Roles and policy Rules, gathers
7
- * common management information for the cloud.
8
- * K2HR3 can dynamically manage information as "who", "what", "operate".
9
- * These are stored as roles, resources, policies in K2hdkc, and the
10
- * client system can dynamically read and modify these information.
11
- *
12
- * For the full copyright and license information, please view
13
- * the license file that was distributed with this source code.
14
- *
15
- * AUTHOR: Takeshi Nakatani
16
- * CREATE: Wed Jun 8 2017
17
- * REVISION:
18
- *
19
- */
20
-
21
- 'use strict';
22
-
23
- var k2hr3 = require('./k2hr3dkc');
24
- var r3keys = require('./k2hr3keys').getK2hr3Keys;
25
- var apiutil = require('./k2hr3apiutil');
26
-
27
- // Debug logging objects
28
- var r3logger = require('../lib/dbglogging');
29
-
30
- //---------------------------------------------------------
31
- // Configuration
32
- // * Keystone api wrapper
33
- // * Get expiration for role tokens
34
- //---------------------------------------------------------
35
- // [NOTE]
36
- // We use config which has keystone.type value.
37
- // Default value is "keystone_v3".
38
- //
39
- var osapi = null;
40
- var expire_rtoken = 0;
41
- var expire_reg_rtoken = 0;
42
-
43
- (function()
44
- {
45
- var r3Conf = require('./k2hr3config').r3ApiConfig;
46
- var apiConf = new r3Conf();
47
-
48
- var keystone_type = './' + apiConf.getKeystoneType();
49
- osapi = require(keystone_type);
50
-
51
- expire_rtoken = apiConf.getExpireTimeRoleToken();
52
- expire_reg_rtoken = apiConf.getExpireTimeRegRoleToken();
53
- }());
54
-
55
- //---------------------------------------------------------
56
- // Get User Token
57
- //---------------------------------------------------------
58
- //
59
- // Get scoped/unscoped user token from keystone
60
- //
61
- function rawGetUserToken(user, passwd, tenant, callback)
62
- {
63
- var _callback = callback;
64
-
65
- if(!apiutil.isSafeString(user)){
66
- var error = new Error('user parameter is wrong');
67
- r3logger.elog(error.message);
68
- _callback(error, null);
69
- return;
70
- }
71
-
72
- var _tenant = apiutil.isSafeString(tenant) ? tenant.toLowerCase() : '';
73
- var _user = user;
74
- var _passwd = apiutil.isSafeString(passwd) ? passwd : '';
75
-
76
- // get unscoped token
77
- rawGetUserUnscopedTokenWrap(_user, _passwd, function(err, jsonres)
78
- {
79
- var error;
80
- if(null !== err){
81
- error = new Error('could not get user access token by ' + err.message);
82
- r3logger.elog(error.message);
83
- _callback(error, null);
84
- return;
85
- }
86
-
87
- // save to local val
88
- _user = jsonres.user; // over write
89
- var _userid = jsonres.userid;
90
- var _username = jsonres.user;
91
- var _unscopedtoken = jsonres.token;
92
- var _tokenexpire = jsonres.expire; // eslint-disable-line no-unused-vars
93
- var _region = jsonres.region; // eslint-disable-line no-unused-vars
94
-
95
- // break when unscoped token
96
- if(!apiutil.isSafeString(_tenant)){
97
- _callback(null, _unscopedtoken);
98
- return;
99
- }
100
-
101
- // get scoped user token
102
- return rawGetScopedUserToken(_unscopedtoken, _username, _userid, _tenant, _callback);
103
- });
104
- }
105
-
106
- //---------------------------------------------------------
107
- // Get User Token from token issued by another authentication system
108
- //---------------------------------------------------------
109
- //
110
- // Get scoped/unscoped user token from token issued by another authentication system
111
- // (ex. openstack identity token which is not registered in k2hr3 yet.)
112
- //
113
- function rawGetUserTokenByToken(token, tenant, callback)
114
- {
115
- var _callback = callback;
116
-
117
- if(!apiutil.isSafeString(token)){
118
- var error = new Error('token parameter is wrong');
119
- r3logger.elog(error.message);
120
- _callback(error, null);
121
- return;
122
- }
123
-
124
- var _tenant = apiutil.isSafeString(tenant) ? tenant.toLowerCase() : '';
125
- var _orgtoken = token;
126
-
127
- // get unscoped token
128
- rawGetUserUnscopedTokenbyTokenWrap(_orgtoken, function(err, jsonres)
129
- {
130
- var error;
131
- if(null !== err){
132
- error = new Error('could not get user access token by ' + err.message);
133
- r3logger.elog(error.message);
134
- _callback(error, null);
135
- return;
136
- }
137
-
138
- // save to local val
139
- var _userid = jsonres.userid;
140
- var _username = jsonres.user;
141
- var _unscopedtoken = jsonres.token;
142
- var _tokenexpire = jsonres.expire; // eslint-disable-line no-unused-vars
143
- var _region = jsonres.region; // eslint-disable-line no-unused-vars
144
-
145
- // break when unscoped token
146
- if(!apiutil.isSafeString(_tenant)){
147
- _callback(null, _unscopedtoken);
148
- return;
149
- }
150
-
151
- // get scoped user token
152
- return rawGetScopedUserToken(_unscopedtoken, _username, _userid, _tenant, _callback);
153
- });
154
- }
155
-
156
- //
157
- // Get scoped user token from unscoped user token
158
- //
159
- function rawGetScopedUserTokenByUnscoped(unscopedtoken, username, tenant, callback)
160
- {
161
- var error;
162
- if(!apiutil.isSafeStrings(unscopedtoken, username, tenant)){
163
- error = new Error('unscopedtoken or username or tenant parameters are wrong');
164
- r3logger.elog(error.message);
165
- callback(error, null);
166
- return;
167
- }
168
-
169
- // user id from user name
170
- var _tenant = tenant.toLowerCase();
171
- var user_info = k2hr3.getUserId(username); // user id from user name
172
- if(null === user_info || !apiutil.isSafeEntity(user_info.name) || !apiutil.isSafeEntity(user_info.id)){
173
- error = new Error('could not find username(' + username + ') from unscoped token in k2hdkc.');
174
- r3logger.elog(error.message);
175
- callback(error, null);
176
- return;
177
- }
178
-
179
- // get scoped user token
180
- return rawGetScopedUserToken(unscopedtoken, user_info.name, user_info.id, _tenant, callback);
181
- }
182
-
183
- //
184
- // Get scoped user token from keystone
185
- //
186
- function rawGetScopedUserToken(unscopedtoken, username, userid, tenant, callback)
187
- {
188
- if(!apiutil.isSafeStrings(unscopedtoken, username, userid, tenant)){
189
- var error = new Error('unscopedtoken or username or userid or tenant parameters are wrong');
190
- r3logger.elog(error.message);
191
- _callback(error, null);
192
- return;
193
- }
194
-
195
- var _unscopedtoken = unscopedtoken;
196
- var _username = username;
197
- var _userid = userid;
198
- var _tenant = apiutil.isSafeString(tenant) ? tenant.toLowerCase() : '';
199
- var _callback = callback;
200
-
201
- // get tenant list for check
202
- osapi.getUserTenantList(_unscopedtoken, _userid, function(err, jsonres)
203
- {
204
- var error;
205
- if(null !== err){
206
- error = new Error('could not get tenant list for user ' + _username + '(token=' + _unscopedtoken + ') by ' + err.message);
207
- r3logger.elog(error.message);
208
- _callback(error, null);
209
- return;
210
- }
211
- //r3logger.dlog('get user tenant list jsonres=\n' + JSON.stringify(jsonres));
212
-
213
- // check tenants(and initialize tenants)
214
- var _tenant_id = null;
215
- var _tenant_name = null;
216
- var _tenant_desc = null;
217
- var _tenant_display = null;
218
- var _tenant_list = new Array(0);
219
- for(var cnt = 0; cnt < jsonres.length; ++cnt){
220
- if(!apiutil.isSafeEntity(jsonres[cnt])){
221
- continue;
222
- }
223
- // over write
224
- var resobj = k2hr3.initUserTenant(_username, _userid, _username, jsonres[cnt].name, jsonres[cnt].id, jsonres[cnt].description, jsonres[cnt].display);
225
- if(!resobj.result){
226
- error = new Error(resobj.message);
227
- r3logger.elog(error.message);
228
- _callback(error, null);
229
- return;
230
- }
231
- if(apiutil.compareCaseString(jsonres[cnt].name, _tenant)){
232
- // find target tenant
233
- _tenant_id = jsonres[cnt].id;
234
- _tenant_name = jsonres[cnt].name;
235
- _tenant_desc = jsonres[cnt].description;
236
- _tenant_display = jsonres[cnt].display;
237
- }
238
- _tenant_list.push(jsonres[cnt].name);
239
- }
240
-
241
- // get and add local tenants
242
- var tmpresobj = k2hr3.listLocalTenant(_username, true);
243
- if(!apiutil.isSafeEntity(tmpresobj) || !apiutil.isSafeEntity(tmpresobj.result) || false === tmpresobj.result){
244
- if(apiutil.isSafeEntity(tmpresobj) && apiutil.isSafeString(tmpresobj.message)){
245
- r3logger.wlog('failed to get local tenant list by ' + tmpresobj.message);
246
- }else{
247
- r3logger.wlog('failed to get local tenant list.');
248
- }
249
- }else{
250
- if(!apiutil.isEmptyArray(tmpresobj.tenants)){
251
- for(var cnt2 = 0; cnt2 < tmpresobj.tenants.length; ++cnt2){
252
- var one_tenant = tmpresobj.tenants[cnt2];
253
- if(!apiutil.isSafeEntity(tmpresobj.tenants[cnt2])){
254
- continue;
255
- }
256
- if(apiutil.compareCaseString(tmpresobj.tenants[cnt2].name, _tenant)){
257
- // find target tenant
258
- _tenant_id = tmpresobj.tenants[cnt2].id;
259
- _tenant_name = tmpresobj.tenants[cnt2].name;
260
- _tenant_desc = tmpresobj.tenants[cnt2].desc; // eslint-disable-line no-unused-vars
261
- _tenant_display = tmpresobj.tenants[cnt2].display; // eslint-disable-line no-unused-vars
262
- }
263
- _tenant_list.push(one_tenant);
264
- }
265
- }
266
- }
267
-
268
- // check and remove old tenant for user
269
- if(!k2hr3.removeComprehensionByNewTenants(_username, _tenant_list)){
270
- r3logger.elog('failed to remove some tenant for user, but continue...');
271
- }
272
-
273
- // get scoped token
274
- osapi.getUserScopedToken(_unscopedtoken, _tenant_name, _tenant_id, function(err, jsonres)
275
- {
276
- var error;
277
- if(null !== err){
278
- error = new Error('could not get scoped user token for user ' + _username + ' by ' + err.message);
279
- r3logger.elog(error.message);
280
- _callback(error, null);
281
- return;
282
- }
283
- //r3logger.dlog('get user scoped token jsonres=\n' + JSON.stringify(jsonres));
284
-
285
- var token_seed = apiutil.isSafeString(jsonres.token_seed) ? jsonres.token_seed : null;
286
- if(!rawSetUserToken(_username, _tenant_name, jsonres.token, jsonres.expire, jsonres.region, token_seed)){
287
- error = new Error('failed to set unscoped/scoped user token');
288
- r3logger.elog(error.message);
289
- _callback(error, null);
290
- return;
291
- }
292
-
293
- // succeed
294
- _callback(null, jsonres.token);
295
- return;
296
- });
297
- });
298
- }
299
-
300
- //---------------------------------------------------------
301
- // set user/tenant token
302
- //---------------------------------------------------------
303
- // tenant undefined(or null) thus token must be unscoped.
304
- // expire UTC ISO 8601 format
305
- //
306
- // [NOTE] Must initialize User/Tenant before calling this function.
307
- //
308
- function rawSetUserToken(user, tenant, token, expire, region, seed)
309
- {
310
- if(!apiutil.isSafeStrings(user, token, expire, region)){ // allow tenant/seed is null
311
- r3logger.elog('some parameters are wrong : user=' + JSON.stringify(user) + ', tenant=' + JSON.stringify(tenant) + ', token=' + JSON.stringify(token) + ', expire=' + JSON.stringify(expire) + ', region=' + JSON.stringify(region));
312
- return false;
313
- }
314
-
315
- var dkcobj = k2hr3.getK2hdkc(true, false); // use permanent object(need to clean)
316
- var keys = r3keys(user, tenant);
317
- var subkeylist;
318
- if(!apiutil.isSafeEntity(dkcobj)){
319
- return false;
320
- }
321
-
322
- //
323
- // Check user key exists and create these.
324
- //
325
- var expire_limit = apiutil.calcExpire(expire); // UTC ISO 8601 to unixtime
326
- var token_value_key = keys.TOKEN_USER_TOP_KEY + '/' + token; // "yrn:yahoo::::token:user/<token>"
327
- var user_token_key = keys.USER_TENANT_AMBIGUOUS_TOKEN_KEY + '/' + token; // "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>"
328
- var user_token_seed_key = user_token_key + '/' + keys.SEED_KW; // "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>/seed"
329
-
330
- // [NOTE]
331
- // If tenant is null, following keys have not tenant keyword in that key string.
332
- // [ not have tenant name ] vs [ have tenant name ]
333
- // keys.USER_TENANT_AMBIGUOUS_KEY ---> "yrn:yahoo::::user:<user>:tenant/" or "yrn:yahoo::::user:<user>:tenant/<tenant>"
334
- // keys.USER_TENANT_AMBIGUOUS_TOKEN_KEY ---> "yrn:yahoo::::user:<user>:tenant//token" or "yrn:yahoo::::user:<user>:tenant/<tenant>/token"
335
- //
336
-
337
- // token top
338
- subkeylist = apiutil.getSafeArray(dkcobj.getSubkeys(keys.USER_TENANT_AMBIGUOUS_KEY, true));
339
- if(apiutil.tryAddStringToArray(subkeylist, keys.USER_TENANT_AMBIGUOUS_TOKEN_KEY)){
340
- if(!dkcobj.setSubkeys(keys.USER_TENANT_AMBIGUOUS_KEY, subkeylist)){ // add subkey yrn:yahoo::::user:<user>:tenant/{<tenant>}/token -> yrn:yahoo::::user:<user>:tenant/{<tenant>}
341
- r3logger.elog('could not add ' + keys.USER_TENANT_AMBIGUOUS_TOKEN_KEY + ' subkey under ' + keys.USER_TENANT_AMBIGUOUS_KEY + ' key');
342
- dkcobj.clean();
343
- return false;
344
- }
345
- }
346
-
347
- // to token key
348
- subkeylist = apiutil.getSafeArray(dkcobj.getSubkeys(keys.USER_TENANT_AMBIGUOUS_TOKEN_KEY, true));
349
- if(apiutil.tryAddStringToArray(subkeylist, user_token_key)){
350
- if(!dkcobj.setSubkeys(keys.USER_TENANT_AMBIGUOUS_TOKEN_KEY, subkeylist)){ // add subkey yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token> -> yrn:yahoo::::user:<user>:tenant/{<tenant>}/token
351
- r3logger.elog('could not add ' + user_token_key + ' subkey under ' + keys.USER_TENANT_AMBIGUOUS_TOKEN_KEY + ' key');
352
- dkcobj.clean();
353
- return false;
354
- }
355
- }
356
-
357
- // get/set token value
358
- var old_value = dkcobj.getValue(user_token_key, null, true, null);
359
- if(old_value != region){
360
- if(!dkcobj.setValue(user_token_key, region, null, null, expire_limit)){ // update new token key(value with region and expire) -> yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>
361
- r3logger.elog('could not set ' + region + '(expire=' + expire + ') to ' + user_token_key + ' key');
362
- dkcobj.clean();
363
- return false;
364
- }
365
- }
366
-
367
- // get/set seed value
368
- if(apiutil.isSafeString(seed)){
369
- old_value = dkcobj.getValue(user_token_seed_key, null, true, null);
370
- if(old_value != seed){
371
- if(!dkcobj.setValue(user_token_seed_key, seed, null, null, expire_limit)){ // update new token seed key(value with expire) -> yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>/seed
372
- r3logger.elog('could not set ' + seed + '(expire=' + expire + ') to ' + user_token_seed_key + ' key');
373
- dkcobj.clean();
374
- return false;
375
- }
376
- }
377
- subkeylist = apiutil.getSafeArray(dkcobj.getSubkeys(user_token_key, true));
378
- if(apiutil.tryAddStringToArray(subkeylist, user_token_seed_key)){
379
- if(!dkcobj.setSubkeys(user_token_key, subkeylist)){ // add subkey yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>/seed -> yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>
380
- r3logger.elog('could not add ' + user_token_seed_key + ' subkey under ' + user_token_key + ' key');
381
- dkcobj.clean();
382
- return false;
383
- }
384
- }
385
- }
386
-
387
- // create new token under token top key
388
- //
389
- // [NOTE]
390
- // This key is not set expire limit. if you need to check expire,
391
- // you look up key under user key.
392
- //
393
- if(!dkcobj.setValue(token_value_key, user_token_key)){ // create(over write) value(="yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>") without expire -> yrn:yahoo::::token/<token>
394
- r3logger.elog('could not set ' + user_token_key + ' value without expire to ' + token_value_key + ' key');
395
- dkcobj.clean();
396
- return false;
397
- }
398
- subkeylist = apiutil.getSafeArray(dkcobj.getSubkeys(keys.TOKEN_USER_TOP_KEY, true));
399
- if(apiutil.tryAddStringToArray(subkeylist, token_value_key)){
400
- if(!dkcobj.setSubkeys(keys.TOKEN_USER_TOP_KEY, subkeylist)){ // add subkey yrn:yahoo::::token:user/<token> -> yrn:yahoo::::token:user
401
- r3logger.elog('could not add ' + token_value_key + ' subkey under ' + keys.TOKEN_USER_TOP_KEY + ' key');
402
- dkcobj.clean();
403
- return false;
404
- }
405
- }
406
-
407
- dkcobj.clean();
408
- return true;
409
- }
410
-
411
- //---------------------------------------------------------
412
- // get user unscoped token
413
- //---------------------------------------------------------
414
- //
415
- // Get user token from keystone
416
- //
417
- // result null or object
418
- // {
419
- // user: user name(if existed, from parameter)
420
- // userid: user id(if existed, from "yrn:yahoo::::user:<user name>:id")
421
- // scoped: false(always false)
422
- // token: token string(id)
423
- // expire: expire string(if existed, null)
424
- // region: region string
425
- // }
426
- //
427
- // [NOTE]
428
- // This function is wrapper for osapi.getUserUnscopedToken().
429
- // This function checks existing unscoped token before call it.
430
- //
431
- function rawGetUserUnscopedTokenWrap(user, passwd, callback)
432
- {
433
- var _user = user;
434
- var _passwd = apiutil.isSafeString(passwd) ? passwd : '';
435
- var _callback = callback;
436
-
437
- // get unscoped token
438
- osapi.getUserUnscopedToken(_user, _passwd, function(err, jsonres)
439
- {
440
- var error;
441
- if(null !== err){
442
- error = new Error('could not get user access token by ' + err.message);
443
- r3logger.elog(error.message);
444
- _callback(error, null);
445
- return;
446
- }
447
-
448
- // init user
449
- var resobj = k2hr3.initUser(jsonres.user, jsonres.userid, jsonres.user, null);
450
- if(!resobj.result){
451
- error = new Error(resobj.message);
452
- r3logger.elog(error.message);
453
- _callback(error, null);
454
- return;
455
- }
456
-
457
- // set unscoped token
458
- var token_seed = apiutil.isSafeString(jsonres.token_seed) ? jsonres.token_seed : null;
459
- if(!rawSetUserToken(jsonres.user, null, jsonres.token, jsonres.expire, jsonres.region, token_seed)){
460
- error = new Error('failed to set unscoped/scoped user token');
461
- r3logger.elog(error.message);
462
- _callback(error, null);
463
- return;
464
- }
465
-
466
- // succeed
467
- _callback(null, jsonres);
468
- return;
469
- });
470
- }
471
-
472
- //---------------------------------------------------------
473
- // get user unscoped token from token issued by another authentication system
474
- //---------------------------------------------------------
475
- //
476
- // Get user token from token issued by another authentication system
477
- //
478
- // result null or object
479
- // {
480
- // user: user name(if existed, from parameter)
481
- // userid: user id(if existed, from "yrn:yahoo::::user:<user name>:id")
482
- // scoped: false(always false)
483
- // token: token string(id)
484
- // expire: expire string(if existed, null)
485
- // region: region string
486
- // }
487
- //
488
- // [NOTE]
489
- // This function is wrapper for osapi.getUserUnscopedTokenByToken().
490
- // This function checks existing unscoped token before call it.
491
- //
492
- function rawGetUserUnscopedTokenbyTokenWrap(token, callback)
493
- {
494
- var _orgtoken = token;
495
- var _callback = callback;
496
-
497
- // get unscoped token
498
- osapi.getUserUnscopedTokenByToken(_orgtoken, function(err, jsonres)
499
- {
500
- var error;
501
- if(null !== err){
502
- error = new Error('could not get user access token by ' + err.message);
503
- r3logger.elog(error.message);
504
- _callback(error, null);
505
- return;
506
- }
507
-
508
- // init user
509
- var resobj = k2hr3.initUser(jsonres.user, jsonres.userid, jsonres.user, null);
510
- if(!resobj.result){
511
- error = new Error(resobj.message);
512
- r3logger.elog(error.message);
513
- _callback(error, null);
514
- return;
515
- }
516
-
517
- // set unscoped token
518
- var token_seed = apiutil.isSafeString(jsonres.token_seed) ? jsonres.token_seed : null;
519
- if(!rawSetUserToken(jsonres.user, null, jsonres.token, jsonres.expire, jsonres.region, token_seed)){
520
- error = new Error('failed to set unscoped/scoped user token');
521
- r3logger.elog(error.message);
522
- _callback(error, null);
523
- return;
524
- }
525
-
526
- // succeed
527
- _callback(null, jsonres);
528
- return;
529
- });
530
- }
531
-
532
- //---------------------------------------------------------
533
- // remove scoped user token
534
- //---------------------------------------------------------
535
- //
536
- // token scoped user token
537
- //
538
- // [NOTE] This removes(force expire) scoped user token for
539
- // using ACR API.
540
- // The token used by ACR must be removed after checking
541
- // it, because this case allows using token one time.
542
- //
543
- function rawRemoveScopedUserToken(token)
544
- {
545
- if(!apiutil.isSafeString(token)){
546
- r3logger.elog('parameter is wrong : token=' + JSON.stringify(token));
547
- return false;
548
- }
549
-
550
- //
551
- // Check token
552
- //
553
- if(0 === token.indexOf('R=')){
554
- r3logger.elog('token(' + JSON.stringify(token) + ') is role token.');
555
- return false;
556
- }else if(0 === token.indexOf('U=')){
557
- token = token.substr(2); // cut 'U='
558
- }
559
- var token_info = rawCheckUserToken(token);
560
- if( null === token_info ||
561
- !apiutil.isSafeString(token_info.user) ||
562
- !apiutil.isSafeString(token_info.tenant) ||
563
- !apiutil.isSafeEntity(token_info.scoped) ||
564
- 'boolean' !== typeof token_info.scoped ||
565
- true !== token_info.scoped )
566
- {
567
- r3logger.elog('token(' + JSON.stringify(token) + ') is something wrong.');
568
- return false;
569
- }
570
-
571
- //
572
- // Remove token
573
- //
574
- var dkcobj = k2hr3.getK2hdkc(true, false); // use permanent object(need to clean)
575
- var subkeylist;
576
- var errmsg = '';
577
- if(!apiutil.isSafeEntity(dkcobj)){
578
- return false;
579
- }
580
-
581
- //
582
- // Keys
583
- //
584
- var keys = r3keys(token_info.user, token_info.tenant);
585
- var token_top_key = keys.TOKEN_USER_TOP_KEY; // "yrn:yahoo::::token:user"
586
- var token_value_key = keys.TOKEN_USER_TOP_KEY + '/' + token; // "yrn:yahoo::::token:user/<token>"
587
- var utoken_top_key = keys.USER_TENANT_AMBIGUOUS_TOKEN_KEY; // "yrn:yahoo::::user:<user>:tenant/<tenant>/token"
588
- var utoken_token_key= keys.USER_TENANT_AMBIGUOUS_TOKEN_KEY + '/' + token; // "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>"
589
- var utoken_seed_key = utoken_token_key + '/' + keys.SEED_KW; // "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>/seed"
590
-
591
- //
592
- // check under token top
593
- //
594
- subkeylist = apiutil.getSafeArray(dkcobj.getSubkeys(token_top_key, true));
595
- if(apiutil.removeStringFromArray(subkeylist, token_value_key)){ // remove subkeys "yrn:yahoo::::token:user/<token>" -> "yrn:yahoo::::token:user"
596
- if(!dkcobj.setSubkeys(token_top_key, subkeylist)){
597
- errmsg += 'could not remove ' + token_value_key + ' subkey under ' + token_top_key + ' key, ';
598
- }
599
- }
600
- if(!dkcobj.remove(token_value_key, false)){ // remove key "yrn:yahoo::::token:user/<token>"
601
- errmsg += 'could not remove ' + token_value_key + 'key, probably it is not existed, ';
602
- }
603
-
604
- //
605
- // check under user top
606
- //
607
- subkeylist = apiutil.getSafeArray(dkcobj.getSubkeys(utoken_top_key, true));
608
- if(apiutil.removeStringFromArray(subkeylist, utoken_token_key)){ // remove subkeys "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>" -> "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token"
609
- if(!dkcobj.setSubkeys(utoken_top_key, subkeylist)){
610
- errmsg += 'could not remove ' + utoken_token_key + ' subkey under ' + utoken_top_key + ' key, ';
611
- }
612
- }
613
- subkeylist = apiutil.getSafeArray(dkcobj.getSubkeys(utoken_token_key, true));
614
- if(apiutil.removeStringFromArray(subkeylist, utoken_seed_key)){ // remove subkeys "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>/seed" -> "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>"
615
- if(!dkcobj.setSubkeys(utoken_token_key, subkeylist)){
616
- errmsg += 'could not remove ' + utoken_seed_key + ' subkey under ' + utoken_token_key + ' key, ';
617
- }
618
- }
619
- if(!dkcobj.remove(utoken_seed_key, false)){ // remove key "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>/seed"
620
- errmsg += 'could not remove ' + utoken_seed_key + 'key, probably it is not existed, ';
621
- }
622
- if(!dkcobj.remove(utoken_token_key, false)){ // remove key "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>"
623
- errmsg += 'could not remove ' + utoken_token_key + 'key, probably it is not existed, ';
624
- }
625
-
626
- if(apiutil.isSafeString(errmsg)){
627
- r3logger.elog(errmsg);
628
- }
629
-
630
- dkcobj.clean();
631
- return true; // Returns true even if there is an error in deletion processing
632
- }
633
-
634
- //---------------------------------------------------------
635
- // Check User Token
636
- //---------------------------------------------------------
637
- //
638
- // Check User Token
639
- //
640
- // result : null or token information
641
- // {
642
- // role: role name
643
- // user: user name
644
- // hostname: always null
645
- // ip: always null
646
- // port: always 0
647
- // cuk: always null
648
- // extra: always null
649
- // tenant: tenant name
650
- // display: display alias name for tenant
651
- // id: tenant id string
652
- // description: description for tenant
653
- // scoped: role token is always scoped(true)
654
- // region: when user token, the creator region name of the token
655
- // }
656
- //
657
- function rawCheckUserToken(token)
658
- {
659
- if(!apiutil.isSafeString(token)){
660
- r3logger.elog('token parameter is wrong');
661
- return null;
662
- }
663
-
664
- // get user/tenant from token
665
- var token_info = rawGetUserTenantByToken(token);
666
- if(null === token_info || !apiutil.isSafeEntity(token_info.user)){
667
- r3logger.elog('token is not any user/tenant(expired or wrong token)');
668
- return null;
669
- }
670
- // add scoped flag
671
- if(apiutil.isSafeEntity(token_info.tenant)){
672
- token_info.scoped = true;
673
- }else{
674
- token_info.scoped = false;
675
- }
676
- token_info.role = null;
677
- token_info.ip = null;
678
- token_info.hostname = null;
679
- token_info.port = 0;
680
- token_info.cuk = null;
681
- token_info.extra = null;
682
-
683
- return token_info;
684
- }
685
-
686
- //---------------------------------------------------------
687
- // [Role Token]
688
- //---------------------------------------------------------
689
- //
690
- // Token: Token Id(################)
691
- // X-Auth-Token: R=Token Id
692
- // Token Id: The "Token Id" is a unique hex number string for 128bit.
693
- // "Token Id" = "(<base id(64bit:8byte)> ^ <crypt id(64bit:8byte)>)" + "(<role id(64bit:8byte)> ^ <crypt id(64bit:8byte)>)"
694
- // Role Token Key: "yrn:yahoo::::token:role/<Token Id>"
695
- // Role Token Value: {
696
- // role: "role full yrn"
697
- // date: "UTC ISO 8601 time at create"
698
- // expire: "UTC ISO 8601 time at expire"
699
- // creator: "Host full yrn" or "User full yrn"
700
- // base: "id from host" or "last 64bit string in UserToken"
701
- // user: "user name", if creator is user, this value is user name.(if not, this is null)
702
- // ip: "ip address", if creator is host, this value is ip address.(if not, this is null)
703
- // hostname: "hostname", if creator is host, this value is hostname.(if not, this is null)
704
- // port: "port number", if creator is host, this value is port number.(if not, this is 0)
705
- // cuk: "cuk", if creator is host on iaas, this value is cuk.(allowed null)
706
- // extra: "extra", if creator is host on iaas, this value is extra.(allowed null)
707
- // tenant: "tenant name" for this role token(this mean token is scoped)
708
- // verify: "random 64bit id for verify token"
709
- // }
710
- //
711
- // [NOTE]
712
- // "role id" which is in "Token Id" is included from role key(yrn:yahoo:<Tenant>:::role:<role name>/id).
713
- // This value is secret, any API could not get this value directly.
714
- //
715
-
716
- //---------------------------------------------------------
717
- // Get Role Token From user(token)
718
- //---------------------------------------------------------
719
- //
720
- // user : this value is parsed from user token
721
- // tenant : this value is parsed from user token
722
- // role : target role name(full yrn or only role name)
723
- // expire_limit : specify expire second(default 24H = 24 * 60 * 60 sec, 0 means no expire time.)
724
- //
725
- // result : {
726
- // result: true/false
727
- // message: null or error message string
728
- // token: undefined(error) or role token string
729
- // }
730
- //
731
- // [NOTE]
732
- // set role token value is following
733
- // {
734
- // role: token's role yrn("yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}")
735
- // date: create date(UTC ISO 8601)
736
- // expire: expire date(UTC ISO 8601)
737
- // creator: creator yrn("yrn:yahoo::::user:<user>" or "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/hosts/ip/<ip:port>")
738
- // user: if creator is user, this value is user name.
739
- // hostname: always null
740
- // ip: always null
741
- // port: if creator is host, this value is port number.(if not, this is 0)
742
- // cuk: if creator is host on iaas, this value is cuk.(allowed null)
743
- // extra: if creator is host on iaas, this value is extra.(allowed null)
744
- // tenant: tenant name for this role token(this mean token is scoped)
745
- // base: 32bytes hex string
746
- // }
747
- //
748
- function rawGetRoleTokenByUser(user, tenant, role, expire_limit)
749
- {
750
- var resobj = {result: true, message: null};
751
-
752
- if(!apiutil.isSafeStrings(user, tenant, role)){ // allow other argument is empty
753
- resobj.result = false;
754
- resobj.message = 'some parameters are wrong : user=' + JSON.stringify(user) + ', tenant=' + JSON.stringify(tenant) + ', role=' + JSON.stringify(role);
755
- r3logger.elog(resobj.message);
756
- return resobj;
757
- }
758
- if(!apiutil.isSafeEntity(expire_limit) || isNaN(expire_limit)){ // expire_limit must be number or null(undefined)
759
- expire_limit = expire_rtoken; // default 24H
760
- }else{
761
- if(0 == expire_limit){
762
- // [NOTE]
763
- // If 0, set the maximum value to 10 years.
764
- // Disable expire by setting a period of time within which this
765
- // application is guaranteed not to survive, as permitted by ISO8601.
766
- //
767
- expire_limit = expire_reg_rtoken;
768
- }
769
- }
770
-
771
- // check role name is only name or full yrn path
772
- var keys = r3keys(user, tenant);
773
- role = role.toLowerCase();
774
- var roleptn = new RegExp('^' + keys.MATCH_ANY_TENANT_ROLE); // regex = /^yrn:yahoo:(.*)::(.*):role:(.*)/
775
- var rolematchs = role.match(roleptn);
776
- if(apiutil.isEmptyArray(rolematchs) || rolematchs.length < 4){
777
- // role is not matched role(maybe not full yrn), then we need check it is another yrn path
778
- roleptn = new RegExp('^' + keys.NO_TENANT_KEY); // regex = /^yrn:yahoo:/
779
- if(role.match(roleptn)){
780
- resobj.result = false;
781
- resobj.message = 'role(' + role + ') is not role yrn path)';
782
- r3logger.elog(resobj.message);
783
- return resobj;
784
- }
785
- // role is only role name, then we do not modify it.
786
- }else{
787
- // check tenant name
788
- if(tenant !== rolematchs[2]){
789
- resobj.result = false;
790
- resobj.message = 'role(' + role + ') yrn has tenant(' + rolematchs[2] + '), but it is not specified tenant(' + tenant + ')';
791
- r3logger.elog(resobj.message);
792
- return resobj;
793
- }
794
- // role is set only role name
795
- role = rolematchs[3];
796
- }
797
-
798
- var dkcobj = k2hr3.getK2hdkc(true, false); // use permanent object(need to clean)
799
- var subkeylist;
800
- if(!apiutil.isSafeEntity(dkcobj)){
801
- resobj.result = false;
802
- resobj.message = 'Not initialize yet.';
803
- r3logger.elog(resobj.message);
804
- return resobj;
805
- }
806
-
807
- //
808
- // keys
809
- //
810
- var role_key = keys.ROLE_TOP_KEY + ':' + role; // "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}"
811
- var role_id_key = role_key + '/' + keys.ID_KW; // "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/id"
812
- var role_tokens_key = role_key + '/' + keys.ROLE_TOKEN_KW; // "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/tokens"
813
-
814
- // user id
815
- var user_id = dkcobj.getValue(keys.USER_ID_KEY, null, true, null); // get user id from "yrn:yahoo::::user:<user name>:id"
816
- if(!apiutil.isSafeString(user_id)){
817
- resobj.result = false;
818
- resobj.message = 'could not get user id(' + keys.USER_ID_KEY + ') value, or it is wrong value(' + JSON.stringify(user_id) + ').';
819
- r3logger.elog(resobj.message);
820
- dkcobj.clean();
821
- return resobj;
822
- }
823
-
824
- // role id
825
- var role_id = dkcobj.getValue(role_id_key, null, true, null);
826
- if(!apiutil.isSafeStrUuid4(role_id)){
827
- var isError = false;
828
- var old_role_id = apiutil.parseJSON(role_id);
829
- if(!apiutil.isEmptyArray(old_role_id) && 4 == old_role_id.length){
830
- // old version id, so reset new valus(UUID4) here.
831
- role_id = apiutil.getStrUuid4();
832
- if(!dkcobj.setValue(role_id_key, role_id)){ // set value -> yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/id
833
- isError = true;
834
- resobj.message = 'could not get role id(' + role_id_key + ') value, because failed to reset new role id instead of old id.';
835
- }
836
- }else{
837
- isError = true;
838
- resobj.message = 'could not get role id(' + role_id_key + ') value, or it is wrong value(' + JSON.stringify(role_id) + ').';
839
- }
840
- if(isError){
841
- resobj.result = false;
842
- r3logger.elog(resobj.message);
843
- dkcobj.clean();
844
- return resobj;
845
- }
846
- }
847
-
848
- // make token value
849
- var now_unixtime = apiutil.getUnixtime();
850
- var token_value = {};
851
- token_value.role = role_key; // "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}"
852
- token_value.date = (new Date(now_unixtime * 1000)).toISOString(); // now date(UTC ISO 8601)
853
- token_value.expire = (new Date((now_unixtime + expire_limit) * 1000)).toISOString(); // expire date(UTC ISO 8601)
854
- token_value.creator = keys.USER_KEY; // "yrn:yahoo::::user:<user>"
855
- token_value.user = user; // user(creator)
856
- token_value.hostname= null; // hostname(creator)
857
- token_value.ip = null; // ip(creator)
858
- token_value.port = 0; // port(creator)
859
- token_value.cuk = null; // cuk(creator)
860
- token_value.extra = null; // extra(creator)
861
- token_value.tenant = tenant; // tenant(scope)
862
-
863
- // role token and yrn key
864
- var role_token = '';
865
- var token_role_key = null;
866
-
867
- // create key
868
- for(var is_loop = true; is_loop; ){ // for eslint
869
- // make role token
870
- var token_elements = apiutil.makeStringToken256(user_id, role_id);
871
- if(!apiutil.isSafeEntity(token_elements)){
872
- resobj.result = false;
873
- resobj.message = 'could not make token from ' + JSON.stringify(user_id) + ' and ' + JSON.stringify(role_id);
874
- r3logger.elog(resobj.message);
875
- dkcobj.clean();
876
- return resobj;
877
- }
878
- role_token = token_elements.str_token;
879
- token_value.base = token_elements.str_base; // token base
880
-
881
- // role token key
882
- token_role_key = keys.TOKEN_ROLE_TOP_KEY + '/' + role_token; // "yrn:yahoo::::token:role/<role token>"
883
-
884
- // get role token for existing check
885
- var value = dkcobj.getValue(token_role_key, null, true, null);
886
- if(!apiutil.isSafeEntity(value)){
887
- // set value to role token
888
- if(!dkcobj.setValue(token_role_key, JSON.stringify(token_value), null, null, expire_limit)){ // set token value -> yrn:yahoo::::token:role/<role token>
889
- resobj.result = false;
890
- resobj.message = 'could not set ' + JSON.stringify(token_value) + ' value to ' + token_role_key + ' key';
891
- r3logger.elog(resobj.message);
892
- dkcobj.clean();
893
- return resobj;
894
- }
895
- break;
896
- }else{
897
- r3logger.dlog('conflict role token(' + role_token + ') which already is used, so remake token for uniq.');
898
- }
899
- }
900
-
901
- // Add token to role token top key's subkey list
902
- subkeylist = apiutil.getSafeArray(dkcobj.getSubkeys(keys.TOKEN_ROLE_TOP_KEY, true));
903
- if(apiutil.tryAddStringToArray(subkeylist, token_role_key)){
904
- if(!dkcobj.setSubkeys(keys.TOKEN_ROLE_TOP_KEY, subkeylist)){ // add subkey yrn:yahoo::::token:role/<role token> -> yrn:yahoo::::token:role
905
- resobj.result = false;
906
- resobj.message = 'could not add ' + token_role_key + ' subkey under ' + keys.TOKEN_ROLE_TOP_KEY + ' key';
907
- r3logger.elog(resobj.message);
908
- dkcobj.clean();
909
- return resobj;
910
- }
911
- }
912
-
913
- // Add token to role tokens key's subkey list
914
- subkeylist = apiutil.getSafeArray(dkcobj.getSubkeys(role_tokens_key, true));
915
- if(apiutil.tryAddStringToArray(subkeylist, token_role_key)){
916
- if(!dkcobj.setSubkeys(role_tokens_key, subkeylist)){ // add subkey yrn:yahoo::::token:role/<role token> -> yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/tokens
917
- resobj.result = false;
918
- resobj.message = 'could not add ' + token_role_key + ' subkey under ' + role_tokens_key + ' key';
919
- r3logger.elog(resobj.message);
920
- dkcobj.clean();
921
- return resobj;
922
- }
923
- }
924
-
925
- // Add role token into result object.
926
- resobj.token = role_token;
927
-
928
- dkcobj.clean();
929
- return resobj;
930
- }
931
-
932
- //---------------------------------------------------------
933
- // Get Role Token From ip address
934
- //---------------------------------------------------------
935
- // ip : ip address
936
- // port : port number(0, undefined, null means any port)
937
- // cuk : container unique key(undefined, null means any)
938
- // tenant : tenant name
939
- // role : target role name(full yrn or only role name)
940
- // expire_limit : specify expire second(default 24H = 24 * 60 * 60 sec)
941
- //
942
- // result : {
943
- // result: true/false
944
- // message: null or error message string
945
- // token: undefined(error) or role token string
946
- // }
947
- //
948
- // [NOTE]
949
- // set role token value is following
950
- // {
951
- // role: token's role yrn("yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}")
952
- // date: create date(UTC ISO 8601)
953
- // expire: expire date(UTC ISO 8601)
954
- // creator: creator yrn("yrn:yahoo::::user:<user>" or "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/hosts/ip/<ip:port>")
955
- // user: always null
956
- // hostname: always null
957
- // ip: if creator is host, this value is ip address.
958
- // port: if creator is host, this value is port number.(if not, this is 0)
959
- // cuk: if creator is host on iaas, this value is cuk.(allowed null)
960
- // extra: if creator is host on iaas, this value is extra.(allowed null)
961
- // tenant: tenant name for this role token(this mean token is scoped)
962
- // base: 32bytes hex string
963
- // }
964
- //
965
- // The role token which is built by host is made by only IP address.
966
- // Hostname can not build a role token, because it is not secure.(= Hostname can easily be disguised.)
967
- // Then only IP address can build a role token without UserToken.
968
- //
969
- function rawGetRoleTokenByIP(ip, port, cuk, tenant, role, expire_limit)
970
- {
971
- var resobj = {result: true, message: null};
972
-
973
- if(!apiutil.isSafeStrings(tenant, role, ip)){ // allow other argument is empty
974
- resobj.result = false;
975
- resobj.message = 'some parameters are wrong : tenant=' + JSON.stringify(tenant) + ', role=' + JSON.stringify(role) + ', ip' + JSON.stringify(ip);
976
- r3logger.elog(resobj.message);
977
- return resobj;
978
- }
979
- if(!apiutil.isSafeString(ip)){
980
- resobj.result = false;
981
- resobj.message = 'ip parameter is empty.';
982
- r3logger.elog(resobj.message);
983
- return resobj;
984
- }
985
- if(!apiutil.isSafeEntity(port) || isNaN(port)){ // port must be number or null(undefined)
986
- port = 0; // force set port 0(any).
987
- }
988
- if(!apiutil.isSafeString(cuk)){ // cuk is string if spacified
989
- cuk = null; // force set null.
990
- }
991
- if(!apiutil.isSafeEntity(expire_limit) || isNaN(expire_limit)){ // expire_limit must be number or null(undefined)
992
- expire_limit = expire_rtoken; // default 24H
993
- }
994
-
995
- // check role name is only name or full yrn path
996
- var keys = r3keys(null, tenant);
997
- role = role.toLowerCase();
998
- var roleptn = new RegExp('^' + keys.MATCH_ANY_TENANT_ROLE); // regex = /^yrn:yahoo:(.*)::(.*):role:(.*)/
999
- var rolematchs = role.match(roleptn);
1000
- if(apiutil.isEmptyArray(rolematchs) || rolematchs.length < 4){
1001
- // role is not matched role(maybe not full yrn), then we need check it is another yrn path
1002
- roleptn = new RegExp('^' + keys.NO_TENANT_KEY); // regex = /^yrn:yahoo:/
1003
- if(role.match(roleptn)){
1004
- resobj.result = false;
1005
- resobj.message = 'role(' + role + ') is not role yrn path)';
1006
- r3logger.elog(resobj.message);
1007
- return resobj;
1008
- }
1009
- // role is only role name, then we do not modify it.
1010
- }else{
1011
- // check tenant name
1012
- if(tenant !== rolematchs[2]){
1013
- resobj.result = false;
1014
- resobj.message = 'role(' + role + ') yrn has tenant(' + rolematchs[2] + '), but it is not specified tenant(' + tenant + ')';
1015
- r3logger.elog(resobj.message);
1016
- return resobj;
1017
- }
1018
- // role is set only role name
1019
- role = rolematchs[3];
1020
- }
1021
-
1022
- var dkcobj = k2hr3.getK2hdkc(true, false); // use permanent object(need to clean)
1023
- var subkeylist;
1024
- if(!apiutil.isSafeEntity(dkcobj)){
1025
- resobj.result = false;
1026
- resobj.message = 'Not initialize yet.';
1027
- r3logger.elog(resobj.message);
1028
- return resobj;
1029
- }
1030
-
1031
- //
1032
- // keys
1033
- //
1034
- var role_key = keys.ROLE_TOP_KEY + ':' + role; // "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}"
1035
- var role_id_key = role_key + '/' + keys.ID_KW; // "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/id"
1036
- var role_tokens_key = role_key + '/' + keys.ROLE_TOKEN_KW; // "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/tokens"
1037
-
1038
- // find host key and get host id for base id
1039
- var host_info = k2hr3.findRoleHost(dkcobj, role_key, null, ip, port, cuk);
1040
- if(apiutil.isEmptyArray(host_info)){
1041
- resobj.result = false;
1042
- resobj.message = 'Not found ip(' + ip + ') with port(' + String(port) + ') and cuk(' + JSON.stringify(cuk) + ') in tenant(' + tenant + ') + role(' + role + ')';
1043
- r3logger.elog(resobj.message);
1044
- dkcobj.clean();
1045
- return resobj;
1046
- }
1047
- var host_value = null;
1048
- for(var pos = 0; pos < host_info.length; ++pos){
1049
- if(!apiutil.isSafeEntity(host_info[pos]) || !apiutil.isSafeString(host_info[pos].key)){
1050
- r3logger.dlog('Found ip(' + ip + ') with port(' + String(port) + ') in tenant(' + tenant + ') + role(' + role + '), but this host info(' + JSON.stringify(host_info[pos]) + ') is something wrong, skip it');
1051
- continue;
1052
- }
1053
- host_value = dkcobj.getValue(host_info[pos].key, null, true, null);
1054
- host_value = apiutil.parseJSON(host_value);
1055
- if( !apiutil.isSafeEntity(host_value) ||
1056
- (!apiutil.isSafeString(host_value.hostname) && !apiutil.isSafeString(host_value.ip)) || // hostname or ip is existed
1057
- !apiutil.isSafeEntity(host_value.port) ||
1058
- !apiutil.isSafeString(host_value[keys.ID_KW]) )
1059
- {
1060
- r3logger.dlog('Found ip(' + ip + ') with port(' + String(port) + ') in tenant(' + tenant + ') + role(' + role + '), but this host value(' + JSON.stringify(host_value) + ') is something wrong, skip it');
1061
- }else{
1062
- // found safe host info, we use this.
1063
- host_value.key = host_info[pos].key;
1064
- host_value.cuk = host_info[pos].cuk;
1065
- host_value.extra= host_info[pos].extra;
1066
- break;
1067
- }
1068
- host_value = null;
1069
- }
1070
- if(null === host_value){
1071
- resobj.result = false;
1072
- resobj.message = 'Found ip(' + ip + ') with port(' + String(port) + ') in tenant(' + tenant + ') + role(' + role + '), but there is not safe any host info';
1073
- r3logger.elog(resobj.message);
1074
- dkcobj.clean();
1075
- return resobj;
1076
- }
1077
-
1078
- // role id
1079
- var role_id = dkcobj.getValue(role_id_key, null, true, null);
1080
- if(!apiutil.isSafeStrUuid4(role_id)){
1081
- var isError = false;
1082
- var old_role_id = apiutil.parseJSON(role_id);
1083
- if(!apiutil.isEmptyArray(old_role_id) && 4 == old_role_id.length){
1084
- // old version id, so reset new valus(UUID4) here.
1085
- role_id = apiutil.getStrUuid4();
1086
- if(!dkcobj.setValue(role_id_key, role_id)){ // set value -> yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/id
1087
- isError = true;
1088
- resobj.message = 'could not get role id(' + role_id_key + ') value, because failed to reset new role id instead of old id.';
1089
- }
1090
- }else{
1091
- isError = true;
1092
- resobj.message = 'could not get role id(' + role_id_key + ') value, or it is wrong value(' + JSON.stringify(role_id) + ').';
1093
- }
1094
- if(isError){
1095
- resobj.result = false;
1096
- r3logger.elog(resobj.message);
1097
- dkcobj.clean();
1098
- return resobj;
1099
- }
1100
- }
1101
-
1102
- // make token value
1103
- var now_unixtime = apiutil.getUnixtime();
1104
- var token_value = {};
1105
- token_value.role = role_key; // "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}"
1106
- token_value.date = (new Date(now_unixtime * 1000)).toISOString(); // now date(UTC ISO 8601)
1107
- token_value.expire = (new Date((now_unixtime + expire_limit) * 1000)).toISOString(); // expire date(UTC ISO 8601)
1108
- token_value.creator = host_value.key; // "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/hosts/ip/<ip:port>"
1109
- token_value.user = null; // user(creator)
1110
- token_value.hostname= null; // hostname(null)
1111
- token_value.ip = host_value.ip; // ip(creator)
1112
- token_value.port = host_value.port; // port(creator)
1113
- token_value.cuk = host_value.cuk; // cuk(creator)
1114
- token_value.extra = host_value.extra; // extra(creator)
1115
- token_value.tenant = tenant; // tenant(scope)
1116
-
1117
- // role token and yrn key
1118
- var role_token = '';
1119
- var token_role_key = null;
1120
-
1121
- // create key
1122
- for(var is_loop = true; is_loop; ){ // for eslint
1123
- // make role token
1124
- var token_elements = apiutil.makeStringToken256(host_value[keys.ID_KW], role_id);
1125
- if(!apiutil.isSafeEntity(token_elements)){
1126
- resobj.result = false;
1127
- resobj.message = 'could not make token from ' + JSON.stringify(host_value[keys.ID_KW]) + ' and ' + JSON.stringify(role_id);
1128
- r3logger.elog(resobj.message);
1129
- dkcobj.clean();
1130
- return resobj;
1131
- }
1132
- role_token = token_elements.str_token;
1133
- token_value.base = token_elements.str_base; // token base
1134
-
1135
- // role token key
1136
- token_role_key = keys.TOKEN_ROLE_TOP_KEY + '/' + role_token; // "yrn:yahoo::::token:role/<role token>"
1137
-
1138
- // get role token for existing check
1139
- var value = dkcobj.getValue(token_role_key, null, true, null);
1140
- if(!apiutil.isSafeEntity(value)){
1141
- // set value to role token
1142
- if(!dkcobj.setValue(token_role_key, JSON.stringify(token_value), null, null, expire_limit)){ // set token value -> yrn:yahoo::::token:role/<role token>
1143
- resobj.result = false;
1144
- resobj.message = 'could not set ' + JSON.stringify(token_value) + ' value to ' + token_role_key + ' key';
1145
- r3logger.elog(resobj.message);
1146
- dkcobj.clean();
1147
- return resobj;
1148
- }
1149
- break;
1150
- }else{
1151
- r3logger.dlog('conflict role token(' + role_token + ') which already is used, so remake token for uniq.');
1152
- }
1153
- }
1154
-
1155
- // Add token to role token top key's subkey list
1156
- subkeylist = apiutil.getSafeArray(dkcobj.getSubkeys(keys.TOKEN_ROLE_TOP_KEY, true));
1157
- if(apiutil.tryAddStringToArray(subkeylist, token_role_key)){
1158
- if(!dkcobj.setSubkeys(keys.TOKEN_ROLE_TOP_KEY, subkeylist)){ // add subkey yrn:yahoo::::token:role/<role token> -> yrn:yahoo::::token:role
1159
- r3logger.elog('could not add ' + token_role_key + ' subkey under ' + keys.TOKEN_ROLE_TOP_KEY + ' key');
1160
- dkcobj.clean();
1161
- return resobj;
1162
- }
1163
- }
1164
-
1165
- // Add token to role tokens key's subkey list
1166
- subkeylist = apiutil.getSafeArray(dkcobj.getSubkeys(role_tokens_key, true));
1167
- if(apiutil.tryAddStringToArray(subkeylist, token_role_key)){
1168
- if(!dkcobj.setSubkeys(role_tokens_key, subkeylist)){ // add subkey yrn:yahoo::::token:role/<role token> -> yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/tokens
1169
- resobj.result = false;
1170
- resobj.message = 'could not add ' + token_role_key + ' subkey under ' + role_tokens_key + ' key';
1171
- r3logger.elog(resobj.message);
1172
- dkcobj.clean();
1173
- return resobj;
1174
- }
1175
- }
1176
-
1177
- // Add role token into result object.
1178
- resobj.token = role_token;
1179
-
1180
- dkcobj.clean();
1181
- return resobj;
1182
- }
1183
-
1184
- //---------------------------------------------------------
1185
- // Remove Role Token by User/IP
1186
- //---------------------------------------------------------
1187
- // token : role token
1188
- // user : this value is parsed from user token(or null)
1189
- // tenant : this value is parsed from user token(or null)
1190
- // ip : client ip address(or null)
1191
- // port : port number when ip address parameter exists
1192
- // cuk : cuk value when ip address parameter exists
1193
- //
1194
- // result : {
1195
- // result: true/false
1196
- // message: null or error message string
1197
- // }
1198
- //
1199
- function rawRemoveRoleToken(token, user, tenant, ip, port, cuk)
1200
- {
1201
- var resobj = {result: true, message: null};
1202
-
1203
- if(!apiutil.isSafeString(token)){ // allow other argument is empty
1204
- resobj.result = false;
1205
- resobj.message = 'token parameter is empty';
1206
- r3logger.elog(resobj.message);
1207
- return resobj;
1208
- }
1209
- if( (apiutil.isSafeString(ip) && (apiutil.isSafeString(user) || apiutil.isSafeString(tenant))) ||
1210
- (!apiutil.isSafeString(ip) && (!apiutil.isSafeString(user) || !apiutil.isSafeString(tenant))) )
1211
- {
1212
- resobj.result = false;
1213
- resobj.message = 'tenant(' + JSON.stringify(tenant) + '), user(' + JSON.stringify(user) + '), ip(' + JSON.stringify(ip) + ') parameters are wrong pattern.';
1214
- r3logger.elog(resobj.message);
1215
- return resobj;
1216
- }
1217
-
1218
- var dkcobj = k2hr3.getK2hdkc(true, false); // use permanent object(need to clean)
1219
- var subkeylist;
1220
- var value;
1221
- if(!apiutil.isSafeEntity(dkcobj)){
1222
- resobj.result = false;
1223
- resobj.message = 'Not initialize yet.';
1224
- r3logger.elog(resobj.message);
1225
- return resobj;
1226
- }
1227
-
1228
- //
1229
- // keys
1230
- //
1231
- var keys = (apiutil.isSafeString(ip) ? r3keys() : r3keys(user, tenant));
1232
- var role_token_key = keys.TOKEN_ROLE_TOP_KEY + '/' + token; // "yrn:yahoo::::token:role/<role token>"
1233
-
1234
- // get role token value
1235
- value = dkcobj.getValue(role_token_key, null, true, null);
1236
- value = apiutil.parseJSON(value);
1237
- if(!apiutil.isSafeEntity(value)){
1238
- // already role token is removed or expired.
1239
- r3logger.dlog('could not get role token(' + role_token_key + ') value, or it is wrong value(' + JSON.stringify(value) + '). We check all role token for expire here.');
1240
- dkcobj.clean();
1241
- //
1242
- // check and remove old role token under token top key("yrn:yahoo::::token:role") if old token is expired
1243
- //
1244
- // [NOTE]
1245
- // This processing is taking time, so it runs asynchronously.
1246
- // And for notes on this processing, refer to NOTE of rawCleanupRoleToken function.
1247
- //
1248
- rawCleanupRoleToken(function(result)
1249
- {
1250
- if(!result){
1251
- r3logger.wlog('Failed to cleanup expired role tokens under ' + keys.TOKEN_ROLE_TOP_KEY + ' key, but continue...');
1252
- }
1253
- });
1254
- // return success
1255
- return resobj;
1256
- }
1257
-
1258
- // check token value
1259
- if( !apiutil.isSafeString(value.role) ||
1260
- !apiutil.isSafeString(value.date) ||
1261
- !apiutil.isSafeString(value.expire) ||
1262
- !apiutil.isSafeString(value.creator) ||
1263
- (!apiutil.isSafeString(value.user) && !apiutil.isSafeString(value.hostname) && !apiutil.isSafeString(value.ip)) ||
1264
- isNaN(value.port) ||
1265
- !apiutil.isSafeString(value.tenant) ||
1266
- !apiutil.isSafeString(value.base) )
1267
- {
1268
- //
1269
- // Not check expired token and ip address is empty here.
1270
- //
1271
- resobj.result = false;
1272
- resobj.message = 'could not get role token(' + role_token_key + ') value, or it is wrong value(' + JSON.stringify(value) + ').';
1273
- r3logger.elog(resobj.message);
1274
- dkcobj.clean();
1275
- return resobj;
1276
- }
1277
-
1278
- // check expire
1279
- if(apiutil.isExpired(value.expire)){
1280
- resobj.result = false;
1281
- resobj.message = 'role token(' + role_token_key + ') is expired by expire date(' + value.expire + ').';
1282
- r3logger.elog(resobj.message);
1283
- dkcobj.clean();
1284
- return resobj;
1285
- }
1286
-
1287
- // keep role tokens key for removing key in its subkey list.
1288
- var role_tokens_key = value.role + '/' + keys.ROLE_TOKEN_KW; // "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/tokens"
1289
-
1290
- // check requester
1291
- if(apiutil.isSafeString(ip)){
1292
- // check ip address bases
1293
- //
1294
- // port
1295
- if(!isNaN(port)){
1296
- port = parseInt(port);
1297
- }else{
1298
- port = 0;
1299
- }
1300
- // cuk
1301
- if(apiutil.isSafeString(cuk) && apiutil.isSafeString(cuk.trim())){
1302
- cuk = cuk.trim();
1303
- }else{
1304
- cuk = null;
1305
- }
1306
-
1307
- // check
1308
- if( value.port != port ||
1309
- apiutil.isSafeString(value.cuk) != apiutil.isSafeString(cuk) ||
1310
- (apiutil.isSafeString(value.cuk) && value.cuk != cuk) )
1311
- {
1312
- resobj.result = false;
1313
- resobj.message = 'could not remove role token(' + token + '), because port(' + JSON.stringify(port) + ' vs ' + JSON.stringify(value.port) + ')/cuk(' + JSON.stringify(cuk) + ' vs ' + JSON.stringify(value.cuk) + ') value is not same.';
1314
- r3logger.elog(resobj.message);
1315
- dkcobj.clean();
1316
- return resobj;
1317
- }
1318
-
1319
- // [NOTE]
1320
- // findHost() is creating k2hdkc object in it, thus we close dkc object here.
1321
- // and re-create dkc object after returning that function.
1322
- //
1323
- dkcobj.clean();
1324
-
1325
- var find_result = k2hr3.findHost(value.tenant, value.role, null, ip, port, cuk, false); // not strict checking
1326
- if(!find_result.result || apiutil.isEmptyArray(find_result.host_info)){
1327
- // ip address is not member of role
1328
- resobj.result = false;
1329
- resobj.message = 'could not remove role token(' + token + '), because ip(' + ip + ') is not role host member.';
1330
- r3logger.elog(resobj.message);
1331
- return resobj;
1332
- }
1333
- dkcobj = k2hr3.getK2hdkc(true, false); // re-creating permanent object(need to clean)
1334
-
1335
- }else{
1336
- // check tenant name
1337
- if(0 !== value.role.indexOf(keys.ROLE_TOP_KEY)){
1338
- // not same tenant name
1339
- resobj.result = false;
1340
- resobj.message = 'could not remove role token(' + token + '), because user(' + user + ')/tenant(' + tenant + ') is not role member.';
1341
- r3logger.elog(resobj.message);
1342
- dkcobj.clean();
1343
- return resobj;
1344
- }
1345
- }
1346
-
1347
- // remove token
1348
- if(!dkcobj.remove(role_token_key, false)){ // remove yrn:yahoo::::token:role/<role token>
1349
- resobj.result = false;
1350
- resobj.message = 'could not remove role token(' + token + '), probably it is not existed.';
1351
- r3logger.elog(resobj.message);
1352
- dkcobj.clean();
1353
- return resobj;
1354
- }
1355
- subkeylist = dkcobj.getSubkeys(keys.TOKEN_ROLE_TOP_KEY, true);
1356
- if(apiutil.removeStringFromArray(subkeylist, role_token_key)){
1357
- if(!dkcobj.setSubkeys(keys.TOKEN_ROLE_TOP_KEY, subkeylist)){ // update subkey -> yrn:yahoo::::token:role
1358
- resobj.result = false;
1359
- resobj.message = 'could not update subkey under ' + keys.TOKEN_ROLE_TOP_KEY + ' key';
1360
- r3logger.elog(resobj.message);
1361
- dkcobj.clean();
1362
- return resobj;
1363
- }
1364
- }
1365
-
1366
- // remove token key from role's tokens subkey.
1367
- subkeylist = apiutil.getSafeArray(dkcobj.getSubkeys(role_tokens_key, true));
1368
- if(apiutil.removeStringFromArray(subkeylist, role_token_key)){
1369
- if(!dkcobj.setSubkeys(role_tokens_key, subkeylist)){ // update subkey -> yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/tokens
1370
- resobj.result = false;
1371
- resobj.message = 'could not update subkey under ' + role_tokens_key + ' key';
1372
- r3logger.elog(resobj.message);
1373
- dkcobj.clean();
1374
- return resobj;
1375
- }
1376
- }
1377
-
1378
- dkcobj.clean();
1379
- return resobj;
1380
- }
1381
-
1382
- //---------------------------------------------------------
1383
- // Remove Role Tokens Directly
1384
- //---------------------------------------------------------
1385
- // dkcobj_permanent : dkcobj object
1386
- // tokens : array to role token yrn path
1387
- //
1388
- // result : true/false
1389
- //
1390
- function rawDirectRemoveRoleTokens(dkcobj_permanent, tokens)
1391
- {
1392
- if(!(dkcobj_permanent instanceof Object) || !dkcobj_permanent.isPermanent()){
1393
- r3logger.elog('dkcobj_parameters are wrong : dkcobj_permanent=' + JSON.stringify(dkcobj_permanent));
1394
- return false;
1395
- }
1396
- if(apiutil.isSafeString(tokens)){
1397
- tokens = [tokens];
1398
- }
1399
- if(apiutil.isEmptyArray(tokens)){
1400
- r3logger.dlog('tokens(' + JSON.stringify(tokens) + ') is empty or not array');
1401
- return true;
1402
- }
1403
-
1404
- //
1405
- // Keys
1406
- //
1407
- var keys = r3keys();
1408
- var subkeylist = dkcobj_permanent.getSubkeys(keys.TOKEN_ROLE_TOP_KEY, true); // get subkeys under "yrn:yahoo::::token:role"
1409
- var matchptn = keys.TOKEN_ROLE_TOP_KEY + '/'; // matching pattern "yrn:yahoo::::token:role/"
1410
- var needupdate = false;
1411
-
1412
- // remove each token
1413
- for(var cnt = 0; cnt < tokens.length; ++cnt){
1414
- if(!apiutil.isSafeString(tokens[cnt])){
1415
- r3logger.elog('token(' + JSON.stringify(tokens[cnt]) + ') yrn path is not string, but continue...');
1416
- continue;
1417
- }
1418
- if(0 !== tokens[cnt].indexOf(matchptn)){
1419
- r3logger.elog('token(' + JSON.stringify(tokens[cnt]) + ') is not full yrn path, but continue...');
1420
- continue;
1421
- }
1422
-
1423
- // remove token
1424
- if(!dkcobj_permanent.remove(tokens[cnt], false)){ // remove yrn:yahoo::::token:role/<role token>
1425
- r3logger.elog('failed to remove token(' + JSON.stringify(tokens[cnt]) + '), but continue...');
1426
- }else{
1427
- // remove token from subkeys(token top key)
1428
- if(apiutil.removeStringFromArray(subkeylist, tokens[cnt])){
1429
- needupdate = true;
1430
- }
1431
- }
1432
- }
1433
- if(needupdate){
1434
- if(!dkcobj_permanent.setSubkeys(keys.TOKEN_ROLE_TOP_KEY, subkeylist)){ // update subkey -> yrn:yahoo::::token:role
1435
- r3logger.elog('failed to reset role token subkeys to ' + keys.TOKEN_ROLE_TOP_KEY + ' top key, but continue...');
1436
- }
1437
- }
1438
- return true;
1439
- }
1440
-
1441
- //---------------------------------------------------------
1442
- // Remove Role Token with checking tenant
1443
- //---------------------------------------------------------
1444
- // token_string : role token string
1445
- // tenant : tenant name
1446
- //
1447
- // result : true/false
1448
- //
1449
- function rawRemoveRoleTokenByPath(token_string, tenant)
1450
- {
1451
- if(!apiutil.isSafeStrings(token_string, tenant)){
1452
- r3logger.elog('token_string(' + JSON.stringify(token_string) + ') or tenant(' + JSON.stringify(tenant) + ') parameter is something wrong.');
1453
- return false;
1454
- }
1455
-
1456
- //
1457
- // Keys
1458
- //
1459
- var keys = r3keys(null, tenant);
1460
- var role_token_key = keys.TOKEN_ROLE_TOP_KEY + '/' + token_string; // role token path "yrn:yahoo::::token:role/<token>"
1461
-
1462
- var dkcobj = k2hr3.getK2hdkc(true, false); // use permanent object(need to clean)
1463
- if(!apiutil.isSafeEntity(dkcobj)){
1464
- r3logger.elog('Not initialize yet.');
1465
- return false;
1466
- }
1467
-
1468
- // get token value
1469
- var value = dkcobj.getValue(role_token_key, null, true, null);
1470
- value = apiutil.parseJSON(value);
1471
- if( !apiutil.isSafeEntity(value) ||
1472
- !apiutil.isSafeString(value.role) ||
1473
- !apiutil.isSafeString(value.date) ||
1474
- !apiutil.isSafeString(value.expire) ||
1475
- !apiutil.isSafeString(value.creator) ||
1476
- (!apiutil.isSafeString(value.user) && !apiutil.isSafeString(value.hostname) && !apiutil.isSafeString(value.ip)) ||
1477
- isNaN(value.port) ||
1478
- !apiutil.isSafeString(value.tenant) ||
1479
- !apiutil.isSafeString(value.base) )
1480
- {
1481
- r3logger.elog('could not get role role_token_key(' + role_token_key + ') value, or it is wrong value(' + JSON.stringify(value) + ') or already expired.');
1482
- dkcobj.clean();
1483
- return false;
1484
- }
1485
-
1486
- // check tenant name
1487
- var roleptn = new RegExp('^' + keys.MATCH_ANY_TENANT_ROLE); // regex = /^yrn:yahoo:(.*)::(.*):role:(.*)/
1488
- var rolematchs = value.role.match(roleptn);
1489
- if(apiutil.isEmptyArray(rolematchs) || rolematchs.length < 4){
1490
- // token's role is not matched role yrn
1491
- r3logger.elog('role path(' + JSON.stringify(value.role) + ') in role token(' + role_token_key + ') value is not role yrn full path.');
1492
- dkcobj.clean();
1493
- return false;
1494
- }
1495
- if(tenant !== rolematchs[2]){
1496
- // tenant name is not matched.
1497
- r3logger.elog('tenant name(' + JSON.stringify(rolematchs[2]) + ') in role token(' + role_token_key + ') value is not as same as specified tenant(' + JSON.stringify(tenant) + ').');
1498
- dkcobj.clean();
1499
- return false;
1500
- }
1501
-
1502
- // remove token
1503
- if(!dkcobj.remove(role_token_key, false)){ // remove yrn:yahoo::::token:role/<role token>
1504
- r3logger.elog('failed to remove token(' + JSON.stringify(role_token_key) + ').');
1505
- dkcobj.clean();
1506
- return false;
1507
- }
1508
-
1509
- // remove token from subkeys(token top key)
1510
- var subkeylist = dkcobj.getSubkeys(keys.TOKEN_ROLE_TOP_KEY, true); // get subkeys under "yrn:yahoo::::token:role"
1511
- if(apiutil.removeStringFromArray(subkeylist, role_token_key)){
1512
- // update subkey
1513
- if(!dkcobj.setSubkeys(keys.TOKEN_ROLE_TOP_KEY, subkeylist)){ // update subkey -> yrn:yahoo::::token:role
1514
- r3logger.elog('failed to reset role token subkeys to ' + keys.TOKEN_ROLE_TOP_KEY + ' top key, but continue...');
1515
- }
1516
- }
1517
-
1518
- // remove token key from role's tokens subkey.
1519
- var role_tokens_key = value.role + '/' + keys.ROLE_TOKEN_KW; // "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/tokens"
1520
- subkeylist = apiutil.getSafeArray(dkcobj.getSubkeys(role_tokens_key, true));
1521
- if(apiutil.removeStringFromArray(subkeylist, role_token_key)){
1522
- if(!dkcobj.setSubkeys(role_tokens_key, subkeylist)){ // update subkey -> yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/tokens
1523
- r3logger.elog('could not update subkey under ' + role_tokens_key + ' key, but continue...');
1524
- }
1525
- }
1526
-
1527
- dkcobj.clean();
1528
- return true;
1529
- }
1530
-
1531
- //---------------------------------------------------------
1532
- // Get List of Role Tokens
1533
- //---------------------------------------------------------
1534
- // role : role yrn full path or role name(path)
1535
- // tenant : for checking role full yrn path
1536
- // expand : whether to expand token information(default false)
1537
- //
1538
- // result : not expand
1539
- // {
1540
- // result: true/false
1541
- // message: null or error message string
1542
- // tokens: [
1543
- // "role token",
1544
- // ....
1545
- // ]
1546
- // }
1547
- //
1548
- // result : expand
1549
- // {
1550
- // result: true/false
1551
- // message: null or error message string
1552
- // tokens: {
1553
- // "token": {
1554
- // date: create date(UTC ISO 8601)
1555
- // expire: expire date(UTC ISO 8601)
1556
- // user: user name if user created this token
1557
- // hostname: hostname if this token was created by host(name)
1558
- // ip: ip address if this token was created by ip
1559
- // port: port number, if specified port when created token
1560
- // cuk: cuk, if specified cuk when created token
1561
- // },
1562
- // ...
1563
- // }
1564
- // }
1565
- //
1566
- function rawGetListRoleTokens(role, tenant, expand)
1567
- {
1568
- var resobj = {result: true, message: null};
1569
-
1570
- if(!apiutil.isSafeStrings(role, tenant)){
1571
- resobj.result = false;
1572
- resobj.message = 'role(' + JSON.stringify(role) + '), tenant(' + JSON.stringify(tenant) + ') parameters are wrong.';
1573
- r3logger.elog(resobj.message);
1574
- return resobj;
1575
- }
1576
- if('boolean' != typeof expand){
1577
- expand = false;
1578
- }
1579
-
1580
- // check role is full yrn path and tenant
1581
- var keys = r3keys(null, tenant);
1582
- var roleptn = new RegExp('^' + keys.MATCH_ANY_TENANT_ROLE); // regex = /^yrn:yahoo:(.*)::(.*):role:(.*)/
1583
- var rolematchs = role.match(roleptn);
1584
- if(apiutil.isEmptyArray(rolematchs) || rolematchs.length < 4){
1585
- // role is not full yrn
1586
- resobj.result = false;
1587
- resobj.message = 'role(' + JSON.stringify(role) + ') is nor full yrn path.';
1588
- r3logger.elog(resobj.message);
1589
- return resobj;
1590
- }else{
1591
- // role is full yrn to role
1592
- if(!apiutil.compareCaseString(rolematchs[2], tenant)){
1593
- resobj.result = false;
1594
- resobj.message = 'tenant(' + JSON.stringify(tenant) + ') is not as same as tenant in role(' + JSON.stringify(role) + ') full yrn.';
1595
- r3logger.elog(resobj.message);
1596
- return resobj;
1597
- }
1598
- }
1599
-
1600
- var dkcobj = k2hr3.getK2hdkc(true, false); // use permanent object(need to clean)
1601
- if(!apiutil.isSafeEntity(dkcobj)){
1602
- resobj.result = false;
1603
- resobj.message = 'Not initialize yet.';
1604
- r3logger.elog(resobj.message);
1605
- return resobj;
1606
- }
1607
-
1608
- // check role path(check id key under role key)
1609
- var id_key = role + '/' + keys.ID_KW; // "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/id"
1610
- var value = dkcobj.getValue(id_key, null, true, null);
1611
- if(!apiutil.isSafeString(value)){
1612
- resobj.result = false;
1613
- resobj.message = 'role(' + JSON.stringify(role) + ') does not exist';
1614
- r3logger.elog(resobj.message);
1615
- dkcobj.clean();
1616
- return resobj;
1617
- }
1618
-
1619
- // get all role tokens
1620
- var tokens_key = role + '/' + keys.ROLE_TOKEN_KW; // "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/tokens"
1621
- var tokenlist = dkcobj.getSubkeys(tokens_key, true);
1622
- if(expand){
1623
- // get each token information
1624
- resobj.tokens = rawGetDirectRoleTokenInfo(dkcobj, tokenlist);
1625
- if(null == resobj.tokens){
1626
- resobj.tokens = {};
1627
- }
1628
- }else{
1629
- // set token list
1630
- resobj.tokens = [];
1631
-
1632
- if(apiutil.isEmptyArray(tokenlist)){ // token list is full yrn path
1633
- tokenlist = [];
1634
- }
1635
- var tokenptn = new RegExp('^' + keys.MATCH_ANY_ROLE_TOKEN); // regex = /^yrn:yahoo::::token:role\/(.*)/
1636
- for(var cnt = 0; cnt < tokenlist.length; ++cnt){
1637
- if(!apiutil.isSafeString(tokenlist[cnt])){
1638
- r3logger.wlog('Found wrong token string(' + JSON.stringify(tokenlist[cnt]) + ') in token list, skip this.');
1639
- }else{
1640
- var tokenmatches = tokenlist[cnt].match(tokenptn);
1641
- if(!apiutil.isEmptyArray(tokenmatches) && 2 <= tokenmatches.length && apiutil.isSafeString(tokenmatches[1])){
1642
- resobj.tokens.push(tokenmatches[1]);
1643
- }else{
1644
- r3logger.wlog('Found wrong token string(' + JSON.stringify(tokenlist[cnt]) + ') in token list, skip this.');
1645
- }
1646
- }
1647
- }
1648
- }
1649
-
1650
- dkcobj.clean();
1651
- return resobj;
1652
- }
1653
-
1654
- //---------------------------------------------------------
1655
- // Get Role Token Directly
1656
- //---------------------------------------------------------
1657
- // dkcobj_permanent : dkcobj object
1658
- // tokens : array to role token yrn path
1659
- //
1660
- // result : {
1661
- // "token": {
1662
- // date: create date(UTC ISO 8601)
1663
- // expire: expire date(UTC ISO 8601)
1664
- // user: user name if user created this token
1665
- // hostname: hostname if this token was created by host(name)
1666
- // ip: ip address if this token was created by ip
1667
- // port: port number, if specified port when created token
1668
- // cuk: cuk, if specified cuk when created token
1669
- // },
1670
- // ...
1671
- // }
1672
- // or null(if error)
1673
- //
1674
- function rawGetDirectRoleTokenInfo(dkcobj_permanent, tokens)
1675
- {
1676
- if(!(dkcobj_permanent instanceof Object) || !dkcobj_permanent.isPermanent()){
1677
- r3logger.elog('dkcobj_parameters are wrong : dkcobj_permanent=' + JSON.stringify(dkcobj_permanent));
1678
- return null;
1679
- }
1680
- if(apiutil.isSafeString(tokens)){
1681
- tokens = [tokens];
1682
- }
1683
- if(apiutil.isEmptyArray(tokens)){
1684
- r3logger.dlog('tokens(' + JSON.stringify(tokens) + ') is empty or not array');
1685
- return null;
1686
- }
1687
-
1688
- //
1689
- // Keys
1690
- //
1691
- var keys = r3keys();
1692
- var matchptn = keys.TOKEN_ROLE_TOP_KEY + '/'; // matching pattern "yrn:yahoo::::token:role/"
1693
- var resobj = {};
1694
- for(var cnt = 0; cnt < tokens.length; ++cnt){
1695
- // check role token path and split token string
1696
- if(!apiutil.isSafeString(tokens[cnt])){
1697
- r3logger.elog('token(' + JSON.stringify(tokens[cnt]) + ') yrn path is not string, but continue...');
1698
- continue;
1699
- }
1700
- if(0 !== tokens[cnt].indexOf(matchptn)){
1701
- r3logger.elog('token(' + JSON.stringify(tokens[cnt]) + ') is not full yrn path, but continue...');
1702
- continue;
1703
- }
1704
- var token_key = tokens[cnt].split(matchptn)[1];
1705
-
1706
- // get/check role token value
1707
- var value = dkcobj_permanent.getValue(tokens[cnt], null, true, null);
1708
- value = apiutil.parseJSON(value);
1709
- if( !apiutil.isSafeEntity(value) ||
1710
- !apiutil.isSafeString(value.role) ||
1711
- !apiutil.isSafeString(value.date) ||
1712
- !apiutil.isSafeString(value.expire) ||
1713
- !apiutil.isSafeString(value.creator) ||
1714
- (!apiutil.isSafeString(value.user) && !apiutil.isSafeString(value.hostname) && !apiutil.isSafeString(value.ip)) ||
1715
- isNaN(value.port) ||
1716
- !apiutil.isSafeString(value.tenant) ||
1717
- !apiutil.isSafeString(value.base) )
1718
- {
1719
- r3logger.dlog('could not get role token(' + tokens[cnt] + ') value, or it is wrong value(' + JSON.stringify(value) + ') or expired, thus skip this.');
1720
- continue;
1721
- }
1722
-
1723
- // check expire by token value
1724
- if(apiutil.isExpired(value.expire)){
1725
- // expired
1726
- continue;
1727
- }
1728
-
1729
- // delete unnecessary keys
1730
- delete value.role;
1731
- delete value.creator;
1732
- delete value.tenant;
1733
- delete value.base;
1734
- delete value.extra;
1735
-
1736
- // add result
1737
- resobj[token_key] = value;
1738
- }
1739
- return resobj;
1740
- }
1741
-
1742
- //---------------------------------------------------------
1743
- // Check Role Token
1744
- //---------------------------------------------------------
1745
- // token : role token
1746
- // ip : client ip address
1747
- // port : if is_strict is true, check port number
1748
- // cuk : if is_strict is true, check cuk
1749
- // is_strict : true means strict checking
1750
- //
1751
- // result : null or token information
1752
- // {
1753
- // role: role name
1754
- // user: null or user name
1755
- // hostname: null or host name
1756
- // ip: null or ip address
1757
- // port: port number(if host is existed), 0 means any
1758
- // cuk: cuk(allowed null)
1759
- // extra: extra(allowed null)
1760
- // tenant: tenant name
1761
- // display: display alias name for tenant
1762
- // id: tenant id string
1763
- // description: description for tenant
1764
- // scoped: role token is always scoped(true)
1765
- // region: role token is always null
1766
- // }
1767
- //
1768
- function rawCheckRoleToken(token, ip, port, cuk, is_strict)
1769
- {
1770
- if(!apiutil.isSafeString(token)){
1771
- r3logger.elog('some parameters are wrong : token=' + JSON.stringify(token));
1772
- return null;
1773
- }
1774
- if(!apiutil.isSafeEntity(port)){
1775
- port = 0;
1776
- }else if(isNaN(port)){
1777
- r3logger.elog('port(' + JSON.stringify(port) + ') parameter is wrong.');
1778
- return null;
1779
- }
1780
- if(!apiutil.isSafeString(cuk)){
1781
- cuk = null;
1782
- }
1783
- if('boolean' != typeof is_strict){
1784
- is_strict = false;
1785
- }
1786
-
1787
- var dkcobj = k2hr3.getK2hdkc(true, false); // use permanent object(need to clean)
1788
- var value;
1789
- if(!apiutil.isSafeEntity(dkcobj)){
1790
- return null;
1791
- }
1792
-
1793
- //
1794
- // keys
1795
- //
1796
- var keys = r3keys();
1797
- var role_token_key = keys.TOKEN_ROLE_TOP_KEY + '/' + token; // "yrn:yahoo::::token:role/<role token>"
1798
-
1799
- // get role token value
1800
- value = dkcobj.getValue(role_token_key, null, true, null);
1801
- value = apiutil.parseJSON(value);
1802
- if(!apiutil.isSafeEntity(value)){
1803
- r3logger.dlog('could not get role token(' + role_token_key + ') value, or it is wrong value(' + JSON.stringify(value) + '). We check all role token for expire here.');
1804
- dkcobj.clean();
1805
- //
1806
- // check and remove old role token under token top key("yrn:yahoo::::token:role") if old token is expired
1807
- //
1808
- // [NOTE]
1809
- // This processing is taking time, so it runs asynchronously.
1810
- // And for notes on this processing, refer to NOTE of rawCleanupRoleToken function.
1811
- //
1812
- rawCleanupRoleToken(function(result)
1813
- {
1814
- if(!result){
1815
- r3logger.wlog('Failed to cleanup expired role tokens under ' + keys.TOKEN_ROLE_TOP_KEY + ' key, but continue...');
1816
- }
1817
- });
1818
- return null;
1819
- }
1820
- if( !apiutil.isSafeString(value.role) ||
1821
- !apiutil.isSafeString(value.date) ||
1822
- !apiutil.isSafeString(value.expire) ||
1823
- !apiutil.isSafeString(value.creator) ||
1824
- (!apiutil.isSafeString(value.user) && !apiutil.isSafeString(value.hostname) && !apiutil.isSafeString(value.ip)) ||
1825
- isNaN(value.port) ||
1826
- !apiutil.isSafeString(value.tenant) ||
1827
- !apiutil.isSafeString(value.base) )
1828
- {
1829
- //
1830
- // Not check expired token and ip address is empty here.
1831
- //
1832
- r3logger.dlog('could not get role token(' + role_token_key + ') value, or it is wrong value(' + JSON.stringify(value) + ').');
1833
- dkcobj.clean();
1834
- return null;
1835
- }
1836
-
1837
- // Get tenant information
1838
- var tenant_keys = r3keys(null, value.tenant);
1839
- value.display = apiutil.getSafeString(dkcobj.getValue(tenant_keys.TENANT_DISP_KEY, null, true, null));
1840
- value.id = apiutil.getSafeString(dkcobj.getValue(tenant_keys.TENANT_ID_KEY, null, true, null));
1841
- value.description = apiutil.getSafeString(dkcobj.getValue(tenant_keys.TENANT_DESC_KEY, null, true, null));
1842
-
1843
- // compare ip address, if they are specified and token is not created by user
1844
- if(!apiutil.isSafeString(value.user)){
1845
- if(!apiutil.isSafeString(ip) || ip !== value.ip){
1846
- r3logger.dlog('role token(' + role_token_key + ') has value(' + JSON.stringify(value) + '), but it is not same ip(' + ip + ').');
1847
- dkcobj.clean();
1848
- return null;
1849
- }
1850
- // strict checking
1851
- if(is_strict){
1852
- if( value.port != port ||
1853
- !apiutil.isSafeString(value.cuk) != apiutil.isSafeString(cuk) ||
1854
- (apiutil.isSafeString(value.cuk) && value.cuk != cuk) )
1855
- {
1856
- r3logger.dlog('failed strictly checking role token(' + role_token_key + ').');
1857
- dkcobj.clean();
1858
- return null;
1859
- }
1860
- }
1861
- }
1862
-
1863
- // check expire
1864
- if(apiutil.isExpired(value.expire)){
1865
- r3logger.dlog('token(' + token + ') is expired.');
1866
- dkcobj.clean();
1867
- return null;
1868
- }
1869
-
1870
- // get seed id(user id or host(ip) id)
1871
- var seed_id = null;
1872
- if(!apiutil.isSafeString(value.user)){
1873
- // creator is host(ip), then get it's id
1874
- var host_value = dkcobj.getValue(value.creator, null, true, null); // get value from "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/hosts/ip/<ip:port>"
1875
- host_value = apiutil.parseJSON(host_value);
1876
- if( !apiutil.isSafeEntity(host_value) ||
1877
- (!apiutil.isSafeString(host_value.hostname) && !apiutil.isSafeString(host_value.ip)) || // hostname or ip is existed
1878
- !apiutil.isSafeEntity(host_value.port) ||
1879
- !apiutil.isSafeString(host_value[keys.ID_KW]) )
1880
- {
1881
- r3logger.dlog('could not get host or ip(' + value.creator + ') value, or it is wrong value(' + JSON.stringify(host_value) + ').');
1882
- dkcobj.clean();
1883
- return null;
1884
- }
1885
- seed_id = host_value[keys.ID_KW];
1886
-
1887
- }else{
1888
- // creator is user, then get user's id
1889
- var user_id_key = value.creator + ':' + keys.ID_KW; // "yrn:yahoo::::user:<user name>:id"
1890
- seed_id = dkcobj.getValue(user_id_key, null, true, null);
1891
- if(!apiutil.isSafeString(seed_id)){
1892
- r3logger.dlog('could not get user id(' + user_id_key + ') value, or it is wrong value(' + JSON.stringify(seed_id) + ').');
1893
- dkcobj.clean();
1894
- return null;
1895
- }
1896
- }
1897
-
1898
- // get role id for verify
1899
- keys = r3keys(null, value.tenant); // remake keys
1900
- var role_key = value.role; // role member is full yrn => "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}"
1901
- var role_id_key = role_key + '/' + keys.ID_KW; // "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/id"
1902
- var role_id = dkcobj.getValue(role_id_key, null, true, null);
1903
- if(!apiutil.isSafeStrUuid4(role_id)){
1904
- r3logger.dlog('could not get role id(' + role_id_key + ') value, or it is wrong value(' + JSON.stringify(role_id) + '), maybe expired this token');
1905
- dkcobj.clean();
1906
- return null;
1907
- }
1908
- dkcobj.clean();
1909
-
1910
- // make verify token
1911
- var token_elements = apiutil.makeStringToken256(seed_id, role_id, value.base);
1912
- if(!apiutil.isSafeEntity(token_elements)){
1913
- r3logger.dlog('could not make verify token from ' + JSON.stringify(seed_id) + ' and ' + JSON.stringify(role_id) + ' and ' + JSON.stringify(value.base));
1914
- dkcobj.clean();
1915
- return null;
1916
- }
1917
- if(token !== token_elements.str_token){
1918
- r3logger.elog('token(' + token + ') verify is failure, verify token is ' + token_elements.str_token + '.');
1919
- dkcobj.clean();
1920
- return null;
1921
- }
1922
-
1923
- // make result
1924
- var token_info = {};
1925
- token_info.role = value.role;
1926
- token_info.user = value.user;
1927
- token_info.hostname = value.hostname; // hostname
1928
- token_info.ip = value.ip;
1929
- token_info.port = value.port;
1930
- token_info.cuk = value.cuk;
1931
- token_info.extra = value.extra;
1932
- token_info.tenant = value.tenant;
1933
- token_info.display = value.display;
1934
- token_info.id = value.id;
1935
- token_info.description = value.description;
1936
- token_info.scoped = true; // role token is always scoped
1937
- token_info.region = null;
1938
-
1939
- return token_info;
1940
- }
1941
-
1942
- //---------------------------------------------------------
1943
- // cleanup user/tenant by token
1944
- //---------------------------------------------------------
1945
- // utility local function
1946
- //
1947
- // [NOTE]
1948
- // This process can be time consuming when subkey list is too many.
1949
- // In that case, there is a possibility that the consistency of the subkey will be lost.
1950
- // If a new token is added to the subkey list during processing with this function, that
1951
- // token subkey will be overwritten(lost) when this function completes processing.
1952
- // Originally, this subkey list of "yrn:yahoo::::token:user" key has no direct use, so this
1953
- // is not a problem. Because it normally reads the sub key(token key) directly.
1954
- // Please do not read subkey(token key) from the subkey list of "yrn:yahoo::::token:user" key.
1955
- // This subkeys are only useful for "notes".
1956
- //
1957
- function rawCleanupUserToken(callback)
1958
- {
1959
- var dkcobj = k2hr3.getK2hdkc(true, false); // use permanent object(need to clean)
1960
- if(!apiutil.isSafeEntity(dkcobj)){
1961
- callback(false);
1962
- return;
1963
- }
1964
-
1965
- var keys = r3keys();
1966
- var subkeylist = dkcobj.getSubkeys(keys.TOKEN_USER_TOP_KEY, true); // get subkeys under "yrn:yahoo::::token:user"
1967
- var retrive_skeys = new Array(0);
1968
- for(var cnt = 0; cnt < subkeylist.length; ++cnt){
1969
- var user_token_key = dkcobj.getValue(subkeylist[cnt], null, true, null);
1970
- if(!apiutil.isSafeString(user_token_key)){
1971
- // value is not existed, so this key should be removing
1972
- retrive_skeys.push(subkeylist[cnt]);
1973
- }else{
1974
- //
1975
- // user_token_key => "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>"
1976
- //
1977
- var value = dkcobj.getValue(user_token_key, null, true, null);
1978
- if(!apiutil.isSafeString(value)){
1979
- // user_token_key is not existed or expired.
1980
- retrive_skeys.push(subkeylist[cnt]);
1981
-
1982
- // try remove user_token_key from "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token" subkey list
1983
- var parent_user_key = apiutil.getParentPath(user_token_key);
1984
- if(apiutil.isSafeString(parent_user_key)){
1985
- var user_skeys = dkcobj.getSubkeys(parent_user_key, true); // get subkeys under "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token"
1986
- if(apiutil.removeStringFromArray(user_skeys, user_token_key)){
1987
- if(!dkcobj.setSubkeys(parent_user_key, user_skeys)){ // update subkey -> "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token"
1988
- r3logger.wlog('could not update subkey under ' + parent_user_key + ' key, but continue...');
1989
- }
1990
- }
1991
- }else{
1992
- r3logger.wlog('could not get parent key from ' + user_token_key + ' key, but skip it and continue...');
1993
- }
1994
- }
1995
- }
1996
- }
1997
- if(0 < retrive_skeys.length){
1998
- // need to remove keys from subkey list
1999
- var is_update = false;
2000
- subkeylist = dkcobj.getSubkeys(keys.TOKEN_USER_TOP_KEY, true); // re-get subkeys under "yrn:yahoo::::token:user"
2001
-
2002
- for(cnt = 0; cnt < retrive_skeys.length; ++cnt){
2003
- if(apiutil.removeStringFromArray(subkeylist, retrive_skeys[cnt])){
2004
- is_update = true;
2005
- }
2006
- }
2007
- if(is_update){
2008
- if(!dkcobj.setSubkeys(keys.TOKEN_USER_TOP_KEY, subkeylist)){ // update subkey -> "yrn:yahoo::::token:user"
2009
- r3logger.elog('could not update subkey under ' + keys.TOKEN_USER_TOP_KEY + ' key, but continue...');
2010
- dkcobj.clean();
2011
- callback(false);
2012
- return;
2013
- }
2014
- }
2015
- }
2016
-
2017
- dkcobj.clean();
2018
- callback(true);
2019
- }
2020
-
2021
- //---------------------------------------------------------
2022
- // cleanup role by token
2023
- //---------------------------------------------------------
2024
- // utility local function
2025
- //
2026
- // [NOTE]
2027
- // This process can be time consuming when subkey list is too many.
2028
- // In that case, there is a possibility that the consistency of the subkey will be lost.
2029
- // If a new token is added to the subkey list during processing with this function, that
2030
- // token subkey will be overwritten(lost) when this function completes processing.
2031
- // Originally, this subkey list of "yrn:yahoo::::token:role" key has no direct use, so this
2032
- // is not a problem. Because it normally reads the sub key(token key) directly.
2033
- // Please do not read subkey(token key) from the subkey list of "yrn:yahoo::::token:role" key.
2034
- // This subkeys are only useful for "notes".
2035
- //
2036
- function rawCleanupRoleToken(callback)
2037
- {
2038
- var dkcobj = k2hr3.getK2hdkc(true, false); // use permanent object(need to clean)
2039
- if(!apiutil.isSafeEntity(dkcobj)){
2040
- callback(false);
2041
- return;
2042
- }
2043
-
2044
- var keys = r3keys();
2045
- var subkeylist = dkcobj.getSubkeys(keys.TOKEN_ROLE_TOP_KEY, true); // get subkeys under "yrn:yahoo::::token:role"
2046
- var is_changed = false;
2047
- var newsubkeylist = new Array(0);
2048
-
2049
- for(var cnt = 0; cnt < subkeylist.length; ++cnt){
2050
- var role_tokens_key;
2051
-
2052
- // not use attributes for getting role path
2053
- var value = dkcobj.getValue(subkeylist[cnt], null, false, null);
2054
- value = apiutil.parseJSON(value);
2055
- if(apiutil.isSafeEntity(value) && apiutil.isSafeString(value.role)){
2056
- role_tokens_key = value.role + '/' + keys.ROLE_TOKEN_KW; // "yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/tokens"
2057
- }else{
2058
- role_tokens_key = null;
2059
- }
2060
-
2061
- // use attributes for getting role path
2062
- value = dkcobj.getValue(subkeylist[cnt], null, true, null);
2063
- if(!apiutil.isSafeString(value)){
2064
- is_changed = true;
2065
-
2066
- // remove role token from role's tokens subkey
2067
- if(null !== role_tokens_key){
2068
- var tokenlist = apiutil.getSafeArray(dkcobj.getSubkeys(role_tokens_key, true));
2069
- if(apiutil.removeStringFromArray(tokenlist, subkeylist[cnt])){
2070
- if(!dkcobj.setSubkeys(role_tokens_key, tokenlist)){ // update subkey -> yrn:yahoo:<service>::<tenant>:role:<role>{/<role>{...}}/tokens
2071
- r3logger.elog('could not update subkey under ' + role_tokens_key + ' key, but continue...');
2072
- }
2073
- }
2074
- }
2075
- }else{
2076
- newsubkeylist.push(subkeylist[cnt]);
2077
- }
2078
- }
2079
-
2080
- if(false === is_changed){
2081
- dkcobj.clean();
2082
- callback(true);
2083
- return;
2084
- }
2085
- if(!dkcobj.setSubkeys(keys.TOKEN_ROLE_TOP_KEY, newsubkeylist)){ // add subkeys -> yrn:yahoo::::token:role
2086
- r3logger.elog('could not update subkeys(tokens) under ' + keys.TOKEN_ROLE_TOP_KEY + ' key');
2087
- dkcobj.clean();
2088
- callback(false);
2089
- return;
2090
- }
2091
- dkcobj.clean();
2092
- callback(true);
2093
- }
2094
-
2095
- //---------------------------------------------------------
2096
- // get tenant list by token
2097
- //---------------------------------------------------------
2098
- // result {user: xxx, tenant: xxxx, region: xxxxx}
2099
- //
2100
- // [NOTE] Must initialize User/Tenant before calling this function.
2101
- //
2102
- function rawGetUserTenantByToken(token)
2103
- {
2104
- if(!apiutil.isSafeString(token)){
2105
- r3logger.elog('token parameters are wrong : token=' + JSON.stringify(token));
2106
- return null;
2107
- }
2108
-
2109
- var dkcobj = k2hr3.getK2hdkc(true, false); // use permanent object(need to clean)
2110
- if(!apiutil.isSafeEntity(dkcobj)){
2111
- return null;
2112
- }
2113
-
2114
- //
2115
- // Get subkeys under token top key
2116
- //
2117
- var keys = r3keys();
2118
- var token_value_key = keys.TOKEN_USER_TOP_KEY + '/' + token; // "yrn:yahoo::::token:user/<token>"
2119
-
2120
- // get token key under user key
2121
- var user_token_key = dkcobj.getValue(token_value_key, null, true, null); // "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>"
2122
- if(!apiutil.isSafeString(user_token_key)){
2123
- r3logger.dlog('token key(' + token_value_key + ') for token(' + token + ') is not existed.');
2124
- dkcobj.clean();
2125
- //
2126
- // check and remove old token under token top key("yrn:yahoo::::token:user" and "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>")
2127
- // if old token is expired
2128
- //
2129
- // [NOTE]
2130
- // This processing is taking time, so it runs asynchronously.
2131
- // And for notes on this processing, refer to NOTE of rawCleanupUserToken function.
2132
- //
2133
- rawCleanupUserToken(function(result)
2134
- {
2135
- if(!result){
2136
- r3logger.wlog('Failed to cleanup expired user tokens under ' + keys.TOKEN_USER_TOP_KEY + ' key, but continue...');
2137
- }
2138
- });
2139
- return null;
2140
- }
2141
-
2142
- // get user token key's value which is region
2143
- var region = dkcobj.getValue(user_token_key, null, true, null); // "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>" value is region
2144
- if(!apiutil.isSafeString(region)){
2145
- r3logger.dlog('token key(' + user_token_key + ') for token(' + token + ') is not existed.');
2146
- dkcobj.clean();
2147
- //
2148
- // check and remove old token under token top key("yrn:yahoo::::token:user" and "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>")
2149
- // if old token is expired
2150
- //
2151
- // [NOTE] look forwards
2152
- //
2153
- rawCleanupUserToken(function(result)
2154
- {
2155
- if(!result){
2156
- r3logger.wlog('Failed to cleanup expired user tokens under ' + keys.TOKEN_USER_TOP_KEY + ' key, but continue...');
2157
- }
2158
- });
2159
- return null;
2160
- }
2161
-
2162
- // user_token_key format is "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>"
2163
- var pattern = new RegExp('^' + keys.MATCH_ANY_USER_TOKEN); // regex = /^yrn:yahoo::::user:(.*):tenant/(.*)/token/(.*)/
2164
- var matches = user_token_key.match(pattern); // reverse to user/tenant names
2165
- if(apiutil.isEmptyArray(matches) || matches.length < 4 || '' === apiutil.getSafeString(matches[1])){
2166
- r3logger.elog('token key(' + token_value_key + ') for token(' + token + ') has wrong format value(' + user_token_key + ')');
2167
- dkcobj.clean();
2168
- return null;
2169
- }
2170
- var user_name = apiutil.getSafeString(matches[1]);
2171
- var tenant_name = apiutil.getSafeString(matches[2]);
2172
- var tenant_display = null;
2173
- var tenant_id = null;
2174
- var tenant_desc = null;
2175
-
2176
- if('' === tenant_name){
2177
- tenant_name = null;
2178
- }else{
2179
- var tenant_keys = r3keys(user_name, tenant_name);
2180
- tenant_display = apiutil.getSafeString(dkcobj.getValue(tenant_keys.TENANT_DISP_KEY, null, true, null));
2181
- tenant_id = apiutil.getSafeString(dkcobj.getValue(tenant_keys.TENANT_ID_KEY, null, true, null));
2182
- tenant_desc = apiutil.getSafeString(dkcobj.getValue(tenant_keys.TENANT_DESC_KEY, null, true, null));
2183
- }
2184
-
2185
- // if token has seed, need to check seed
2186
- var user_token_seed_key = user_token_key + '/' + keys.SEED_KW; // "yrn:yahoo::::user:<user>:tenant/{<tenant>}/token/<token>/seed"
2187
- var token_seed = dkcobj.getValue(user_token_seed_key, null, true, null);
2188
- dkcobj.clean();
2189
-
2190
- if(apiutil.isSafeString(token_seed)){
2191
- // token has seed, then we need to check manually.
2192
- //
2193
- //r3logger.dlog('token key(' + user_token_key + ') has seed.');
2194
-
2195
- var vres = osapi.verifyUserToken(user_name, tenant_name, token, token_seed);
2196
- if(!vres.result){
2197
- r3logger.elog('failed to verify token(' + token + ') with seed by ' + vres.message);
2198
- return null;
2199
- }
2200
- }
2201
-
2202
- var result = {
2203
- user: user_name,
2204
- tenant: tenant_name,
2205
- display: tenant_display,
2206
- id: tenant_id,
2207
- description: tenant_desc,
2208
- region: region
2209
- };
2210
-
2211
- return result;
2212
- }
2213
-
2214
- //---------------------------------------------------------
2215
- // get tenant list by user
2216
- //---------------------------------------------------------
2217
- // result [
2218
- // {
2219
- // name: "tenant name", => tenant name which is "key" in k2hdkc
2220
- // display: "display tenant name" => display alias name for tenant
2221
- // id: "tenant id" => tenant id string
2222
- // description: "tenant description" => description for tenant
2223
- // },
2224
- // ...
2225
- // ]
2226
- //
2227
- // [NOTE] Must initialize User/Tenant before calling this function.
2228
- //
2229
- function rawGetTenantListByUserWithDkc(dkcobj_permanent, user)
2230
- {
2231
- if(!(dkcobj_permanent instanceof Object) || !dkcobj_permanent.isPermanent()){
2232
- r3logger.elog('dkcobj_parameters are wrong : dkcobj_permanent=' + JSON.stringify(dkcobj_permanent));
2233
- return null;
2234
- }
2235
- if(!apiutil.isSafeString(user)){
2236
- r3logger.elog('user parameters are wrong : user=' + JSON.stringify(user));
2237
- return null;
2238
- }
2239
-
2240
- //
2241
- // Get subkeys under token top key
2242
- //
2243
- var keys = r3keys(user);
2244
- var subkeylist = dkcobj_permanent.getSubkeys(keys.USER_TENANT_TOP_KEY, true); // get subkeys from "yrn:yahoo::::user:<user>:tenant"
2245
-
2246
- // remove no tenant key in tenant subkey list
2247
- if(apiutil.removeStringFromArray(subkeylist, keys.USER_TENANT_COMMON_KEY)){ // remove "yrn:yahoo::::user:<user>:tenant/"
2248
- r3logger.dlog('found ' + keys.USER_TENANT_COMMON_KEY + ' subkey in ' + keys.USER_TENANT_TOP_KEY + ' = user(' + user + ') tenant top key');
2249
- }else{
2250
- r3logger.dlog('not found ' + keys.USER_TENANT_COMMON_KEY + ' subkey in ' + keys.USER_TENANT_TOP_KEY + ' = user(' + user + ') tenant top key');
2251
- }
2252
- if(apiutil.isEmptyArray(subkeylist)){
2253
- r3logger.wlog('There is no tenant for user(' + user + ')');
2254
- return null;
2255
- }
2256
-
2257
- // modify tenant name from yrn full path to only tenant name
2258
- var pattern = new RegExp('^' + keys.USER_TENANT_COMMON_KEY + '(.*)'); // regex = /^yrn:yahoo::::user:<user>\:tenant\/(.*)/
2259
- var name_list = new Array(0);
2260
- for(var cnt = 0; cnt < subkeylist.length; ++cnt){
2261
- var tenant_matches = subkeylist[cnt].match(pattern); // reverse to tenant name
2262
- if(!apiutil.isEmptyArray(tenant_matches) && 2 <= tenant_matches.length && '' !== apiutil.getSafeString(tenant_matches[1])){
2263
- name_list.push(apiutil.getSafeString(tenant_matches[1]));
2264
- }
2265
- }
2266
- if(apiutil.isEmptyArray(name_list)){
2267
- r3logger.wlog('There is no tenant for user(' + user + ')');
2268
- return null;
2269
- }
2270
-
2271
- // get display name for each tenant
2272
- var tenant_list = new Array(0);
2273
- for(cnt = 0; cnt < name_list.length; ++cnt){
2274
- var tenant_keys = r3keys(user, name_list[cnt]);
2275
- var tenant_display = apiutil.getSafeString(dkcobj_permanent.getValue(tenant_keys.TENANT_DISP_KEY, null, true, null));
2276
- var tenant_id = apiutil.getSafeString(dkcobj_permanent.getValue(tenant_keys.TENANT_ID_KEY, null, true, null));
2277
- var tenant_desc = apiutil.getSafeString(dkcobj_permanent.getValue(tenant_keys.TENANT_DESC_KEY, null, true, null));
2278
-
2279
- tenant_list.push({
2280
- name: name_list[cnt],
2281
- display: tenant_display,
2282
- id: tenant_id,
2283
- description: tenant_desc
2284
- });
2285
- }
2286
-
2287
- return tenant_list;
2288
- }
2289
-
2290
- // result [
2291
- // {
2292
- // name: "tenant name", => tenant name which is "key" in k2hdkc
2293
- // display: "display tenant name" => display alias name for tenant
2294
- // id: "tenant id" => tenant id string
2295
- // description: "tenant description" => description for tenant
2296
- // },
2297
- // ...
2298
- // ]
2299
- //
2300
- // [NOTE] Must initialize User/Tenant before calling this function.
2301
- //
2302
- function rawGetTenantListByUser(user)
2303
- {
2304
- var dkcobj = k2hr3.getK2hdkc(true, false); // use permanent object(need to clean)
2305
- if(!apiutil.isSafeEntity(dkcobj)){
2306
- return null;
2307
- }
2308
- var result = rawGetTenantListByUserWithDkc(dkcobj, user);
2309
- dkcobj.clean();
2310
- return result;
2311
- }
2312
-
2313
- //
2314
- // Initialize tenant list by unscoped user token
2315
- //
2316
- function rawInitializeTenantListByUnscoped(unscopedtoken, username, callback)
2317
- {
2318
- var error;
2319
- if(!apiutil.isSafeStrings(unscopedtoken, username)){
2320
- error = new Error('unscopedtoken or username parameters are wrong');
2321
- r3logger.elog(error.message);
2322
- callback(error, null);
2323
- return;
2324
- }
2325
-
2326
- // user id from user name
2327
- var user_info = k2hr3.getUserId(username); // user id from user name
2328
- if(null === user_info || !apiutil.isSafeEntity(user_info.name) || !apiutil.isSafeEntity(user_info.id)){
2329
- error = new Error('could not find username(' + username + ') from unscoped token in k2hdkc.');
2330
- r3logger.elog(error.message);
2331
- callback(error, null);
2332
- return;
2333
- }
2334
-
2335
- // get scoped user token
2336
- return rawInitializeTenantListByToken(unscopedtoken, user_info.name, user_info.id, callback);
2337
- }
2338
-
2339
- //
2340
- // Initialize tenant list
2341
- //
2342
- function rawInitializeTenantListByToken(unscopedtoken, username, userid, callback)
2343
- {
2344
- if(!apiutil.isSafeStrings(unscopedtoken, username, userid)){
2345
- var error = new Error('unscopedtoken or username or userid parameters are wrong');
2346
- r3logger.elog(error.message);
2347
- _callback(error, null);
2348
- return;
2349
- }
2350
-
2351
- var _unscopedtoken = unscopedtoken;
2352
- var _username = username;
2353
- var _userid = userid;
2354
- var _callback = callback;
2355
-
2356
- // get tenant list for check
2357
- osapi.getUserTenantList(_unscopedtoken, _userid, function(err, jsonres)
2358
- {
2359
- var error;
2360
- if(null !== err){
2361
- error = new Error('could not get tenant list for user ' + _username + '(token=' + _unscopedtoken + ') by ' + err.message);
2362
- r3logger.elog(error.message);
2363
- _callback(error, null);
2364
- return;
2365
- }
2366
- //r3logger.dlog('get user tenant list jsonres=\n' + JSON.stringify(jsonres));
2367
-
2368
- // check tenants(and initialize tenants)
2369
- var _name_list = new Array(0);
2370
- var _tenant_list = new Array(0);
2371
- for(var cnt = 0; cnt < jsonres.length; ++cnt){
2372
- if(!apiutil.isSafeEntity(jsonres[cnt])){
2373
- continue;
2374
- }
2375
- // over write
2376
- var resobj = k2hr3.initUserTenant(_username, _userid, _username, jsonres[cnt].name, jsonres[cnt].id, jsonres[cnt].description, jsonres[cnt].display);
2377
- if(!resobj.result){
2378
- error = new Error(resobj.message);
2379
- r3logger.elog(error.message);
2380
- _callback(error, null);
2381
- return;
2382
- }
2383
-
2384
- _name_list.push(jsonres[cnt].name);
2385
- _tenant_list.push({
2386
- name: jsonres[cnt].name,
2387
- display: jsonres[cnt].display
2388
- });
2389
- }
2390
-
2391
- // get and add local tenants
2392
- var tmpresobj = k2hr3.listLocalTenant(_username, true);
2393
- if(!apiutil.isSafeEntity(tmpresobj) || !apiutil.isSafeEntity(tmpresobj.result) || false === tmpresobj.result){
2394
- if(apiutil.isSafeEntity(tmpresobj) && apiutil.isSafeString(tmpresobj.message)){
2395
- r3logger.wlog('failed to get local tenant list by ' + tmpresobj.message);
2396
- }else{
2397
- r3logger.wlog('failed to get local tenant list.');
2398
- }
2399
- }else{
2400
- if(!apiutil.isEmptyArray(tmpresobj.tenants)){
2401
- for(var cnt2 = 0; cnt2 < tmpresobj.tenants.length; ++cnt2){
2402
- var one_tenant = tmpresobj.tenants[cnt2];
2403
- if(!apiutil.isSafeEntity(one_tenant)){
2404
- continue;
2405
- }
2406
- _name_list.push(one_tenant.name);
2407
- _tenant_list.push({
2408
- name: one_tenant.name,
2409
- display: one_tenant.display
2410
- });
2411
- }
2412
- }
2413
- }
2414
-
2415
- // check and remove old tenant for user
2416
- if(!k2hr3.removeComprehensionByNewTenants(_username, _name_list)){
2417
- r3logger.elog('failed to remove some tenant for user, but continue...');
2418
- }
2419
-
2420
- // succeed
2421
- _callback(null, _tenant_list);
2422
- return;
2423
- });
2424
- }
2425
-
2426
- function rawCheckTenantInTenantList(tenants, tenant)
2427
- {
2428
- if(apiutil.isEmptyArray(tenants) || (!apiutil.isSafeString(tenant) && isNaN(tenant))){
2429
- return false;
2430
- }
2431
- for(var cnt = 0; cnt < tenants.length; ++cnt){
2432
- if(!apiutil.isSafeString(tenants[cnt].name) && isNaN(tenants[cnt].name)){
2433
- continue;
2434
- }
2435
- if(String(tenants[cnt].name).trim().toLowerCase() === String(tenant).trim().toLowerCase()){
2436
- // found
2437
- return true;
2438
- }
2439
- }
2440
- return false;
2441
- }
2442
-
2443
- //---------------------------------------------------------
2444
- // Check Token Automatically
2445
- //---------------------------------------------------------
2446
- // req : request from http(s)
2447
- // is_scoped : check scoped token(default not scoped check)
2448
- // is_user : = true : token must be user token
2449
- // = false : token must be role token
2450
- // = other : both token type is allowed, automatically checking.
2451
- //
2452
- // result : {
2453
- // result: true/false
2454
- // message: null or error message string
2455
- // status: status code
2456
- // token: undefined(error) or token string
2457
- // token_type; undefined(error) or "user" or "role"
2458
- // token_info: undefined(error) or token information object
2459
- // }
2460
- //
2461
- // token is following:
2462
- // {
2463
- // role: role name
2464
- // user: null or user name
2465
- // hostname: null or host name
2466
- // ip: null or host ip address
2467
- // port: port number(if host is existed), 0 means any
2468
- // cuk: cuk(allowed null)
2469
- // extra: extra(allowed null)
2470
- // tenant: tenant name
2471
- // display: display alias name for tenant
2472
- // id: tenant id string
2473
- // description: description for tenant
2474
- // scoped: role token is always scoped(true)
2475
- // }
2476
-
2477
- function rawCheckToken(req, is_scoped, is_user)
2478
- {
2479
- var resobj = {result: true, status: 200, message: null};
2480
-
2481
- if(!apiutil.isSafeEntity(req)){
2482
- resobj.result = false;
2483
- resobj.message = 'POST body does not have policy data';
2484
- resobj.status = 400; // 400: Bad Request
2485
- r3logger.elog(resobj.message);
2486
- return resobj;
2487
- }
2488
- if('boolean' !== typeof is_scoped){
2489
- is_scoped = false; // default no scope check
2490
- }
2491
- var user_type = true;
2492
- var role_type = true;
2493
- if('boolean' === typeof is_user){
2494
- if(is_user){
2495
- role_type = false;
2496
- }else{
2497
- user_type = false;
2498
- }
2499
- }
2500
-
2501
- //------------------------------
2502
- // check token
2503
- //------------------------------
2504
- var token;
2505
- var token_type;
2506
- var token_info;
2507
- if(rawIsRoleAuthToken(req)){
2508
- // Get IP address
2509
- var ip = apiutil.getClientIpAddress(req);
2510
- if(!apiutil.isSafeString(ip)){
2511
- resobj.result = false;
2512
- resobj.message = 'Could not get client ip address from request';
2513
- resobj.status = 401; // 401: Unauthorized
2514
- r3logger.elog(resobj.message);
2515
- return resobj;
2516
- }
2517
- // Token is ROLE
2518
- if(!role_type){
2519
- resobj.result = false;
2520
- resobj.message = 'x-auth-token header token is not role token';
2521
- resobj.status = 400; // 400: Bad Request
2522
- r3logger.elog(resobj.message);
2523
- return resobj;
2524
- }
2525
- // get token
2526
- token = rawGetAuthTokenHeader(req, true);
2527
- if(null === token){
2528
- resobj.result = false;
2529
- resobj.message = 'There is no x-auth-token header';
2530
- resobj.status = 400; // 400: Bad Request
2531
- r3logger.elog(resobj.message);
2532
- return resobj;
2533
- }
2534
- // get token information
2535
- //
2536
- // [NOTE]
2537
- // we set always ip address to token(and role/hosts) value now.
2538
- // then we do not need to convert ip to hostname here.
2539
- //
2540
-
2541
- token_info = rawCheckRoleToken(token, ip); // not strictly checking
2542
- if(null === token_info || !apiutil.isSafeEntity(token_info.role)){
2543
- resobj.result = false;
2544
- resobj.message = 'token(' + token + ') is not existed, because it is expired or not set yet.';
2545
- resobj.status = 401; // 401: Unauthorized
2546
- r3logger.elog(resobj.message);
2547
- return resobj;
2548
-
2549
- }else if(is_scoped && !token_info.scoped){
2550
- resobj.result = false;
2551
- resobj.message = 'token(' + token + ') is not scoped.';
2552
- resobj.status = 401; // 401: Unauthorized
2553
- r3logger.elog(resobj.message);
2554
- return resobj;
2555
- }
2556
- token_type = 'role';
2557
-
2558
- }else{
2559
- // Token is USER
2560
- if(!user_type){
2561
- resobj.result = false;
2562
- resobj.message = 'x-auth-token header token is not user token';
2563
- resobj.status = 400; // 400: Bad Request
2564
- r3logger.elog(resobj.message);
2565
- return resobj;
2566
- }
2567
- // get token
2568
- token = rawGetAuthTokenHeader(req, false);
2569
- if(null === token){
2570
- resobj.result = false;
2571
- resobj.message = 'There is no x-auth-token header';
2572
- resobj.status = 400; // 400: Bad Request
2573
- r3logger.elog(resobj.message);
2574
- return resobj;
2575
- }
2576
- // get token information
2577
- token_info = rawCheckUserToken(token);
2578
- if(null === token_info || !apiutil.isSafeEntity(token_info.user)){
2579
- resobj.result = false;
2580
- resobj.message = 'token(' + token + ') is not existed, because it is expired or not set yet.';
2581
- resobj.status = 401; // 401: Unauthorized
2582
- r3logger.elog(resobj.message);
2583
- return resobj;
2584
-
2585
- }else if(is_scoped && !token_info.scoped){
2586
- resobj.result = false;
2587
- resobj.message = 'token(' + token + ') is not scoped.';
2588
- resobj.status = 401; // 401: Unauthorized
2589
- r3logger.elog(resobj.message);
2590
- return resobj;
2591
- }
2592
- token_type = 'user';
2593
- }
2594
-
2595
- resobj.token = token;
2596
- resobj.token_type = token_type;
2597
- resobj.token_info = token_info;
2598
-
2599
- return resobj;
2600
- }
2601
-
2602
- //---------------------------------------------------------
2603
- // Parse Token from X-Auth-Token header in request
2604
- //---------------------------------------------------------
2605
- function rawHasAuthTokenHeader(req)
2606
- {
2607
- if( apiutil.isSafeEntity(req) &&
2608
- apiutil.isSafeEntity(req.headers) &&
2609
- apiutil.isSafeEntity(req.headers['x-auth-token']) )
2610
- {
2611
- return true;
2612
- }
2613
- return false;
2614
- }
2615
-
2616
- function rawGetAuthTokenHeader(req, is_role)
2617
- {
2618
- if('boolean' !== typeof is_role){
2619
- is_role = false;
2620
- }
2621
- if( apiutil.isSafeEntity(req) &&
2622
- apiutil.isSafeEntity(req.headers) &&
2623
- apiutil.isSafeEntity(req.headers['x-auth-token']) &&
2624
- apiutil.isSafeString(req.headers['x-auth-token']) )
2625
- {
2626
- var token = req.headers['x-auth-token'];
2627
- if(is_role){
2628
- if(0 !== token.indexOf('R=')){
2629
- return null;
2630
- }
2631
- token = token.substr(2); // cut 'R='
2632
- }else{
2633
- if(0 === token.indexOf('U=')){
2634
- token = token.substr(2); // cut 'U='
2635
- }
2636
- }
2637
- return token;
2638
- }
2639
- return null;
2640
- }
2641
-
2642
- function rawIsUserAuthToken(req)
2643
- {
2644
- if( apiutil.isSafeEntity(req) &&
2645
- apiutil.isSafeEntity(req.headers) &&
2646
- apiutil.isSafeEntity(req.headers['x-auth-token']) &&
2647
- apiutil.isSafeString(req.headers['x-auth-token']) )
2648
- {
2649
- var token = req.headers['x-auth-token'];
2650
- if(-1 === token.indexOf('U=')){ // user token has 'U='
2651
- return true;
2652
- }else if(-1 === token.indexOf('R=')){
2653
- return true; // user token does not have any prefix
2654
- }
2655
- }
2656
- return false;
2657
- }
2658
-
2659
- function rawIsRoleAuthToken(req)
2660
- {
2661
- if( apiutil.isSafeEntity(req) &&
2662
- apiutil.isSafeEntity(req.headers) &&
2663
- apiutil.isSafeEntity(req.headers['x-auth-token']) &&
2664
- apiutil.isSafeString(req.headers['x-auth-token']) )
2665
- {
2666
- var token = req.headers['x-auth-token'];
2667
- if(0 === token.indexOf('R=')){
2668
- return true; // role token has 'R='
2669
- }
2670
- }
2671
- return false;
2672
- }
2673
-
2674
- //---------------------------------------------------------
2675
- // Exports
2676
- //---------------------------------------------------------
2677
- exports.getUserToken = function(user, passwd, tenant, callback)
2678
- {
2679
- return rawGetUserToken(user, passwd, tenant, callback);
2680
- };
2681
-
2682
- exports.getUserTokenByToken = function(token, tenant, callback)
2683
- {
2684
- return rawGetUserTokenByToken(token, tenant, callback);
2685
- };
2686
-
2687
- exports.getScopedUserToken = function(unscopedtoken, username, tenant, callback)
2688
- {
2689
- return rawGetScopedUserTokenByUnscoped(unscopedtoken, username, tenant, callback);
2690
- };
2691
-
2692
- exports.removeScopedUserToken = function(token)
2693
- {
2694
- return rawRemoveScopedUserToken(token);
2695
- };
2696
-
2697
- exports.checkUserToken = function(token)
2698
- {
2699
- return rawCheckUserToken(token);
2700
- };
2701
-
2702
- exports.getRoleTokenByUser = function(user, tenant, role, expire_limit)
2703
- {
2704
- return rawGetRoleTokenByUser(user, tenant, role, expire_limit);
2705
- };
2706
-
2707
- exports.getRoleTokenByIP = function(ip, port, cuk, tenant, role, expire_limit)
2708
- {
2709
- return rawGetRoleTokenByIP(ip, port, cuk, tenant, role, expire_limit);
2710
- };
2711
-
2712
- exports.removeRoleTokenByUser = function(token, user, tenant)
2713
- {
2714
- return rawRemoveRoleToken(token, user, tenant, null, 0, null, null);
2715
- };
2716
-
2717
- exports.directRemoveRoleTokens = function(dkcobj_permanent, tokens)
2718
- {
2719
- return rawDirectRemoveRoleTokens(dkcobj_permanent, tokens);
2720
- };
2721
-
2722
- exports.removeRoleTokenByPath = function(token_string, tenant)
2723
- {
2724
- return rawRemoveRoleTokenByPath(token_string, tenant);
2725
- };
2726
-
2727
- exports.getListRoleTokens = function(role, tenant, expand)
2728
- {
2729
- return rawGetListRoleTokens(role, tenant, expand);
2730
- };
2731
-
2732
- exports.getDirectRoleTokenInfo = function(dkcobj_permanent, tokens)
2733
- {
2734
- return rawGetDirectRoleTokenInfo(dkcobj_permanent, tokens);
2735
- };
2736
-
2737
- exports.removeRoleTokenByIP = function(token, ip, port, cuk)
2738
- {
2739
- return rawRemoveRoleToken(token, null, null, ip, port, cuk);
2740
- };
2741
-
2742
- exports.checkRoleToken = function(token, ip, port, cuk, is_strict)
2743
- {
2744
- return rawCheckRoleToken(token, ip, port, cuk, is_strict);
2745
- };
2746
-
2747
- exports.getTenantListWithDkc = function(dkcobj_permanent, user)
2748
- {
2749
- return rawGetTenantListByUserWithDkc(dkcobj_permanent, user);
2750
- };
2751
-
2752
- exports.getTenantList = function(user)
2753
- {
2754
- return rawGetTenantListByUser(user);
2755
- };
2756
-
2757
- exports.initializeTenantList = function(unscopedtoken, username, callback)
2758
- {
2759
- return rawInitializeTenantListByUnscoped(unscopedtoken, username, callback);
2760
- };
2761
-
2762
- exports.checkTenantInTenantList = function(tenants, tenant)
2763
- {
2764
- return rawCheckTenantInTenantList(tenants, tenant);
2765
- };
2766
-
2767
- exports.hasAuthTokenHeader = function(req)
2768
- {
2769
- return rawHasAuthTokenHeader(req);
2770
- };
2771
-
2772
- exports.getAuthTokenHeader = function(req, is_role)
2773
- {
2774
- return rawGetAuthTokenHeader(req, is_role);
2775
- };
2776
-
2777
- exports.isUserAuthToken = function(req)
2778
- {
2779
- return rawIsUserAuthToken(req);
2780
- };
2781
-
2782
- exports.isRoleAuthToken = function(req)
2783
- {
2784
- return rawIsRoleAuthToken(req);
2785
- };
2786
-
2787
- exports.checkToken = function(req, is_scoped, is_user)
2788
- {
2789
- return rawCheckToken(req, is_scoped, is_user);
2790
- };
2791
-
2792
- /*
2793
- * Local variables:
2794
- * tab-width: 4
2795
- * c-basic-offset: 4
2796
- * End:
2797
- * vim600: noexpandtab sw=4 ts=4 fdm=marker
2798
- * vim<600: noexpandtab sw=4 ts=4
2799
- */