80 lines
3.1 KiB
TypeScript
80 lines
3.1 KiB
TypeScript
/**
|
||
* 密钥安全管理模块测试
|
||
* 验证:密钥必须来自环境变量,缺失时拒绝启动,绝不使用硬编码fallback
|
||
*/
|
||
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
||
|
||
describe("secrets - 密钥安全管理", () => {
|
||
const originalEnv = { ...process.env };
|
||
|
||
afterEach(() => {
|
||
// 恢复环境变量
|
||
process.env = { ...originalEnv };
|
||
});
|
||
|
||
it("所有必要密钥已配置时,validateSecrets应通过", async () => {
|
||
process.env.NAC_MYSQL_URL = "mysql://user:pass@host:3306/db";
|
||
process.env.NAC_MONGO_URL = "mongodb://user:pass@host:27017/db";
|
||
process.env.NAC_JWT_SECRET = "test-jwt-secret-at-least-32-chars-long";
|
||
|
||
const { validateSecrets } = await import("./secrets");
|
||
expect(() => validateSecrets()).not.toThrow();
|
||
});
|
||
|
||
it("NAC_MYSQL_URL缺失时,validateSecrets应抛出错误", async () => {
|
||
delete process.env.NAC_MYSQL_URL;
|
||
process.env.NAC_MONGO_URL = "mongodb://user:pass@host:27017/db";
|
||
process.env.NAC_JWT_SECRET = "test-jwt-secret-at-least-32-chars-long";
|
||
|
||
// 动态重新导入以绕过模块缓存
|
||
const mod = await import("./secrets?t=" + Date.now());
|
||
expect(() => mod.validateSecrets()).toThrow(/NAC_MYSQL_URL/);
|
||
});
|
||
|
||
it("NAC_MONGO_URL缺失时,validateSecrets应抛出错误", async () => {
|
||
process.env.NAC_MYSQL_URL = "mysql://user:pass@host:3306/db";
|
||
delete process.env.NAC_MONGO_URL;
|
||
process.env.NAC_JWT_SECRET = "test-jwt-secret-at-least-32-chars-long";
|
||
|
||
const mod = await import("./secrets?t=" + Date.now());
|
||
expect(() => mod.validateSecrets()).toThrow(/NAC_MONGO_URL/);
|
||
});
|
||
|
||
it("NAC_JWT_SECRET缺失时,validateSecrets应抛出错误", async () => {
|
||
process.env.NAC_MYSQL_URL = "mysql://user:pass@host:3306/db";
|
||
process.env.NAC_MONGO_URL = "mongodb://user:pass@host:27017/db";
|
||
delete process.env.NAC_JWT_SECRET;
|
||
|
||
const mod = await import("./secrets?t=" + Date.now());
|
||
expect(() => mod.validateSecrets()).toThrow(/NAC_JWT_SECRET/);
|
||
});
|
||
|
||
it("getNacMysqlUrl在密钥未配置时应抛出错误,而非返回硬编码值", async () => {
|
||
delete process.env.NAC_MYSQL_URL;
|
||
const mod = await import("./secrets?t=" + Date.now());
|
||
expect(() => mod.getNacMysqlUrl()).toThrow(/NAC_MYSQL_URL/);
|
||
});
|
||
|
||
it("getNacJwtSecret在密钥未配置时应抛出错误,而非返回硬编码值", async () => {
|
||
delete process.env.NAC_JWT_SECRET;
|
||
const mod = await import("./secrets?t=" + Date.now());
|
||
expect(() => mod.getNacJwtSecret()).toThrow(/NAC_JWT_SECRET/);
|
||
});
|
||
|
||
it("密钥值不应出现在错误消息中(防止密钥泄露)", async () => {
|
||
const secretValue = "super-secret-password-12345";
|
||
process.env.NAC_MYSQL_URL = `mysql://user:${secretValue}@host:3306/db`;
|
||
delete process.env.NAC_MONGO_URL;
|
||
process.env.NAC_JWT_SECRET = "test-secret";
|
||
|
||
const mod = await import("./secrets?t=" + Date.now());
|
||
try {
|
||
mod.validateSecrets();
|
||
} catch (e) {
|
||
const errorMsg = (e as Error).message;
|
||
// 错误消息中不应包含任何密钥值
|
||
expect(errorMsg).not.toContain(secretValue);
|
||
}
|
||
});
|
||
});
|