@cloudbase/manager-node 5.5.3 → 5.5.5

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/lib/env/index.js CHANGED
@@ -12,6 +12,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.EnvService = void 0;
13
13
  const cos_nodejs_sdk_v5_1 = __importDefault(require("cos-nodejs-sdk-v5"));
14
14
  const util_1 = __importDefault(require("util"));
15
+ const http_request_1 = require("../utils/http-request");
16
+ const signature_nodejs_1 = require("@cloudbase/signature-nodejs");
15
17
  const error_1 = require("../error");
16
18
  const utils_1 = require("../utils");
17
19
  const constant_1 = require("../constant");
@@ -26,6 +28,7 @@ class EnvService {
26
28
  this.tcbService = new utils_1.CloudService(environment.cloudBaseContext, 'tcb', '2018-06-08');
27
29
  this.commonService = environment.getCommonService('lowcode', '2021-01-08');
28
30
  this.billingService = new billing_1.BillingService(environment.cloudBaseContext);
31
+ this.tokenCache = new Map();
29
32
  }
30
33
  /**
31
34
  * 列出所有环境
@@ -410,6 +413,74 @@ class EnvService {
410
413
  async describeApiKeyList(options) {
411
414
  return this.tcbService.request('DescribeApiKeyList', Object.assign({ EnvId: this.envId }, options));
412
415
  }
416
+ /**
417
+ * 根据密钥信息获取管理员访问令牌
418
+ * 使用 secretId、secretKey 和 sessionToken 签发访问令牌
419
+ * 默认从初始化时的 cloudBaseContext 中读取密钥,也可显式传入 credentials 覆盖
420
+ * @param {Object} [credentials] 密钥信息,不传则使用初始化时的密钥
421
+ * @param {string} credentials.secretId 密钥ID
422
+ * @param {string} credentials.secretKey 密钥Key
423
+ * @param {string} [credentials.token] sessionToken
424
+ * @returns {Promise<string>} 访问令牌
425
+ */
426
+ async getAdminAccessToken(credentials) {
427
+ const { secretId, secretKey, token } = credentials || this.environment.cloudBaseContext;
428
+ if (!secretId || !secretKey) {
429
+ throw new error_1.CloudBaseError('missing secretId or secretKey of tencent cloud');
430
+ }
431
+ const envId = this.envId;
432
+ const cacheKey = `access_token_secret_${envId}_${secretId}`;
433
+ const cached = this.tokenCache.get(cacheKey);
434
+ if (cached && cached.expiry > Date.now()) {
435
+ return cached.token;
436
+ }
437
+ const host = `${envId}${this.environment.cloudBaseContext.isInternalEndpoint()
438
+ ? '.api.intl.tcloudbasegateway.com'
439
+ : '.api.tcloudbasegateway.com'}`;
440
+ const url = `https://${host}/auth/v1/token/clientCredential`;
441
+ const method = 'POST';
442
+ const headers = {
443
+ 'Content-Type': 'application/json',
444
+ Host: host,
445
+ };
446
+ const data = { grant_type: 'client_credentials' };
447
+ const timestamp = Math.floor(new Date().getTime() / 1000) - 1;
448
+ const { authorization, timestamp: signTimestamp } = (0, signature_nodejs_1.sign)({
449
+ secretId,
450
+ secretKey,
451
+ method,
452
+ url,
453
+ headers,
454
+ params: data,
455
+ timestamp,
456
+ withSignedParams: false,
457
+ isCloudApi: true,
458
+ });
459
+ headers['Authorization'] = `${authorization}, Timestamp=${signTimestamp}${token ? `, Token=${token}` : ''}`;
460
+ headers['X-Signature-Expires'] = 600;
461
+ headers['X-Timestamp'] = signTimestamp;
462
+ try {
463
+ const response = await (0, http_request_1.fetch)(url, {
464
+ method,
465
+ headers,
466
+ body: JSON.stringify(data),
467
+ });
468
+ const res = await response.json();
469
+ const access_token = res === null || res === void 0 ? void 0 : res.access_token;
470
+ const expires_in = (res === null || res === void 0 ? void 0 : res.expires_in) || 0;
471
+ if (access_token && expires_in) {
472
+ this.tokenCache.set(cacheKey, {
473
+ token: access_token,
474
+ expiry: Date.now() + (expires_in * 1000) / 2,
475
+ });
476
+ }
477
+ return access_token;
478
+ }
479
+ catch (e) {
480
+ console.log(e);
481
+ throw e;
482
+ }
483
+ }
413
484
  // 创建自定义登录私钥
414
485
  async createCustomLoginKeys() {
415
486
  return this.cloudService.request('CreateCustomLoginKeys', {
@@ -18,7 +18,11 @@ class PermissionService {
18
18
  constructor(environment) {
19
19
  this.environment = environment;
20
20
  this.tcbService = new utils_1.CloudService(environment.cloudBaseContext, 'tcb', '2018-06-08');
21
+ this.lowcodeService = new utils_1.CloudService(environment.cloudBaseContext, 'lowcode', '2021-01-08');
21
22
  }
23
+ /**
24
+ * @deprecated 已废弃,网关鉴权策略已由 OPA 接管,请使用 modifyEnvAuthzConfig 替代
25
+ */
22
26
  async modifyResourcePermission(options) {
23
27
  const { EnvId } = this.environment.lazyEnvironmentConfig;
24
28
  const { resourceType, resource, permission, securityRule } = options;
@@ -51,6 +55,9 @@ class PermissionService {
51
55
  }
52
56
  return this.tcbService.request('ModifyResourcePermission', reqData);
53
57
  }
58
+ /**
59
+ * @deprecated 已废弃,网关鉴权策略已由 OPA 接管,请使用 describeResourcePolicyList 或 describeEnvAuthzConfig 替代
60
+ */
54
61
  async describeResourcePermission(options) {
55
62
  const { EnvId } = this.environment.lazyEnvironmentConfig;
56
63
  const { resourceType, resources } = options;
@@ -288,6 +295,104 @@ class PermissionService {
288
295
  RoleIds: roleIds
289
296
  });
290
297
  }
298
+ /**
299
+ * 拉取环境下的所有用户自定义的网关鉴权策略列表
300
+ * 注意:PG 环境无需调用,直接按照无存量策略处理;
301
+ * 若环境 meta 中 authz_engine 值为 opa,则网关策略不生效,无需调用
302
+ */
303
+ async describeResourcePolicyList(options = {}) {
304
+ const { resourceType } = options;
305
+ if (resourceType !== undefined && (typeof resourceType !== 'string' || resourceType.trim().length === 0)) {
306
+ throw new Error('Invalid resourceType');
307
+ }
308
+ // PG 环境无需调用,直接返回空策略列表
309
+ if (await this.isPostgresqlEnv()) {
310
+ const emptyData = { PolicyList: [], Total: '0' };
311
+ return {
312
+ Data: emptyData,
313
+ RequestId: ''
314
+ };
315
+ }
316
+ // authz_engine 为 opa 时网关策略不生效,无需调用,直接返回空策略列表
317
+ if (await this.isOpaAuthzEngine()) {
318
+ const emptyData = { PolicyList: [], Total: '0' };
319
+ return {
320
+ Data: emptyData,
321
+ RequestId: ''
322
+ };
323
+ }
324
+ const { EnvId } = this.environment.lazyEnvironmentConfig;
325
+ const reqData = {
326
+ EnvId,
327
+ ResourceType: resourceType || 'policy'
328
+ };
329
+ return this.lowcodeService.request('DescribeResourcePolicyList', reqData);
330
+ }
331
+ /**
332
+ * 拉取环境下的鉴权策略配置
333
+ * key: authz.platform.extension.rego - 单独为该环境配置的策略
334
+ * key: authz.user.rego - 用户配置的策略
335
+ */
336
+ async describeEnvAuthzConfig(options) {
337
+ const { key } = options;
338
+ if (!key || (key !== 'authz.platform.extension.rego' && key !== 'authz.user.rego')) {
339
+ throw new Error('key must be "authz.platform.extension.rego" or "authz.user.rego"');
340
+ }
341
+ const { EnvId } = this.environment.lazyEnvironmentConfig;
342
+ return this.tcbService.request('DescribeEnvConfig', {
343
+ EnvId,
344
+ Key: key
345
+ });
346
+ }
347
+ /**
348
+ * 保存用户编写的 rego 策略,保存后旧网关鉴权将直接失效
349
+ */
350
+ async modifyEnvAuthzConfig(options) {
351
+ const { EnvId } = this.environment.lazyEnvironmentConfig;
352
+ const { key, value } = options;
353
+ if (key !== 'authz.user.rego') {
354
+ throw new Error('key must be "authz.user.rego"');
355
+ }
356
+ if (typeof value !== 'string' || value.trim().length === 0) {
357
+ throw new Error('value is required and must be a non-empty string');
358
+ }
359
+ return this.tcbService.request('ModifyEnvConfig', {
360
+ EnvId,
361
+ Key: key,
362
+ Value: value
363
+ });
364
+ }
365
+ /**
366
+ * 获取完整的环境基础信息(含 PostgreSQL、Meta 等字段)
367
+ */
368
+ async getEnvBaseInfo() {
369
+ var _a;
370
+ const { EnvId } = this.environment.lazyEnvironmentConfig;
371
+ const params = { EnvId };
372
+ const res = await this.environment.getEnvService().describeEnvInfo(params);
373
+ return ((_a = res === null || res === void 0 ? void 0 : res.EnvInfo) === null || _a === void 0 ? void 0 : _a.EnvBaseInfo) || {};
374
+ }
375
+ /**
376
+ * 判断当前环境是否为 PostgreSQL 环境
377
+ * PostgreSQL 是数组且长度 > 0 时为 PG 环境
378
+ */
379
+ async isPostgresqlEnv() {
380
+ const envBaseInfo = await this.getEnvBaseInfo();
381
+ return Array.isArray(envBaseInfo.PostgreSQL) && envBaseInfo.PostgreSQL.length > 0;
382
+ }
383
+ /**
384
+ * 判断当前环境的 authz_engine 是否为 opa
385
+ * 从环境 Meta 中查找 Key 为 authz_engine 的标签,Value 为 opa 表示已切到 OPA
386
+ */
387
+ async isOpaAuthzEngine() {
388
+ const envBaseInfo = await this.getEnvBaseInfo();
389
+ const meta = envBaseInfo === null || envBaseInfo === void 0 ? void 0 : envBaseInfo.Meta;
390
+ if (!Array.isArray(meta)) {
391
+ return false;
392
+ }
393
+ const authzEngineTag = meta.find(tag => tag.Key === 'authz_engine');
394
+ return (authzEngineTag === null || authzEngineTag === void 0 ? void 0 : authzEngineTag.Value) === 'opa';
395
+ }
291
396
  }
292
397
  exports.PermissionService = PermissionService;
293
398
  __decorate([
@@ -308,3 +413,12 @@ __decorate([
308
413
  __decorate([
309
414
  (0, utils_1.preLazy)()
310
415
  ], PermissionService.prototype, "deleteRoles", null);
416
+ __decorate([
417
+ (0, utils_1.preLazy)()
418
+ ], PermissionService.prototype, "describeResourcePolicyList", null);
419
+ __decorate([
420
+ (0, utils_1.preLazy)()
421
+ ], PermissionService.prototype, "describeEnvAuthzConfig", null);
422
+ __decorate([
423
+ (0, utils_1.preLazy)()
424
+ ], PermissionService.prototype, "modifyEnvAuthzConfig", null);
@@ -1335,8 +1335,8 @@ class StorageService {
1335
1335
  typeof cacheControl === 'number' ? `max-age=${cacheControl}` : String(cacheControl);
1336
1336
  }
1337
1337
  if (metadata) {
1338
- // X-Metadata 放在 Header 里,具体大小限制由服务端/网关决定
1339
- headers['X-Metadata'] = Buffer.from(JSON.stringify(metadata), 'utf8').toString('base64');
1338
+ // x-metadata 放在 Header 里,具体大小限制由服务端/网关决定
1339
+ headers['x-metadata'] = Buffer.from(JSON.stringify(metadata), 'utf8').toString('base64');
1340
1340
  }
1341
1341
  if (upsert) {
1342
1342
  headers['x-upsert'] = 'true';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudbase/manager-node",
3
- "version": "5.5.3",
3
+ "version": "5.5.5",
4
4
  "description": "The node manage service api for cloudbase.",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -41,6 +41,7 @@
41
41
  "typescript": "^5.8.3"
42
42
  },
43
43
  "dependencies": {
44
+ "@cloudbase/signature-nodejs": "^1.0.0",
44
45
  "@cloudbase/database": "^0.6.2",
45
46
  "archiver": "^3.1.1",
46
47
  "cos-nodejs-sdk-v5": "^2.14.0",
@@ -559,6 +559,7 @@ export declare class EnvService {
559
559
  private envType?;
560
560
  private commonService;
561
561
  private billingService;
562
+ private tokenCache;
562
563
  constructor(environment: Environment);
563
564
  /**
564
565
  * 列出所有环境
@@ -779,6 +780,21 @@ export declare class EnvService {
779
780
  * @returns {Promise<IDescribeApiKeyListRes>}
780
781
  */
781
782
  describeApiKeyList(options?: IDescribeApiKeyListParams): Promise<IDescribeApiKeyListRes>;
783
+ /**
784
+ * 根据密钥信息获取管理员访问令牌
785
+ * 使用 secretId、secretKey 和 sessionToken 签发访问令牌
786
+ * 默认从初始化时的 cloudBaseContext 中读取密钥,也可显式传入 credentials 覆盖
787
+ * @param {Object} [credentials] 密钥信息,不传则使用初始化时的密钥
788
+ * @param {string} credentials.secretId 密钥ID
789
+ * @param {string} credentials.secretKey 密钥Key
790
+ * @param {string} [credentials.token] sessionToken
791
+ * @returns {Promise<string>} 访问令牌
792
+ */
793
+ getAdminAccessToken(credentials?: {
794
+ secretId: string;
795
+ secretKey: string;
796
+ token?: string;
797
+ }): Promise<string>;
782
798
  createCustomLoginKeys(): Promise<{
783
799
  PrivateKey: string;
784
800
  KeyID: string;
@@ -484,6 +484,10 @@ export interface EnvBaseInfo {
484
484
  Key: string;
485
485
  Value: string;
486
486
  }>;
487
+ Meta?: Array<{
488
+ Key: string;
489
+ Value: string;
490
+ }>;
487
491
  CreateTime?: string;
488
492
  UpdateTime?: string;
489
493
  EnvPreferences?: Record<string, any>;
@@ -1,13 +1,20 @@
1
1
  import { Environment } from '../environment';
2
- import { ModifyResourcePermissionOptions, ModifyResourcePermissionResp, DescribeResourcePermissionOptions, DescribeResourcePermissionResp, CreateRoleOptions, CreateRoleResp, DescribeRoleListOptions, DescribeRoleListResp, ModifyRoleOptions, ModifyRoleResp, DeleteRolesOptions, DeleteRolesResp } from './types';
2
+ import { ModifyResourcePermissionOptions, ModifyResourcePermissionResp, DescribeResourcePermissionOptions, DescribeResourcePermissionResp, CreateRoleOptions, CreateRoleResp, DescribeRoleListOptions, DescribeRoleListResp, ModifyRoleOptions, ModifyRoleResp, DeleteRolesOptions, DeleteRolesResp, DescribeResourcePolicyListOptions, DescribeResourcePolicyListResp, DescribeEnvAuthzConfigOptions, DescribeEnvAuthzConfigResp, ModifyEnvAuthzConfigOptions } from './types';
3
3
  export declare class PermissionService {
4
4
  private environment;
5
5
  private tcbService;
6
+ private lowcodeService;
6
7
  constructor(environment: Environment);
8
+ /**
9
+ * @deprecated 已废弃,网关鉴权策略已由 OPA 接管,请使用 modifyEnvAuthzConfig 替代
10
+ */
7
11
  modifyResourcePermission(options: ModifyResourcePermissionOptions): Promise<{
8
12
  Data: ModifyResourcePermissionResp;
9
13
  RequestId: string;
10
14
  }>;
15
+ /**
16
+ * @deprecated 已废弃,网关鉴权策略已由 OPA 接管,请使用 describeResourcePolicyList 或 describeEnvAuthzConfig 替代
17
+ */
11
18
  describeResourcePermission(options: DescribeResourcePermissionOptions): Promise<{
12
19
  Data: DescribeResourcePermissionResp;
13
20
  RequestId: string;
@@ -28,4 +35,43 @@ export declare class PermissionService {
28
35
  Data: DeleteRolesResp;
29
36
  RequestId: string;
30
37
  }>;
38
+ /**
39
+ * 拉取环境下的所有用户自定义的网关鉴权策略列表
40
+ * 注意:PG 环境无需调用,直接按照无存量策略处理;
41
+ * 若环境 meta 中 authz_engine 值为 opa,则网关策略不生效,无需调用
42
+ */
43
+ describeResourcePolicyList(options?: DescribeResourcePolicyListOptions): Promise<{
44
+ Data: DescribeResourcePolicyListResp;
45
+ RequestId: string;
46
+ }>;
47
+ /**
48
+ * 拉取环境下的鉴权策略配置
49
+ * key: authz.platform.extension.rego - 单独为该环境配置的策略
50
+ * key: authz.user.rego - 用户配置的策略
51
+ */
52
+ describeEnvAuthzConfig(options: DescribeEnvAuthzConfigOptions): Promise<{
53
+ Item: DescribeEnvAuthzConfigResp;
54
+ RequestId: string;
55
+ }>;
56
+ /**
57
+ * 保存用户编写的 rego 策略,保存后旧网关鉴权将直接失效
58
+ */
59
+ modifyEnvAuthzConfig(options: ModifyEnvAuthzConfigOptions): Promise<{
60
+ AffectedRows: number;
61
+ RequestId: string;
62
+ }>;
63
+ /**
64
+ * 获取完整的环境基础信息(含 PostgreSQL、Meta 等字段)
65
+ */
66
+ private getEnvBaseInfo;
67
+ /**
68
+ * 判断当前环境是否为 PostgreSQL 环境
69
+ * PostgreSQL 是数组且长度 > 0 时为 PG 环境
70
+ */
71
+ private isPostgresqlEnv;
72
+ /**
73
+ * 判断当前环境的 authz_engine 是否为 opa
74
+ * 从环境 Meta 中查找 Key 为 authz_engine 的标签,Value 为 opa 表示已切到 OPA
75
+ */
76
+ private isOpaAuthzEngine;
31
77
  }
@@ -125,3 +125,37 @@ export interface DeleteRolesResp {
125
125
  SuccessCount?: number;
126
126
  FailedCount?: number;
127
127
  }
128
+ export interface ResourcePolicyItem {
129
+ Effect?: string;
130
+ IsAccess?: boolean;
131
+ PolicyId?: string;
132
+ ResourceId?: string;
133
+ ResourceName?: string;
134
+ ResourceTitle?: string;
135
+ ResourceType?: string;
136
+ RoleId?: string;
137
+ RoleIdentity?: string;
138
+ RoleName?: string;
139
+ SafeRule?: string;
140
+ }
141
+ export interface DescribeResourcePolicyListOptions {
142
+ resourceType?: string;
143
+ }
144
+ export interface DescribeResourcePolicyListResp {
145
+ PolicyList: ResourcePolicyItem[];
146
+ Total: string;
147
+ }
148
+ export interface DescribeEnvAuthzConfigOptions {
149
+ key: 'authz.platform.extension.rego' | 'authz.user.rego';
150
+ }
151
+ export interface DescribeEnvAuthzConfigResp {
152
+ Key: string;
153
+ Value: string;
154
+ }
155
+ export interface ModifyEnvAuthzConfigOptions {
156
+ key: 'authz.user.rego';
157
+ value: string;
158
+ }
159
+ export interface ModifyEnvAuthzConfigResp {
160
+ AffectedRows: number;
161
+ }
@@ -18,7 +18,7 @@ export interface IUploadObjectHttpOptions {
18
18
  * 缓存控制;传 number 自动转换为 max-age=<value>,传 string 直接作为 Cache-Control 头值
19
19
  */
20
20
  cacheControl?: number | string;
21
- /** 自定义 metadata(JSON 对象),将以 Base64 编码后放入 X-Metadata 头 */
21
+ /** 自定义 metadata(JSON 对象),将以 Base64 编码后放入 x-metadata 头 */
22
22
  metadata?: Record<string, any>;
23
23
  /** 爬虫指令(X-Robots-Tag 头) */
24
24
  xRobotsTag?: string;