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.
- package/config/k2hr3-init.sh.templ +2 -2
- package/dist/.gitkeep +0 -0
- package/dist/src/app.js +262 -0
- package/{bin → dist/src/bin}/run.sh +1 -1
- package/dist/src/bin/watcher.js +113 -0
- package/dist/src/bin/www.js +217 -0
- package/dist/src/lib/basicipcheck.js +392 -0
- package/dist/src/lib/cacerts.js +106 -0
- package/dist/src/lib/dbglogging.js +190 -0
- package/dist/src/lib/dummyuserapi.js +719 -0
- package/dist/src/lib/ipwatch.js +354 -0
- package/dist/src/lib/k2hr3acrutil.js +532 -0
- package/dist/src/lib/k2hr3apiutil.js +1444 -0
- package/dist/src/lib/k2hr3cliutil.js +183 -0
- package/dist/src/lib/k2hr3config.js +832 -0
- package/dist/src/lib/k2hr3cryptutil.js +258 -0
- package/dist/src/lib/k2hr3dkc.js +12121 -0
- package/dist/src/lib/k2hr3extdata.js +198 -0
- package/dist/src/lib/k2hr3keys.js +207 -0
- package/dist/src/lib/k2hr3resutil.js +111 -0
- package/dist/src/lib/k2hr3template.js +6546 -0
- package/dist/src/lib/k2hr3tokens.js +2643 -0
- package/dist/src/lib/k2hr3userdata.js +296 -0
- package/dist/src/lib/k8soidc.js +1000 -0
- package/dist/src/lib/openstackapiv2.js +695 -0
- package/dist/src/lib/openstackapiv3.js +932 -0
- package/dist/src/lib/openstackep.js +667 -0
- package/{tests/auto_common.js → dist/src/lib/types.js} +4 -38
- package/dist/src/routes/acr.js +704 -0
- package/dist/src/routes/debugVerify.js +294 -0
- package/dist/src/routes/extdata.js +219 -0
- package/dist/src/routes/list.js +264 -0
- package/dist/src/routes/policy.js +840 -0
- package/dist/src/routes/resource.js +1489 -0
- package/dist/src/routes/role.js +2627 -0
- package/dist/src/routes/service.js +908 -0
- package/dist/src/routes/tenant.js +1141 -0
- package/dist/src/routes/userTokens.js +482 -0
- package/dist/src/routes/userdata.js +212 -0
- package/dist/src/routes/version.js +103 -0
- package/package.json +152 -121
- package/ChangeLog +0 -372
- package/app.js +0 -292
- package/bin/watcher +0 -122
- package/bin/www +0 -180
- package/eslint.config.mjs +0 -68
- package/lib/basicipcheck.js +0 -376
- package/lib/cacerts.js +0 -71
- package/lib/dbglogging.js +0 -151
- package/lib/dummyuserapi.js +0 -766
- package/lib/ipwatch.js +0 -379
- package/lib/k2hr3acrutil.js +0 -516
- package/lib/k2hr3apiutil.js +0 -1494
- package/lib/k2hr3cliutil.js +0 -191
- package/lib/k2hr3config.js +0 -826
- package/lib/k2hr3cryptutil.js +0 -254
- package/lib/k2hr3dkc.js +0 -12632
- package/lib/k2hr3extdata.js +0 -198
- package/lib/k2hr3keys.js +0 -234
- package/lib/k2hr3resutil.js +0 -100
- package/lib/k2hr3template.js +0 -6925
- package/lib/k2hr3tokens.js +0 -2799
- package/lib/k2hr3userdata.js +0 -312
- package/lib/k8soidc.js +0 -1012
- package/lib/openstackapiv2.js +0 -764
- package/lib/openstackapiv3.js +0 -1032
- package/lib/openstackep.js +0 -553
- package/routes/acr.js +0 -738
- package/routes/debugVerify.js +0 -263
- package/routes/extdata.js +0 -232
- package/routes/list.js +0 -270
- package/routes/policy.js +0 -869
- package/routes/resource.js +0 -1441
- package/routes/role.js +0 -2664
- package/routes/service.js +0 -894
- package/routes/tenant.js +0 -1095
- package/routes/userTokens.js +0 -511
- package/routes/userdata.js +0 -218
- package/routes/version.js +0 -108
- package/templ/Dockerfile.templ +0 -71
- package/tests/auto_acr.js +0 -1101
- package/tests/auto_acr_spec.js +0 -79
- package/tests/auto_all_spec.js +0 -142
- package/tests/auto_control_subprocess.sh +0 -243
- package/tests/auto_extdata.js +0 -220
- package/tests/auto_extdata_spec.js +0 -79
- package/tests/auto_init_config_json.sh +0 -275
- package/tests/auto_k2hdkc_server.ini +0 -109
- package/tests/auto_k2hdkc_slave.ini +0 -83
- package/tests/auto_list.js +0 -439
- package/tests/auto_list_spec.js +0 -79
- package/tests/auto_policy.js +0 -1579
- package/tests/auto_policy_spec.js +0 -79
- package/tests/auto_resource.js +0 -10956
- package/tests/auto_resource_spec.js +0 -79
- package/tests/auto_role.js +0 -6150
- package/tests/auto_role_spec.js +0 -79
- package/tests/auto_service.js +0 -770
- package/tests/auto_service_spec.js +0 -79
- package/tests/auto_subprocesses.js +0 -114
- package/tests/auto_template.sh +0 -126
- package/tests/auto_tenant.js +0 -1100
- package/tests/auto_tenant_spec.js +0 -79
- package/tests/auto_token_util.js +0 -219
- package/tests/auto_userdata.js +0 -292
- package/tests/auto_userdata_spec.js +0 -79
- package/tests/auto_usertokens.js +0 -565
- package/tests/auto_usertokens_spec.js +0 -79
- package/tests/auto_version.js +0 -127
- package/tests/auto_version_spec.js +0 -79
- package/tests/auto_watcher.js +0 -157
- package/tests/auto_watcher_spec.js +0 -79
- package/tests/k2hdkc_test.data +0 -986
- package/tests/k2hdkc_test_load.sh +0 -255
- package/tests/k2hr3template_test.js +0 -187
- package/tests/k2hr3template_test.sh +0 -339
- package/tests/k2hr3template_test_async.js +0 -216
- package/tests/k2hr3template_test_template.result +0 -7117
- package/tests/k2hr3template_test_template.txt +0 -3608
- package/tests/k2hr3template_test_vars.js +0 -194
- package/tests/manual_acr_delete.js +0 -143
- package/tests/manual_acr_get.js +0 -297
- package/tests/manual_acr_postput.js +0 -215
- package/tests/manual_allusertenant_get.js +0 -113
- package/tests/manual_extdata_get.js +0 -191
- package/tests/manual_k2hr3keys_get.js +0 -84
- package/tests/manual_list_gethead.js +0 -230
- package/tests/manual_policy_delete.js +0 -132
- package/tests/manual_policy_gethead.js +0 -275
- package/tests/manual_policy_postput.js +0 -297
- package/tests/manual_resource_delete.js +0 -433
- package/tests/manual_resource_gethead.js +0 -423
- package/tests/manual_resource_postput.js +0 -487
- package/tests/manual_role_delete.js +0 -404
- package/tests/manual_role_gethead.js +0 -547
- package/tests/manual_role_postput.js +0 -544
- package/tests/manual_service_delete.js +0 -153
- package/tests/manual_service_gethead.js +0 -178
- package/tests/manual_service_postput.js +0 -348
- package/tests/manual_tenant_delete.js +0 -186
- package/tests/manual_tenant_gethead.js +0 -268
- package/tests/manual_tenant_postput.js +0 -293
- package/tests/manual_test.sh +0 -352
- package/tests/manual_userdata_get.js +0 -173
- package/tests/manual_usertoken_gethead.js +0 -136
- package/tests/manual_usertoken_postput.js +0 -310
- package/tests/manual_version_get.js +0 -127
- package/tests/run_local_test_k2hdkc.sh +0 -174
- package/tests/test.sh +0 -333
package/lib/openstackapiv2.js
DELETED
|
@@ -1,764 +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 http = require('http');
|
|
24
|
-
var https = require('https');
|
|
25
|
-
|
|
26
|
-
var cacerts = require('../lib/cacerts');
|
|
27
|
-
var apiutil = require('./k2hr3apiutil');
|
|
28
|
-
var osksep = require('./openstackep'); // OpenStack KeyStone EndPoint(=osksep)
|
|
29
|
-
|
|
30
|
-
// Debug logging objects
|
|
31
|
-
var r3logger = require('../lib/dbglogging');
|
|
32
|
-
|
|
33
|
-
//
|
|
34
|
-
// Get Unscoped token by user name and passwd from Openstack identity v2 API
|
|
35
|
-
//
|
|
36
|
-
// Document: https://developer.openstack.org/api-ref/identity/v2/?expanded=authenticate-detail
|
|
37
|
-
//
|
|
38
|
-
// Request: {
|
|
39
|
-
// "auth": {
|
|
40
|
-
// "tenantName": "",
|
|
41
|
-
// "passwordCredentials": {
|
|
42
|
-
// "username": "user",
|
|
43
|
-
// "password": "passphrase"
|
|
44
|
-
// }
|
|
45
|
-
// }
|
|
46
|
-
// }
|
|
47
|
-
//
|
|
48
|
-
// Response: {
|
|
49
|
-
// "access": {
|
|
50
|
-
// "metadata": {
|
|
51
|
-
// "is_admin": 0,
|
|
52
|
-
// "roles": []
|
|
53
|
-
// },
|
|
54
|
-
// "serviceCatalog": [],
|
|
55
|
-
// "token": {
|
|
56
|
-
// "audit_ids": [
|
|
57
|
-
// "######################"
|
|
58
|
-
// ],
|
|
59
|
-
// "expires": "2017-06-16T07:12:01Z", (*2)
|
|
60
|
-
// "id": "*************************......", (*1)
|
|
61
|
-
// "issued_at": "2017-06-15T07:12:01.822673"
|
|
62
|
-
// },
|
|
63
|
-
// "user": {
|
|
64
|
-
// "id": "************************.....", (*4)
|
|
65
|
-
// "name": "name", (*3)
|
|
66
|
-
// "roles": [],
|
|
67
|
-
// "roles_links": [],
|
|
68
|
-
// "username": "user"
|
|
69
|
-
// }
|
|
70
|
-
// }
|
|
71
|
-
// }
|
|
72
|
-
//
|
|
73
|
-
// callback(error, result):
|
|
74
|
-
// result = {
|
|
75
|
-
// user: user name (*3)
|
|
76
|
-
// userid: user id (*4)
|
|
77
|
-
// scoped: false (always false)
|
|
78
|
-
// token: token string(id) (*1)
|
|
79
|
-
// expire: expire string (*2)
|
|
80
|
-
// region: region string (region name for keystone endpoint)
|
|
81
|
-
// token_seed: seed ({publisher: 'OPENSTACKV2'})
|
|
82
|
-
// }
|
|
83
|
-
//
|
|
84
|
-
function rawGetUserUnscopedTokenV2(uname, passwd, callback)
|
|
85
|
-
{
|
|
86
|
-
if(!apiutil.isSafeString(uname)){
|
|
87
|
-
var error = new Error('some parameters are wrong : uname=' + JSON.stringify(uname));
|
|
88
|
-
r3logger.elog(error.message);
|
|
89
|
-
callback(error, null);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
if(!apiutil.isSafeString(passwd)){
|
|
93
|
-
passwd = null;
|
|
94
|
-
}
|
|
95
|
-
var _uname = uname;
|
|
96
|
-
var _passwd = passwd;
|
|
97
|
-
var _callback = callback;
|
|
98
|
-
|
|
99
|
-
// get end points for keystone
|
|
100
|
-
osksep.getKeystoneEndpoint(function(err, keystone_ep)
|
|
101
|
-
{
|
|
102
|
-
if(null !== err){
|
|
103
|
-
var error = new Error('could not get keystone end point by ' + err.message);
|
|
104
|
-
r3logger.elog(error.message);
|
|
105
|
-
_callback(error, null);
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
// got safe endpoint for keystone
|
|
109
|
-
//r3logger.dlog(keystone_ep);
|
|
110
|
-
|
|
111
|
-
// build parameters for request
|
|
112
|
-
var body = {
|
|
113
|
-
'auth': {
|
|
114
|
-
'tenantName': '', // unscoped token by no tenant name
|
|
115
|
-
'passwordCredentials': {
|
|
116
|
-
'username': _uname,
|
|
117
|
-
'password': _passwd
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
var strbody = JSON.stringify(body);
|
|
122
|
-
var headers = {
|
|
123
|
-
'Content-Type': 'application/json',
|
|
124
|
-
'Content-Length': strbody.length
|
|
125
|
-
};
|
|
126
|
-
var options = {
|
|
127
|
-
'host': keystone_ep.hostname,
|
|
128
|
-
'port': keystone_ep.port,
|
|
129
|
-
'path': keystone_ep.pathname + '/v2.0/tokens',
|
|
130
|
-
'method': 'POST',
|
|
131
|
-
'headers': headers
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
var httpobj;
|
|
135
|
-
if(apiutil.compareCaseString('https:', keystone_ep.protocol)){
|
|
136
|
-
if(null !== cacerts.ca){
|
|
137
|
-
options.ca = cacerts.ca;
|
|
138
|
-
}
|
|
139
|
-
options.agent = new https.Agent(options);
|
|
140
|
-
httpobj = https;
|
|
141
|
-
}else{
|
|
142
|
-
options.agent = new http.Agent(options);
|
|
143
|
-
httpobj = http;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// send request
|
|
147
|
-
var req = httpobj.request(options, function(res)
|
|
148
|
-
{
|
|
149
|
-
var body = '';
|
|
150
|
-
var status = res.statusCode;
|
|
151
|
-
var error;
|
|
152
|
-
|
|
153
|
-
r3logger.dlog('response status: ' + res.statusCode);
|
|
154
|
-
r3logger.dlog('response header: ' + JSON.stringify(res.headers));
|
|
155
|
-
res.setEncoding('utf8');
|
|
156
|
-
|
|
157
|
-
res.on('data', function(chunk)
|
|
158
|
-
{
|
|
159
|
-
//r3logger.dlog('response chunk: ' + chunk);
|
|
160
|
-
body += chunk;
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
res.on('end', function(result) // eslint-disable-line no-unused-vars
|
|
164
|
-
{
|
|
165
|
-
if(300 <= status){
|
|
166
|
-
error = new Error('could not get unscoped token by status=' + String(status));
|
|
167
|
-
r3logger.elog(error.message);
|
|
168
|
-
_callback(error, null);
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
//r3logger.dlog('response body: ' + body);
|
|
172
|
-
|
|
173
|
-
var res_body = body;
|
|
174
|
-
if(apiutil.checkSimpleJSON(body)){
|
|
175
|
-
res_body = JSON.parse(body);
|
|
176
|
-
}
|
|
177
|
-
if( !apiutil.isSafeEntity(res_body) ||
|
|
178
|
-
!apiutil.isSafeEntity(res_body.access) ||
|
|
179
|
-
!apiutil.isSafeEntity(res_body.access.user) ||
|
|
180
|
-
!apiutil.isSafeEntity(res_body.access.user.name) ||
|
|
181
|
-
!apiutil.compareCaseString(res_body.access.user.name, _uname) ||
|
|
182
|
-
!apiutil.isSafeString(res_body.access.user.id) ||
|
|
183
|
-
!apiutil.isSafeEntity(res_body.access.token) ||
|
|
184
|
-
!apiutil.isSafeString(res_body.access.token.id) ||
|
|
185
|
-
!apiutil.isSafeString(res_body.access.token.expires))
|
|
186
|
-
{
|
|
187
|
-
error = new Error('could not get unscoped token by something wrong response body');
|
|
188
|
-
r3logger.elog(error.message);
|
|
189
|
-
_callback(error, null);
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// convert openstack user id(16 bytes hex string) to UUID(not UUID4)
|
|
194
|
-
var user_id_uuid4 = apiutil.cvtNumberStringToUuid4(res_body.access.user.id, 16);
|
|
195
|
-
|
|
196
|
-
// build result
|
|
197
|
-
var resobj = {};
|
|
198
|
-
resobj.user = res_body.access.user.name.toLowerCase();
|
|
199
|
-
resobj.userid = user_id_uuid4;
|
|
200
|
-
resobj.scoped = false;
|
|
201
|
-
resobj.token = res_body.access.token.id.toLowerCase();
|
|
202
|
-
resobj.expire = res_body.access.token.expires;
|
|
203
|
-
resobj.region = keystone_ep.region.toLowerCase();
|
|
204
|
-
resobj.token_seed = JSON.stringify({ publisher: 'OPENSTACKV2' });
|
|
205
|
-
_callback(null, resobj);
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
req.on('error', function(exception) {
|
|
209
|
-
r3logger.elog('problem with request: ' + exception.message);
|
|
210
|
-
_callback(exception);
|
|
211
|
-
return;
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
// write data to request body
|
|
215
|
-
req.write(strbody);
|
|
216
|
-
req.end();
|
|
217
|
-
}, false);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
//
|
|
221
|
-
// Get Scoped token by unscoped token and tenant name from Openstack identity v2 API
|
|
222
|
-
//
|
|
223
|
-
// Document: https://developer.openstack.org/api-ref/identity/v2/?expanded=authenticate-detail
|
|
224
|
-
//
|
|
225
|
-
// Request: {
|
|
226
|
-
// "auth": {
|
|
227
|
-
// "tenantName": "tenant",
|
|
228
|
-
// "token" : {
|
|
229
|
-
// "id": "**********************....."
|
|
230
|
-
// }
|
|
231
|
-
// }
|
|
232
|
-
// }
|
|
233
|
-
//
|
|
234
|
-
// Response: {
|
|
235
|
-
// "access": {
|
|
236
|
-
// "metadata": {
|
|
237
|
-
// "is_admin": 0,
|
|
238
|
-
// "roles": [
|
|
239
|
-
// "************************......."
|
|
240
|
-
// ]
|
|
241
|
-
// },
|
|
242
|
-
// "serviceCatalog": [
|
|
243
|
-
// {
|
|
244
|
-
// "endpoints": [
|
|
245
|
-
// {
|
|
246
|
-
// "adminURL": "http://xxx.yahoo.co.jp:8776/v1/3b737f48168d32c23928b....",
|
|
247
|
-
// "id": "*****************.......",
|
|
248
|
-
// "internalURL": "http://xxx.yahoo.co.jp:8776/v1/3b737f48168d32c23928b....",
|
|
249
|
-
// "publicURL": "https://yyy.yahoo.co.jp:8776/v1/3b737f48168d32c23928b55f....",
|
|
250
|
-
// "region": "region name" (*4)
|
|
251
|
-
// }
|
|
252
|
-
// ],
|
|
253
|
-
// "endpoints_links": [],
|
|
254
|
-
// "name": "cinder",
|
|
255
|
-
// "type": "identity" (*4)
|
|
256
|
-
// },
|
|
257
|
-
// ...
|
|
258
|
-
// ],
|
|
259
|
-
// "token": {
|
|
260
|
-
// "audit_ids": [
|
|
261
|
-
// "######################",
|
|
262
|
-
// "######################"
|
|
263
|
-
// ],
|
|
264
|
-
// "expires": "2017-06-16T07:06:31Z", (*2)
|
|
265
|
-
// "id": "********************************", (*1)
|
|
266
|
-
// "issued_at": "2017-06-15T07:31:12.027688",
|
|
267
|
-
// "tenant": {
|
|
268
|
-
// "description": null,
|
|
269
|
-
// "enabled": true,
|
|
270
|
-
// "id": "************************...",
|
|
271
|
-
// "name": "tenant name" (*5: tenant name)
|
|
272
|
-
// }
|
|
273
|
-
// },
|
|
274
|
-
// "user": {
|
|
275
|
-
// "id": "************************...", (*4)
|
|
276
|
-
// "name": "user", (*3)
|
|
277
|
-
// "roles": [
|
|
278
|
-
// {
|
|
279
|
-
// "name": "_member_"
|
|
280
|
-
// }
|
|
281
|
-
// ],
|
|
282
|
-
// "roles_links": [],
|
|
283
|
-
// "username": "user name"
|
|
284
|
-
// }
|
|
285
|
-
// }
|
|
286
|
-
// }
|
|
287
|
-
//
|
|
288
|
-
// callback(error, result):
|
|
289
|
-
// result = {
|
|
290
|
-
// user: user name (*3)
|
|
291
|
-
// userid: user id (*4)
|
|
292
|
-
// scoped: true (always true)
|
|
293
|
-
// token: token string(id) (*1)
|
|
294
|
-
// expire: expire string (*2)
|
|
295
|
-
// region: region string (identity's *4 for region name)
|
|
296
|
-
// token_seed: seed ({publisher: 'OPENSTACKV2'})
|
|
297
|
-
// }
|
|
298
|
-
//
|
|
299
|
-
function rawGetUserScopedTokenV2(unscopedtoken, tenant, callback)
|
|
300
|
-
{
|
|
301
|
-
if(!apiutil.isSafeStrings(unscopedtoken, tenant)){
|
|
302
|
-
var error = new Error('some parameters are wrong : unscopedtoken=' + JSON.stringify(unscopedtoken) + ', tenant=' + JSON.stringify(tenant));
|
|
303
|
-
r3logger.elog(error.message);
|
|
304
|
-
callback(error, null);
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
var _unscopedtoken = unscopedtoken;
|
|
308
|
-
var _tenant = tenant;
|
|
309
|
-
var _callback = callback;
|
|
310
|
-
|
|
311
|
-
// get end points for keystone
|
|
312
|
-
osksep.getKeystoneEndpoint(function(err, keystone_ep)
|
|
313
|
-
{
|
|
314
|
-
var error;
|
|
315
|
-
if(null !== err){
|
|
316
|
-
error = new Error('could not get keystone end point by ' + err.message);
|
|
317
|
-
r3logger.elog(error.message);
|
|
318
|
-
_callback(error, null);
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
// got safe endpoint for keystone
|
|
322
|
-
//r3logger.dlog(keystone_ep);
|
|
323
|
-
|
|
324
|
-
// build parameters for request
|
|
325
|
-
var body = {
|
|
326
|
-
'auth': {
|
|
327
|
-
'tenantName': _tenant,
|
|
328
|
-
'token': {
|
|
329
|
-
'id': _unscopedtoken
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
};
|
|
333
|
-
var strbody = JSON.stringify(body);
|
|
334
|
-
var headers = {
|
|
335
|
-
'Content-Type': 'application/json',
|
|
336
|
-
'Content-Length': strbody.length
|
|
337
|
-
};
|
|
338
|
-
var options = {
|
|
339
|
-
'host': keystone_ep.hostname,
|
|
340
|
-
'port': keystone_ep.port,
|
|
341
|
-
'path': keystone_ep.pathname + '/v2.0/tokens',
|
|
342
|
-
'method': 'POST',
|
|
343
|
-
'headers': headers
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
var httpobj;
|
|
347
|
-
if(apiutil.compareCaseString('https:', keystone_ep.protocol)){
|
|
348
|
-
if(null !== cacerts.ca){
|
|
349
|
-
options.ca = cacerts.ca;
|
|
350
|
-
}
|
|
351
|
-
options.agent = new https.Agent(options);
|
|
352
|
-
httpobj = https;
|
|
353
|
-
}else{
|
|
354
|
-
options.agent = new http.Agent(options);
|
|
355
|
-
httpobj = http;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
// send request
|
|
359
|
-
var req = httpobj.request(options, function(res)
|
|
360
|
-
{
|
|
361
|
-
var body = '';
|
|
362
|
-
var status = res.statusCode;
|
|
363
|
-
|
|
364
|
-
r3logger.dlog('response status: ' + res.statusCode);
|
|
365
|
-
r3logger.dlog('response header: ' + JSON.stringify(res.headers));
|
|
366
|
-
res.setEncoding('utf8');
|
|
367
|
-
|
|
368
|
-
res.on('data', function(chunk)
|
|
369
|
-
{
|
|
370
|
-
//r3logger.dlog('response chunk: ' + chunk);
|
|
371
|
-
body += chunk;
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
res.on('end', function(result) // eslint-disable-line no-unused-vars
|
|
375
|
-
{
|
|
376
|
-
if(300 <= status){
|
|
377
|
-
error = new Error('could not get scoped token by status=' + String(status));
|
|
378
|
-
r3logger.elog(error.message);
|
|
379
|
-
_callback(error, null);
|
|
380
|
-
return;
|
|
381
|
-
}
|
|
382
|
-
//r3logger.dlog('response body: ' + body);
|
|
383
|
-
|
|
384
|
-
var res_body = body;
|
|
385
|
-
if(apiutil.checkSimpleJSON(body)){
|
|
386
|
-
res_body = JSON.parse(body);
|
|
387
|
-
}
|
|
388
|
-
if( !apiutil.isSafeEntity(res_body) ||
|
|
389
|
-
!apiutil.isSafeEntity(res_body.access) ||
|
|
390
|
-
apiutil.isEmptyArray(res_body.access.serviceCatalog) ||
|
|
391
|
-
!apiutil.isSafeEntity(res_body.access.user) ||
|
|
392
|
-
!apiutil.isSafeString(res_body.access.user.name) ||
|
|
393
|
-
!apiutil.isSafeString(res_body.access.user.id) ||
|
|
394
|
-
!apiutil.isSafeEntity(res_body.access.token) ||
|
|
395
|
-
!apiutil.isSafeString(res_body.access.token.id) ||
|
|
396
|
-
!apiutil.isSafeEntity(res_body.access.token.expires) ||
|
|
397
|
-
!apiutil.isSafeEntity(res_body.access.token.tenant) ||
|
|
398
|
-
!apiutil.isSafeString(res_body.access.token.tenant.name)||
|
|
399
|
-
!apiutil.compareCaseString(res_body.access.token.tenant.name, _tenant))
|
|
400
|
-
{
|
|
401
|
-
error = new Error('could not get scoped token by something wrong response body');
|
|
402
|
-
r3logger.elog(error.message);
|
|
403
|
-
_callback(error, null);
|
|
404
|
-
return;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
// check & get region
|
|
408
|
-
var region = null;
|
|
409
|
-
for(var cnt = 0; cnt < res_body.access.serviceCatalog.length && null === region; ++cnt){
|
|
410
|
-
if( !apiutil.isSafeEntity(res_body.access.serviceCatalog[cnt]) ||
|
|
411
|
-
apiutil.isEmptyArray(res_body.access.serviceCatalog[cnt].endpoints) ||
|
|
412
|
-
!apiutil.isSafeString(res_body.access.serviceCatalog[cnt].type) )
|
|
413
|
-
{
|
|
414
|
-
r3logger.wlog('one of response for scoped token is something wrong : ' + JSON.stringify(res_body.access.serviceCatalog[cnt]));
|
|
415
|
-
continue;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
// target region by type=identity
|
|
419
|
-
if(!apiutil.compareCaseString('identity', res_body.access.serviceCatalog[cnt].type)){
|
|
420
|
-
continue;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
// check region
|
|
424
|
-
for(var cnt2 = 0; cnt2 < res_body.access.serviceCatalog[cnt].endpoints.length; ++cnt2){
|
|
425
|
-
if( apiutil.isSafeEntity(res_body.access.serviceCatalog[cnt].endpoints[cnt2]) &&
|
|
426
|
-
apiutil.isSafeString(res_body.access.serviceCatalog[cnt].endpoints[cnt2].region))
|
|
427
|
-
{
|
|
428
|
-
if(apiutil.compareCaseString(res_body.access.serviceCatalog[cnt].endpoints[cnt2].region, keystone_ep.region)){
|
|
429
|
-
// found
|
|
430
|
-
region = res_body.access.serviceCatalog[cnt].endpoints[cnt2].region;
|
|
431
|
-
break;
|
|
432
|
-
}else{
|
|
433
|
-
r3logger.wlog('unknown region(' + res_body.access.serviceCatalog[cnt].endpoints[cnt2].region + '), we need to find region(' + keystone_ep.region + '), so skip this');
|
|
434
|
-
}
|
|
435
|
-
}else{
|
|
436
|
-
r3logger.wlog('one of response endpoint for scoped token is something wrong : ' + JSON.stringify(res_body.access.serviceCatalog[cnt].endpoints[cnt2]));
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
if(null === region){
|
|
441
|
-
error = new Error('could not find request region in result.');
|
|
442
|
-
r3logger.elog(error.message);
|
|
443
|
-
_callback(error, null);
|
|
444
|
-
return;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// convert openstack user id(16 bytes hex string) to UUID(not UUID4)
|
|
448
|
-
var user_id_uuid4 = apiutil.cvtNumberStringToUuid4(res_body.access.user.id, 16);
|
|
449
|
-
|
|
450
|
-
// build result
|
|
451
|
-
var resobj = {};
|
|
452
|
-
resobj.user = res_body.access.user.name.toLowerCase();
|
|
453
|
-
resobj.userid = user_id_uuid4;
|
|
454
|
-
resobj.scoped = true;
|
|
455
|
-
resobj.token = res_body.access.token.id.toLowerCase();
|
|
456
|
-
resobj.expire = res_body.access.token.expires;
|
|
457
|
-
resobj.region = region.toLowerCase();
|
|
458
|
-
resobj.token_seed = JSON.stringify({ publisher: 'OPENSTACKV2' });
|
|
459
|
-
_callback(null, resobj);
|
|
460
|
-
});
|
|
461
|
-
});
|
|
462
|
-
req.on('error', function(exception) {
|
|
463
|
-
r3logger.elog('problem with request: ' + exception.message);
|
|
464
|
-
_callback(exception);
|
|
465
|
-
return;
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
// write data to request body
|
|
469
|
-
req.write(strbody);
|
|
470
|
-
req.end();
|
|
471
|
-
}, false);
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
//
|
|
475
|
-
// Verify User Token for OpenStack V2
|
|
476
|
-
//
|
|
477
|
-
// user : target user name for token
|
|
478
|
-
// token : check token
|
|
479
|
-
// token_seed : token seed data
|
|
480
|
-
//
|
|
481
|
-
// result : {
|
|
482
|
-
// result: true/false
|
|
483
|
-
// message: null or error message string
|
|
484
|
-
// }
|
|
485
|
-
//
|
|
486
|
-
function rawVerifyUserTokenPublisherV2(token_seed)
|
|
487
|
-
{
|
|
488
|
-
if(!apiutil.isSafeString(token_seed)){
|
|
489
|
-
return false;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// parse seed
|
|
493
|
-
var seed = token_seed;
|
|
494
|
-
if(apiutil.checkSimpleJSON(token_seed)){
|
|
495
|
-
seed = JSON.parse(token_seed);
|
|
496
|
-
}
|
|
497
|
-
if( !apiutil.isSafeEntity(seed) ||
|
|
498
|
-
!apiutil.isSafeString(seed.publisher) ||
|
|
499
|
-
(seed.publisher != 'OPENSTACKV2') ) // publisher must be 'OPENSTACKV2'
|
|
500
|
-
{
|
|
501
|
-
return false;
|
|
502
|
-
}
|
|
503
|
-
return true;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
function rawWrapVerifyUserTokenPublisherV2(token_seed)
|
|
507
|
-
{
|
|
508
|
-
var resobj = {result: true, message: null};
|
|
509
|
-
|
|
510
|
-
if(!rawVerifyUserTokenPublisherV2(token_seed)){
|
|
511
|
-
resobj.result = false;
|
|
512
|
-
resobj.message = 'token_seed(not printable) is not safe entity.';
|
|
513
|
-
r3logger.elog(resobj.message);
|
|
514
|
-
return resobj;
|
|
515
|
-
}
|
|
516
|
-
return resobj;
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
function rawVerifyUserTokenV2(user, token, token_seed)
|
|
520
|
-
{
|
|
521
|
-
var resobj = {result: true, message: null};
|
|
522
|
-
|
|
523
|
-
if(!apiutil.isSafeStrings(user, token, token_seed)){
|
|
524
|
-
resobj.result = false;
|
|
525
|
-
resobj.message = 'some parameters are wrong : token=' + JSON.stringify(token) + ', token_seed=<not printable>, user=' + JSON.stringify(user);
|
|
526
|
-
r3logger.elog(resobj.message);
|
|
527
|
-
return resobj;
|
|
528
|
-
}
|
|
529
|
-
// check seed
|
|
530
|
-
if(!rawVerifyUserTokenPublisherV2(token_seed)){
|
|
531
|
-
resobj.result = false;
|
|
532
|
-
resobj.message = 'token_seed(not printable) is not safe entity.';
|
|
533
|
-
r3logger.elog(resobj.message);
|
|
534
|
-
return resobj;
|
|
535
|
-
}
|
|
536
|
-
return resobj;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
//
|
|
540
|
-
// Get tenant list by unscoped token from Openstack identity v2 API
|
|
541
|
-
//
|
|
542
|
-
// Document: https://developer.openstack.org/api-ref/identity/v2/?expanded=list-tenants-detail
|
|
543
|
-
//
|
|
544
|
-
// Request: X-Auth-Token: <unscoped token>
|
|
545
|
-
//
|
|
546
|
-
// Response: {
|
|
547
|
-
// "tenants": [
|
|
548
|
-
// {
|
|
549
|
-
// "description": null, (*1)
|
|
550
|
-
// "enabled": true,
|
|
551
|
-
// "id": "***************************.....", (*2)
|
|
552
|
-
// "name": "tenant name" (*3)
|
|
553
|
-
// },
|
|
554
|
-
// {
|
|
555
|
-
// "description": null,
|
|
556
|
-
// "enabled": true,
|
|
557
|
-
// "id": "**************************......",
|
|
558
|
-
// "name": "tenant name"
|
|
559
|
-
// }
|
|
560
|
-
// ],
|
|
561
|
-
// "tenants_links": []
|
|
562
|
-
// }
|
|
563
|
-
//
|
|
564
|
-
// callback(error, result):
|
|
565
|
-
// result = [
|
|
566
|
-
// {
|
|
567
|
-
// name: tenant name (*3)
|
|
568
|
-
// id: tenant id (*2)
|
|
569
|
-
// description: tenant description (*1)
|
|
570
|
-
// display: display name (*3)
|
|
571
|
-
// },
|
|
572
|
-
// ...
|
|
573
|
-
// ]
|
|
574
|
-
//
|
|
575
|
-
// [TODO]
|
|
576
|
-
// Should not we use "tenant id" instead of "tenant name" for "name"?
|
|
577
|
-
// We need this consideration.
|
|
578
|
-
//
|
|
579
|
-
function rawGetUserTenantListV2(unscopedtoken, callback)
|
|
580
|
-
{
|
|
581
|
-
if(!apiutil.isSafeString(unscopedtoken)){
|
|
582
|
-
var error = new Error('parameter is wrong : unscopedtoken=' + JSON.stringify(unscopedtoken));
|
|
583
|
-
r3logger.elog(error.message);
|
|
584
|
-
callback(error, null);
|
|
585
|
-
return;
|
|
586
|
-
}
|
|
587
|
-
var _unscopedtoken = unscopedtoken;
|
|
588
|
-
var _callback = callback;
|
|
589
|
-
|
|
590
|
-
// get end points for keystone
|
|
591
|
-
osksep.getKeystoneEndpoint(function(err, keystone_ep)
|
|
592
|
-
{
|
|
593
|
-
var error;
|
|
594
|
-
if(null !== err){
|
|
595
|
-
error = new Error('could not get keystone end point by ' + err.message);
|
|
596
|
-
r3logger.elog(error.message);
|
|
597
|
-
_callback(error, null);
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
// got safe endpoint for keystone
|
|
601
|
-
//r3logger.dlog(keystone_ep);
|
|
602
|
-
|
|
603
|
-
// build parameters for request
|
|
604
|
-
var headers = {
|
|
605
|
-
'Content-Type': 'application/json',
|
|
606
|
-
'X-Auth-Token': _unscopedtoken,
|
|
607
|
-
'Content-Length': 0
|
|
608
|
-
};
|
|
609
|
-
var options = {
|
|
610
|
-
'host': keystone_ep.hostname,
|
|
611
|
-
'port': keystone_ep.port,
|
|
612
|
-
'path': keystone_ep.pathname + '/v2.0/tenants',
|
|
613
|
-
'method': 'GET',
|
|
614
|
-
'headers': headers
|
|
615
|
-
};
|
|
616
|
-
|
|
617
|
-
var httpobj;
|
|
618
|
-
if(apiutil.compareCaseString('https:', keystone_ep.protocol)){
|
|
619
|
-
if(null !== cacerts.ca){
|
|
620
|
-
options.ca = cacerts.ca;
|
|
621
|
-
}
|
|
622
|
-
options.agent = new https.Agent(options);
|
|
623
|
-
httpobj = https;
|
|
624
|
-
}else{
|
|
625
|
-
options.agent = new http.Agent(options);
|
|
626
|
-
httpobj = http;
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
// send request
|
|
630
|
-
var req = httpobj.get(options, function(res)
|
|
631
|
-
{
|
|
632
|
-
var body = '';
|
|
633
|
-
var status = res.statusCode;
|
|
634
|
-
|
|
635
|
-
r3logger.dlog('response status: ' + res.statusCode);
|
|
636
|
-
r3logger.dlog('response header: ' + JSON.stringify(res.headers));
|
|
637
|
-
res.setEncoding('utf8');
|
|
638
|
-
|
|
639
|
-
res.on('data', function(chunk)
|
|
640
|
-
{
|
|
641
|
-
//r3logger.dlog('response chunk: ' + chunk);
|
|
642
|
-
body += chunk;
|
|
643
|
-
});
|
|
644
|
-
|
|
645
|
-
res.on('end', function(result) // eslint-disable-line no-unused-vars
|
|
646
|
-
{
|
|
647
|
-
if(300 <= status){
|
|
648
|
-
error = new Error('could not get scoped token by status=' + String(status));
|
|
649
|
-
r3logger.elog(error.message);
|
|
650
|
-
_callback(error, null);
|
|
651
|
-
return;
|
|
652
|
-
}
|
|
653
|
-
//r3logger.dlog('response body: ' + body);
|
|
654
|
-
|
|
655
|
-
var res_body = body;
|
|
656
|
-
if(apiutil.checkSimpleJSON(body)){
|
|
657
|
-
res_body = JSON.parse(body);
|
|
658
|
-
}
|
|
659
|
-
if( !apiutil.isSafeEntity(res_body) ||
|
|
660
|
-
apiutil.isEmptyArray(res_body.tenants) )
|
|
661
|
-
{
|
|
662
|
-
error = new Error('failed to get tenant list by unscoped token.');
|
|
663
|
-
r3logger.elog(error.message);
|
|
664
|
-
_callback(error, null);
|
|
665
|
-
return;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
// convert result array
|
|
669
|
-
var resobj = new Array(0);
|
|
670
|
-
for(var cnt = 0; cnt < res_body.tenants.length; ++cnt){
|
|
671
|
-
if( !apiutil.isSafeEntity(res_body.tenants[cnt]) ||
|
|
672
|
-
!apiutil.isSafeString(res_body.tenants[cnt].id) ||
|
|
673
|
-
!apiutil.isSafeString(res_body.tenants[cnt].name) )
|
|
674
|
-
{
|
|
675
|
-
r3logger.wlog('one of response for tenant list is something wrong : ' + JSON.stringify(res_body.tenants[cnt]));
|
|
676
|
-
continue;
|
|
677
|
-
}
|
|
678
|
-
var tenant = {};
|
|
679
|
-
tenant.name = res_body.tenants[cnt].name.toLowerCase();
|
|
680
|
-
tenant.id = res_body.tenants[cnt].id.toLowerCase();
|
|
681
|
-
tenant.description = apiutil.getSafeString(res_body.tenants[cnt].description);
|
|
682
|
-
tenant.display = res_body.tenants[cnt].name;
|
|
683
|
-
resobj.push(tenant);
|
|
684
|
-
}
|
|
685
|
-
if(0 === resobj.length){
|
|
686
|
-
error = new Error('could not get any tenant list by unscoped token.');
|
|
687
|
-
r3logger.elog(error.message);
|
|
688
|
-
_callback(error, null);
|
|
689
|
-
return;
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
_callback(null, resobj);
|
|
693
|
-
});
|
|
694
|
-
});
|
|
695
|
-
|
|
696
|
-
req.on('error', function(exception) {
|
|
697
|
-
r3logger.elog('problem with request: ' + exception.message);
|
|
698
|
-
callback(exception);
|
|
699
|
-
return;
|
|
700
|
-
});
|
|
701
|
-
}, false);
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
//---------------------------------------------------------
|
|
705
|
-
// Exports
|
|
706
|
-
//---------------------------------------------------------
|
|
707
|
-
exports.getUserUnscopedToken = function(uname, passwd, callback)
|
|
708
|
-
{
|
|
709
|
-
return rawGetUserUnscopedTokenV2(uname, passwd, callback);
|
|
710
|
-
};
|
|
711
|
-
|
|
712
|
-
//
|
|
713
|
-
// update token : not implemented
|
|
714
|
-
//
|
|
715
|
-
exports.getUserUnscopedTokenByToken = function(token, callback)
|
|
716
|
-
{
|
|
717
|
-
var error = new Error('getUserUnscopedTokenByToken is not implemented');
|
|
718
|
-
r3logger.elog(error.message);
|
|
719
|
-
callback(error, null);
|
|
720
|
-
};
|
|
721
|
-
|
|
722
|
-
//
|
|
723
|
-
// tenantname : for keystone v2 api
|
|
724
|
-
// tenantid : not used
|
|
725
|
-
//
|
|
726
|
-
exports.getUserScopedToken = function(unscopedtoken, tenantname, tenantid, callback)
|
|
727
|
-
{
|
|
728
|
-
return rawGetUserScopedTokenV2(unscopedtoken, tenantname, callback);
|
|
729
|
-
};
|
|
730
|
-
|
|
731
|
-
//
|
|
732
|
-
// Verify seed publisher type
|
|
733
|
-
//
|
|
734
|
-
exports.verifyUserTokenPublisher = function(token_seed)
|
|
735
|
-
{
|
|
736
|
-
return rawWrapVerifyUserTokenPublisherV2(token_seed);
|
|
737
|
-
};
|
|
738
|
-
|
|
739
|
-
//
|
|
740
|
-
// Verify token
|
|
741
|
-
//
|
|
742
|
-
// tenant is not used.
|
|
743
|
-
//
|
|
744
|
-
exports.verifyUserToken = function(user, tenant, token, token_seed)
|
|
745
|
-
{
|
|
746
|
-
return rawVerifyUserTokenV2(user, token, token_seed);
|
|
747
|
-
};
|
|
748
|
-
|
|
749
|
-
//
|
|
750
|
-
// userid : not used
|
|
751
|
-
//
|
|
752
|
-
exports.getUserTenantList = function(unscopedtoken, userid, callback)
|
|
753
|
-
{
|
|
754
|
-
return rawGetUserTenantListV2(unscopedtoken, callback);
|
|
755
|
-
};
|
|
756
|
-
|
|
757
|
-
/*
|
|
758
|
-
* Local variables:
|
|
759
|
-
* tab-width: 4
|
|
760
|
-
* c-basic-offset: 4
|
|
761
|
-
* End:
|
|
762
|
-
* vim600: noexpandtab sw=4 ts=4 fdm=marker
|
|
763
|
-
* vim<600: noexpandtab sw=4 ts=4
|
|
764
|
-
*/
|