k2hr3-api 1.0.42 → 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 -378
  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
@@ -0,0 +1,667 @@
1
+ "use strict";
2
+ /*
3
+ * K2HR3 REST API
4
+ *
5
+ * Copyright 2017 Yahoo Japan Corporation.
6
+ *
7
+ * K2HR3 is K2hdkc based Resource and Roles and policy Rules, gathers
8
+ * common management information for the cloud.
9
+ * K2HR3 can dynamically manage information as "who", "what", "operate".
10
+ * These are stored as roles, resources, policies in K2hdkc, and the
11
+ * client system can dynamically read and modify these information.
12
+ *
13
+ * For the full copyright and license information, please view
14
+ * the license file that was distributed with this source code.
15
+ *
16
+ * AUTHOR: Takeshi Nakatani
17
+ * CREATE: Wed Jun 8 2017
18
+ * REVISION:
19
+ *
20
+ */
21
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ var desc = Object.getOwnPropertyDescriptor(m, k);
24
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
25
+ desc = { enumerable: true, get: function() { return m[k]; } };
26
+ }
27
+ Object.defineProperty(o, k2, desc);
28
+ }) : (function(o, m, k, k2) {
29
+ if (k2 === undefined) k2 = k;
30
+ o[k2] = m[k];
31
+ }));
32
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
33
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
34
+ }) : function(o, v) {
35
+ o["default"] = v;
36
+ });
37
+ var __importStar = (this && this.__importStar) || (function () {
38
+ var ownKeys = function(o) {
39
+ ownKeys = Object.getOwnPropertyNames || function (o) {
40
+ var ar = [];
41
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
42
+ return ar;
43
+ };
44
+ return ownKeys(o);
45
+ };
46
+ return function (mod) {
47
+ if (mod && mod.__esModule) return mod;
48
+ var result = {};
49
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
50
+ __setModuleDefault(result, mod);
51
+ return result;
52
+ };
53
+ })();
54
+ var __importDefault = (this && this.__importDefault) || function (mod) {
55
+ return (mod && mod.__esModule) ? mod : { "default": mod };
56
+ };
57
+ Object.defineProperty(exports, "__esModule", { value: true });
58
+ exports.openstackep = void 0;
59
+ const https = __importStar(require("https"));
60
+ const http = __importStar(require("http"));
61
+ const k2hr3apiutil_1 = __importDefault(require("./k2hr3apiutil"));
62
+ const dbglogging_1 = __importDefault(require("./dbglogging"));
63
+ const k2hr3keys_1 = require("./k2hr3keys");
64
+ const cacerts_1 = require("./cacerts");
65
+ ;
66
+ //
67
+ // Type checking
68
+ //
69
+ const rawIsValTypeKeystoneEndpoint = (val) => {
70
+ if (!k2hr3apiutil_1.default.isPlainObject(val)) {
71
+ return false;
72
+ }
73
+ const _obj = val;
74
+ const _isUrl = (key) => k2hr3apiutil_1.default.isString(_obj[key]);
75
+ const _isChecked = (key) => k2hr3apiutil_1.default.isBoolean(_obj[key]);
76
+ const _isStatus = (key) => k2hr3apiutil_1.default.isSafeNumber(_obj[key]);
77
+ return (_isUrl('url') &&
78
+ _isChecked('checked') &&
79
+ _isStatus('status'));
80
+ };
81
+ const rawIsValTypeKeystoneEndpointMap = (val) => {
82
+ if (!k2hr3apiutil_1.default.isPlainObject(val)) {
83
+ return false;
84
+ }
85
+ for (const [, value] of Object.entries(val)) {
86
+ if (!k2hr3apiutil_1.default.isSafeString(value) && !rawIsValTypeKeystoneEndpoint(value)) {
87
+ return false;
88
+ }
89
+ }
90
+ return true;
91
+ };
92
+ const rawIsValTypeGetKeystoneEndpointArgs = (val) => {
93
+ if (!k2hr3apiutil_1.default.isPlainObject(val)) {
94
+ return false;
95
+ }
96
+ const _obj = val;
97
+ const _isIsV3 = (key) => k2hr3apiutil_1.default.isBoolean(_obj[key]);
98
+ const _isIsTest = (key) => k2hr3apiutil_1.default.isBoolean(_obj[key]);
99
+ const _isTimeout = (key) => k2hr3apiutil_1.default.isSafeNumber(_obj[key]);
100
+ const _isCallback = (key) => {
101
+ const func = _obj[key];
102
+ if (!k2hr3apiutil_1.default.isPlainObject(func) || !k2hr3apiutil_1.default.isFunction(func)) {
103
+ return false;
104
+ }
105
+ if (!k2hr3apiutil_1.default.isSafeEntity(func.length) || 3 !== func.length) {
106
+ return false;
107
+ }
108
+ return true;
109
+ };
110
+ return (_isIsV3('is_v3') &&
111
+ _isIsTest('is_test') &&
112
+ _isTimeout('timeout') &&
113
+ _isCallback('callback'));
114
+ };
115
+ const rawIsValTypeUrlKeystoneEndpoint = (val) => {
116
+ if (!k2hr3apiutil_1.default.isPlainObject(val)) {
117
+ return false;
118
+ }
119
+ // check UrlWithStringQuery
120
+ if ((k2hr3apiutil_1.default.isSafeEntity(val.query) && !k2hr3apiutil_1.default.isString(val.query)) ||
121
+ (k2hr3apiutil_1.default.isSafeEntity(val.href) && !k2hr3apiutil_1.default.isString(val.href)) ||
122
+ (k2hr3apiutil_1.default.isSafeEntity(val.protocol) && !k2hr3apiutil_1.default.isString(val.protocol)) ||
123
+ (k2hr3apiutil_1.default.isSafeEntity(val.auth) && !k2hr3apiutil_1.default.isString(val.auth)) ||
124
+ (k2hr3apiutil_1.default.isSafeEntity(val.host) && !k2hr3apiutil_1.default.isString(val.host)) ||
125
+ (k2hr3apiutil_1.default.isSafeEntity(val.hostname) && !k2hr3apiutil_1.default.isString(val.hostname)) ||
126
+ (k2hr3apiutil_1.default.isSafeEntity(val.port) && !k2hr3apiutil_1.default.isString(val.port)) ||
127
+ (k2hr3apiutil_1.default.isSafeEntity(val.pathname) && !k2hr3apiutil_1.default.isString(val.pathname)) ||
128
+ (k2hr3apiutil_1.default.isSafeEntity(val.search) && !k2hr3apiutil_1.default.isString(val.search)) ||
129
+ (k2hr3apiutil_1.default.isSafeEntity(val.path) && !k2hr3apiutil_1.default.isString(val.path)) ||
130
+ (k2hr3apiutil_1.default.isSafeEntity(val.hash) && !k2hr3apiutil_1.default.isString(val.hash)) ||
131
+ (k2hr3apiutil_1.default.isSafeEntity(val.query) && !k2hr3apiutil_1.default.isSafeEntity(val.query)) ||
132
+ (k2hr3apiutil_1.default.isSafeEntity(val.slashes) && !k2hr3apiutil_1.default.isBoolean(val.slashes))) {
133
+ return false;
134
+ }
135
+ // valTypeUrlKeystoneEndpoint
136
+ if (k2hr3apiutil_1.default.isSafeEntity(val.region) && !k2hr3apiutil_1.default.isString(val.region)) {
137
+ return false;
138
+ }
139
+ return true;
140
+ };
141
+ const rawIsDynamicOpenstackEpModule = (mod) => {
142
+ if (!k2hr3apiutil_1.default.isPlainObject(mod)) {
143
+ return false;
144
+ }
145
+ if (!('getDynamicKeystoneEndpoints' in mod)) {
146
+ return false;
147
+ }
148
+ if (!k2hr3apiutil_1.default.isPlainObject(mod.getDynamicKeystoneEndpoints) || !k2hr3apiutil_1.default.isFunction(mod.getDynamicKeystoneEndpoints)) {
149
+ return false;
150
+ }
151
+ if (!k2hr3apiutil_1.default.isSafeEntity(mod.getDynamicKeystoneEndpoints.length) || 2 !== mod.getDynamicKeystoneEndpoints.length) { // getDynamicKeystoneEndpoints must have 2 arguments.
152
+ return false;
153
+ }
154
+ return true;
155
+ };
156
+ //---------------------------------------------------------
157
+ // Callback function for testing one keystone endpoint
158
+ //---------------------------------------------------------
159
+ // Input parameter:
160
+ // err : if error is occurred, error object is set(if no error, this is null).
161
+ // callback : specify the callback to be called when all epallmap is checked.
162
+ // epallmap : all of keystone endpoint
163
+ // region : checked region
164
+ // status_code : check result
165
+ //
166
+ // Result: callback(error, epallmap)
167
+ // error : if error is occurred, error object is set(if no error, this is null).
168
+ // epallmap : all endpoint mapping
169
+ //
170
+ // [NOTE]
171
+ // The callback function is only called when all checks of
172
+ // epallmap are complete.
173
+ // This assumes that the caller will call this function on all
174
+ // epallmaps.
175
+ //
176
+ const rawTestKeystoneEpCallback = (err, callback, epallmap, region, status_code) => {
177
+ if (!k2hr3apiutil_1.default.isSafeEntity(callback) || !k2hr3apiutil_1.default.isSafeString(region) || !k2hr3apiutil_1.default.isPlainObject(epallmap)) {
178
+ const error = new Error('some parameters are wrong : epallmap=' + JSON.stringify(epallmap) + ', region=' + JSON.stringify(region));
179
+ dbglogging_1.default.elog(error.message);
180
+ if (k2hr3apiutil_1.default.isSafeEntity(callback)) {
181
+ callback(error);
182
+ }
183
+ return;
184
+ }
185
+ const tmpEpRegin = epallmap[region];
186
+ if (!rawIsValTypeKeystoneEndpoint(tmpEpRegin)) {
187
+ const error = new Error('some parameters are wrong : epallmap=' + JSON.stringify(epallmap) + ', region=' + JSON.stringify(region));
188
+ dbglogging_1.default.elog(error.message);
189
+ if (k2hr3apiutil_1.default.isSafeEntity(callback)) {
190
+ callback(error);
191
+ }
192
+ return;
193
+ }
194
+ if (!k2hr3apiutil_1.default.isSafeNumber(status_code)) {
195
+ dbglogging_1.default.elog('parameter is wrong : status_code=' + JSON.stringify(status_code) + ', but continue with status_code(500).');
196
+ status_code = 500; // status code = internal error
197
+ }
198
+ if (null !== err) {
199
+ dbglogging_1.default.elog('failed test about keystone endpoint(' + tmpEpRegin.url + ') for region(' + region + ') by ' + err.message + ', but continue with status_code(500).');
200
+ status_code = 500; // status code = internal error
201
+ }
202
+ // set checked flag and status result
203
+ //
204
+ // [NOTE][TODO]
205
+ // Under control by this flag, exclusion control is not perfect.
206
+ // In other words, the callback function may be called multiple times.
207
+ // (However, the callback function will be called at least once.)
208
+ // Currently, exclusion control here is not performed, and the caller
209
+ // recognizes multiple calls. Here is the code to fix.
210
+ //
211
+ epallmap[region].checked = true;
212
+ epallmap[region].status = status_code;
213
+ // check for finish
214
+ let is_finish = true;
215
+ for (const test_region in epallmap) {
216
+ const tmpOneRegion = epallmap[test_region];
217
+ if (!rawIsValTypeKeystoneEndpoint(tmpOneRegion)) {
218
+ continue;
219
+ }
220
+ if (!tmpOneRegion.checked) {
221
+ is_finish = false;
222
+ break;
223
+ }
224
+ }
225
+ if (is_finish) {
226
+ // checked all of endpoints, then call original callback.
227
+ //
228
+ // [NOTE]
229
+ // Perhaps this function passes here multiple times.
230
+ //
231
+ callback(null);
232
+ }
233
+ };
234
+ //---------------------------------------------------------
235
+ // Test one keystone endpoint
236
+ //---------------------------------------------------------
237
+ // Input parameter
238
+ // epallmap : all of keystone endpoint
239
+ // region : target one region for checking
240
+ // endpoint : target one endpoint for checking
241
+ // is_v3 : keystone v3 or v2
242
+ // timeout : timeout for checking one endpoint
243
+ // lastest_callback : callback function which is called end of last checking endpoint.
244
+ //
245
+ // Result: lastest_callback(error, orgcb, epallmap, region, status_code, orgcb)
246
+ // error : error object
247
+ // orgcb : original callback
248
+ // epallmap : all endpoint mapping
249
+ // region : region
250
+ // status_code : status code for request(timeout = 504)
251
+ //
252
+ // [NOTE]
253
+ // The lastest_callback callback function is only called when
254
+ // all checks of epallmap are complete.
255
+ // This assumes that the caller will call this function on all
256
+ // epallmaps.
257
+ //
258
+ const rawTestKeystoneEndpoint = (epallmap, region, endpoint, is_v3, timeout, lastest_callback) => {
259
+ if (!k2hr3apiutil_1.default.isSafeEntity(epallmap) || !k2hr3apiutil_1.default.isSafeEntity(lastest_callback) || !k2hr3apiutil_1.default.isSafeString(region) || !k2hr3apiutil_1.default.isSafeString(endpoint)) {
260
+ const error = new Error('some parameters are wrong : epallmap=' + JSON.stringify(epallmap) + ', region=' + JSON.stringify(region) + ', endpoint=' + JSON.stringify(endpoint));
261
+ dbglogging_1.default.elog(error.message);
262
+ rawTestKeystoneEpCallback(error, lastest_callback, epallmap, region, 500); // return result code = 500
263
+ return;
264
+ }
265
+ if (!k2hr3apiutil_1.default.isSafeNumber(timeout)) {
266
+ const error = new Error('parameter is wrong : timeout=' + JSON.stringify(timeout));
267
+ dbglogging_1.default.elog(error.message);
268
+ rawTestKeystoneEpCallback(error, lastest_callback, epallmap, region, 500); // return result code = 500
269
+ return;
270
+ }
271
+ if (!k2hr3apiutil_1.default.isBoolean(is_v3)) {
272
+ is_v3 = true;
273
+ }
274
+ const _epallmap = epallmap;
275
+ const _region = region;
276
+ const _endpoint = endpoint;
277
+ const _is_v3 = is_v3;
278
+ const _timeout = timeout;
279
+ const _lastest_cb = lastest_callback;
280
+ // Make request body data
281
+ // This body failed authorization.(wrong user/passwd)
282
+ //
283
+ let strbody;
284
+ if (!_is_v3) {
285
+ const body = {
286
+ 'auth': {
287
+ 'tenantName': '', // unscoped token for test
288
+ 'passwordCredentials': {
289
+ 'username': '', // user name is empty for testing
290
+ 'password': '' // unauthorized passwd
291
+ }
292
+ }
293
+ };
294
+ strbody = JSON.stringify(body);
295
+ }
296
+ else {
297
+ const body = {
298
+ 'auth': {
299
+ 'identity': {
300
+ 'password': {
301
+ 'user': {
302
+ 'domain': {
303
+ 'id': 'default'
304
+ },
305
+ 'name': '', // user name is empty for testing
306
+ 'password': '' // unauthorized passwd
307
+ }
308
+ },
309
+ 'methods': ['password']
310
+ }
311
+ }
312
+ };
313
+ strbody = JSON.stringify(body);
314
+ }
315
+ const ep = k2hr3apiutil_1.default.urlParse(_endpoint);
316
+ const is_sec = k2hr3apiutil_1.default.compareCaseString('https:', ep.protocol);
317
+ const agent = is_sec ? https : http;
318
+ const headers = {
319
+ 'Content-Type': 'application/json',
320
+ 'Content-Length': strbody.length
321
+ };
322
+ const options = {
323
+ 'host': k2hr3apiutil_1.default.getSafeString(ep.hostname),
324
+ 'port': k2hr3apiutil_1.default.isSafeNumber(ep.port) ? ep.port : 0,
325
+ 'path': _is_v3 ? '/v3/auth/tokens' : '/v2.0/tokens',
326
+ 'method': 'POST',
327
+ 'headers': headers,
328
+ 'ca': (is_sec && null !== cacerts_1.ca) ? ((0, cacerts_1.ca)() ?? undefined) : undefined
329
+ };
330
+ // send request
331
+ const req = agent.request(options, (res) => {
332
+ let _body = '';
333
+ const _status = res.statusCode;
334
+ dbglogging_1.default.dlog('response status: ' + res.statusCode);
335
+ dbglogging_1.default.dlog('response header: ' + JSON.stringify(res.headers));
336
+ res.setEncoding('utf8');
337
+ res.on('data', (chunk) => {
338
+ //r3logger.dlog('response chunk: ' + chunk);
339
+ _body += chunk;
340
+ });
341
+ res.on('end', () => {
342
+ dbglogging_1.default.dlog('response body: ' + _body.slice(0, 36) + '...'); // for eslint to use _body.
343
+ rawTestKeystoneEpCallback(null, _lastest_cb, _epallmap, _region, _status ?? 500); // return result code
344
+ });
345
+ });
346
+ req.on('error', (err) => {
347
+ rawTestKeystoneEpCallback(err, _lastest_cb, _epallmap, _region, 504); // return result code = 500
348
+ });
349
+ req.on('socket', (socket) => {
350
+ socket.setTimeout(_timeout, () => {
351
+ req.abort();
352
+ rawTestKeystoneEpCallback(null, _lastest_cb, _epallmap, _region, 504); // return result code = 504
353
+ });
354
+ });
355
+ // write data to request body
356
+ req.write(strbody);
357
+ req.end();
358
+ };
359
+ //---------------------------------------------------------
360
+ // Callback function for dynamic/static endpoint list
361
+ //---------------------------------------------------------
362
+ // Input parameter:
363
+ // cbargs : parent function parameter in this object
364
+ // timeout : rawGetKeystoneEndpoint function argument
365
+ // is_test : rawGetKeystoneEndpoint function argument
366
+ // is_v3 : rawGetKeystoneEndpoint function argument
367
+ // callback : rawGetKeystoneEndpoint function argument
368
+ // err : if error is occurred, error object is set(if no error, this is null).
369
+ // epmap : keystone endpoint map which is result of dynamic/static list.
370
+ //
371
+ // Result: callback(error, keystone_ep)
372
+ // error : error object
373
+ // keystone_ep : url object with region string element
374
+ //
375
+ const rawGetKeystoneEndpointsCallback = (cbargs, err, epmap) => {
376
+ const _cbargs = cbargs;
377
+ if (null !== err) {
378
+ const error = new Error('failed to get dynamic keystone endpoints : ' + err.message);
379
+ dbglogging_1.default.elog(error.message);
380
+ _cbargs.callback(error, null);
381
+ return;
382
+ }
383
+ if (!rawIsValTypeKeystoneEndpointMap(epmap)) {
384
+ const error = new Error('getting dynamic keystone endpoints is something wrong.');
385
+ dbglogging_1.default.elog(error.message);
386
+ _cbargs.callback(error, null);
387
+ return;
388
+ }
389
+ //
390
+ // check and register endpoints to k2hdkc
391
+ //
392
+ const keys = (0, k2hr3keys_1.getK2hr3Keys)();
393
+ const epallmap = {};
394
+ for (const region in epmap) {
395
+ const tmpRegionEp = epmap[region];
396
+ if (!k2hr3apiutil_1.default.isSafeString(tmpRegionEp)) {
397
+ // wrong data
398
+ dbglogging_1.default.wlog('dynamic keystone endpoint for ' + region + ' is something wrong(' + JSON.stringify(tmpRegionEp) + '), thus skip it.');
399
+ continue;
400
+ }
401
+ const region_url = tmpRegionEp;
402
+ // register only https!
403
+ const ep = k2hr3apiutil_1.default.urlParse(region_url);
404
+ if (!k2hr3apiutil_1.default.compareCaseString('https:', ep.protocol)) {
405
+ // not https
406
+ dbglogging_1.default.wlog('dynamic keystone endpoint for ' + region + ' is not https(' + ep.protocol + '), it is not good endpoint.');
407
+ }
408
+ // add to temporary
409
+ const tmpmap = {
410
+ 'url': region_url,
411
+ 'checked': false,
412
+ 'status': 0
413
+ };
414
+ epallmap[region] = tmpmap;
415
+ }
416
+ if (!_cbargs.is_test) {
417
+ // not need to test(only updates), finish here
418
+ //
419
+ // [NOTE]
420
+ // keystone endpoint is null
421
+ //
422
+ _cbargs.callback(null, null);
423
+ return;
424
+ }
425
+ // test all endpoints(asynchronous)
426
+ for (const region in epallmap) {
427
+ // check each endpoint
428
+ //
429
+ // [NOTE]
430
+ // The callback function is called only when all the elements of
431
+ // epallmap are checked.
432
+ //
433
+ const tmpRegionEp = epallmap[region];
434
+ if (!rawIsValTypeKeystoneEndpoint(tmpRegionEp)) {
435
+ continue;
436
+ }
437
+ rawTestKeystoneEndpoint(epallmap, region, tmpRegionEp.url, _cbargs.is_v3, _cbargs.timeout, (err) => {
438
+ const _callback = _cbargs.callback;
439
+ const _epallmap = epallmap;
440
+ if (null !== err) {
441
+ const error = new Error('failed to check keystone endpoints : ' + err.message);
442
+ dbglogging_1.default.elog(error.message);
443
+ _callback(error, null);
444
+ return;
445
+ }
446
+ // set all endpoint map
447
+ for (const region2 in _epallmap) {
448
+ // register endpoint(type should be VALUE_KEYSTONE_NORMAL)
449
+ //
450
+ // [NOTE][TODO]
451
+ // Now, we do not distinguish v2 and v3 keystone, we are registering it into k2hdkc.
452
+ // This may possibly cause problems.
453
+ //
454
+ const tmpRegionEp2 = _epallmap[region2];
455
+ if (!rawIsValTypeKeystoneEndpoint(tmpRegionEp2)) {
456
+ continue;
457
+ }
458
+ // [NOTE]
459
+ // k2hr3dkc is loaded here using require to lazily load it.
460
+ // This prevents errors caused by circular loading.
461
+ //
462
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
463
+ const k2hr3 = require('./k2hr3dkc').default;
464
+ const res_ep = k2hr3.setKeystoneEndpointAll(region2, tmpRegionEp2.url, keys.VALUE_KEYSTONE_NORMAL, 0);
465
+ if (!res_ep.result) {
466
+ dbglogging_1.default.elog('could not set keystone endpoint(' + tmpRegionEp2.url + ') for region2(' + region2 + ') into k2hdkc, but continue...');
467
+ }
468
+ else {
469
+ dbglogging_1.default.mlog('add new keystone endpoint(' + tmpRegionEp2.url + ') for region2(' + region2 + ') into k2hdkc.');
470
+ }
471
+ }
472
+ // call ownself with not reentrant flag
473
+ rawGetKeystoneEndpoint((err, keystone_ep) => {
474
+ if (null !== err) {
475
+ const error = new Error('failed to get keystone endpoint : ' + err.message);
476
+ dbglogging_1.default.elog(error.message);
477
+ _callback(error, null);
478
+ return;
479
+ }
480
+ //
481
+ // returns keystone endpoint after remaking all endpoint
482
+ //
483
+ _callback(null, keystone_ep);
484
+ }, _cbargs.is_v3, _cbargs.is_test, _cbargs.timeout, false);
485
+ });
486
+ }
487
+ };
488
+ //---------------------------------------------------------
489
+ // Get one of endpoint for keystone from static urls
490
+ //---------------------------------------------------------
491
+ // Input parameter
492
+ // callback : specify callback function
493
+ // is_v3 : keystone api v3 or v2(default v3)
494
+ // is_test : specify whether to test each keystone
495
+ // endpoint after unable to find a valid
496
+ // keystone endpoint and re-creating it.
497
+ // (default true)
498
+ // timeout : specify the timeout required to check
499
+ // each keystone endpoint.
500
+ // (default 30s)
501
+ // is_remake_keystone_ep : if keystone endpoint is not registered,
502
+ // it specifies whether to recreate it.
503
+ // (default false)
504
+ //
505
+ // Result: callback(error, keystone_ep)
506
+ // error : error object
507
+ // keystone_ep : url object with region string element
508
+ //
509
+ let last_region = null;
510
+ let last_endpoint = null;
511
+ let ksepinit = false;
512
+ let kseplist = null;
513
+ let ksepobj = null;
514
+ const rawInitializeKeystoneEpList = async () => {
515
+ if (ksepinit) {
516
+ // already initialized
517
+ return;
518
+ }
519
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
520
+ const { r3ApiConfig } = require('./k2hr3config');
521
+ const apiConf = new r3ApiConfig();
522
+ if (apiConf.isKeystoneEpList()) {
523
+ kseplist = apiConf.getKeystoneEpList();
524
+ }
525
+ else if (apiConf.isKeystoneEpFile()) {
526
+ const ksepobjPath = './' + apiConf.getKeystoneEpFile();
527
+ const mod = await k2hr3apiutil_1.default.tryLoadModule(ksepobjPath);
528
+ if (rawIsDynamicOpenstackEpModule(mod)) {
529
+ ksepobj = mod;
530
+ }
531
+ }
532
+ ksepinit = true;
533
+ };
534
+ const rawGetKeystoneEndpoint = (callback, is_v3, is_test, timeout, is_remake_keystone_ep) => {
535
+ if (!k2hr3apiutil_1.default.isSafeNumber(timeout)) {
536
+ timeout = 30000; // default 30s
537
+ }
538
+ if (!k2hr3apiutil_1.default.isBoolean(is_test)) {
539
+ is_test = true; // default true
540
+ }
541
+ if (!k2hr3apiutil_1.default.isBoolean(is_v3)) {
542
+ is_v3 = true; // default v3
543
+ }
544
+ if (!k2hr3apiutil_1.default.isBoolean(is_remake_keystone_ep)) {
545
+ is_remake_keystone_ep = false;
546
+ }
547
+ // [NOTE]
548
+ // This object is inherited from getDynamicKeystoneEndpoints
549
+ // to rawGetKeystoneEndpointsCallback.
550
+ // Ultimately, this function is called recursively and receives
551
+ // the data of this object as an argument.
552
+ //
553
+ const cbargs = {
554
+ timeout: timeout,
555
+ is_test: is_test,
556
+ is_v3: is_v3,
557
+ callback: callback
558
+ };
559
+ if (k2hr3apiutil_1.default.isSafeString(last_endpoint)) {
560
+ // there is a cache for endpoint/region
561
+ const keystone_ep = k2hr3apiutil_1.default.urlParse(last_endpoint);
562
+ if (rawIsValTypeUrlKeystoneEndpoint(keystone_ep)) {
563
+ keystone_ep.region = k2hr3apiutil_1.default.isSafeString(last_region) ? last_region : undefined;
564
+ cbargs.callback(null, keystone_ep);
565
+ return;
566
+ }
567
+ }
568
+ // there is no cache for endpoint/region
569
+ // [NOTE]
570
+ // k2hr3dkc is loaded here using require to lazily load it.
571
+ // This prevents errors caused by circular loading.
572
+ //
573
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
574
+ const k2hr3 = require('./k2hr3dkc').default;
575
+ const allres = k2hr3.getKeystoneEndpointAll();
576
+ if (!allres.result) {
577
+ dbglogging_1.default.elog('failed to get all keystone endpoint : ' + k2hr3apiutil_1.default.getSafeString(allres.message) + 'but continue for recovering.');
578
+ }
579
+ let keystones = {};
580
+ if (k2hr3apiutil_1.default.isSafeEntity(allres.keystones)) {
581
+ keystones = allres.keystones;
582
+ }
583
+ // search OK status from all
584
+ const keys = (0, k2hr3keys_1.getK2hr3Keys)();
585
+ for (const region in keystones) {
586
+ const tmpKSRegion = keystones[region];
587
+ const tmpStatus = k2hr3apiutil_1.default.isSafeNumeric(tmpKSRegion.status) ? k2hr3apiutil_1.default.cvtToNumber(tmpKSRegion.status) : null;
588
+ if (k2hr3apiutil_1.default.isPlainObject(tmpKSRegion) &&
589
+ k2hr3apiutil_1.default.isSafeString(tmpKSRegion.url) &&
590
+ k2hr3apiutil_1.default.isSafeString(tmpKSRegion.type) &&
591
+ (keys.VALUE_KEYSTONE_NORMAL === tmpKSRegion.type) &&
592
+ k2hr3apiutil_1.default.isSafeNumeric(tmpKSRegion.status) &&
593
+ k2hr3apiutil_1.default.isSafeNumber(tmpStatus) && (tmpStatus < 500)) // allow 0, 2xx, 3xx, 4xx
594
+ {
595
+ // found reachable endpoint, then set cache and result
596
+ last_region = region;
597
+ last_endpoint = tmpKSRegion.url;
598
+ const keystone_ep = k2hr3apiutil_1.default.urlParse(last_endpoint);
599
+ if (rawIsValTypeUrlKeystoneEndpoint(keystone_ep)) {
600
+ keystone_ep.region = last_region;
601
+ cbargs.callback(null, keystone_ep);
602
+ return;
603
+ }
604
+ }
605
+ }
606
+ //
607
+ // There are no available endpoints
608
+ //
609
+ if (!is_remake_keystone_ep) {
610
+ const error = new Error('there is no safe keystone endpoints.');
611
+ dbglogging_1.default.elog(error.message);
612
+ cbargs.callback(error, null);
613
+ return;
614
+ }
615
+ //
616
+ // Initialize endpoint list(object)
617
+ //
618
+ rawInitializeKeystoneEpList();
619
+ //
620
+ // try to remake keystone endpoint
621
+ //
622
+ if (rawIsValTypeKeystoneEndpointMap(kseplist)) {
623
+ //
624
+ // Get a static keystone endpoint.
625
+ //
626
+ rawGetKeystoneEndpointsCallback(cbargs, null, kseplist);
627
+ }
628
+ else if (k2hr3apiutil_1.default.isSafeEntity(ksepobj)) {
629
+ //
630
+ // Get keystone endpoint list dynamically.
631
+ //
632
+ ksepobj.getDynamicKeystoneEndpoints(cbargs, rawGetKeystoneEndpointsCallback);
633
+ }
634
+ else {
635
+ //
636
+ // Wrong configuration
637
+ //
638
+ const error = new Error('keystone endpoint configuration is something wrong.');
639
+ dbglogging_1.default.elog(error.message);
640
+ cbargs.callback(error, null);
641
+ return;
642
+ }
643
+ };
644
+ //---------------------------------------------------------
645
+ // Exports
646
+ //---------------------------------------------------------
647
+ //
648
+ // Functions
649
+ //
650
+ exports.openstackep = {
651
+ isValTypeKeystoneEndpoint: rawIsValTypeKeystoneEndpoint,
652
+ isValTypeKeystoneEndpointMap: rawIsValTypeKeystoneEndpointMap,
653
+ isValTypeGetKeystoneEndpointArgs: rawIsValTypeGetKeystoneEndpointArgs,
654
+ getKeystoneEndpoint: rawGetKeystoneEndpoint
655
+ };
656
+ //
657
+ // Default
658
+ //
659
+ exports.default = exports.openstackep;
660
+ /*
661
+ * Local variables:
662
+ * tab-width: 4
663
+ * c-basic-offset: 4
664
+ * End:
665
+ * vim600: noexpandtab sw=4 ts=4 fdm=marker
666
+ * vim<600: noexpandtab sw=4 ts=4
667
+ */