feat(iam): 完整实现 iam 身份认证与权限服务

包含 jwt/jwks/audit/grpc、rbac、cache、redis/kafka 配置等完整实现
This commit is contained in:
SpecialX
2026-07-10 19:09:39 +08:00
parent 06e0f9139b
commit a35e759d64
32 changed files with 2589 additions and 778 deletions

View File

@@ -0,0 +1,54 @@
import { readFileSync } from "node:fs";
import { env } from "./env.js";
/**
* JWT RS256 密钥对加载president §2.15:本地文件密钥)。
*
* - 私钥IAM 签发 access_token / refresh_token
* - 公钥api-gateway 通过 JWKS 或 gRPC GetPublicKey 拉取验签
*
* 启动时一次性加载到内存,避免每次签名/验签的 IO 开销。
* kidKey ID用于 JWKS 端点多密钥轮换场景下标识密钥。
*/
export interface JwtKeyPair {
privateKey: string;
publicKey: string;
kid: string;
alg: "RS256";
}
let keyPair: JwtKeyPair | null = null;
export function getJwtKeyPair(): JwtKeyPair {
if (!keyPair) {
const privateKey = readFileSync(env.IAM_PRIVATE_KEY_PATH, "utf-8");
const publicKey = readFileSync(env.IAM_PUBLIC_KEY_PATH, "utf-8");
keyPair = {
privateKey,
publicKey,
kid: env.JWT_KEY_ID,
alg: "RS256",
};
}
return keyPair;
}
/**
* TTL 计算:将 "15m" / "7d" 等字符串转为秒数。
* 用于 JWT expiresIn 配置与响应中的 expires_in 字段。
*/
export function ttlToSeconds(ttl: string): number {
const match = /^(\d+)([smhd])$/.exec(ttl);
if (!match || match[1] === undefined || match[2] === undefined) {
throw new Error(`Invalid TTL format: ${ttl}`);
}
const value = Number.parseInt(match[1], 10);
const unit = match[2] as "s" | "m" | "h" | "d";
const multipliers: Record<"s" | "m" | "h" | "d", number> = {
s: 1,
m: 60,
h: 3600,
d: 86400,
};
return value * multipliers[unit];
}