Files
qinglong/docs/operations/ql3-local-identity-credential.md
T

246 lines
8.6 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.
# `ql3-identity` 本机 Identity/Credential 管理
`ql3-identity` 是一次命令、一次进程的 Owner-only 管理入口。它不启动管理服务,也不把
credential token 写入 argv、stdout、stderr、command JSON 或 SQLite。
## 前置条件
- 已完成 Fresh Setup,当前 credential 属于 `default` Project 的 active Owner
- deployment root、其子目录、SQLite、Owner credential presentation 与 command
file 均由当前 real/effective UID 拥有;
- 目录权限为 `0700`,文件权限为 `0600`
- Owner pepper keyring 中存在与 SQLite active pepper 完全匹配的材料;
- managed credential delivery 使用独立、规范化、非 symlink 的 `0700` 目录。
## 实例 Authority Project
Identity 与 API credential 是实例级对象,不属于任意单个业务 Project。
`ql3-identity` 只接受实例 authority Project 的当前 Owner
- 新部署以全库最早成功消费的 Owner bootstrap challenge 所属 Project 为 authority
- 没有任何 consumed bootstrap challenge 的旧库兼容回退到迁移内建的 `default`
- 后续给其他 Project 授予 Owner 不会转移该 authority
- secondary Project Owner 使用自己的 `projectId` 调用时,返回统一 authorization
error,并记录 `instance_authority_project_required`
- 当前没有 authority Project 转移命令,不要通过直接编辑数据库模拟转移。
command 中的 `projectId` 必须填写该 authority Project。它会在服务授权和最终 SQLite
事务各验证一次;直接调用 repository 不能绕过。
所有示例中的 UUID、subject 和路径都必须替换。command file 创建完成后执行:
```sh
ql3-identity run --command-file /srv/qinglong3/commands/identity.json
```
## 查询当前版本
后续 mutation 所需的 `expectedCurrentVersion` 必须通过受支持的 inspect 命令取得,
不要直接查询 SQLite。Identity 精确查询示例:
```json
{
"schemaVersion": 1,
"operation": "identity.inspect",
"options": {
"deploymentRoot": "/srv/qinglong3",
"databasePath": "/srv/qinglong3/qinglong3.sqlite",
"profile": "edge",
"ownerPepperKeyringDirectory": "/srv/qinglong3/owner-keys",
"credentialFilePath": "/srv/qinglong3/owner-credential.json"
},
"request": {
"projectId": "default",
"target": { "type": "agent", "id": "agent-planner" },
"requestId": "identity-inspect-agent-planner",
"auditEventId": "10111111-1111-4111-8111-111111111111"
}
}
```
Credential 精确查询把 operation 改为 `credential.inspect`request 改为:
```json
{
"projectId": "default",
"credentialId": "agent-planner-primary",
"requestId": "credential-inspect-agent-planner",
"auditEventId": "10222222-2222-4222-8222-222222222222"
}
```
成功命中只返回 subject、status/state、version 和时间窗;不存在返回:
```json
{
"schemaVersion": 1,
"operation": "credential.inspect",
"projectId": "default",
"found": false
}
```
`found:false` 只会在 Owner authorization 与事务内 credential/Project/RoleBinding
围栏全部通过后返回。输出不会包含 secret digest、pepper key ID、token、数据库路径
或交付路径。每次人工查询使用新的 `auditEventId`inspect 不是 mutation,也不使用
`mutationId``failureAuditEventId``expectedCurrentVersion`
## 注册 Identity
```json
{
"schemaVersion": 1,
"operation": "identity.register",
"options": {
"deploymentRoot": "/srv/qinglong3",
"databasePath": "/srv/qinglong3/qinglong3.sqlite",
"profile": "edge",
"ownerPepperKeyringDirectory": "/srv/qinglong3/owner-keys",
"credentialFilePath": "/srv/qinglong3/owner-credential.json"
},
"request": {
"projectId": "default",
"target": { "type": "agent", "id": "agent-planner" },
"expectedCurrentVersion": 0,
"mutationId": "11111111-1111-4111-8111-111111111111",
"requestId": "identity-register-agent-planner",
"failureAuditEventId": "11111111-1111-4111-8111-111111111112"
}
}
```
`identity.enable``identity.disable` 使用相同结构,并把
`expectedCurrentVersion` 设为当前 Identity version。仍有 active Owner binding 的
User Identity 不能被禁用。
## 签发或轮换 Credential
```json
{
"schemaVersion": 1,
"operation": "credential.issue",
"options": {
"deploymentRoot": "/srv/qinglong3",
"databasePath": "/srv/qinglong3/qinglong3.sqlite",
"profile": "edge",
"ownerPepperKeyringDirectory": "/srv/qinglong3/owner-keys",
"credentialFilePath": "/srv/qinglong3/owner-credential.json",
"credentialDeliveryDirectory": "/srv/qinglong3/managed-credentials"
},
"request": {
"projectId": "default",
"target": { "type": "agent", "id": "agent-planner" },
"credentialId": "agent-planner-primary",
"expectedCurrentVersion": 0,
"lifetimeMs": 86400000,
"mutationId": "22222222-2222-4222-8222-222222222221",
"requestId": "credential-issue-agent-planner",
"failureAuditEventId": "22222222-2222-4222-8222-222222222222"
}
}
```
轮换时把 operation 改为 `credential.rotate`,并使用当前 credential version。
`lifetimeMs` 范围为 60 秒至两年。
成功输出示例:
```json
{
"schemaVersion": 1,
"operation": "credential.issue",
"status": "inserted",
"projectId": "default",
"target": { "type": "agent", "id": "agent-planner" },
"credentialId": "agent-planner-primary",
"version": 1,
"state": "active",
"expiresAtMs": 1780000000000,
"delivery": {
"fileName": "managed-credential-22222222-2222-4222-8222-222222222221.ready.json",
"digest": "64-char-lowercase-sha256"
}
}
```
输出没有绝对路径和 token。ready 文件位于 command 指定的 delivery directory
权限为 `0600`,其 JSON 可以直接作为后续 `credentialFilePath`。如果 CLI 在 commit
后中断,必须原样重放同一个 command;不要更换 mutation、request、target、version
或 lifetime。
## 确认交付
consumer 已复制、安装并真实验证 ready credential 后,提交确认:
```json
{
"schemaVersion": 1,
"operation": "credential.delivery.acknowledge",
"options": {
"deploymentRoot": "/srv/qinglong3",
"databasePath": "/srv/qinglong3/qinglong3.sqlite",
"profile": "edge",
"ownerPepperKeyringDirectory": "/srv/qinglong3/owner-keys",
"credentialFilePath": "/srv/qinglong3/owner-credential.json",
"credentialDeliveryDirectory": "/srv/qinglong3/managed-credentials"
},
"request": {
"projectId": "default",
"credentialMutationId": "22222222-2222-4222-8222-222222222221",
"expectedDeliveryDigest": "replace-with-issue-output-digest",
"mutationId": "33333333-3333-4333-8333-333333333331",
"requestId": "credential-delivery-ack-agent-planner",
"failureAuditEventId": "33333333-3333-4333-8333-333333333332"
}
}
```
数据库 acknowledgement 先提交,随后 pending/ready 文件才删除。响应丢失时原样
重放;`cleanup:"absent"` 表示数据库已经确认且文件已在前一次执行中安全删除。
不要在 consumer 尚未验证前 acknowledge,也不要把唯一正在用于本命令认证的
credential presentation 提前删除。
## 撤销 Credential
`credential.revoke` 不需要 delivery directory 或 lifetime
```json
{
"schemaVersion": 1,
"operation": "credential.revoke",
"options": {
"deploymentRoot": "/srv/qinglong3",
"databasePath": "/srv/qinglong3/qinglong3.sqlite",
"profile": "edge",
"ownerPepperKeyringDirectory": "/srv/qinglong3/owner-keys",
"credentialFilePath": "/srv/qinglong3/owner-credential.json"
},
"request": {
"projectId": "default",
"target": { "type": "agent", "id": "agent-planner" },
"credentialId": "agent-planner-primary",
"expectedCurrentVersion": 1,
"mutationId": "44444444-4444-4444-8444-444444444441",
"requestId": "credential-revoke-agent-planner",
"failureAuditEventId": "44444444-4444-4444-8444-444444444442"
}
}
```
撤销 Owner 当前使用的 credential 前,必须先签发并验证另一把有效 credential。
数据库会拒绝撤销 active Owner 的最后一把凭据。
## 运维规则
- 先使用 exact inspect 取得当前 version,再创建 mutation command;不要把数据库表当作
产品 API
- command file 是不可变 mutation 载体;响应不确定时只允许原样重放;
- 不编辑 pending/ready 文件,不按 mtime 自动清理;
- `mutation_conflict` 表示相同 mutation ID 已用于不同语义,必须人工调查;
- `owner_continuity_required` 表示操作会造成 Owner 无法接管;
- `credential_or_policy_fence_rejected` 表示认证后 authority 已变化,应重新认证并使用
新 mutation
- managed delivery 上限是 64 个条目;长期未确认项需要人工核对,不得用通用目录
GC 删除。