k2hr3-api 1.0.42 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/k2hr3-init.sh.templ +4 -4
- package/dist/.gitkeep +0 -0
- package/dist/src/app.js +262 -0
- package/{bin → dist/src/bin}/run.sh +1 -1
- package/dist/src/bin/watcher.js +113 -0
- package/dist/src/bin/www.js +217 -0
- package/dist/src/lib/basicipcheck.js +392 -0
- package/dist/src/lib/cacerts.js +106 -0
- package/dist/src/lib/dbglogging.js +190 -0
- package/dist/src/lib/dummyuserapi.js +719 -0
- package/dist/src/lib/ipwatch.js +354 -0
- package/dist/src/lib/k2hr3acrutil.js +532 -0
- package/dist/src/lib/k2hr3apiutil.js +1444 -0
- package/dist/src/lib/k2hr3cliutil.js +183 -0
- package/dist/src/lib/k2hr3config.js +832 -0
- package/dist/src/lib/k2hr3cryptutil.js +258 -0
- package/dist/src/lib/k2hr3dkc.js +12121 -0
- package/dist/src/lib/k2hr3extdata.js +198 -0
- package/dist/src/lib/k2hr3keys.js +207 -0
- package/dist/src/lib/k2hr3resutil.js +111 -0
- package/dist/src/lib/k2hr3template.js +6546 -0
- package/dist/src/lib/k2hr3tokens.js +2643 -0
- package/dist/src/lib/k2hr3userdata.js +296 -0
- package/dist/src/lib/k8soidc.js +1000 -0
- package/dist/src/lib/openstackapiv2.js +695 -0
- package/dist/src/lib/openstackapiv3.js +932 -0
- package/dist/src/lib/openstackep.js +667 -0
- package/{tests/auto_common.js → dist/src/lib/types.js} +4 -38
- package/dist/src/routes/acr.js +704 -0
- package/dist/src/routes/debugVerify.js +294 -0
- package/dist/src/routes/extdata.js +219 -0
- package/dist/src/routes/list.js +264 -0
- package/dist/src/routes/policy.js +840 -0
- package/dist/src/routes/resource.js +1489 -0
- package/dist/src/routes/role.js +2627 -0
- package/dist/src/routes/service.js +908 -0
- package/dist/src/routes/tenant.js +1141 -0
- package/dist/src/routes/userTokens.js +482 -0
- package/dist/src/routes/userdata.js +212 -0
- package/dist/src/routes/version.js +103 -0
- package/package.json +152 -121
- package/ChangeLog +0 -378
- package/app.js +0 -292
- package/bin/watcher +0 -122
- package/bin/www +0 -180
- package/eslint.config.mjs +0 -68
- package/lib/basicipcheck.js +0 -376
- package/lib/cacerts.js +0 -71
- package/lib/dbglogging.js +0 -151
- package/lib/dummyuserapi.js +0 -766
- package/lib/ipwatch.js +0 -379
- package/lib/k2hr3acrutil.js +0 -516
- package/lib/k2hr3apiutil.js +0 -1494
- package/lib/k2hr3cliutil.js +0 -191
- package/lib/k2hr3config.js +0 -826
- package/lib/k2hr3cryptutil.js +0 -254
- package/lib/k2hr3dkc.js +0 -12632
- package/lib/k2hr3extdata.js +0 -198
- package/lib/k2hr3keys.js +0 -234
- package/lib/k2hr3resutil.js +0 -100
- package/lib/k2hr3template.js +0 -6925
- package/lib/k2hr3tokens.js +0 -2799
- package/lib/k2hr3userdata.js +0 -312
- package/lib/k8soidc.js +0 -1012
- package/lib/openstackapiv2.js +0 -764
- package/lib/openstackapiv3.js +0 -1032
- package/lib/openstackep.js +0 -553
- package/routes/acr.js +0 -738
- package/routes/debugVerify.js +0 -263
- package/routes/extdata.js +0 -232
- package/routes/list.js +0 -270
- package/routes/policy.js +0 -869
- package/routes/resource.js +0 -1441
- package/routes/role.js +0 -2664
- package/routes/service.js +0 -894
- package/routes/tenant.js +0 -1095
- package/routes/userTokens.js +0 -511
- package/routes/userdata.js +0 -218
- package/routes/version.js +0 -108
- package/templ/Dockerfile.templ +0 -71
- package/tests/auto_acr.js +0 -1101
- package/tests/auto_acr_spec.js +0 -79
- package/tests/auto_all_spec.js +0 -142
- package/tests/auto_control_subprocess.sh +0 -243
- package/tests/auto_extdata.js +0 -220
- package/tests/auto_extdata_spec.js +0 -79
- package/tests/auto_init_config_json.sh +0 -275
- package/tests/auto_k2hdkc_server.ini +0 -109
- package/tests/auto_k2hdkc_slave.ini +0 -83
- package/tests/auto_list.js +0 -439
- package/tests/auto_list_spec.js +0 -79
- package/tests/auto_policy.js +0 -1579
- package/tests/auto_policy_spec.js +0 -79
- package/tests/auto_resource.js +0 -10956
- package/tests/auto_resource_spec.js +0 -79
- package/tests/auto_role.js +0 -6150
- package/tests/auto_role_spec.js +0 -79
- package/tests/auto_service.js +0 -770
- package/tests/auto_service_spec.js +0 -79
- package/tests/auto_subprocesses.js +0 -114
- package/tests/auto_template.sh +0 -126
- package/tests/auto_tenant.js +0 -1100
- package/tests/auto_tenant_spec.js +0 -79
- package/tests/auto_token_util.js +0 -219
- package/tests/auto_userdata.js +0 -292
- package/tests/auto_userdata_spec.js +0 -79
- package/tests/auto_usertokens.js +0 -565
- package/tests/auto_usertokens_spec.js +0 -79
- package/tests/auto_version.js +0 -127
- package/tests/auto_version_spec.js +0 -79
- package/tests/auto_watcher.js +0 -157
- package/tests/auto_watcher_spec.js +0 -79
- package/tests/k2hdkc_test.data +0 -986
- package/tests/k2hdkc_test_load.sh +0 -255
- package/tests/k2hr3template_test.js +0 -187
- package/tests/k2hr3template_test.sh +0 -339
- package/tests/k2hr3template_test_async.js +0 -216
- package/tests/k2hr3template_test_template.result +0 -7117
- package/tests/k2hr3template_test_template.txt +0 -3608
- package/tests/k2hr3template_test_vars.js +0 -194
- package/tests/manual_acr_delete.js +0 -143
- package/tests/manual_acr_get.js +0 -297
- package/tests/manual_acr_postput.js +0 -215
- package/tests/manual_allusertenant_get.js +0 -113
- package/tests/manual_extdata_get.js +0 -191
- package/tests/manual_k2hr3keys_get.js +0 -84
- package/tests/manual_list_gethead.js +0 -230
- package/tests/manual_policy_delete.js +0 -132
- package/tests/manual_policy_gethead.js +0 -275
- package/tests/manual_policy_postput.js +0 -297
- package/tests/manual_resource_delete.js +0 -433
- package/tests/manual_resource_gethead.js +0 -423
- package/tests/manual_resource_postput.js +0 -487
- package/tests/manual_role_delete.js +0 -404
- package/tests/manual_role_gethead.js +0 -547
- package/tests/manual_role_postput.js +0 -544
- package/tests/manual_service_delete.js +0 -153
- package/tests/manual_service_gethead.js +0 -178
- package/tests/manual_service_postput.js +0 -348
- package/tests/manual_tenant_delete.js +0 -186
- package/tests/manual_tenant_gethead.js +0 -268
- package/tests/manual_tenant_postput.js +0 -293
- package/tests/manual_test.sh +0 -352
- package/tests/manual_userdata_get.js +0 -173
- package/tests/manual_usertoken_gethead.js +0 -136
- package/tests/manual_usertoken_postput.js +0 -310
- package/tests/manual_version_get.js +0 -127
- package/tests/run_local_test_k2hdkc.sh +0 -174
- package/tests/test.sh +0 -333
package/lib/openstackapiv3.js
DELETED
|
@@ -1,1032 +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 v3 API
|
|
35
|
-
//
|
|
36
|
-
// Document: https://developer.openstack.org/api-ref/identity/v3/?expanded=password-authentication-with-unscoped-authorization-detail
|
|
37
|
-
//
|
|
38
|
-
// Request: {
|
|
39
|
-
// "auth": {
|
|
40
|
-
// "identity": {
|
|
41
|
-
// "password": {
|
|
42
|
-
// "user": {
|
|
43
|
-
// "domain": {
|
|
44
|
-
// "id": "default"
|
|
45
|
-
// },
|
|
46
|
-
// "password": "*********",
|
|
47
|
-
// "name": "*********"
|
|
48
|
-
// }
|
|
49
|
-
// },
|
|
50
|
-
// "methods": ["password"]
|
|
51
|
-
// }
|
|
52
|
-
// }
|
|
53
|
-
// }
|
|
54
|
-
//
|
|
55
|
-
// Response:
|
|
56
|
-
// Header "X-Subject-Token: 16e4638398574f1d9364............" (*1)
|
|
57
|
-
// Body {
|
|
58
|
-
// "token": {
|
|
59
|
-
// "audit_ids": [
|
|
60
|
-
// "################....."
|
|
61
|
-
// ],
|
|
62
|
-
// "expires_at": "2017-06-17T00:20:38.863072Z", (*2)
|
|
63
|
-
// "extras": {},
|
|
64
|
-
// "issued_at": "2017-06-16T00:20:38.863143Z",
|
|
65
|
-
// "methods": [
|
|
66
|
-
// "password"
|
|
67
|
-
// ],
|
|
68
|
-
// "user": {
|
|
69
|
-
// "domain": {
|
|
70
|
-
// "id": "default",
|
|
71
|
-
// "name": "Default"
|
|
72
|
-
// },
|
|
73
|
-
// "id": "*****************************...", (*4)
|
|
74
|
-
// "name": "user name" (*3)
|
|
75
|
-
// }
|
|
76
|
-
// }
|
|
77
|
-
// }
|
|
78
|
-
//
|
|
79
|
-
// callback(error, result):
|
|
80
|
-
// result = {
|
|
81
|
-
// user: user name (*3)
|
|
82
|
-
// userid: user id (*4)
|
|
83
|
-
// scoped: false (always false)
|
|
84
|
-
// token: token string(id) (*1)
|
|
85
|
-
// expire: expire string (*2)
|
|
86
|
-
// region: region string (region name for keystone endpoint)
|
|
87
|
-
// token_seed: seed ({publisher: 'OPENSTACKV3'})
|
|
88
|
-
// }
|
|
89
|
-
//
|
|
90
|
-
function rawGetUserUnscopedTokenV3(uname, passwd, callback)
|
|
91
|
-
{
|
|
92
|
-
if(!apiutil.isSafeString(uname)){
|
|
93
|
-
var error = new Error('some parameters are wrong : uname=' + JSON.stringify(uname));
|
|
94
|
-
r3logger.elog(error.message);
|
|
95
|
-
callback(error, null);
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
if(!apiutil.isSafeString(passwd)){
|
|
99
|
-
passwd = null;
|
|
100
|
-
}
|
|
101
|
-
var _uname = uname;
|
|
102
|
-
var _passwd = passwd;
|
|
103
|
-
var _callback = callback;
|
|
104
|
-
|
|
105
|
-
// get end points for keystone
|
|
106
|
-
osksep.getKeystoneEndpoint(function(err, keystone_ep)
|
|
107
|
-
{
|
|
108
|
-
if(null !== err){
|
|
109
|
-
var error = new Error('could not get keystone end point by ' + err.message);
|
|
110
|
-
r3logger.elog(error.message);
|
|
111
|
-
_callback(error, null);
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
// got safe endpoint for keystone
|
|
115
|
-
//r3logger.dlog(keystone_ep);
|
|
116
|
-
|
|
117
|
-
// build parameters for request
|
|
118
|
-
var body = {
|
|
119
|
-
'auth': {
|
|
120
|
-
'identity': {
|
|
121
|
-
'password': {
|
|
122
|
-
'user': {
|
|
123
|
-
'domain': {
|
|
124
|
-
'id': 'default'
|
|
125
|
-
},
|
|
126
|
-
'password': _passwd,
|
|
127
|
-
'name': _uname
|
|
128
|
-
}
|
|
129
|
-
},
|
|
130
|
-
'methods': ['password']
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
var strbody = JSON.stringify(body);
|
|
135
|
-
var headers = {
|
|
136
|
-
'Content-Type': 'application/json',
|
|
137
|
-
'Content-Length': strbody.length
|
|
138
|
-
};
|
|
139
|
-
var options = {
|
|
140
|
-
'host': keystone_ep.hostname,
|
|
141
|
-
'port': keystone_ep.port,
|
|
142
|
-
'path': keystone_ep.pathname + '/v3/auth/tokens',
|
|
143
|
-
'method': 'POST',
|
|
144
|
-
'headers': headers
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
var httpobj;
|
|
148
|
-
if(apiutil.compareCaseString('https:', keystone_ep.protocol)){
|
|
149
|
-
if(null !== cacerts.ca){
|
|
150
|
-
options.ca = cacerts.ca;
|
|
151
|
-
}
|
|
152
|
-
options.agent = new https.Agent(options);
|
|
153
|
-
httpobj = https;
|
|
154
|
-
}else{
|
|
155
|
-
options.agent = new http.Agent(options);
|
|
156
|
-
httpobj = http;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// send request
|
|
160
|
-
var req = httpobj.request(options, function(res)
|
|
161
|
-
{
|
|
162
|
-
var body = '';
|
|
163
|
-
var status = res.statusCode;
|
|
164
|
-
var headers = res.headers;
|
|
165
|
-
var error;
|
|
166
|
-
|
|
167
|
-
r3logger.dlog('response status: ' + res.statusCode);
|
|
168
|
-
r3logger.dlog('response header: ' + JSON.stringify(res.headers));
|
|
169
|
-
res.setEncoding('utf8');
|
|
170
|
-
|
|
171
|
-
res.on('data', function(chunk)
|
|
172
|
-
{
|
|
173
|
-
//r3logger.dlog('response chunk: ' + chunk);
|
|
174
|
-
body += chunk;
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
res.on('end', function(result) // eslint-disable-line no-unused-vars
|
|
178
|
-
{
|
|
179
|
-
if(300 <= status){
|
|
180
|
-
error = new Error('could not get unscoped token by status=' + String(status));
|
|
181
|
-
r3logger.elog(error.message);
|
|
182
|
-
_callback(error, null);
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
if(!apiutil.isSafeEntity(headers) || !apiutil.isSafeString(headers['x-subject-token'])){
|
|
186
|
-
error = new Error('could not find unscoped token in header(X-Subject-Token)');
|
|
187
|
-
r3logger.elog(error.message);
|
|
188
|
-
_callback(error, null);
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
//r3logger.dlog('response body: ' + body);
|
|
192
|
-
|
|
193
|
-
var res_body = body;
|
|
194
|
-
if(apiutil.checkSimpleJSON(body)){
|
|
195
|
-
res_body = JSON.parse(body);
|
|
196
|
-
}
|
|
197
|
-
if( !apiutil.isSafeEntity(res_body) ||
|
|
198
|
-
!apiutil.isSafeEntity(res_body.token) ||
|
|
199
|
-
!apiutil.isSafeString(res_body.token.expires_at) ||
|
|
200
|
-
!apiutil.isSafeEntity(res_body.token.user) ||
|
|
201
|
-
!apiutil.isSafeString(res_body.token.user.id) ||
|
|
202
|
-
!apiutil.isSafeString(res_body.token.user.name) ||
|
|
203
|
-
!apiutil.compareCaseString(res_body.token.user.name, _uname))
|
|
204
|
-
{
|
|
205
|
-
error = new Error('could not get unscoped token by something wrong response body : ' + body);
|
|
206
|
-
r3logger.elog(error.message);
|
|
207
|
-
_callback(error, null);
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// convert openstack user id(16 bytes hex string) to UUID(not UUID4)
|
|
212
|
-
var user_id_uuid4 = apiutil.cvtNumberStringToUuid4(res_body.token.user.id, 16);
|
|
213
|
-
|
|
214
|
-
// build result
|
|
215
|
-
var resobj = {};
|
|
216
|
-
resobj.user = res_body.token.user.name.toLowerCase();
|
|
217
|
-
resobj.userid = user_id_uuid4;
|
|
218
|
-
resobj.scoped = false;
|
|
219
|
-
resobj.token = headers['x-subject-token'];
|
|
220
|
-
resobj.expire = res_body.token.expires_at;
|
|
221
|
-
resobj.region = keystone_ep.region.toLowerCase();
|
|
222
|
-
resobj.token_seed = JSON.stringify({ publisher: 'OPENSTACKV3' });
|
|
223
|
-
_callback(null, resobj);
|
|
224
|
-
return;
|
|
225
|
-
});
|
|
226
|
-
});
|
|
227
|
-
req.on('error', function(exception) {
|
|
228
|
-
r3logger.elog('problem with request: ' + exception.message);
|
|
229
|
-
_callback(exception);
|
|
230
|
-
return;
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
// write data to request body
|
|
234
|
-
req.write(strbody);
|
|
235
|
-
req.end();
|
|
236
|
-
}, true);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
//
|
|
240
|
-
// Get Unscoped token by openstack token from Openstack identity v3 API
|
|
241
|
-
//
|
|
242
|
-
// Document: https://docs.openstack.org/api-ref/identity/v3/?expanded=token-authentication-with-unscoped-authorization-detail#token-authentication-with-unscoped-authorization
|
|
243
|
-
//
|
|
244
|
-
// Request: {
|
|
245
|
-
// "auth": {
|
|
246
|
-
// "identity": {
|
|
247
|
-
// "methods": [
|
|
248
|
-
// "token"
|
|
249
|
-
// ],
|
|
250
|
-
// "token": {
|
|
251
|
-
// "id": "**********"
|
|
252
|
-
// }
|
|
253
|
-
// }
|
|
254
|
-
// }
|
|
255
|
-
// }
|
|
256
|
-
//
|
|
257
|
-
//
|
|
258
|
-
// Response:
|
|
259
|
-
// Header "X-Subject-Token: 16e4638398574f1d9364............" (*1)
|
|
260
|
-
// {
|
|
261
|
-
// "token": {
|
|
262
|
-
// "audit_ids": [
|
|
263
|
-
// "################....."
|
|
264
|
-
// ],
|
|
265
|
-
// "expires_at": "2017-06-17T00:20:38.863072Z", (*2)
|
|
266
|
-
// "issued_at": "2015-11-05T21:00:33.819948Z",
|
|
267
|
-
// "methods": [
|
|
268
|
-
// "token"
|
|
269
|
-
// ],
|
|
270
|
-
// "user": {
|
|
271
|
-
// "domain": {
|
|
272
|
-
// "id": "default",
|
|
273
|
-
// "name": "Default"
|
|
274
|
-
// },
|
|
275
|
-
// "id": "*****************************...", (*4)
|
|
276
|
-
// "name": "user name" (*3)
|
|
277
|
-
// "password_expires_at": null
|
|
278
|
-
// }
|
|
279
|
-
// }
|
|
280
|
-
// }
|
|
281
|
-
//
|
|
282
|
-
// callback(error, result):
|
|
283
|
-
// result = {
|
|
284
|
-
// user: user name (*3)
|
|
285
|
-
// userid: user id (*4)
|
|
286
|
-
// scoped: false (always false)
|
|
287
|
-
// token: token string(id) (*1)
|
|
288
|
-
// expire: expire string (*2)
|
|
289
|
-
// region: region string (region name for keystone endpoint)
|
|
290
|
-
// token_seed: seed ({publisher: 'OPENSTACKV3'})
|
|
291
|
-
// }
|
|
292
|
-
//
|
|
293
|
-
function rawGetUserUnscopedTokenByOstokenV3(ostoken, callback)
|
|
294
|
-
{
|
|
295
|
-
if(!apiutil.isSafeString(ostoken)){
|
|
296
|
-
var error = new Error('some parameter is wrong : ostoken=' + JSON.stringify(ostoken));
|
|
297
|
-
r3logger.elog(error.message);
|
|
298
|
-
callback(error, null);
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
var _ostoken = ostoken;
|
|
302
|
-
var _callback = callback;
|
|
303
|
-
|
|
304
|
-
// get end points for keystone
|
|
305
|
-
osksep.getKeystoneEndpoint(function(err, keystone_ep)
|
|
306
|
-
{
|
|
307
|
-
if(null !== err){
|
|
308
|
-
var error = new Error('could not get keystone end point by ' + err.message);
|
|
309
|
-
r3logger.elog(error.message);
|
|
310
|
-
_callback(error, null);
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
// got safe endpoint for keystone
|
|
314
|
-
//r3logger.dlog(keystone_ep);
|
|
315
|
-
|
|
316
|
-
// build parameters for request
|
|
317
|
-
var body = {
|
|
318
|
-
'auth': {
|
|
319
|
-
'identity': {
|
|
320
|
-
'token': {
|
|
321
|
-
'id': _ostoken,
|
|
322
|
-
},
|
|
323
|
-
'methods': ['token']
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
};
|
|
327
|
-
var strbody = JSON.stringify(body);
|
|
328
|
-
var headers = {
|
|
329
|
-
'Content-Type': 'application/json',
|
|
330
|
-
'Content-Length': strbody.length
|
|
331
|
-
};
|
|
332
|
-
var options = {
|
|
333
|
-
'host': keystone_ep.hostname,
|
|
334
|
-
'port': keystone_ep.port,
|
|
335
|
-
'path': keystone_ep.pathname + '/v3/auth/tokens',
|
|
336
|
-
'method': 'POST',
|
|
337
|
-
'headers': headers
|
|
338
|
-
};
|
|
339
|
-
|
|
340
|
-
var httpobj;
|
|
341
|
-
if(apiutil.compareCaseString('https:', keystone_ep.protocol)){
|
|
342
|
-
if(null !== cacerts.ca){
|
|
343
|
-
options.ca = cacerts.ca;
|
|
344
|
-
}
|
|
345
|
-
options.agent = new https.Agent(options);
|
|
346
|
-
httpobj = https;
|
|
347
|
-
}else{
|
|
348
|
-
options.agent = new http.Agent(options);
|
|
349
|
-
httpobj = http;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// send request
|
|
353
|
-
var req = httpobj.request(options, function(res)
|
|
354
|
-
{
|
|
355
|
-
var body = '';
|
|
356
|
-
var status = res.statusCode;
|
|
357
|
-
var headers = res.headers;
|
|
358
|
-
var error;
|
|
359
|
-
|
|
360
|
-
r3logger.dlog('response status: ' + res.statusCode);
|
|
361
|
-
r3logger.dlog('response header: ' + JSON.stringify(res.headers));
|
|
362
|
-
res.setEncoding('utf8');
|
|
363
|
-
|
|
364
|
-
res.on('data', function(chunk)
|
|
365
|
-
{
|
|
366
|
-
//r3logger.dlog('response chunk: ' + chunk);
|
|
367
|
-
body += chunk;
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
res.on('end', function(result) // eslint-disable-line no-unused-vars
|
|
371
|
-
{
|
|
372
|
-
if(300 <= status){
|
|
373
|
-
error = new Error('could not get unscoped token by status=' + String(status));
|
|
374
|
-
r3logger.elog(error.message);
|
|
375
|
-
_callback(error, null);
|
|
376
|
-
return;
|
|
377
|
-
}
|
|
378
|
-
if(!apiutil.isSafeEntity(headers) || !apiutil.isSafeString(headers['x-subject-token'])){
|
|
379
|
-
error = new Error('could not find unscoped token in header(X-Subject-Token)');
|
|
380
|
-
r3logger.elog(error.message);
|
|
381
|
-
_callback(error, null);
|
|
382
|
-
return;
|
|
383
|
-
}
|
|
384
|
-
//r3logger.dlog('response body: ' + body);
|
|
385
|
-
|
|
386
|
-
var res_body = body;
|
|
387
|
-
if(apiutil.checkSimpleJSON(body)){
|
|
388
|
-
res_body = JSON.parse(body);
|
|
389
|
-
}
|
|
390
|
-
if( !apiutil.isSafeEntity(res_body) ||
|
|
391
|
-
!apiutil.isSafeEntity(res_body.token) ||
|
|
392
|
-
!apiutil.isSafeString(res_body.token.expires_at)||
|
|
393
|
-
!apiutil.isSafeEntity(res_body.token.user) ||
|
|
394
|
-
!apiutil.isSafeString(res_body.token.user.id) ||
|
|
395
|
-
!apiutil.isSafeString(res_body.token.user.name) )
|
|
396
|
-
{
|
|
397
|
-
error = new Error('could not get unscoped token by something wrong response body : ' + body);
|
|
398
|
-
r3logger.elog(error.message);
|
|
399
|
-
_callback(error, null);
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// convert openstack user id(16 bytes hex string) to UUID(not UUID4)
|
|
404
|
-
var user_id_uuid4 = apiutil.cvtNumberStringToUuid4(res_body.token.user.id, 16);
|
|
405
|
-
|
|
406
|
-
// build result
|
|
407
|
-
var resobj = {};
|
|
408
|
-
resobj.user = res_body.token.user.name.toLowerCase();
|
|
409
|
-
resobj.userid = user_id_uuid4;
|
|
410
|
-
resobj.scoped = false;
|
|
411
|
-
resobj.token = headers['x-subject-token'];
|
|
412
|
-
resobj.expire = res_body.token.expires_at;
|
|
413
|
-
resobj.region = keystone_ep.region.toLowerCase();
|
|
414
|
-
resobj.token_seed = JSON.stringify({ publisher: 'OPENSTACKV3' });
|
|
415
|
-
_callback(null, resobj);
|
|
416
|
-
});
|
|
417
|
-
});
|
|
418
|
-
req.on('error', function(exception) {
|
|
419
|
-
r3logger.elog('problem with request: ' + exception.message);
|
|
420
|
-
_callback(exception);
|
|
421
|
-
return;
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
// write data to request body
|
|
425
|
-
req.write(strbody);
|
|
426
|
-
req.end();
|
|
427
|
-
}, true);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
//
|
|
431
|
-
// Get Scoped token by unscoped token and tenant name from Openstack identity v3 API
|
|
432
|
-
//
|
|
433
|
-
// Document: https://developer.openstack.org/api-ref/identity/v3/?expanded=token-authentication-with-scoped-authorization-detail
|
|
434
|
-
//
|
|
435
|
-
// Request: {
|
|
436
|
-
// "auth": {
|
|
437
|
-
// "identity": {
|
|
438
|
-
// "methods": [
|
|
439
|
-
// "token"
|
|
440
|
-
// ],
|
|
441
|
-
// "token": {
|
|
442
|
-
// "id": "<unscoped token>"
|
|
443
|
-
// }
|
|
444
|
-
// },
|
|
445
|
-
// "scope": {
|
|
446
|
-
// "project": {
|
|
447
|
-
// "id": "<project(tenant) id>"
|
|
448
|
-
// }
|
|
449
|
-
// }
|
|
450
|
-
// }
|
|
451
|
-
// }
|
|
452
|
-
//
|
|
453
|
-
// Response:
|
|
454
|
-
// Header "X-Subject-Token: 16e4638398574f1d9364............" (*1)
|
|
455
|
-
// Body {
|
|
456
|
-
// "token": {
|
|
457
|
-
// "audit_ids": [
|
|
458
|
-
// "######################",
|
|
459
|
-
// "######################"
|
|
460
|
-
// ],
|
|
461
|
-
// "catalog": [
|
|
462
|
-
// {
|
|
463
|
-
// "endpoints": [
|
|
464
|
-
// {
|
|
465
|
-
// "id": "*****************************...",
|
|
466
|
-
// "interface": "public" (=public, others are admin/internal),
|
|
467
|
-
// "region": "***************", (*5)
|
|
468
|
-
// "region_id": ###############
|
|
469
|
-
// "url": "http://keystone/v2.0"
|
|
470
|
-
// },
|
|
471
|
-
// ...
|
|
472
|
-
// ],
|
|
473
|
-
// "id": "*****************************...",
|
|
474
|
-
// "name": "keystone",
|
|
475
|
-
// "type": "identity" (=identity)
|
|
476
|
-
// },
|
|
477
|
-
// ...
|
|
478
|
-
// ],
|
|
479
|
-
// "expires_at": "2017-06-17T00:46:16.923305Z", (*2)
|
|
480
|
-
// "extras": {},
|
|
481
|
-
// "issued_at": "2017-06-16T01:07:56.325351Z",
|
|
482
|
-
// "methods": [
|
|
483
|
-
// "token",
|
|
484
|
-
// "password"
|
|
485
|
-
// ],
|
|
486
|
-
// "project": {
|
|
487
|
-
// "domain": {
|
|
488
|
-
// "id": "default",
|
|
489
|
-
// "name": "Default"
|
|
490
|
-
// },
|
|
491
|
-
// "id": "*****************************...", (=project id)
|
|
492
|
-
// "name": "project name" (*5: project(tenant) name)
|
|
493
|
-
// },
|
|
494
|
-
// "roles": [
|
|
495
|
-
// {
|
|
496
|
-
// "id": "*****************************...",
|
|
497
|
-
// "name": "_member_"
|
|
498
|
-
// }
|
|
499
|
-
// ],
|
|
500
|
-
// "user": {
|
|
501
|
-
// "domain": {
|
|
502
|
-
// "id": "default",
|
|
503
|
-
// "name": "Default"
|
|
504
|
-
// },
|
|
505
|
-
// "id": "*****************************...", (*4: user id)
|
|
506
|
-
// "name": "user name" (*3: user name)
|
|
507
|
-
// }
|
|
508
|
-
// }
|
|
509
|
-
// }
|
|
510
|
-
//
|
|
511
|
-
// callback(error, result):
|
|
512
|
-
// result = {
|
|
513
|
-
// user: user name (*3)
|
|
514
|
-
// userid: user id (*4)
|
|
515
|
-
// scoped: true (always true)
|
|
516
|
-
// token: token string(id) (*1)
|
|
517
|
-
// expire: expire string (*2)
|
|
518
|
-
// region: region string (identity's *5 for region name)
|
|
519
|
-
// token_seed: seed ({publisher: 'OPENSTACKV3'})
|
|
520
|
-
// }
|
|
521
|
-
//
|
|
522
|
-
function rawGetUserScopedTokenV3(unscopedtoken, tenantid, callback)
|
|
523
|
-
{
|
|
524
|
-
var error;
|
|
525
|
-
if(!apiutil.isSafeString(unscopedtoken)){
|
|
526
|
-
error = new Error('parameter is wrong : unscopedtoken=' + JSON.stringify(unscopedtoken));
|
|
527
|
-
r3logger.elog(error.message);
|
|
528
|
-
callback(error, null);
|
|
529
|
-
return;
|
|
530
|
-
}
|
|
531
|
-
if(!apiutil.isSafeString(tenantid) && isNaN(tenantid)){
|
|
532
|
-
// id allows hex character string, decimal character string, decimal number value.
|
|
533
|
-
//
|
|
534
|
-
error = new Error('parameter is wrong : tenantid=' + JSON.stringify(tenantid));
|
|
535
|
-
r3logger.elog(error.message);
|
|
536
|
-
callback(error, null);
|
|
537
|
-
return;
|
|
538
|
-
}
|
|
539
|
-
if(!apiutil.isSafeString(tenantid)){
|
|
540
|
-
// to string
|
|
541
|
-
tenantid = String(tenantid);
|
|
542
|
-
}
|
|
543
|
-
var _unscopedtoken = unscopedtoken;
|
|
544
|
-
var _tenantid = tenantid;
|
|
545
|
-
var _callback = callback;
|
|
546
|
-
|
|
547
|
-
// get end points for keystone
|
|
548
|
-
osksep.getKeystoneEndpoint(function(err, keystone_ep)
|
|
549
|
-
{
|
|
550
|
-
var error;
|
|
551
|
-
if(null !== err){
|
|
552
|
-
error = new Error('could not get keystone end point by ' + err.message);
|
|
553
|
-
r3logger.elog(error.message);
|
|
554
|
-
_callback(error, null);
|
|
555
|
-
return;
|
|
556
|
-
}
|
|
557
|
-
// got safe endpoint for keystone
|
|
558
|
-
//r3logger.dlog(keystone_ep);
|
|
559
|
-
|
|
560
|
-
// build parameters for request
|
|
561
|
-
var body = {
|
|
562
|
-
'auth': {
|
|
563
|
-
'identity': {
|
|
564
|
-
'methods': [
|
|
565
|
-
'token'
|
|
566
|
-
],
|
|
567
|
-
'token': {
|
|
568
|
-
'id': _unscopedtoken
|
|
569
|
-
}
|
|
570
|
-
},
|
|
571
|
-
'scope': {
|
|
572
|
-
'project': {
|
|
573
|
-
'id': _tenantid
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
};
|
|
578
|
-
var strbody = JSON.stringify(body);
|
|
579
|
-
var headers = {
|
|
580
|
-
'Content-Type': 'application/json',
|
|
581
|
-
'Content-Length': strbody.length
|
|
582
|
-
};
|
|
583
|
-
var options = {
|
|
584
|
-
'host': keystone_ep.hostname,
|
|
585
|
-
'port': keystone_ep.port,
|
|
586
|
-
'path': keystone_ep.pathname + '/v3/auth/tokens',
|
|
587
|
-
'method': 'POST',
|
|
588
|
-
'headers': headers
|
|
589
|
-
};
|
|
590
|
-
|
|
591
|
-
var httpobj;
|
|
592
|
-
if(apiutil.compareCaseString('https:', keystone_ep.protocol)){
|
|
593
|
-
if(null !== cacerts.ca){
|
|
594
|
-
options.ca = cacerts.ca;
|
|
595
|
-
}
|
|
596
|
-
options.agent = new https.Agent(options);
|
|
597
|
-
httpobj = https;
|
|
598
|
-
}else{
|
|
599
|
-
options.agent = new http.Agent(options);
|
|
600
|
-
httpobj = http;
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
// send request
|
|
604
|
-
var req = httpobj.request(options, function(res)
|
|
605
|
-
{
|
|
606
|
-
var body = '';
|
|
607
|
-
var status = res.statusCode;
|
|
608
|
-
var headers = res.headers;
|
|
609
|
-
|
|
610
|
-
r3logger.dlog('response status: ' + res.statusCode);
|
|
611
|
-
r3logger.dlog('response header: ' + JSON.stringify(res.headers));
|
|
612
|
-
res.setEncoding('utf8');
|
|
613
|
-
|
|
614
|
-
res.on('data', function(chunk)
|
|
615
|
-
{
|
|
616
|
-
//r3logger.dlog('response chunk: ' + chunk);
|
|
617
|
-
body += chunk;
|
|
618
|
-
});
|
|
619
|
-
|
|
620
|
-
res.on('end', function(result) // eslint-disable-line no-unused-vars
|
|
621
|
-
{
|
|
622
|
-
if(300 <= status){
|
|
623
|
-
error = new Error('could not get scoped token by status=' + String(status));
|
|
624
|
-
r3logger.elog(error.message);
|
|
625
|
-
_callback(error, null);
|
|
626
|
-
return;
|
|
627
|
-
}
|
|
628
|
-
if(!apiutil.isSafeEntity(headers) || !apiutil.isSafeString(headers['x-subject-token'])){
|
|
629
|
-
error = new Error('could not find unscoped token in header(X-Subject-Token)');
|
|
630
|
-
r3logger.elog(error.message);
|
|
631
|
-
_callback(error, null);
|
|
632
|
-
return;
|
|
633
|
-
}
|
|
634
|
-
//r3logger.dlog('response body: ' + body);
|
|
635
|
-
|
|
636
|
-
var res_body = body;
|
|
637
|
-
if(apiutil.checkSimpleJSON(body)){
|
|
638
|
-
res_body = JSON.parse(body);
|
|
639
|
-
}
|
|
640
|
-
if( !apiutil.isSafeEntity(res_body) ||
|
|
641
|
-
!apiutil.isSafeEntity(res_body.token) ||
|
|
642
|
-
apiutil.isEmptyArray(res_body.token.catalog) ||
|
|
643
|
-
!apiutil.isSafeEntity(res_body.token.expires_at) ||
|
|
644
|
-
!apiutil.isSafeEntity(res_body.token.project) ||
|
|
645
|
-
!apiutil.isSafeString(res_body.token.project.id) ||
|
|
646
|
-
!apiutil.compareCaseString(res_body.token.project.id, _tenantid) ||
|
|
647
|
-
!apiutil.isSafeString(res_body.token.project.name) ||
|
|
648
|
-
!apiutil.isSafeEntity(res_body.token.user) ||
|
|
649
|
-
!apiutil.isSafeString(res_body.token.user.id) ||
|
|
650
|
-
!apiutil.isSafeString(res_body.token.user.name) )
|
|
651
|
-
{
|
|
652
|
-
error = new Error('could not get scoped token by something wrong response body : ' + body);
|
|
653
|
-
r3logger.elog(error.message);
|
|
654
|
-
_callback(error, null);
|
|
655
|
-
return;
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
// check & get region
|
|
659
|
-
var region = null;
|
|
660
|
-
for(var cnt = 0; cnt < res_body.token.catalog.length && null === region; ++cnt){
|
|
661
|
-
if( !apiutil.isSafeEntity(res_body.token.catalog[cnt]) ||
|
|
662
|
-
apiutil.isEmptyArray(res_body.token.catalog[cnt].endpoints) ||
|
|
663
|
-
!apiutil.isSafeString(res_body.token.catalog[cnt].type) )
|
|
664
|
-
{
|
|
665
|
-
r3logger.wlog('one of response for scoped token is something wrong : ' + JSON.stringify(res_body.token.catalog[cnt]));
|
|
666
|
-
continue;
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
// target region by type=identity
|
|
670
|
-
if(!apiutil.compareCaseString('identity', res_body.token.catalog[cnt].type)){
|
|
671
|
-
continue;
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
// check region
|
|
675
|
-
for(var cnt2 = 0; cnt2 < res_body.token.catalog[cnt].endpoints.length; ++cnt2){
|
|
676
|
-
if( apiutil.isSafeEntity(res_body.token.catalog[cnt].endpoints[cnt2]) &&
|
|
677
|
-
apiutil.isSafeString(res_body.token.catalog[cnt].endpoints[cnt2].interface) &&
|
|
678
|
-
apiutil.compareCaseString('public', res_body.token.catalog[cnt].endpoints[cnt2].interface) &&
|
|
679
|
-
apiutil.isSafeString(res_body.token.catalog[cnt].endpoints[cnt2].region) )
|
|
680
|
-
{
|
|
681
|
-
if(apiutil.compareCaseString(res_body.token.catalog[cnt].endpoints[cnt2].region, keystone_ep.region)){
|
|
682
|
-
// found
|
|
683
|
-
region = res_body.token.catalog[cnt].endpoints[cnt2].region;
|
|
684
|
-
break;
|
|
685
|
-
}else{
|
|
686
|
-
r3logger.wlog('unknown region(' + res_body.token.catalog[cnt].endpoints[cnt2].region + '), we need to find region(' + keystone_ep.region + '), so skip this');
|
|
687
|
-
}
|
|
688
|
-
}else{
|
|
689
|
-
r3logger.dlog('one of response endpoint for scoped token is not target or something wrong : ' + JSON.stringify(res_body.token.catalog[cnt].endpoints[cnt2]));
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
if(null === region){
|
|
694
|
-
error = new Error('could not find request region in result.');
|
|
695
|
-
r3logger.elog(error.message);
|
|
696
|
-
_callback(error, null);
|
|
697
|
-
return;
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
// convert openstack user id(16 bytes hex string) to UUID(not UUID4)
|
|
701
|
-
var user_id_uuid4 = apiutil.cvtNumberStringToUuid4(res_body.token.user.id, 16);
|
|
702
|
-
|
|
703
|
-
// build result
|
|
704
|
-
var resobj = {};
|
|
705
|
-
resobj.user = res_body.token.user.name.toLowerCase();
|
|
706
|
-
resobj.userid = user_id_uuid4;
|
|
707
|
-
resobj.scoped = true;
|
|
708
|
-
resobj.token = headers['x-subject-token'];
|
|
709
|
-
resobj.expire = res_body.token.expires_at;
|
|
710
|
-
resobj.region = region.toLowerCase();
|
|
711
|
-
resobj.token_seed = JSON.stringify({ publisher: 'OPENSTACKV3' });
|
|
712
|
-
_callback(null, resobj);
|
|
713
|
-
});
|
|
714
|
-
});
|
|
715
|
-
req.on('error', function(exception) {
|
|
716
|
-
r3logger.elog('problem with request: ' + exception.message);
|
|
717
|
-
_callback(exception);
|
|
718
|
-
return;
|
|
719
|
-
});
|
|
720
|
-
|
|
721
|
-
// write data to request body
|
|
722
|
-
req.write(strbody);
|
|
723
|
-
req.end();
|
|
724
|
-
}, true);
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
//
|
|
728
|
-
// Verify User Token for OpenStack V3
|
|
729
|
-
//
|
|
730
|
-
// user : target user name for token
|
|
731
|
-
// token : check token
|
|
732
|
-
// token_seed : token seed data
|
|
733
|
-
//
|
|
734
|
-
// result : {
|
|
735
|
-
// result: true/false
|
|
736
|
-
// message: null or error message string
|
|
737
|
-
// }
|
|
738
|
-
//
|
|
739
|
-
function rawVerifyUserTokenPublisherV3(token_seed)
|
|
740
|
-
{
|
|
741
|
-
if(!apiutil.isSafeString(token_seed)){
|
|
742
|
-
return false;
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
// parse seed
|
|
746
|
-
var seed = token_seed;
|
|
747
|
-
if(apiutil.checkSimpleJSON(token_seed)){
|
|
748
|
-
seed = JSON.parse(token_seed);
|
|
749
|
-
}
|
|
750
|
-
if( !apiutil.isSafeEntity(seed) ||
|
|
751
|
-
!apiutil.isSafeString(seed.publisher) ||
|
|
752
|
-
(seed.publisher != 'OPENSTACKV3') ) // publisher must be 'OPENSTACKV3'
|
|
753
|
-
{
|
|
754
|
-
return false;
|
|
755
|
-
}
|
|
756
|
-
return true;
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
function rawWrapVerifyUserTokenPublisherV3(token_seed)
|
|
760
|
-
{
|
|
761
|
-
var resobj = {result: true, message: null};
|
|
762
|
-
|
|
763
|
-
if(!rawVerifyUserTokenPublisherV3(token_seed)){
|
|
764
|
-
resobj.result = false;
|
|
765
|
-
resobj.message = 'token_seed(not printable) is not safe entity.';
|
|
766
|
-
r3logger.elog(resobj.message);
|
|
767
|
-
return resobj;
|
|
768
|
-
}
|
|
769
|
-
return resobj;
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
function rawVerifyUserTokenV3(user, token, token_seed)
|
|
773
|
-
{
|
|
774
|
-
var resobj = {result: true, message: null};
|
|
775
|
-
|
|
776
|
-
if(!apiutil.isSafeStrings(user, token, token_seed)){
|
|
777
|
-
resobj.result = false;
|
|
778
|
-
resobj.message = 'some parameters are wrong : token=' + JSON.stringify(token) + ', token_seed=<not printable>, user=' + JSON.stringify(user);
|
|
779
|
-
r3logger.elog(resobj.message);
|
|
780
|
-
return resobj;
|
|
781
|
-
}
|
|
782
|
-
// check seed
|
|
783
|
-
if(!rawVerifyUserTokenPublisherV3(token_seed)){
|
|
784
|
-
resobj.result = false;
|
|
785
|
-
resobj.message = 'token_seed(not printable) is not safe entity.';
|
|
786
|
-
r3logger.elog(resobj.message);
|
|
787
|
-
return resobj;
|
|
788
|
-
}
|
|
789
|
-
return resobj;
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
//
|
|
793
|
-
// Get tenant list by unscoped token from Openstack identity v3 API
|
|
794
|
-
//
|
|
795
|
-
// Document: https://developer.openstack.org/api-ref/identity/v3/?expanded=list-projects-detail
|
|
796
|
-
//
|
|
797
|
-
// Request: X-Auth-Token: <unscoped token>
|
|
798
|
-
// https://keystone/v3/users/<user id>/projects
|
|
799
|
-
//
|
|
800
|
-
// Response: {
|
|
801
|
-
// "links": {
|
|
802
|
-
// "next": null,
|
|
803
|
-
// "previous": null,
|
|
804
|
-
// "self": "https://keystone/v3/users/<user id>/projects"
|
|
805
|
-
// },
|
|
806
|
-
// "projects": [
|
|
807
|
-
// {
|
|
808
|
-
// "description": null, (*1)
|
|
809
|
-
// "domain_id": "default",
|
|
810
|
-
// "enabled": true,
|
|
811
|
-
// "id": "<project id>", (*2)
|
|
812
|
-
// "is_domain": false,
|
|
813
|
-
// "links": {
|
|
814
|
-
// "self": "https://keystone/v3/projects/<project id>"
|
|
815
|
-
// },
|
|
816
|
-
// "name": "******", (*3)
|
|
817
|
-
// "parent_id": null
|
|
818
|
-
// },
|
|
819
|
-
// ...
|
|
820
|
-
// ]
|
|
821
|
-
// }
|
|
822
|
-
//
|
|
823
|
-
// callback(error, result):
|
|
824
|
-
// result = [
|
|
825
|
-
// {
|
|
826
|
-
// name: project(tenant) name (*3)
|
|
827
|
-
// id: project(tenant) id (*2)
|
|
828
|
-
// description: project(tenant) description (*1)
|
|
829
|
-
// display: display name (*3)
|
|
830
|
-
// },
|
|
831
|
-
// ...
|
|
832
|
-
// ]
|
|
833
|
-
//
|
|
834
|
-
// [TODO]
|
|
835
|
-
// Should not we use "tenant id" instead of "tenant name" for "name"?
|
|
836
|
-
// We need this consideration.
|
|
837
|
-
//
|
|
838
|
-
function rawGetUserTenantListV3(unscopedtoken, userid, callback)
|
|
839
|
-
{
|
|
840
|
-
var error;
|
|
841
|
-
if(!apiutil.isSafeStrings(unscopedtoken, userid)){
|
|
842
|
-
error = new Error('parameter is wrong : unscopedtoken=' + JSON.stringify(unscopedtoken) + ', userid=' + JSON.stringify(userid));
|
|
843
|
-
r3logger.elog(error.message);
|
|
844
|
-
callback(error, null);
|
|
845
|
-
return;
|
|
846
|
-
}
|
|
847
|
-
var _unscopedtoken = unscopedtoken;
|
|
848
|
-
var _callback = callback;
|
|
849
|
-
|
|
850
|
-
// convert user id(UUID) to openstack user id(16 bytes hex string)
|
|
851
|
-
var _bin_userid = apiutil.cvtStrToBinUuid4(userid);
|
|
852
|
-
if(null == _bin_userid){
|
|
853
|
-
error = new Error('parameter is wrong : userid=' + JSON.stringify(userid));
|
|
854
|
-
r3logger.elog(error.message);
|
|
855
|
-
callback(error, null);
|
|
856
|
-
return;
|
|
857
|
-
}
|
|
858
|
-
var _userid = _bin_userid.toString('hex');
|
|
859
|
-
|
|
860
|
-
// get end points for keystone
|
|
861
|
-
osksep.getKeystoneEndpoint(function(err, keystone_ep)
|
|
862
|
-
{
|
|
863
|
-
var error;
|
|
864
|
-
if(null !== err){
|
|
865
|
-
error = new Error('could not get keystone end point by ' + err.message);
|
|
866
|
-
r3logger.elog(error.message);
|
|
867
|
-
_callback(error, null);
|
|
868
|
-
return;
|
|
869
|
-
}
|
|
870
|
-
// got safe endpoint for keystone
|
|
871
|
-
//r3logger.dlog(keystone_ep);
|
|
872
|
-
|
|
873
|
-
// build parameters for request
|
|
874
|
-
var headers = {
|
|
875
|
-
'Content-Type': 'application/json',
|
|
876
|
-
'X-Auth-Token': _unscopedtoken,
|
|
877
|
-
'Content-Length': 0
|
|
878
|
-
};
|
|
879
|
-
var options = {
|
|
880
|
-
'host': keystone_ep.hostname,
|
|
881
|
-
'port': keystone_ep.port,
|
|
882
|
-
'path': keystone_ep.pathname + '/v3/users/' + _userid + '/projects',
|
|
883
|
-
'method': 'GET',
|
|
884
|
-
'headers': headers
|
|
885
|
-
};
|
|
886
|
-
|
|
887
|
-
var httpobj;
|
|
888
|
-
if(apiutil.compareCaseString('https:', keystone_ep.protocol)){
|
|
889
|
-
if(null !== cacerts.ca){
|
|
890
|
-
options.ca = cacerts.ca;
|
|
891
|
-
}
|
|
892
|
-
options.agent = new https.Agent(options);
|
|
893
|
-
httpobj = https;
|
|
894
|
-
}else{
|
|
895
|
-
options.agent = new http.Agent(options);
|
|
896
|
-
httpobj = http;
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
// send request
|
|
900
|
-
var req = httpobj.get(options, function(res)
|
|
901
|
-
{
|
|
902
|
-
var body = '';
|
|
903
|
-
var status = res.statusCode;
|
|
904
|
-
|
|
905
|
-
r3logger.dlog('response status: ' + res.statusCode);
|
|
906
|
-
r3logger.dlog('response header: ' + JSON.stringify(res.headers));
|
|
907
|
-
res.setEncoding('utf8');
|
|
908
|
-
|
|
909
|
-
res.on('data', function(chunk)
|
|
910
|
-
{
|
|
911
|
-
//r3logger.dlog('response chunk: ' + chunk);
|
|
912
|
-
body += chunk;
|
|
913
|
-
});
|
|
914
|
-
|
|
915
|
-
res.on('end', function(result) // eslint-disable-line no-unused-vars
|
|
916
|
-
{
|
|
917
|
-
if(300 <= status){
|
|
918
|
-
error = new Error('could not get scoped token by status=' + String(status));
|
|
919
|
-
r3logger.elog(error.message);
|
|
920
|
-
_callback(error, null);
|
|
921
|
-
return;
|
|
922
|
-
}
|
|
923
|
-
//r3logger.dlog('response body: ' + body);
|
|
924
|
-
|
|
925
|
-
var res_body = body;
|
|
926
|
-
if(apiutil.checkSimpleJSON(body)){
|
|
927
|
-
res_body = JSON.parse(body);
|
|
928
|
-
}
|
|
929
|
-
if( !apiutil.isSafeEntity(res_body) ||
|
|
930
|
-
apiutil.isEmptyArray(res_body.projects) )
|
|
931
|
-
{
|
|
932
|
-
error = new Error('failed to get project(tenant) list by unscoped token.');
|
|
933
|
-
r3logger.elog(error.message);
|
|
934
|
-
_callback(error, null);
|
|
935
|
-
return;
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
// convert result array
|
|
939
|
-
var resobj = new Array(0);
|
|
940
|
-
for(var cnt = 0; cnt < res_body.projects.length; ++cnt){
|
|
941
|
-
if( !apiutil.isSafeEntity(res_body.projects[cnt]) ||
|
|
942
|
-
!apiutil.isSafeString(res_body.projects[cnt].id) ||
|
|
943
|
-
!apiutil.isSafeString(res_body.projects[cnt].name) )
|
|
944
|
-
{
|
|
945
|
-
r3logger.wlog('one of response for project(tenant) list is something wrong : ' + JSON.stringify(res_body.projects[cnt]));
|
|
946
|
-
continue;
|
|
947
|
-
}
|
|
948
|
-
var tenant = {};
|
|
949
|
-
tenant.name = res_body.projects[cnt].name.toLowerCase();
|
|
950
|
-
tenant.id = res_body.projects[cnt].id.toLowerCase();
|
|
951
|
-
tenant.description = apiutil.getSafeString(res_body.projects[cnt].description);
|
|
952
|
-
tenant.display = res_body.projects[cnt].name;
|
|
953
|
-
resobj.push(tenant);
|
|
954
|
-
}
|
|
955
|
-
if(0 === resobj.length){
|
|
956
|
-
error = new Error('could not get any projects(tenant) list by unscoped token.');
|
|
957
|
-
r3logger.elog(error.message);
|
|
958
|
-
_callback(error, null);
|
|
959
|
-
return;
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
_callback(null, resobj);
|
|
963
|
-
});
|
|
964
|
-
});
|
|
965
|
-
|
|
966
|
-
req.on('error', function(exception) {
|
|
967
|
-
r3logger.elog('problem with request: ' + exception.message);
|
|
968
|
-
callback(exception);
|
|
969
|
-
return;
|
|
970
|
-
});
|
|
971
|
-
}, true);
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
//---------------------------------------------------------
|
|
975
|
-
// Exports
|
|
976
|
-
//---------------------------------------------------------
|
|
977
|
-
exports.getUserUnscopedToken = function(uname, passwd, callback)
|
|
978
|
-
{
|
|
979
|
-
return rawGetUserUnscopedTokenV3(uname, passwd, callback);
|
|
980
|
-
};
|
|
981
|
-
|
|
982
|
-
//
|
|
983
|
-
// token : unscoped/scoped token for openstack
|
|
984
|
-
//
|
|
985
|
-
exports.getUserUnscopedTokenByToken = function(token, callback)
|
|
986
|
-
{
|
|
987
|
-
return rawGetUserUnscopedTokenByOstokenV3(token, callback);
|
|
988
|
-
};
|
|
989
|
-
|
|
990
|
-
//
|
|
991
|
-
// tenantname : not used
|
|
992
|
-
// tenantid : for keystone v3 api
|
|
993
|
-
//
|
|
994
|
-
exports.getUserScopedToken = function(unscopedtoken, tenantname, tenantid, callback)
|
|
995
|
-
{
|
|
996
|
-
return rawGetUserScopedTokenV3(unscopedtoken, tenantid, callback);
|
|
997
|
-
};
|
|
998
|
-
|
|
999
|
-
//
|
|
1000
|
-
// Verify seed publisher type
|
|
1001
|
-
//
|
|
1002
|
-
exports.verifyUserTokenPublisher = function(token_seed)
|
|
1003
|
-
{
|
|
1004
|
-
return rawWrapVerifyUserTokenPublisherV3(token_seed);
|
|
1005
|
-
};
|
|
1006
|
-
|
|
1007
|
-
//
|
|
1008
|
-
// Verify token
|
|
1009
|
-
//
|
|
1010
|
-
// tenant is not used.
|
|
1011
|
-
//
|
|
1012
|
-
exports.verifyUserToken = function(user, tenant, token, token_seed)
|
|
1013
|
-
{
|
|
1014
|
-
return rawVerifyUserTokenV3(user, token, token_seed);
|
|
1015
|
-
};
|
|
1016
|
-
|
|
1017
|
-
//
|
|
1018
|
-
// userid : for keystone v3 api
|
|
1019
|
-
//
|
|
1020
|
-
exports.getUserTenantList = function(unscopedtoken, userid, callback)
|
|
1021
|
-
{
|
|
1022
|
-
return rawGetUserTenantListV3(unscopedtoken, userid, callback);
|
|
1023
|
-
};
|
|
1024
|
-
|
|
1025
|
-
/*
|
|
1026
|
-
* Local variables:
|
|
1027
|
-
* tab-width: 4
|
|
1028
|
-
* c-basic-offset: 4
|
|
1029
|
-
* End:
|
|
1030
|
-
* vim600: noexpandtab sw=4 ts=4 fdm=marker
|
|
1031
|
-
* vim<600: noexpandtab sw=4 ts=4
|
|
1032
|
-
*/
|