Files
qinglong/docs/operations/ql3-cluster-security-administration.md
T

131 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# QingLong 3.0 Cluster Security Administration
该命令是 Cluster Identity、API Credential 和 Security Audit 的短生命周期管理入口,不适用于 Edge/Standalone,也不会启动 HTTP listener。每次进程只执行一个命令,最多打开一个 admin PostgreSQL 连接,然后退出。
## 私有输入
准备一个仅当前操作者可访问的目录;command、assertion、keyset 和 pepper 必须使用规范绝对路径,私有文件不能向 group/world 开放。credential issue/rotate 还需要一个已存在的私有 delivery 目录,但目标文件必须不存在。
keyset 使用既有 generation/revocation 协议,例如:
```json
{
"schemaVersion": 1,
"generation": 1,
"issuer": "https://identity.example.test/",
"audience": "qinglong3-security-administration",
"keys": [
{
"alg": "EdDSA",
"crv": "Ed25519",
"kid": "REPLACE_WITH_KEY_ID",
"kty": "OKP",
"use": "sig",
"x": "REPLACE_WITH_ED25519_PUBLIC_JWK_X"
}
],
"revokedKids": [],
"assuranceMappings": [
{
"acr": "urn:example:mfa",
"assurance": "multi_factor",
"requiredAmr": ["pwd", "otp"]
},
{
"acr": "urn:example:hardware",
"assurance": "hardware",
"requiredAmr": ["hwk"]
}
],
"constraints": {
"maxAssertionBytes": 8192,
"maxLifetimeMs": 300000,
"maxAuthenticationAgeMs": 300000,
"clockSkewMs": 5000
}
}
```
JWT header 必须使用 `typ=ql3-security-administration+jwt`payload 的 issuer/audience 必须匹配 keyset,并包含 `ql3_purpose=security-administration`。只接受当前、未撤销的强认证 principal。其他管理面即使使用同一签名 key,也会因 type/purpose/audience 不同而被拒绝。
pepper 是现有 API credential digest authority 要求的 32-byte canonical base64url 值。它必须与已存 credential 的 pepper authority 一致,不要为了单次命令临时生成新值,也不要写入 command JSON。
## 精确命令
注册 Identity
```json
{
"schemaVersion": 1,
"operation": "identity.register",
"request": {
"mutationId": "123e4567-e89b-42d3-a456-426614174301",
"requestId": "security-identity-register-20260825-1",
"expectedCurrentVersion": 0,
"subject": { "type": "api_app", "id": "automation-client" }
}
}
```
`identity.enable``identity.disable` 使用相同 request shape,只需修改 operation、mutationId、requestId 和 expectedCurrentVersion。
签发 API Credential
```json
{
"schemaVersion": 1,
"operation": "credential.issue",
"request": {
"mutationId": "123e4567-e89b-42d3-a456-426614174302",
"requestId": "security-credential-issue-20260825-1",
"expectedCurrentVersion": 0,
"credentialId": "automation-primary",
"subject": { "type": "api_app", "id": "automation-client" },
"notBeforeAtMs": 1787596800000,
"expiresAtMs": 1787683200000
}
}
```
`credential.rotate` 使用同一完整 shape 和新的 mutationId`credential.revoke` 必须删除 `notBeforeAtMs``expiresAtMs`,且不提供 `--delivery`。所有 mutation 都必须携带当前版本 fence。
有界查询 Security Audit
```json
{
"schemaVersion": 1,
"operation": "audit.list",
"request": {
"limit": 25,
"filter": { "outcome": "allowed" }
}
}
```
limit 范围为 1200。可选 filter 只有 projectId、subject 和 outcome;翻页使用上一页的 exact `{occurredAtMs,eventId}` 作为 `before`,不支持 offset、自由文本或无界导出。
## 执行
生产默认要求 TLS hostname verification
```sh
export QL3_POSTGRES_ADMIN_URL='postgresql://ql3_admin:REDACTED@postgres.example.test:5432/qinglong'
export QL3_POSTGRES_ADMIN_TLS_SERVERNAME='postgres.example.test'
export QL3_POSTGRES_ADMIN_TLS_CA_FILE='/secure/qinglong3/postgres-ca.pem'
ql3-cluster-admin security \
--command=/secure/qinglong3/security-command.json \
--assertion=/secure/qinglong3/security-assertion.jwt \
--keyset=/secure/qinglong3/security-keyset.json \
--pepper=/secure/qinglong3/api-credential-pepper \
--delivery=/secure/qinglong3/delivery/new-api-credential.json
```
也可以直接调用同镜像内的 `ql3-security-admin`。测试环境只有同时设置 `QL3_POSTGRES_ADMIN_TLS_MODE=disable``QL3_POSTGRES_ADMIN_ALLOW_INSECURE=true` 才能关闭 TLS;生产禁止这样部署。
成功签发或轮换时,stdout 只包含 delivery 文件名和 SHA-256。token 只存在于新建的 `0600` delivery 文件。目标已存在时命令失败且绝不覆盖。精确重放返回 `status=existing` 且不重新发布 token;如果首次响应丢失,先检查原 delivery 文件,确实丢失时使用新的 mutationId 执行 rotate,不能尝试恢复旧 token。
## 当前边界
本入口没有远程 API/UI、双人复核或 break-glass、pepper rotation、audit retention/export/alert,也没有默认安装的 Kubernetes Job。生产部署应把它放在受控工作站或自行审查的一次性 Job 中,并确保 admin database credential 不进入常驻 Cluster Control。完整安全决策见 [ADR-0500](../adr/ADR-0500-short-lived-cluster-security-administration-command.md)。