@pengzi/kms 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -65,7 +65,7 @@ kms
65
65
  选择: 密钥管理 → 获取密钥值
66
66
  ```
67
67
 
68
- 详细 CLI 使用说明请查看:[CLI 使用指南](./docs/CLI_GUIDE.md)
68
+ 详细 CLI 使用说明请查看:[CLI 工具指南](./docs/guides/cli-guide.md)
69
69
 
70
70
  ### 方式 2: 使用 Node.js SDK
71
71
 
@@ -179,9 +179,330 @@ auditLogs.logs.forEach(log => {
179
179
  });
180
180
  ```
181
181
 
182
+ ## 完整使用指南
183
+
184
+ ### 连接配置
185
+
186
+ #### MongoDB Atlas(推荐,自动 TLS)
187
+
188
+ ```typescript
189
+ const kms = new KMSClient({
190
+ connectionString: 'mongodb+srv://user:pass@cluster.mongodb.net',
191
+ databaseName: 'kms'
192
+ });
193
+ await kms.connect();
194
+ ```
195
+
196
+ #### 自建 MongoDB + TLS
197
+
198
+ ```typescript
199
+ const kms = new KMSClient({
200
+ connectionString: 'mongodb://localhost:27017',
201
+ databaseName: 'kms',
202
+ connectionOptions: {
203
+ tls: true,
204
+ tlsCAFile: '/etc/ssl/mongodb/ca.pem'
205
+ }
206
+ });
207
+ await kms.connect();
208
+ ```
209
+
210
+ #### 开发环境(本地 MongoDB)
211
+
212
+ ```typescript
213
+ const kms = new KMSClient({
214
+ connectionString: 'mongodb://localhost:27017',
215
+ databaseName: 'kms'
216
+ });
217
+ await kms.connect();
218
+ ```
219
+
220
+ ### 用户管理
221
+
222
+ ```typescript
223
+ // 创建用户
224
+ const user = await kms.createUser(projectId, {
225
+ username: 'developer1',
226
+ password: 'UserPassword123!',
227
+ roles: ['developer'] // 可选: admin, operator, developer, readonly, auditor
228
+ });
229
+
230
+ // 授予角色
231
+ await kms.grantRole(projectId, user.userId, 'operator');
232
+
233
+ // 撤销角色
234
+ await kms.revokeRole(projectId, user.userId, 'developer');
235
+ ```
236
+
237
+ ### 密钥管理完整流程
238
+
239
+ ```typescript
240
+ // 1. 创建密钥
241
+ const key = await kms.createKey(projectId, masterPassword, {
242
+ keyName: 'production-db',
243
+ keyType: KeyType.MONGODB,
244
+ value: 'mongodb://user:pass@host:27017/db',
245
+ tags: ['production', 'database'],
246
+ description: '生产环境主数据库',
247
+ expiresAt: new Date('2025-12-31') // 可选:设置过期时间
248
+ });
249
+
250
+ // 2. 列出密钥(分页)
251
+ const { keys, total } = await kms.listKeys(projectId, {
252
+ keyType: KeyType.MONGODB,
253
+ tags: ['production']
254
+ }, {
255
+ page: 1,
256
+ limit: 20
257
+ });
258
+
259
+ // 3. 更新密钥
260
+ const updatedKey = await kms.updateKey(
261
+ projectId,
262
+ masterPassword,
263
+ key.keyId,
264
+ {
265
+ description: '更新的描述',
266
+ tags: ['production', 'database', 'important']
267
+ }
268
+ );
269
+
270
+ // 4. 删除密钥
271
+ await kms.deleteKey(projectId, key.keyId);
272
+ ```
273
+
274
+ ### 审计日志查询
275
+
276
+ ```typescript
277
+ // 查看最近日志
278
+ const recentLogs = await kms.getRecentLogs(projectId, 50);
279
+
280
+ // 高级查询
281
+ const auditLogs = await kms.getAuditLogs(projectId, {
282
+ page: 1,
283
+ limit: 20,
284
+ action: 'CREATE_KEY', // 可选:过滤操作类型
285
+ userId: 'user123', // 可选:过滤用户
286
+ startDate: new Date('2025-01-01'),
287
+ endDate: new Date('2025-12-31')
288
+ });
289
+
290
+ console.log('总记录数:', auditLogs.total);
291
+ console.log('当前页:', auditLogs.page);
292
+ ```
293
+
294
+ ### 项目管理
295
+
296
+ ```typescript
297
+ // 列出所有项目
298
+ const projects = await kms.listProjects();
299
+
300
+ // 获取项目详情
301
+ const project = await kms.getProject(projectId);
302
+
303
+ // 删除项目(会删除所有密钥)
304
+ await kms.deleteProject(projectId);
305
+ ```
306
+
182
307
  ## 高级用法
183
308
 
184
- ### Express集成示例
309
+ ### Express 集成示例
310
+
311
+ ```typescript
312
+ import express from 'express';
313
+ import { KMSClient, KeyType } from '@pengzi/kms';
314
+
315
+ const app = express();
316
+ app.use(express.json());
317
+
318
+ const kms = new KMSClient({
319
+ connectionString: process.env.MONGODB_URI,
320
+ databaseName: 'kms'
321
+ });
322
+
323
+ await kms.connect();
324
+
325
+ // 中间件:设置当前用户
326
+ app.use((req, res, next) => {
327
+ kms.setCurrentUser(req.user?.id || 'api-user');
328
+ next();
329
+ });
330
+
331
+ // API: 创建密钥
332
+ app.post('/api/keys', async (req, res) => {
333
+ try {
334
+ const { projectId, masterPassword, keyName, keyType, value } = req.body;
335
+
336
+ const key = await kms.createKey(projectId, masterPassword, {
337
+ keyName,
338
+ keyType,
339
+ value,
340
+ tags: ['api-created']
341
+ });
342
+
343
+ res.json({ success: true, keyId: key.keyId });
344
+ } catch (error) {
345
+ res.status(400).json({ error: error.message });
346
+ }
347
+ });
348
+
349
+ // API: 获取密钥
350
+ app.get('/api/keys/:keyId', async (req, res) => {
351
+ try {
352
+ const { projectId, masterPassword } = req.headers;
353
+ const { keyId } = req.params;
354
+
355
+ const keyValue = await kms.getKey(
356
+ projectId,
357
+ masterPassword,
358
+ keyId
359
+ );
360
+
361
+ res.json({ value: keyValue.value });
362
+ } catch (error) {
363
+ res.status(404).json({ error: error.message });
364
+ }
365
+ });
366
+
367
+ // API: 列出密钥
368
+ app.get('/api/keys', async (req, res) => {
369
+ try {
370
+ const { projectId } = req.query;
371
+ const { keys, total } = await kms.listKeys(projectId);
372
+
373
+ res.json({ keys, total });
374
+ } catch (error) {
375
+ res.status(500).json({ error: error.message });
376
+ }
377
+ });
378
+
379
+ app.listen(3000, () => {
380
+ console.log('KMS API server running on port 3000');
381
+ });
382
+ ```
383
+
384
+ ### 环境变量配置
385
+
386
+ 创建 `.env` 文件:
387
+
388
+ ```bash
389
+ # MongoDB 连接
390
+ MONGODB_URI=mongodb+srv://user:pass@cluster.mongodb.net
391
+ KMS_DATABASE=kms
392
+
393
+ # 或者使用加密连接
394
+ KMS_ENCRYPTED_CONNECTION={"encrypted":"..."}
395
+
396
+ # 私钥(如果使用加密连接)
397
+ KMS_PRIVATE_KEY_FILE=/path/to/private-key.pem
398
+ ```
399
+
400
+ 使用环境变量:
401
+
402
+ ```typescript
403
+ import dotenv from 'dotenv';
404
+ dotenv.config();
405
+
406
+ const kms = new KMSClient({
407
+ connectionString: process.env.MONGODB_URI,
408
+ databaseName: process.env.KMS_DATABASE || 'kms'
409
+ });
410
+ ```
411
+
412
+ ### 使用加密连接字符串
413
+
414
+ ```typescript
415
+ import {
416
+ loadEncryptedConfig,
417
+ createClientFromEncryptedConfig
418
+ } from '@pengzi/kms';
419
+
420
+ // 从配置文件加载加密的连接字符串
421
+ const config = loadEncryptedConfig('./config/encrypted-db.json');
422
+
423
+ // 创建客户端
424
+ const kms = await createClientFromEncryptedConfig(config);
425
+ ```
426
+
427
+ ### 错误处理最佳实践
428
+
429
+ ```typescript
430
+ import {
431
+ KMSClient,
432
+ KeyNotFoundError,
433
+ AuthenticationError,
434
+ ForbiddenError,
435
+ ValidationError,
436
+ ProjectNotFoundError
437
+ } from '@pengzi/kms';
438
+
439
+ async function getKeySafely(
440
+ kms: KMSClient,
441
+ projectId: string,
442
+ masterPassword: string,
443
+ keyId: string
444
+ ) {
445
+ try {
446
+ const keyValue = await kms.getKey(projectId, masterPassword, keyId);
447
+ return { success: true, value: keyValue.value };
448
+ } catch (error) {
449
+ if (error instanceof KeyNotFoundError) {
450
+ return { success: false, error: '密钥不存在' };
451
+ } else if (error instanceof AuthenticationError) {
452
+ return { success: false, error: '主密码错误' };
453
+ } else if (error instanceof ForbiddenError) {
454
+ return { success: false, error: '权限不足' };
455
+ } else if (error instanceof ValidationError) {
456
+ return { success: false, error: '数据验证失败' };
457
+ } else if (error instanceof ProjectNotFoundError) {
458
+ return { success: false, error: '项目不存在' };
459
+ } else {
460
+ return { success: false, error: '未知错误' };
461
+ }
462
+ }
463
+ }
464
+
465
+ // 使用
466
+ const result = await getKeySafely(kms, projectId, masterPassword, keyId);
467
+ if (result.success) {
468
+ console.log('密钥值:', result.value);
469
+ } else {
470
+ console.error('错误:', result.error);
471
+ }
472
+ ```
473
+
474
+ ### TypeScript 支持
475
+
476
+ KMS 提供完整的 TypeScript 类型定义:
477
+
478
+ ```typescript
479
+ import {
480
+ KMSClient,
481
+ KeyType,
482
+ Role,
483
+ KeyStatus,
484
+ Permission
485
+ } from '@pengzi/kms';
486
+
487
+ // 类型安全的密钥创建
488
+ const keyData: CreateKeyData = {
489
+ keyName: 'my-redis',
490
+ keyType: KeyType.REDIS,
491
+ value: 'redis://localhost:6379',
492
+ tags: ['cache'],
493
+ description: 'Redis 缓存'
494
+ };
495
+
496
+ // 类型安全的项目创建
497
+ const projectOptions: CreateProjectOptions = {
498
+ projectName: 'my-app',
499
+ masterPassword: 'StrongPassword123!',
500
+ metadata: {
501
+ environment: 'production',
502
+ team: 'backend'
503
+ }
504
+ };
505
+ ```
185
506
 
186
507
  ```typescript
187
508
  import express from 'express';
@@ -227,13 +548,22 @@ app.listen(3000);
227
548
  ```
228
549
 
229
550
  更多示例请查看:
230
- - [基础使用示例](./examples/basic-usage.ts)
231
- - [Express集成](./examples/with-express.ts)
232
- - [数据库连接管理](./examples/database-connections.ts)
551
+ - [📊 可视化流程指南](./docs/kms-visual-guide.html) - 交互式完整流程说明 ⭐ 推荐
552
+ - [快速入门](./docs/getting-started/quickstart.md)
553
+ - [CLI 工具指南](./docs/guides/cli-guide.md)
554
+ - [API 使用示例](./docs/guides/api-usage.md)
555
+
556
+ ## 文档
233
557
 
234
- ## API文档
558
+ 完整文档请查看:[文档导航](./docs/README.md)
235
559
 
236
- 完整的API文档请查看:[API.md](./docs/API.md)
560
+ ### 核心文档
561
+ - [📊 可视化流程指南](./docs/kms-visual-guide.html) - 交互式完整流程说明 ⭐ 推荐
562
+ - [安装指南](./docs/getting-started/installation.md) - 详细的安装步骤
563
+ - [5分钟快速入门](./docs/getting-started/quickstart.md) - 快速上手指南
564
+ - [CLI 工具指南](./docs/guides/cli-guide.md) - 交互式命令行工具
565
+ - [TLS/SSL 配置流程](./docs/guides/tls-workflow.md) - TLS 配置完整流程 ⭐ 推荐
566
+ - [API 参考](./docs/api/reference.md) - 完整的 API 文档
237
567
 
238
568
  ## 安全最佳实践
239
569
 
@@ -286,7 +616,7 @@ app.listen(3000);
286
616
  - 监控失败的登录尝试
287
617
  - 设置安全告警
288
618
 
289
- 完整的安全指南请查看:[SECURITY.md](./docs/SECURITY.md)
619
+ 完整的安全指南请查看:[安全最佳实践](./docs/security/best-practices.md)
290
620
 
291
621
  ## 支持的密钥类型
292
622
 
@@ -306,36 +636,430 @@ app.listen(3000);
306
636
  | `readonly` | 只读用户 | 列出密钥 |
307
637
  | `auditor` | 审计员 | 查看审计日志 |
308
638
 
639
+ ## 实际应用场景
640
+
641
+ ### 场景 1: 微服务架构中的密钥管理
642
+
643
+ ```typescript
644
+ // 服务 A: 创建密钥
645
+ const serviceA = async () => {
646
+ const kms = new KMSClient({
647
+ connectionString: process.env.MONGODB_URI,
648
+ databaseName: 'kms'
649
+ });
650
+ await kms.connect();
651
+
652
+ const project = await kms.createProject('microservices-app', masterPassword);
653
+
654
+ // 为每个服务创建密钥
655
+ await kms.createKey(project.projectId, masterPassword, {
656
+ keyName: 'user-service-db',
657
+ keyType: KeyType.MONGODB,
658
+ value: process.env.USER_DB_URL,
659
+ tags: ['user-service', 'database']
660
+ });
661
+
662
+ await kms.createKey(project.projectId, masterPassword, {
663
+ keyName: 'order-service-db',
664
+ keyType: KeyType.MONGODB,
665
+ value: process.env.ORDER_DB_URL,
666
+ tags: ['order-service', 'database']
667
+ });
668
+ };
669
+
670
+ // 服务 B: 获取密钥
671
+ const serviceB = async () => {
672
+ const kms = new KMSClient({
673
+ connectionString: process.env.MONGODB_URI,
674
+ databaseName: 'kms'
675
+ });
676
+ await kms.connect();
677
+
678
+ // 只获取自己需要的密钥
679
+ const { keys } = await kms.listKeys(projectId, {
680
+ tags: ['user-service']
681
+ });
682
+
683
+ keys.forEach(async (key) => {
684
+ const keyValue = await kms.getKey(projectId, masterPassword, key.keyId);
685
+ // 使用连接字符串初始化数据库连接
686
+ await connectToDatabase(keyValue.value);
687
+ });
688
+ };
689
+ ```
690
+
691
+ ### 场景 2: 多环境部署
692
+
693
+ ```typescript
694
+ const environments = ['development', 'staging', 'production'];
695
+
696
+ for (const env of environments) {
697
+ const projectName = `myapp-${env}`;
698
+ const project = await kms.createProject(projectName, masterPassword);
699
+
700
+ // 为每个环境创建相应的密钥
701
+ await kms.createKey(project.projectId, masterPassword, {
702
+ keyName: 'database',
703
+ keyType: KeyType.MONGODB,
704
+ value: envDatabases[env],
705
+ tags: [env, 'database']
706
+ });
707
+ }
708
+ ```
709
+
710
+ ### 场景 3: 密钥轮换
711
+
712
+ ```typescript
713
+ async function rotateKey(projectId: string, keyId: string, masterPassword: string) {
714
+ const kms = new KMSClient({ /* config */ });
715
+ await kms.connect();
716
+
717
+ // 1. 获取旧密钥值(如果需要)
718
+ const oldValue = await kms.getKey(projectId, masterPassword, keyId);
719
+
720
+ // 2. 更新为新值
721
+ const newValue = generateNewConnectionString();
722
+ await kms.updateKey(projectId, masterPassword, keyId, {
723
+ value: newValue
724
+ });
725
+
726
+ // 3. 通知相关服务(使用消息队列)
727
+ await notifyServicesKeyRotated(keyId, newValue);
728
+
729
+ console.log(`密钥 ${keyId} 已轮换`);
730
+ }
731
+ ```
732
+
733
+ ### 场景 4: 访问控制
734
+
735
+ ```typescript
736
+ // 为不同团队创建不同的项目
737
+ const frontendTeam = await kms.createProject('frontend-app', masterPassword);
738
+ const backendTeam = await kms.createProject('backend-app', masterPassword);
739
+
740
+ // 创建不同权限的用户
741
+ const frontendDev = await kms.createUser(frontendTeam.projectId, {
742
+ username: 'frontend-dev',
743
+ password: 'Password123!',
744
+ roles: ['developer'] // 只读权限
745
+ });
746
+
747
+ const backendAdmin = await kms.createUser(backendTeam.projectId, {
748
+ username: 'backend-admin',
749
+ password: 'AdminPass123!',
750
+ roles: ['admin'] // 完全权限
751
+ });
752
+
753
+ // 前端开发者尝试访问后端项目(会失败)
754
+ try {
755
+ await kms.createKey(backendTeam.projectId, masterPassword, {
756
+ keyName: 'test-key',
757
+ keyType: KeyType.CUSTOM,
758
+ value: 'test-value'
759
+ });
760
+ } catch (error) {
761
+ console.error('权限被拒绝');
762
+ }
763
+ ```
764
+
765
+ ## CLI 工具使用
766
+
767
+ ### 安装和启动
768
+
769
+ ```bash
770
+ # 全局安装
771
+ npm install -g @pengzi/kms
772
+
773
+ # 启动 CLI
774
+ kms
775
+ ```
776
+
777
+ ### 配置文件
778
+
779
+ 创建 `~/.kms/config.json`:
780
+
781
+ ```json
782
+ {
783
+ "connectionString": "mongodb://localhost:27017",
784
+ "databaseName": "kms"
785
+ }
786
+ ```
787
+
788
+ ### 常用命令
789
+
790
+ ```bash
791
+ # 创建项目
792
+ 选择: 1 (项目管理) → 1 (创建新项目)
793
+
794
+ # 创建密钥
795
+ 选择: 2 (密钥管理) → 1 (创建密钥)
796
+
797
+ # 获取密钥值
798
+ 选择: 2 (密钥管理) → 3 (获取密钥值)
799
+
800
+ # 查看审计日志
801
+ 选择: 4 (审计日志) → 1 (查看最近日志)
802
+ ```
803
+
804
+ 详细的 CLI 使用说明请查看:[CLI 工具指南](./docs/guides/cli-guide.md)
805
+
309
806
  ## 错误处理
310
807
 
311
808
  ```typescript
312
809
  import {
313
- KMSError,
314
- ProjectNotFoundError,
810
+ KMSClient,
315
811
  KeyNotFoundError,
316
812
  AuthenticationError,
317
813
  ForbiddenError,
318
- ValidationError
319
- } from '@your-org/kms';
814
+ ValidationError,
815
+ ProjectNotFoundError
816
+ } from '@pengzi/kms';
320
817
 
321
818
  try {
322
819
  const key = await kms.getKey(projectId, masterPassword, keyId);
323
820
  } catch (error) {
324
821
  if (error instanceof KeyNotFoundError) {
325
- console.error('Key not found');
822
+ console.error('密钥不存在');
326
823
  } else if (error instanceof AuthenticationError) {
327
- console.error('Invalid master password');
824
+ console.error('主密码错误或用户未认证');
328
825
  } else if (error instanceof ForbiddenError) {
329
- console.error('Permission denied');
826
+ console.error('权限不足');
827
+ } else if (error instanceof ValidationError) {
828
+ console.error('数据验证失败:', error.message);
829
+ } else if (error instanceof ProjectNotFoundError) {
830
+ console.error('项目不存在');
330
831
  } else {
331
- console.error('Error:', error.message);
832
+ console.error('未知错误:', error.message);
833
+ }
834
+ }
835
+ ```
836
+
837
+ ## 最佳实践
838
+
839
+ ### 1. 密钥命名规范
840
+
841
+ ```typescript
842
+ // 好的命名 ✅
843
+ const goodKeyNames = [
844
+ 'production-mongodb-primary',
845
+ 'staging-redis-cache',
846
+ 'dev-postgresql-analytics',
847
+ 'stripe-api-key'
848
+ ];
849
+
850
+ // 不好的命名 ❌
851
+ const badKeyNames = [
852
+ 'db', // 太模糊
853
+ 'key1', // 无意义
854
+ 'test', // 不明确
855
+ 'a' // 太短
856
+ ];
857
+ ```
858
+
859
+ ### 2. 标签使用
860
+
861
+ ```typescript
862
+ // 使用有意义的标签
863
+ await kms.createKey(projectId, masterPassword, {
864
+ keyName: 'mongodb-primary',
865
+ keyType: KeyType.MONGODB,
866
+ value: connectionString,
867
+ tags: [
868
+ 'production', // 环境
869
+ 'database', // 类型
870
+ 'mongodb', // 技术
871
+ 'primary', // 用途
872
+ 'critical' // 重要级别
873
+ ]
874
+ });
875
+ ```
876
+
877
+ ### 3. 主密码管理
878
+
879
+ ```typescript
880
+ // ❌ 不要硬编码主密码
881
+ const masterPassword = 'password123';
882
+
883
+ // ❌ 不要将主密码存储在代码仓库
884
+ const masterPassword = fs.readFileSync('password.txt');
885
+
886
+ // ✅ 使用环境变量
887
+ const masterPassword = process.env.MASTER_PASSWORD;
888
+
889
+ // ✅ 或使用密钥管理服务
890
+ const masterPassword = await getKeyFromVault();
891
+ ```
892
+
893
+ ### 4. 连接池配置
894
+
895
+ ```typescript
896
+ const kms = new KMSClient({
897
+ connectionString: 'mongodb://localhost:27017',
898
+ databaseName: 'kms',
899
+ connectionOptions: {
900
+ maxPoolSize: 50, // 最大连接数
901
+ minPoolSize: 10, // 最小连接数
902
+ connectTimeoutMS: 10000, // 连接超时
903
+ socketTimeoutMS: 30000, // Socket 超时
904
+ serverSelectionTimeoutMS: 5000 // 服务器选择超时
905
+ }
906
+ });
907
+ ```
908
+
909
+ ### 5. 错误处理和重试
910
+
911
+ ```typescript
912
+ async function getKeyWithRetry(
913
+ kms: KMSClient,
914
+ projectId: string,
915
+ masterPassword: string,
916
+ keyId: string,
917
+ maxRetries = 3
918
+ ) {
919
+ for (let i = 0; i < maxRetries; i++) {
920
+ try {
921
+ return await kms.getKey(projectId, masterPassword, keyId);
922
+ } catch (error) {
923
+ if (i === maxRetries - 1) throw error;
924
+
925
+ // 等待后重试
926
+ await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
927
+ }
928
+ }
929
+ }
930
+ ```
931
+
932
+ ## 性能优化
933
+
934
+ ### 1. 批量操作
935
+
936
+ ```typescript
937
+ // 批量创建密钥
938
+ const keysToCreate = [
939
+ { name: 'db1', type: KeyType.MONGODB, value: '...' },
940
+ { name: 'db2', type: KeyType.MONGODB, value: '...' },
941
+ { name: 'cache', type: KeyType.REDIS, value: '...' }
942
+ ];
943
+
944
+ const promises = keysToCreate.map(keyData =>
945
+ kms.createKey(projectId, masterPassword, keyData)
946
+ );
947
+
948
+ const results = await Promise.all(promises);
949
+ ```
950
+
951
+ ### 2. 分页查询
952
+
953
+ ```typescript
954
+ // 使用分页减少内存使用
955
+ const pageSize = 100;
956
+ let page = 1;
957
+ let hasMore = true;
958
+
959
+ while (hasMore) {
960
+ const { keys, total } = await kms.listKeys(projectId, {}, {
961
+ page,
962
+ limit: pageSize
963
+ });
964
+
965
+ // 处理当前页的密钥
966
+ keys.forEach(key => {
967
+ // 处理密钥
968
+ });
969
+
970
+ // 检查是否还有更多数据
971
+ hasMore = page * pageSize < total;
972
+ page++;
973
+ }
974
+ ```
975
+
976
+ ### 3. 连接复用
977
+
978
+ ```typescript
979
+ // ❌ 不好的做法:每次操作都创建新连接
980
+ async function badExample() {
981
+ const kms1 = new KMSClient({ /* config */ });
982
+ await kms1.connect();
983
+ await kms1.createKey(...);
984
+ await kms1.disconnect();
985
+
986
+ const kms2 = new KMSClient({ /* config */ });
987
+ await kms2.connect();
988
+ await kms2.getKey(...);
989
+ await kms2.disconnect();
990
+ }
991
+
992
+ // ✅ 好的做法:复用连接
993
+ class KMSManager {
994
+ private client: KMSClient;
995
+
996
+ constructor() {
997
+ this.client = new KMSClient({ /* config */ });
998
+ }
999
+
1000
+ async init() {
1001
+ await this.client.connect();
1002
+ }
1003
+
1004
+ async createKey(...args: any[]) {
1005
+ return await this.client.createKey(...args);
1006
+ }
1007
+
1008
+ async destroy() {
1009
+ await this.client.disconnect();
1010
+ }
1011
+ }
1012
+ ```
1013
+
1014
+ ## 安全注意事项
1015
+
1016
+ ### 敏感信息处理
1017
+
1018
+ ```typescript
1019
+ // ❌ 不要在日志中记录密钥值
1020
+ console.log('密钥值:', keyValue.value);
1021
+
1022
+ // ❌ 不要在错误消息中暴露密钥值
1023
+ throw new Error(`密钥 ${keyValue.value} 创建失败`);
1024
+
1025
+ // ✅ 只记录必要信息
1026
+ console.log('密钥 ID:', key.keyId);
1027
+ console.log('密钥名称:', key.keyName);
1028
+ ```
1029
+
1030
+ ### 审计和监控
1031
+
1032
+ ```typescript
1033
+ // 定期检查审计日志
1034
+ async function securityAudit(kms: KMSClient, projectId: string) {
1035
+ const logs = await kms.getAuditLogs(projectId, {
1036
+ limit: 1000
1037
+ });
1038
+
1039
+ // 检查异常活动
1040
+ const suspiciousActivities = logs.logs.filter(log => {
1041
+ return !log.details.success ||
1042
+ log.action === 'PERMISSION_DENIED' ||
1043
+ log.action === 'LOGIN_FAILED';
1044
+ });
1045
+
1046
+ if (suspiciousActivities.length > 0) {
1047
+ console.warn('发现可疑活动:', suspiciousActivities);
1048
+ // 发送告警
1049
+ await sendAlert(suspiciousActivities);
332
1050
  }
333
1051
  }
334
1052
  ```
335
1053
 
336
1054
  ## 开发
337
1055
 
1056
+ ### 本地开发
1057
+
338
1058
  ```bash
1059
+ # 克隆项目
1060
+ git clone https://github.com/pengzi/kms.git
1061
+ cd kms
1062
+
339
1063
  # 安装依赖
340
1064
  npm install
341
1065
 
@@ -352,6 +1076,32 @@ npm run lint
352
1076
  npm run format
353
1077
  ```
354
1078
 
1079
+ ### 运行测试
1080
+
1081
+ ```bash
1082
+ # 单元测试
1083
+ npm test
1084
+
1085
+ # 测试覆盖率
1086
+ npm run test:coverage
1087
+
1088
+ # 集成测试
1089
+ cd test-kms
1090
+ node simple-test.js
1091
+ ```
1092
+
1093
+ ### 贡献指南
1094
+
1095
+ 我们欢迎所有形式的贡献!
1096
+
1097
+ 1. Fork 项目
1098
+ 2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
1099
+ 3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
1100
+ 4. 推送到分支 (`git push origin feature/AmazingFeature`)
1101
+ 5. 创建 Pull Request
1102
+
1103
+ 详细贡献指南请查看:[贡献指南](./docs/development/contributing.md)
1104
+
355
1105
  ## 项目结构
356
1106
 
357
1107
  ```
@@ -375,10 +1125,34 @@ kms/
375
1125
 
376
1126
  ## 许可证
377
1127
 
378
- MIT
1128
+ MIT License
1129
+
1130
+ Copyright (c) 2025 pzdemons
1131
+
1132
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
1133
+
1134
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
1135
+
1136
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
379
1137
 
380
1138
  ## 联系方式
381
1139
 
382
- - 作者:pzdemons
383
- - 问题反馈:[GitHub Issues](https://github.com/pzdemons/kms/issues)
384
- - 安全问题:security@pzdemons.com
1140
+ - **作者**: pzdemons
1141
+ - **包名**: @pengzi/kms
1142
+ - **GitHub**: [pengzi/kms](https://github.com/pengzi/kms)
1143
+ - **问题反馈**: [GitHub Issues](https://github.com/pengzi/kms/issues)
1144
+ - **安全问题**: 请通过私有渠道报告
1145
+
1146
+ ## 相关资源
1147
+
1148
+ - [完整文档](./docs/README.md)
1149
+ - [API 参考](./docs/api/reference.md)
1150
+ - [更新日志](./docs/about/changelog.md)
1151
+ - [测试报告](./docs/about/test-reports/)
1152
+
1153
+ ---
1154
+
1155
+ **当前版本**: v1.2.0
1156
+ **最后更新**: 2025-05-15
1157
+ **Node.js**: >= 18.0.0
1158
+ **MongoDB**: >= 4.4