Skip to content

sign-kms · 模块详解

本仓库 submodule:sign-kms/。本章引用的所有路径均为相对于该 submodule 根。

cmd/kms/

文件关键符号行号
main.gomain():flag→config→signet→wireApp→app.Run35, 76-126
wire.gowireApp() providers24-32

main() 详细顺序见 核心流程 · Server 启动

internal/conf/

文件关键 message
conf.protoBootstrap(8-13)、Server(55-66:network/addr/timeout/http_addr/web_dist_path/tls/https)、TLS(68-78)、Data(80-86)、HSM(51-53)、HSMProvider(39-49)、Observability(15-24,含 Metrics/Tracing/Logging 子 message 26-37)

make config 生成 conf.pb.go

internal/server/

文件关键符号行号
grpc.goNewGRPCServer、中间件链 recovery → signet → GrpcAuthMiddleware → auditRegisterKmsServiceServer23-56, 26-28, 54
grpc.gomTLS 配置(条件 Tls.Enable=true && CaFile 非空)44-51, 82
http.goNewHTTPServer、中间件 recovery → signet → loggingHttpAuthMiddlewareRegisterKmsManageServiceHTTPServerobs.RegisterRoutes45-98, 49-51, 56, 70, 73
http.go静态文件(嵌入式 + SPA fallback)22-43, 76-95

internal/service/

文件RPC 方法行号
kms_service.goGenerateKeypairGetPublicKeySignVerifyHealthCheck20-29 / 31-40 / 42-60 / 62-78 / 80
kms_manage_service.goSigninSignoutCurrentCreateNsGetAccessToken(共 14 个 RPC)26-47 / 49-59 / 61-67 / 69-86 / 88-102

完整 HTTP RPC 列表见 06-api · HTTP 端点

internal/biz/

kms_biz.go

来源:internal/biz/kms_biz.go

方法行号
NewKmsBiz42
partitionMu(per-partition mutex)51
resolveNamespace(缓存 + DB 查询)58
invalidateNamespace73
getSession(从分区 pool 借会话)79
getProviderContext105
CloseAllSessions118
PoolStatus123
GenerateKeyPair143
GenerateKeyPairForPartition161
Sign268
Verify320
GetPublicKey373

GenerateKeyPairForPartition 核心步骤(:161-264):

  • per-partition mutex 锁(:170-172
  • 重试最多 3 次,失败丢弃坏会话(:192-213
  • 公钥字节提取(:218)→ raw EC 点 → sha256finalId hex(:226-232
  • 设置 CKA_LABEL = CKA_ID = finalId:234-244
  • DB 落盘:algorithm=ECcurve=P-256、可选 tag:246-261

kms_manage_biz.go

来源:internal/biz/kms_manage_biz.go

方法行号
NewKmsManageBiz45
CreateNs(路由到 soft / hardware)54
createSoftNs69
createHardwareNs110
ListProviders206
GetAccessToken212
GetNamespaceInfo295
ListNamespaces323
CreateKey377
SyncKeys404
ListAccessTokens495
DisableAccessToken509
EnableAccessToken516
UpdateAccessTokenKeys541
ListKeys565
ValidateCredentials582

Token 签发关键步骤(GetAccessToken:251-279):

  • tokenID = "at_" + 12 位随机字母数字:254
  • 先写 AccessToken DB(DB 是权威),再签 JWT(:258-266
  • JWT claims 含 ID (JTI)SubjectIssuedAtExpiresAtPartitionID = ns.TokenLabelRoleKeys:270-279

其它

文件用途
biz.goProviderSetNewKmsBizNewObservableKmsBizNewKmsManageBiz
kms_observable.goObservableKmsBiz 包装 KmsBiz,叠加 OTEL 指标;KmsService 依赖此对象(NewObservableKmsBiz:30)

SKI 推导(extractRawECPoint / getPublicKeyBytes)在 kms_biz.go 内,单测见 ski_test.go

internal/data/

Repository 模式包装 Ent client。

Ent schema(internal/data/ent/schema/

文件实体行号
namespace.goNamespace(id / name / token_label / user_pin / so_pin / provider_id / description / 时间戳)18-51
keypair.goKeypair(id / tag / algorithm / curve / public_key / public_key_pem / key_type / status / namespace_id / metadata / 时间戳)30-75
user.goUser(username / password_hash / is_active / 时间戳)15-25
access_token.goAccessToken(id=JTI / subject / role / keys / status / namespace_id / expires_at / 时间戳)25-57

关键设计点:

  • Keypair.id 由服务器从公钥点 sha256 推导(keypair.go:18-23),既是主键也是 HSM CKA_LABEL/CKA_ID
  • AccessToken.keys 第 37-39 行注释明确:DB 是权威源,JWT 中的 keys 仅供参考;DB 修改可立即在下次请求生效(由 pkg/auth/grpc_auth.go:62-74 覆盖)。

初始化

文件用途
init_user.go首次启动管理员账号(读 DEFAULT_ADMIN_PWD env)

pkg/pkcs11/

文件关键符号行号
registry.goProviderInstanceProviderRegistryNewProviderRegistryregister14-26 / 60-64 / 68-92 / 102
session_pool.goSessionPoolPoolStatusNewSessionPoolDefaultPoolSize=5MaxPoolSize=30HealthCheckInterval=30s24-41 / 44-50 / 54-95 / 18-20

Borrow / Return / Discard / WarmupHandleCache 具体行号 [未核]。

pkg/auth/

文件关键符号行号
claims.goKMSClaimsRoleReadonlyRoleReadWriteRoleAdminroleOpsRoleAllows11-22 / 26-28 / 42-46 / 49
grpc_auth.goGrpcAuthMiddleware、token 解析、TokenStore.GetByJTI 覆盖 keys48 / 49-80 / 62-74
http_auth.goHttpAuthMiddleware、白名单 /api/v1/signin27 / 28-56
config.goCookieNameGetAuthSecret(未设置 panic)、DefaultExpiry=24hDefaultTokenExpiry=365dMaxTokenExpiry=730d15 / 38, 44 / 55 / 58 / 60

api/v1/

文件serviceRPC
kms.protoKmsService(行 7-13)GenerateKeypairGetPublicKeySignVerifyHealthCheck(行 8-12)
manage.protoKmsManageService(行 11-81)14 个 RPC(含 google.api.http 注解)

完整 HTTP 路径与请求类型见 06-api · HTTP 端点

p11client/

来源:p11client/

文件用途
kms_so.cPKCS#11 代理实现,定义完整函数表(69 个 C_* 函数)
grpc_client_helper.c / .hgRPC 客户端辅助
proto/kms.pb-c.c / .hprotobuf-c 生成
include/pkcs11.h / pkcs11t.h / pkcs11f.hPKCS#11 标准头
test_pkcs11.c / simulation_test.c / known_key_test.c测试

kms_so.c 定义了 PKCS#11 全套 69 个 C_* 函数。其中与 KMS 操作相关的为实质实现,按源码顺序:C_Initialize / C_Finalize / C_GetInfo / C_GetFunctionList / C_GetSlotList / C_GetSlotInfo / C_GetTokenInfo / C_GetMechanismList / C_GetMechanismInfo / C_InitToken / C_InitPIN / C_SetPIN / C_OpenSession / C_CloseSession / C_CloseAllSessions / C_GetSessionInfo / C_Login / C_Logout / C_GenerateKeyPair / C_GetPublicKey / C_SignInit / C_Sign / C_GetAttributeValue / C_SetAttributeValue / C_FindObjectsInit / C_FindObjects / C_FindObjectsFinal / C_VerifyInit / C_Verify。其余函数(加解密、摘要、Wrap/Unwrap、随机数等)为桩实现,返回 CKR_FUNCTION_NOT_SUPPORTED

环境变量(kms_so.c):

  • KMS_SO_DEBUG:39
  • SIGN_KMS_ENDPOINT:202

web/

框架React 19.2.0、React Router 7.10.1
样式Tailwind CSS 4.1.18(via @tailwindcss/vite
UIshadcn/ui(Radix + Tailwind)
构建rolldown-vite 7.2.5
Scripts(package.jsondevbuildlintpreviewui

scripts/

脚本用途
init-softhsm.sh创建 7 个测试 partition + EC P-256 密钥(见 03-quickstart

docs/

来源:docs/ 目录。

  • design-multi-hsm-provider.md — HSM Provider 层多后端支持设计
  • design-p11client-v2.md — PKCS#11 代理库设计
  • grafana/sign-kms-overview.json — Grafana 仪表板定义

具体设计文档内容 [未核]。

看代码推荐路径

  1. cmd/kms/main.gowire.go 了解依赖链。
  2. internal/server/grpc.go + http.go → 看中间件链与服务注册。
  3. 任选一个端到端:internal/service/kms_service.go:Signinternal/biz/kms_biz.go:Sign(268)getSession(79)pkg/pkcs11/session_pool.go:Borrow
  4. 管理面:internal/service/kms_manage_service.go:GetAccessTokeninternal/biz/kms_manage_biz.go:GetAccessToken(212)
  5. pkg/auth/grpc_auth.go:48-80 → 看 JWT 解析与 DB 覆盖。
  6. internal/data/ent/schema/*.go → DB 实体定义。
  7. p11client/kms_so.c → 想懂客户端 .so 时再读。