@pengzi/kms 1.1.0 → 1.1.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.
Files changed (71) hide show
  1. package/README.md +39 -3
  2. package/dist/cli/cli/kms.js +1050 -0
  3. package/dist/cli/kms.js +1050 -0
  4. package/dist/cli/src/client.js +254 -0
  5. package/dist/cli/src/core/asymmetric-crypto.js +170 -0
  6. package/dist/cli/src/core/crypto.js +99 -0
  7. package/dist/cli/src/core/crypto.service.js +66 -0
  8. package/dist/cli/src/core/key-derivation.js +95 -0
  9. package/dist/cli/src/index.js +50 -0
  10. package/dist/cli/src/models/audit.model.js +82 -0
  11. package/dist/cli/src/models/key.model.js +119 -0
  12. package/dist/cli/src/models/project.model.js +53 -0
  13. package/dist/cli/src/models/user.model.js +140 -0
  14. package/dist/cli/src/repositories/audit.repository.js +115 -0
  15. package/dist/cli/src/repositories/base.repository.js +94 -0
  16. package/dist/cli/src/repositories/key.repository.js +125 -0
  17. package/dist/cli/src/repositories/project.repository.js +81 -0
  18. package/dist/cli/src/repositories/user.repository.js +101 -0
  19. package/dist/cli/src/services/audit.service.js +111 -0
  20. package/dist/cli/src/services/auth.service.js +176 -0
  21. package/dist/cli/src/services/key.service.js +137 -0
  22. package/dist/cli/src/services/permission.service.js +142 -0
  23. package/dist/cli/src/services/project.service.js +102 -0
  24. package/dist/cli/src/types/audit.types.js +54 -0
  25. package/dist/cli/src/types/crypto.types.js +5 -0
  26. package/dist/cli/src/types/index.js +90 -0
  27. package/dist/cli/src/types/key.types.js +27 -0
  28. package/dist/cli/src/types/project.types.js +15 -0
  29. package/dist/cli/src/types/user.types.js +48 -0
  30. package/dist/cli/src/utils/config-loader.js +125 -0
  31. package/dist/cli/src/utils/constants.js +118 -0
  32. package/dist/cli/src/utils/error-handler.js +108 -0
  33. package/dist/client.d.ts.map +1 -1
  34. package/dist/client.js +2 -0
  35. package/dist/client.js.map +1 -1
  36. package/dist/models/key.model.js +1 -1
  37. package/dist/models/key.model.js.map +1 -1
  38. package/dist/services/key.service.d.ts +5 -0
  39. package/dist/services/key.service.d.ts.map +1 -1
  40. package/dist/services/key.service.js +12 -4
  41. package/dist/services/key.service.js.map +1 -1
  42. package/dist/src/client.js +254 -0
  43. package/dist/src/core/asymmetric-crypto.js +170 -0
  44. package/dist/src/core/crypto.js +99 -0
  45. package/dist/src/core/crypto.service.js +66 -0
  46. package/dist/src/core/key-derivation.js +95 -0
  47. package/dist/src/index.js +50 -0
  48. package/dist/src/models/audit.model.js +82 -0
  49. package/dist/src/models/key.model.js +119 -0
  50. package/dist/src/models/project.model.js +53 -0
  51. package/dist/src/models/user.model.js +140 -0
  52. package/dist/src/repositories/audit.repository.js +115 -0
  53. package/dist/src/repositories/base.repository.js +94 -0
  54. package/dist/src/repositories/key.repository.js +125 -0
  55. package/dist/src/repositories/project.repository.js +81 -0
  56. package/dist/src/repositories/user.repository.js +101 -0
  57. package/dist/src/services/audit.service.js +111 -0
  58. package/dist/src/services/auth.service.js +176 -0
  59. package/dist/src/services/key.service.js +137 -0
  60. package/dist/src/services/permission.service.js +142 -0
  61. package/dist/src/services/project.service.js +102 -0
  62. package/dist/src/types/audit.types.js +54 -0
  63. package/dist/src/types/crypto.types.js +5 -0
  64. package/dist/src/types/index.js +90 -0
  65. package/dist/src/types/key.types.js +27 -0
  66. package/dist/src/types/project.types.js +15 -0
  67. package/dist/src/types/user.types.js +48 -0
  68. package/dist/src/utils/config-loader.js +125 -0
  69. package/dist/src/utils/constants.js +118 -0
  70. package/dist/src/utils/error-handler.js +108 -0
  71. package/package.json +7 -2
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ /**
3
+ * 配置加载工具
4
+ * 用于从加密配置文件中加载连接字符串
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.loadEncryptedConfig = loadEncryptedConfig;
41
+ exports.loadConfigFromEnvironment = loadConfigFromEnvironment;
42
+ exports.createClientFromEncryptedConfig = createClientFromEncryptedConfig;
43
+ exports.readPrivateKeyFile = readPrivateKeyFile;
44
+ const fs = __importStar(require("fs"));
45
+ const path = __importStar(require("path"));
46
+ const asymmetric_crypto_1 = require("../core/asymmetric-crypto");
47
+ const asymmetric_crypto_2 = require("../core/asymmetric-crypto");
48
+ /**
49
+ * 从加密配置文件加载配置
50
+ * @param configPath 配置文件路径
51
+ * @param privateKeyPem 私钥(可选,默认从环境变量读取)
52
+ * @param passphrase 私钥密码(可选,默认从环境变量读取)
53
+ * @returns KMS 客户端配置
54
+ */
55
+ function loadEncryptedConfig(configPath, privateKeyPem, passphrase) {
56
+ // 读取配置文件
57
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
58
+ // 获取私钥
59
+ const finalPrivateKeyPem = privateKeyPem || process.env.KMS_PRIVATE_KEY;
60
+ if (!finalPrivateKeyPem) {
61
+ throw new Error('私钥未提供。请设置 KMS_PRIVATE_KEY 环境变量或传入 privateKeyPem 参数');
62
+ }
63
+ // 获取密码
64
+ const finalPassphrase = passphrase || (0, asymmetric_crypto_1.getPrivateKeyPassphrase)();
65
+ // 解密连接字符串
66
+ const connectionString = (0, asymmetric_crypto_2.parseEncryptedConnectionStringConfig)({ encryptedConnectionString: config.encryptedConnectionString }, finalPrivateKeyPem, finalPassphrase);
67
+ return {
68
+ connectionString,
69
+ databaseName: config.databaseName || 'kms',
70
+ connectionOptions: config.connectionOptions
71
+ };
72
+ }
73
+ /**
74
+ * 从环境变量和文件加载配置
75
+ * 优先级:加密配置文件 > 环境变量
76
+ * @returns KMS 客户端配置
77
+ */
78
+ function loadConfigFromEnvironment() {
79
+ const configPath = process.env.KMS_ENCRYPTED_CONFIG_PATH;
80
+ if (configPath && fs.existsSync(configPath)) {
81
+ return loadEncryptedConfig(configPath);
82
+ }
83
+ // 回退到环境变量
84
+ const connectionString = process.env.KMS_CONNECTION_STRING || process.env.MONGO_URL;
85
+ if (!connectionString) {
86
+ throw new Error('未找到连接字符串。请设置 KMS_ENCRYPTED_CONFIG_PATH 或 KMS_CONNECTION_STRING 环境变量');
87
+ }
88
+ return {
89
+ connectionString,
90
+ databaseName: process.env.KMS_DATABASE_NAME || 'kms',
91
+ connectionOptions: {
92
+ connectTimeoutMS: process.env.KMS_CONNECT_TIMEOUT
93
+ ? parseInt(process.env.KMS_CONNECT_TIMEOUT, 10)
94
+ : undefined,
95
+ socketTimeoutMS: process.env.KMS_SOCKET_TIMEOUT
96
+ ? parseInt(process.env.KMS_SOCKET_TIMEOUT, 10)
97
+ : undefined,
98
+ maxPoolSize: process.env.KMS_MAX_POOL_SIZE
99
+ ? parseInt(process.env.KMS_MAX_POOL_SIZE, 10)
100
+ : undefined
101
+ }
102
+ };
103
+ }
104
+ /**
105
+ * 创建 KMS 客户端(从加密配置)
106
+ * @param configPath 配置文件路径
107
+ * @param privateKeyPem 私钥(可选)
108
+ * @param passphrase 私钥密码(可选)
109
+ * @returns KMS 客户端选项
110
+ */
111
+ function createClientFromEncryptedConfig(configPath, privateKeyPem, passphrase) {
112
+ return loadEncryptedConfig(configPath, privateKeyPem, passphrase);
113
+ }
114
+ /**
115
+ * 读取私钥文件
116
+ * @param filePath 私钥文件路径
117
+ * @returns 私钥内容
118
+ */
119
+ function readPrivateKeyFile(filePath) {
120
+ const absolutePath = path.resolve(filePath);
121
+ if (!fs.existsSync(absolutePath)) {
122
+ throw new Error(`私钥文件不存在: ${absolutePath}`);
123
+ }
124
+ return fs.readFileSync(absolutePath, 'utf-8');
125
+ }
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ /**
3
+ * 系统常量定义
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.COLLECTIONS = exports.KEY_TYPES = exports.ROLE_PERMISSIONS = exports.SECURITY_CONFIG = void 0;
7
+ exports.generateId = generateId;
8
+ exports.validatePasswordStrength = validatePasswordStrength;
9
+ const types_1 = require("../types");
10
+ /**
11
+ * 安全配置常量
12
+ */
13
+ exports.SECURITY_CONFIG = {
14
+ // 密钥派生配置
15
+ KEY_DERIVATION: {
16
+ ALGORITHM: 'pbkdf2',
17
+ ITERATIONS: 100000,
18
+ KEY_LENGTH: 32, // 256 bits
19
+ DIGEST: 'sha256',
20
+ },
21
+ // 加密配置
22
+ ENCRYPTION: {
23
+ ALGORITHM: 'aes-256-gcm',
24
+ KEY_LENGTH: 32, // 256 bits
25
+ IV_LENGTH: 16, // 128 bits
26
+ AUTH_TAG_LENGTH: 16, // 128 bits
27
+ },
28
+ // 密码策略
29
+ PASSWORD_POLICY: {
30
+ MIN_LENGTH: 12,
31
+ REQUIRE_UPPERCASE: true,
32
+ REQUIRE_LOWERCASE: true,
33
+ REQUIRE_NUMBERS: true,
34
+ REQUIRE_SPECIAL_CHARS: true,
35
+ },
36
+ // 速率限制
37
+ RATE_LIMITING: {
38
+ WINDOW_MS: 15 * 60 * 1000, // 15分钟
39
+ MAX_REQUESTS: 100,
40
+ },
41
+ // API密钥长度
42
+ API_KEY_LENGTH: 64,
43
+ };
44
+ /**
45
+ * 角色-权限映射
46
+ */
47
+ exports.ROLE_PERMISSIONS = {
48
+ [types_1.Role.ADMIN]: [
49
+ types_1.Permission.PROJECT_CREATE,
50
+ types_1.Permission.PROJECT_UPDATE,
51
+ types_1.Permission.PROJECT_DELETE,
52
+ types_1.Permission.KEY_CREATE,
53
+ types_1.Permission.KEY_READ,
54
+ types_1.Permission.KEY_UPDATE,
55
+ types_1.Permission.KEY_DELETE,
56
+ types_1.Permission.KEY_LIST,
57
+ types_1.Permission.USER_CREATE,
58
+ types_1.Permission.USER_UPDATE,
59
+ types_1.Permission.USER_DELETE,
60
+ types_1.Permission.AUDIT_READ,
61
+ ],
62
+ [types_1.Role.OPERATOR]: [
63
+ types_1.Permission.KEY_READ,
64
+ types_1.Permission.KEY_UPDATE,
65
+ types_1.Permission.KEY_LIST,
66
+ types_1.Permission.AUDIT_READ,
67
+ ],
68
+ [types_1.Role.DEVELOPER]: [types_1.Permission.KEY_READ, types_1.Permission.KEY_LIST],
69
+ [types_1.Role.READONLY]: [types_1.Permission.KEY_LIST],
70
+ [types_1.Role.AUDITOR]: [types_1.Permission.AUDIT_READ],
71
+ };
72
+ /**
73
+ * 密钥类型列表
74
+ */
75
+ exports.KEY_TYPES = ['mongodb', 'mysql', 'postgresql', 'redis', 'custom'];
76
+ /**
77
+ * 集合名称
78
+ */
79
+ exports.COLLECTIONS = {
80
+ PROJECTS: 'projects',
81
+ KEYS: 'keys',
82
+ USERS: 'users',
83
+ AUDIT_LOGS: 'audit_logs',
84
+ };
85
+ /**
86
+ * ID生成器
87
+ */
88
+ function generateId(prefix) {
89
+ const timestamp = Date.now().toString(36);
90
+ const random = Math.random().toString(36).substring(2, 11);
91
+ return `${prefix}_${timestamp}${random}`;
92
+ }
93
+ /**
94
+ * 密码强度验证
95
+ */
96
+ function validatePasswordStrength(password) {
97
+ const errors = [];
98
+ const policy = exports.SECURITY_CONFIG.PASSWORD_POLICY;
99
+ if (password.length < policy.MIN_LENGTH) {
100
+ errors.push(`Password must be at least ${policy.MIN_LENGTH} characters long`);
101
+ }
102
+ if (policy.REQUIRE_UPPERCASE && !/[A-Z]/.test(password)) {
103
+ errors.push('Password must contain at least one uppercase letter');
104
+ }
105
+ if (policy.REQUIRE_LOWERCASE && !/[a-z]/.test(password)) {
106
+ errors.push('Password must contain at least one lowercase letter');
107
+ }
108
+ if (policy.REQUIRE_NUMBERS && !/\d/.test(password)) {
109
+ errors.push('Password must contain at least one number');
110
+ }
111
+ if (policy.REQUIRE_SPECIAL_CHARS && !/[!@#$%^&*(),.?":{}|<>]/.test(password)) {
112
+ errors.push('Password must contain at least one special character');
113
+ }
114
+ return {
115
+ valid: errors.length === 0,
116
+ errors,
117
+ };
118
+ }
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ /**
3
+ * 错误处理工具
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ErrorCode = void 0;
7
+ exports.createKMSError = createKMSError;
8
+ exports.asyncError = asyncError;
9
+ exports.formatErrorMessage = formatErrorMessage;
10
+ const types_1 = require("../types");
11
+ /**
12
+ * 错误代码枚举
13
+ */
14
+ var ErrorCode;
15
+ (function (ErrorCode) {
16
+ // 项目错误 (1xxx)
17
+ ErrorCode["PROJECT_NOT_FOUND"] = "PROJECT_NOT_FOUND";
18
+ ErrorCode["PROJECT_ALREADY_EXISTS"] = "PROJECT_ALREADY_EXISTS";
19
+ ErrorCode["PROJECT_SUSPENDED"] = "PROJECT_SUSPENDED";
20
+ // 密钥错误 (2xxx)
21
+ ErrorCode["KEY_NOT_FOUND"] = "KEY_NOT_FOUND";
22
+ ErrorCode["KEY_ALREADY_EXISTS"] = "KEY_ALREADY_EXISTS";
23
+ ErrorCode["KEY_EXPIRED"] = "KEY_EXPIRED";
24
+ ErrorCode["KEY_DISABLED"] = "KEY_DISABLED";
25
+ // 用户错误 (3xxx)
26
+ ErrorCode["USER_NOT_FOUND"] = "USER_NOT_FOUND";
27
+ ErrorCode["USER_ALREADY_EXISTS"] = "USER_ALREADY_EXISTS";
28
+ ErrorCode["USER_LOCKED"] = "USER_LOCKED";
29
+ // 认证错误 (4xxx)
30
+ ErrorCode["AUTHENTICATION_FAILED"] = "AUTHENTICATION_FAILED";
31
+ ErrorCode["INVALID_PASSWORD"] = "INVALID_PASSWORD";
32
+ ErrorCode["INVALID_API_KEY"] = "INVALID_API_KEY";
33
+ // 权限错误 (5xxx)
34
+ ErrorCode["PERMISSION_DENIED"] = "PERMISSION_DENIED";
35
+ ErrorCode["INSUFFICIENT_PERMISSIONS"] = "INSUFFICIENT_PERMISSIONS";
36
+ // 验证错误 (6xxx)
37
+ ErrorCode["VALIDATION_ERROR"] = "VALIDATION_ERROR";
38
+ ErrorCode["INVALID_INPUT"] = "INVALID_INPUT";
39
+ ErrorCode["MISSING_REQUIRED_FIELD"] = "MISSING_REQUIRED_FIELD";
40
+ // 加密错误 (7xxx)
41
+ ErrorCode["CRYPTO_ERROR"] = "CRYPTO_ERROR";
42
+ ErrorCode["ENCRYPTION_FAILED"] = "ENCRYPTION_FAILED";
43
+ ErrorCode["DECRYPTION_FAILED"] = "DECRYPTION_FAILED";
44
+ // 数据库错误 (8xxx)
45
+ ErrorCode["DATABASE_ERROR"] = "DATABASE_ERROR";
46
+ ErrorCode["CONNECTION_FAILED"] = "CONNECTION_FAILED";
47
+ // 通用错误 (9xxx)
48
+ ErrorCode["INTERNAL_ERROR"] = "INTERNAL_ERROR";
49
+ ErrorCode["NOT_IMPLEMENTED"] = "NOT_IMPLEMENTED";
50
+ })(ErrorCode || (exports.ErrorCode = ErrorCode = {}));
51
+ /**
52
+ * 创建KMS错误
53
+ */
54
+ function createKMSError(code, message) {
55
+ const messages = {
56
+ [ErrorCode.PROJECT_NOT_FOUND]: 'Project not found',
57
+ [ErrorCode.PROJECT_ALREADY_EXISTS]: 'Project already exists',
58
+ [ErrorCode.PROJECT_SUSPENDED]: 'Project is suspended',
59
+ [ErrorCode.KEY_NOT_FOUND]: 'Key not found',
60
+ [ErrorCode.KEY_ALREADY_EXISTS]: 'Key already exists',
61
+ [ErrorCode.KEY_EXPIRED]: 'Key has expired',
62
+ [ErrorCode.KEY_DISABLED]: 'Key is disabled',
63
+ [ErrorCode.USER_NOT_FOUND]: 'User not found',
64
+ [ErrorCode.USER_ALREADY_EXISTS]: 'User already exists',
65
+ [ErrorCode.USER_LOCKED]: 'User account is locked',
66
+ [ErrorCode.AUTHENTICATION_FAILED]: 'Authentication failed',
67
+ [ErrorCode.INVALID_PASSWORD]: 'Invalid password',
68
+ [ErrorCode.INVALID_API_KEY]: 'Invalid API key',
69
+ [ErrorCode.PERMISSION_DENIED]: 'Permission denied',
70
+ [ErrorCode.INSUFFICIENT_PERMISSIONS]: 'Insufficient permissions',
71
+ [ErrorCode.VALIDATION_ERROR]: 'Validation error',
72
+ [ErrorCode.INVALID_INPUT]: 'Invalid input',
73
+ [ErrorCode.MISSING_REQUIRED_FIELD]: 'Missing required field',
74
+ [ErrorCode.CRYPTO_ERROR]: 'Cryptographic error',
75
+ [ErrorCode.ENCRYPTION_FAILED]: 'Encryption failed',
76
+ [ErrorCode.DECRYPTION_FAILED]: 'Decryption failed',
77
+ [ErrorCode.DATABASE_ERROR]: 'Database error',
78
+ [ErrorCode.CONNECTION_FAILED]: 'Connection failed',
79
+ [ErrorCode.INTERNAL_ERROR]: 'Internal error',
80
+ [ErrorCode.NOT_IMPLEMENTED]: 'Not implemented',
81
+ };
82
+ return new types_1.KMSError(message || messages[code], code);
83
+ }
84
+ /**
85
+ * 包装异步错误
86
+ */
87
+ function asyncError(fn) {
88
+ return (async (...args) => {
89
+ try {
90
+ return await fn(...args);
91
+ }
92
+ catch (error) {
93
+ if (error instanceof types_1.KMSError) {
94
+ throw error;
95
+ }
96
+ throw createKMSError(ErrorCode.INTERNAL_ERROR, error instanceof Error ? error.message : 'Unknown error');
97
+ }
98
+ });
99
+ }
100
+ /**
101
+ * 格式化错误消息
102
+ */
103
+ function formatErrorMessage(error) {
104
+ if (error instanceof types_1.KMSError) {
105
+ return `[${error.code}] ${error.message}`;
106
+ }
107
+ return error.message;
108
+ }
package/package.json CHANGED
@@ -1,16 +1,21 @@
1
1
  {
2
2
  "name": "@pengzi/kms",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "High-security Key Management System for Node.js applications",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "kms": "./dist/cli/kms.js",
9
+ "kms-cli": "./dist/cli/kms.js"
10
+ },
7
11
  "scripts": {
8
12
  "build": "tsc",
13
+ "build:cli": "tsc cli/kms.ts --outDir dist --module commonjs --target es2020 --moduleResolution node --esModuleInterop --rootDir .",
9
14
  "test": "jest",
10
15
  "test:coverage": "jest --coverage",
11
16
  "lint": "eslint src/**/*.ts",
12
17
  "format": "prettier --write src/**/*.ts",
13
- "prepublishOnly": "npm run build"
18
+ "prepublishOnly": "npm run build && npm run build:cli"
14
19
  },
15
20
  "keywords": [
16
21
  "kms",