概览 — 这个页面做什么
项目 是一个登记册,把团队运行的每个项目的元数据集中到一处共享。对每个项目,您在这里登记它的源码仓库(GitHub 等)、CI/CD 流水线(Jenkins)、所使用的 Web 服务与数据库、备份对象,以及最关键的一项 —— 它的机密信息存放在哪里。这样团队中的任何人都能一眼回答:「这个项目由什么组成,部署到哪里,哪一份机密信息在什么位置?」
本页面 不是部署工具。 真正的构建与部署发生在 Jenkins 中。InfraGuard 不会从这里触发任何流水线;所登记的数据是 共享文档。您保存的 URL、Job 名称与分支仅仅是参考链接与标签 —— 不会被执行。
核心设计原则:
- 绝不内联保存机密信息的值。 密码、令牌与密钥的 实际值 不会保存在这里。取而代之的是,您要么 (1) 引用 清单保管库(
infr_vault_key)中的一把密钥,要么 (2) 只在 打码的核对清单 中记录「哪一份机密信息在什么位置」。 - 所有内容都在 一个带标签页的模态框 中编辑(概览・源码・CI/CD・关联・备份・机密)。
- 创建/更新/删除以及保管库取值查看,全部写入 审计日志(
infr_audit_log)。
何时使用
- 新同事加入时,需要迅速搞清「这个项目的仓库、部署 URL 和数据库是什么?」
- 梳理每个项目的 web/db 依赖关系,以便在故障期间立刻估量影响范围。
- 记录项目所依赖的 机密信息地图(哪把密钥在哪里,哪一条保管库条目属于本项目)。
- 把备份对象与频率作为项目元数据记录下来,与您的备份策略对应起来。
页面构成
KPI 条
| 单元 | 含义 |
|---|---|
| 项目 | 已登记项目总数 |
| 对外 | accessible=1 的项目(具有对外 URL) |
| 内部 | accessible=0 的项目(仅限内部,不对外暴露) |
| 已归档 | status=archived 的项目 |
项目卡片
每张卡片显示:
- 图标与名称 — 可从外部访问的项目使用
mdi-web;仅限内部的使用mdi-folder-lock-outline。 - URL 链接 — 若
accessible且存在 URL,则显示在新标签页中打开的链接;否则显示internal徽标。 - 状态徽标 — active/paused/archived。
- 一行摘要。
- 构成标签片 — 只显示已登记的元素: 源码・Jenkins・环境 N・Web N・数据库 N・备份 N・机密 N。
- 分组标签(类别)以及编辑/删除按钮(当您具备写入权限时)。
编辑模态框(6 个标签页)
这是一个宽模态框(.infr-modal__panel--wide),按标签页拆分输入项。
| 标签页 | 输入项 |
|---|---|
| 概览 | 名称(必填)・键(slug)・状态・分组・对外访问开关・URL・摘要・标签 |
| 源码 | 仓库提供方(GitHub/GitLab/Gitea/Bitbucket/其他)・仓库 URL・默认分支・可见性(public/private/internal) |
| CI/CD | Jenkins URL + 环境重复行(按 dev/staging/prod 分别填写: 部署 URL・分支・Jenkins Job・备注) |
| 关联 | Web 服务 复选框(已登记的 infr_web_service)+ 数据库(采集器) 复选框(access=database 的采集器) |
| 备份 | 备份对象重复行(种类・对象・计划・备注) |
| 机密 | 保管库密钥引用(勾选并查看取值)+ 机密核对清单重复行(条目・位置・引用・备注) |
使用方法
登记一个项目
- 点击右上角的 [添加项目](需要写入权限)。
- 在 概览 标签页填写名称(必填)。键(slug)为可选,且必须匹配
^[a-z0-9_-]+$(例如coin-market)。 - 若该服务可从外部访问,请打开 可从外部访问 开关并填写其 URL。若仅限内部,保持关闭即可,此时 URL 输入框会被禁用。
- 按需填写其余标签页(源码、CI/CD、关联、备份、机密)—— 全部为可选。
- [保存] —— 服务端进行校验,向
infr_project执行 upsert,并刷新卡片。
登记 CI/CD 环境
在 CI/CD 标签页填写 Jenkins URL,然后用 [添加环境] 逐行添加部署目标:
{
"env": "prod",
"url": "https://coin.example.com",
"branch": "main",
"jenkins_job": "coin_market-deploy-prod",
"note": "blue/green"
}
env只接受白名单dev/staging/prod(其他任何取值都会被服务端强制改为dev)。- 每个字符串字段都按长度截断(URL 255・分支 120・Job 191・备注 255)。
- 最多 20 个环境。
关联 web/db
在 关联 标签页勾选本项目所使用的资源。
- Web 服务 —— 从 服务 ▸ Web 中已登记的
infr_web_service列表(名称・域名)里挑选。保存为 web_service id 的数组。 - 数据库(采集器) —— 以 access=database 登记的采集器(管理 ▸ 采集器 / 服务 ▸ 数据库)的 键数组。
每种关联最多 50 条。
声明备份对象
使用 备份 标签页的重复行记录本项目的备份策略(种类・对象・计划・备注)。这属于 参考性元数据,不会被执行 —— 真正的备份作业在 计划看板 中管理。
管理机密信息(核心功能)
机密信息 同时使用两种机制。两者都不会把真实的机密值保存进 infr_project。
1) 保管库密钥引用(vault_key_ids)
- 在 机密 标签页勾选清单保管库(资产 ▸ 清单 ▸ 密钥库,
infr_vault_key)中的密钥,以建立关联。 - 该列表以 打码 形式下发(仅 id・类别・标题・用户名 —— 不含取值)。
- 对已关联的密钥按下 [查看] 会调用
POST /service/projects/vault-reveal,仅在那一刻解密取值并返回。
保管库取值的 查看会被审计。 每次查看都会向
infr_audit_log写入vault_key.reveal(target=vault_key、via=project)。取值只会短暂显示,点击即复制到剪贴板 —— 请仅在确有需要时查看。保存下来的项目记录 只持有密钥 id 的引用。
2) 机密核对清单(secrets,已打码)
对于不在保管库中(或由外部保管)的机密信息,只记录位置。取值绝不保存。
| 字段 | 示例 |
|---|---|
label |
STRIPE_SECRET_KEY |
location |
.env (prod server /var/www) |
ref |
1Password › Coin › prod |
note |
rotate quarterly |
服务端的 cleanList() 只保留允许的键(label/location/ref/note),并把每一项截断到 255 个字符。若四个字段全为空,则该行被丢弃。
删除
从编辑模态框左下角或卡片上的 [删除] 进行删除。确认之后,POST /service/projects/delete 会删除 infr_project 中的行,并记录 project.delete。
数据来源
| 数据 | 来源 |
|---|---|
| 项目记录 | infr_project(迁移 000715) |
| 分组(类别) | infr_asset_group(经由 group_id) |
| Web 服务候选项 | infr_web_service(名称・域名) |
| 数据库(采集器)候选项 | access=database 的 infr_collector(key・title・host_alias) |
| 保管库密钥候选项 | infr_vault_key —— 已打码(id・类别・标题・用户名,不含取值) |
| 保管库取值查看 | infr_vault_key.revealSecret()(解密,仅在查看时进行) |
| 审计日志 | infr_audit_log(project.create/update/delete、vault_key.reveal) |
存储结构(infr_project 节选)
key varchar(60) unique nullable # slug
group_id int -> infr_asset_group
name varchar(160) # 必填
status enum(active,paused,archived)
accessible boolean default 1
url varchar(255) # accessible=1 时对外暴露
summary text
repo_provider enum(github,gitlab,gitea,bitbucket,other)
repo_url / default_branch / visibility(public,private,internal)
jenkins_url varchar(255)
environments json [{env,url,branch,jenkins_job,note}]
web_refs json -> infr_web_service id array
db_refs json -> infr_collector(database) key array
backup_targets json [{kind,target,schedule,note}]
vault_key_ids json -> infr_vault_key id array (values stay in the vault)
secrets json [{label,location,ref,note}] # 核对清单,不保存取值
tags / meta json
本页面 不做实时轮询。 只有在保存、删除或点击刷新按钮(
GET /service/projects/list)时才会重新加载列表。实时状态由 服务 ▸ 目录 与 服务 ▸ Web 负责。
访问权限
| 操作 | 路由 | 最低级别 |
|---|---|---|
| 读取(index/list) | GET /service/projects、/list |
1(demo,infr.auth) |
| 查看保管库取值 | POST /service/projects/vault-reveal |
1(并记入审计) |
| 保存(创建/更新) | POST /service/projects/save |
2(staff) |
| 删除 | POST /service/projects/delete |
2(staff) |
- 写入闸门会检查会话中的
infr_user_level >= 2(canWrite())。不通过则返回403+project.err.forbidden。 - 保存时,
vault_key_ids会被过滤到 只剩真实存在的保管库密钥 id(InfrVaultKey::whereIn(...)存在性检查)。伪造的 id 会被静默丢弃。 - 级别为 demo=1・staff=5・admin=10;部分区域另由
infr.level:N中间件单独把关。
排障与 FAQ
Q. 我点保存却得到 403。 写入需要 2 级或更高级别。查看者(1 级)账号只能读取以及查看保管库取值。请让管理员提升您的级别。
Q. [查看] 返回的是空值。
要么该保管库条目本身没有存放机密(hasSecret=false),要么解密失败(例如 APP_KEY 已更换)。请在 清单 ▸ 密钥库 中重新设置取值。revealSecret() 在失败时返回 null。
Q. Web/数据库 关联列表里什么都没有。 Web 服务必须先存在于 服务 ▸ Web 中,而数据库候选项需要 access=database 的采集器。登记之后重新打开项目模态框,候选项就会出现。
Q. 保存键(slug)时报格式错误。
键只允许小写字母、数字、连字符与下划线(^[a-z0-9_-]+$,最长 60)。请去掉空格、大写字母及其他符号。键是可选的,因此也可以留空。
Q. 我能在这里触发部署吗? 不能。部署在 Jenkins 中运行。本页面保存 Jenkins URL 与 Job 名称 仅作为文档。
Q. 我能直接把机密的取值写进机密备注里吗?
绝对不要。secrets 是一份不保存任何取值的 位置地图。请把真实取值放进加密的 清单 ▸ 密钥库 保管库,并通过 vault_key_ids 引用。
相关内容
- 服务 ▸ Web —— 通过
web_refs关联的 Web 服务。 - 服务 ▸ 数据库 —— 通过
db_refs关联的数据库采集器。 - 服务 ▸ 目录 —— 各实例的守护进程存活状态(实时状态在那里)。
- 计划看板 —— 定义并运行真正的备份作业。
- 资产 ▸ 清单 —— 保管库密钥的来源页面(
infr_vault_key)。 - 审计日志 —— 核对 project.create/update/delete 与 vault_key.reveal 的记录。
