diff --git a/docs/qiniu-cloud/ansible-automation.md b/docs/qiniu-cloud/ansible-automation.md index 97f3e6e..6f62c46 100644 --- a/docs/qiniu-cloud/ansible-automation.md +++ b/docs/qiniu-cloud/ansible-automation.md @@ -6,28 +6,41 @@ ## 一、整体结构 +```mermaid +graph TD + Root["ansible/"] --> MF["gather-host-facts.yml"] + Root --> GF["group_vars/all.yml"] + Root --> PG["postgresql-deploy.yml"] + Root --> PG_R["postgresql-rollback.yml"] + Root --> Tasks["tasks/cleanup-controller-ssh-key.yml"] + Root --> Tpl["templates/postgresql-instance.conf.j2"] + + Root --> MySQL["mysql/"] + Root --> PGHA["postgresql_ha/"] + + MySQL --> M Deploy["deploy.yml"] + MySQL --> M Pre["precheck.yml"] + MySQL --> M Fail["failover.yml"] + MySQL --> M Roll["rollback.yml"] + MySQL --> M Conf["config-apply.yml"] + MySQL --> Mvars["vars/ / tasks/ / templates/ / files/"] + + PGHA --> P Deploy["deploy.yml"] + PGHA --> P Pre["preflight.yml"] + PGHA --> P Accept["final_acceptance.yml"] + PGHA --> P Switch["control-switchover.yml"] + PGHA --> P Restart["control-restart.yml"] + PGHA --> P Clean["cleanup.yml"] + + style Root fill:#e1f5fe + style MySQL fill:#fff3e0 + style PGHA fill:#e8f5e9 ``` -ansible/ -├── README.md -├── gather-host-facts.yml # 目标主机事实采集 -├── inventory.example.yml # MySQL 本地运行示例 inventory -├── group_vars/all.yml # 全局变量(SSH 密钥管理) -├── postgresql-deploy.yml # 单机/主从 PostgreSQL 交付入口 -├── postgresql-rollback.yml # PostgreSQL 单机/主从回滚 -├── files/ -│ └── postgresql-xinfra@.service # PostgreSQL systemd 模板单元 -├── tasks/ -│ └── cleanup-controller-ssh-key.yml # 跨服务复用:清理控制端临时 SSH 私钥 -├── templates/ -│ └── postgresql-instance.conf.j2 # 单机/主从 PostgreSQL 配置模板 -├── mysql/ # MySQL 自动化(独立子目录) -│ ├── deploy.yml / precheck.yml / rollback.yml / failover.yml / ... -│ ├── vars/ / tasks/ / templates/ / files/ -└── postgresql_ha/ # PostgreSQL HA 集群 - ├── deploy.yml / preflight.yml / cleanup.yml / final_acceptance.yml - ├── control-switchover.yml / control-restart.yml / control-acceptance.yml - ├── templates/ / inventory.yml / galaxy.yml / README.md -``` + +!!! note "💡 三套自动化体系" + - `mysql/` — MySQL 原生交付(11 个 Playbook),覆盖部署/回滚/故障切换/巡检/配置变更等 + - `postgresql-deploy.yml` — 轻量级单机/主从 PostgreSQL 交付 + - `postgresql_ha/` — 生产级 PostgreSQL HA 集群(Patroni + etcd + HAProxy + Keepalived + pgBackRest) **角色划分:** - `mysql/` — 完整的 MySQL 原生交付生命周期 @@ -44,6 +57,9 @@ ansible/ | Playbook | 职责 | |----------|------| | `deploy.yml` | 唯一部署入口:回调(precheck) → 参数校验 → MHA 制品安装 → 回调(install) → MySQL 二进制安装 → 回调(configure) → 账号配置 → 复制配置 → MHA 配置 → 回调(healthcheck) → TCP 端口检查 → 回调(register) | + +!!! note "💡 Deploy 流水线" + `deploy.yml` 是 MySQL 唯一部署入口,通过回调机制(callback.yml)向 AWX 上报进度。每个阶段都有独立回调,支持前端实时追踪任务状态。 | `precheck.yml` | 只读预检查:Python 脚本检查磁盘空间、内存、端口、制品可用性、目录冲突,输出结构化 JSON | | `rollback.yml` | 回滚:停止 MHA Manager → 清理 SSH 授权 → 删除 MHA 工作目录 → 停止实例 → 删除配置/二进制/数据/运行时目录 | | `failover.yml` | 两阶段切换:(1) 普通 primary_replica 主从切换(无 MHA)(2) MHA 模式切换(masterha_master_switch) | @@ -192,32 +208,43 @@ ansible/ **拓扑:3 节点共置** -``` -┌─────────────────────────────────────────────────────────────┐ -│ VIP (Keepalived) │ -│ ┌───────────────┐ │ -│ │ HAProxy:5432 │ │ -│ │ (读写分离) │ │ -│ └───────┬───────┘ │ -│ ┌────────────────┼────────────────┐ │ -│ ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐ │ -│ │ Node 1 │ │ Node 2 │ │ Node 3 │ │ -│ │ PG+Patroni│ │ PG+Patroni│ │ PG+Patroni│ │ -│ │ etcd+pgBR │ │ etcd+pgBR │ │ etcd+pgBR │ │ -│ │ HAProxy │ │ HAProxy │ │ HAProxy │ │ -│ │ Keepalived│ │ Keepalived│ │ Keepalived│ │ -│ └───────────┘ └───────────┘ └───────────┘ │ -└─────────────────────────────────────────────────────────────┘ +```mermaid +graph TD + VIP["VIP (Keepalived)"] --> HA["HAProxy:5432 (读写分离)"] + + HA --> N1["Node 1\nPG+Patroni\ndetcd+pgBR\nHAProxy+Keepalived"] + HA --> N2["Node 2\nPG+Patroni\ndetcd+pgBR\nHAProxy+Keepalived"] + HA --> N3["Node 3\nPG+Patroni\ndetcd+pgBR\nHAProxy+Keepalived"] + + N1 -.->|"etcd quorum"| N2 + N2 -.->|"etcd quorum"| N3 + N3 -.->|"etcd quorum"| N1 + + style VIP fill:#fff3e0 + style HA fill:#e1f5fe + style N1 fill:#e8f5e9 + style N2 fill:#e8f5e9 + style N3 fill:#e8f5e9 ``` **服务依赖链:** + +```mermaid +graph LR + ETCd["etcd"] --> Patroni["Patroni"] + Patroni --> Exporter["postgres-exporter"] + HAProxy["HAProxy"] -.->|"健康检查 /primary"| Patroni + Keepalived["Keepalived"] -.->|"VRRP 心跳"| HAProxy + + style ETCd fill:#e1f5fe + style Patroni fill:#e8f5e9 ``` -xinfra-pgha-etcd@{uuid}.service - → xinfra-patroni.service - → xinfra-postgres-exporter.service -xinfra-haproxy.service (独立) -keepalived.service (依赖 HAProxy 健康检查脚本) -``` + +!!! note "💡 HA 架构要点" + - **DCS:** 独立 etcd 3 节点集群(非系统 etcd),用于 Patroni 分布式协调 + - **VIP:** Keepalived unicast 模式在 3 个 HAProxy 之间漂移,nopreempt 避免脑裂 + - **读写分离:** HAProxy 通过 Patroni REST API `/primary` 健康检查路由到主库 + - **备份冗余:** pgBackRest 双仓库(repo1/repo2 分布在不同节点) **关键设计:** - DCS:独立 etcd 3 节点集群(非系统 etcd) @@ -358,10 +385,23 @@ ansible_ssh_private_key_file: "{{ xinfra_ssh_private_key_file }}" ## 六、设计亮点 -1. **原子安装**:aria2 多线程下载 + SHA256 校验 + flock 并发锁,保证二进制安装的原子性和幂等性 -2. **凭据安全**:临时文件存储(`mktemp` + `chmod 600` + `trap`),避免命令行泄露;SSH 密钥 ed25519 + `restrict` 前缀 -3. **GTID 复制**:全流程 GTID 模式,Clone 后自动重新生成 server_uuid,校验 errant/missing GTID -4. **MHA 集成**:自动化 MHA 制品安装、配置、验收、故障转移回调 -5. **PG HA 全栈**:Patroni + etcd + HAProxy + Keepalived + pgBackRest,VIP 漂移 + 读写分离 + 双仓库备份 -6. **不可变 APT 快照**:内部 PyPI + APT 仓库,GPG 签名,幂等性校验 -7. **AWX 集成**:完整的 Project/Inventory/Template/Workflow 自动化配置 +!!! note "💡 原子安装" + aria2 多线程下载 + SHA256 校验 + flock 并发锁,保证二进制安装的原子性和幂等性。 + +!!! note "💡 凭据安全" + 临时文件存储(`mktemp` + `chmod 600` + `trap`),避免命令行泄露;SSH 密钥 ed25519 + `restrict` 前缀。 + +!!! note "💡 GTID 复制" + 全流程 GTID 模式,Clone 后自动重新生成 server_uuid,校验 errant/missing GTID。 + +!!! note "💡 MHA 集成" + 自动化 MHA 制品安装、配置、验收、故障转移回调。 + +!!! note "💡 PG HA 全栈" + Patroni + etcd + HAProxy + Keepalived + pgBackRest,VIP 漂移 + 读写分离 + 双仓库备份。 + +!!! note "💡 不可变 APT 快照" + 内部 PyPI + APT 仓库,GPG 签名,幂等性校验。 + +!!! note "💡 AWX 集成" + 完整的 Project/Inventory/Template/Workflow 自动化配置。 diff --git a/docs/qiniu-cloud/architecture.md b/docs/qiniu-cloud/architecture.md index 74bac1a..dea082d 100644 --- a/docs/qiniu-cloud/architecture.md +++ b/docs/qiniu-cloud/architecture.md @@ -24,9 +24,8 @@ config.Load() → vault.New(cfg) → database.Open(dsn) → database.AutoMigrate → router.New(deps) → r.Run(cfg.HTTPAddr) ``` -- Vault 在 `VAULT_ENABLED=false` 时为 nil,不影响启动 -- Redis 在 `REDIS_ENABLED=false` 时为 nil -- AutoMigrate 通过 `AUTO_MIGRATE` 环境变量控制 +!!! note "💡 启动链路" + Vault 和 Redis 都支持通过环境变量禁用(`VAULT_ENABLED=false` / `REDIS_ENABLED=false`),此时对应客户端为 nil,不影响核心服务启动。`AutoMigrate` 通过 `AUTO_MIGRATE` 环境变量控制,生产环境建议关闭自动迁移。 **Receptor Worker 启动流程:** @@ -41,23 +40,24 @@ config.Load() → ValidateReceptorWorkerConfig() → database.Open() → databas ### 1.2 分层架构 +```mermaid +graph TD + A["cmd/ 入口"] --> B["internal/router 路由"] + B --> C["internal/handler HTTP处理"] + C --> D["internal/service 业务逻辑"] + D --> E["internal/model 数据模型"] + D --> F["internal/database"] + D --> G["internal/auth / sso / vault"] + D --> H["internal/cache / config"] + D --> I["internal/wayne / artifactmanifest"] + + style A fill:#e1f5fe + style C fill:#f3e5f5 + style D fill:#e8f5e9 ``` -┌─────────────────────────────────────────────────┐ -│ cmd/ (入口) │ -├─────────────────────────────────────────────────┤ -│ internal/router (路由) │ -├─────────────────────────────────────────────────┤ -│ internal/handler (HTTP 处理) │ -├─────────────────────────────────────────────────┤ -│ internal/service (业务逻辑) │ -├─────────────────────────────────────────────────┤ -│ internal/model (数据模型) internal/database │ -├─────────────────────────────────────────────────┤ -│ internal/auth internal/sso internal/vault │ -│ internal/cache internal/config │ -│ internal/wayne internal/artifactmanifest │ -└─────────────────────────────────────────────────┘ -``` + +!!! note "💡 分层设计" + 后端采用经典分层架构:`cmd` 负责启动编排,`router` 定义路由,`handler` 处理 HTTP 请求,`service` 封装业务逻辑,`model` + `database` 管理数据层。`auth/sso/vault/cache` 等作为公共组件被 service 层依赖。 ### 1.3 路由设计 @@ -168,6 +168,9 @@ config.Load() → ValidateReceptorWorkerConfig() → database.Open() → databas 共 **40+ 张数据表**,核心模型分组: +!!! note "💡 数据模型概览" + 模型按业务域划分为 7 大组:用户与权限(7 表)、交付系统(12+ 表)、MySQL HA(5 表)、PostgreSQL HA(8 表)、机器与 Receptor(6 表)、执行配置(3 表)、Archery 集成(5 表)。所有模型通过 GORM AutoMigrate 自动迁移。 + **用户与权限:** - `User` — ID, Username, DisplayName, Email, Phone, Source, ExternalID, Status, IsAdmin, LastLoginAt(软删除) - `BusinessLine` — Name(唯一) @@ -214,6 +217,24 @@ config.Load() → ValidateReceptorWorkerConfig() → database.Open() → databas ### 1.7 认证机制 +```mermaid +graph LR + subgraph "登录方式" + A["本地登录 POST /login"] + B["SAML SSO GET /login/internal-sso"] + C["OAuth2 /authorize"] + end + + A --> JWT["JWT 签发/校验"] + B --> JWT + C --> JWT + + JWT --> MW["AuthMiddleware (Bearer Token)"] + + style JWT fill:#fff3e0 + style MW fill:#e8f5e9 +``` + **JWT(`internal/auth/`):** - `Claims` — HS256 访问令牌(UserID, Username, Email, DisplayName, IsAdmin) - `OAuthCodeClaims` — HS256 OAuth 授权码 @@ -230,6 +251,9 @@ config.Load() → ValidateReceptorWorkerConfig() → database.Open() → databas - OAuth Code 存储在 Redis(SetNX + TTL) - Token 端点:access_token(HS256)+ id_token(RS256) +!!! note "💡 认证网关" + 三种登录方式最终都汇聚到 JWT 签发,后端通过统一的 `AuthMiddleware` 校验 Bearer Token。SAML 和 OAuth 作为 SSO 协议接入,本地登录在 SSO 启用时自动禁用。 + ### 1.8 配置管理 `Config` 结构体包含 **200+ 个配置项**,全部通过环境变量加载,支持 `.env.local`、`.env.server`、`.env` 文件。 @@ -470,26 +494,28 @@ PaginatedData = { total: number, items: T[] } ## 三、前后端交互模型 +```mermaid +graph TD + FE["Vue 3 SPA (Vite)"] -->|"POST /api/v1/*"| BE["Gin HTTP Server"] + BE -->|"JSON Response"| FE + + BE --> MySQL["MySQL (GORM)"] + BE --> Redis["Redis (缓存/会话)"] + BE --> Vault["Vault (密钥管理)"] + + BE --> AWX["AWX (Ansible)"] + BE --> Wayne["Wayne (K8s管理)"] + BE --> Archery["Archery (SQL审核)"] + + style FE fill:#e1f5fe + style BE fill:#fff3e0 + style MySQL fill:#fce4ec + style Redis fill:#fce4ec + style Vault fill:#fce4ec ``` -┌──────────────┐ /api/v1/* ┌──────────────┐ -│ Vue 3 SPA │ ──────────────── → │ Gin HTTP │ -│ (Vite) │ ← ───────────── ─ │ Server │ -└──────────────┘ JSON Response └──────┬───────┘ - │ - ┌─────────────────────┼─────────────────────┐ - │ │ │ - ┌─────▼─────┐ ┌──────▼──────┐ ┌──────▼──────┐ - │ MySQL │ │ Redis │ │ Vault │ - │ (GORM) │ │ (缓存/会话) │ │ (密钥管理) │ - └───────────┘ └─────────────┘ └─────────────┘ - │ - ┌─────────────────────┼─────────────────────┐ - │ │ │ - ┌─────▼─────┐ ┌──────▼──────┐ ┌──────▼──────┐ - │ AWX │ │ Wayne │ │ Archery │ - │ (Ansible) │ │ (K8s 管理) │ │ (SQL 审核) │ - └───────────┘ └─────────────┘ └─────────────┘ -``` + +!!! note "💡 交互模型" + 前端通过 RESTful API 与后端通信,后端依赖 MySQL 持久化、Redis 缓存与会话、Vault 密钥管理。外部系统 AWX(Ansible 自动化)、Wayne(K8s 管理)、Archery(SQL 审核)通过 HTTP API 集成。 **认证流程:** 1. 前端存储 JWT token 于 localStorage diff --git a/docs/qiniu-cloud/deployment-cicd.md b/docs/qiniu-cloud/deployment-cicd.md index 070d0c9..d74650a 100644 --- a/docs/qiniu-cloud/deployment-cicd.md +++ b/docs/qiniu-cloud/deployment-cicd.md @@ -28,6 +28,9 @@ - 入口点:`/usr/local/bin/authserver` - 本地镜像标签:`xinfra-server:latest`(Makefile) +!!! note "💡 多阶段构建" + 前端和后端都采用 Docker 多阶段构建:构建阶段使用完整工具链(Node/Go),运行阶段使用最小化镜像(nginx/alpine),最终镜像体积大幅减小。后端以非 root 用户(65532)运行,遵循最小权限原则。 + ### 1.3 Nginx 配置 — `nginx.frontend.conf` **监听端口:** `80` @@ -43,6 +46,9 @@ 代理头:`Host`、`X-Real-IP` +!!! note "💡 Nginx 反向代理" + Nginx 作为前端入口,将 `/api/`、`/auth/`、`/swagger/` 统一代理到后端 `8083` 端口,SPA 路由通过 `try_files` fallback 到 `index.html` 实现前端路由。 + ### 1.4 本地开发数据库 — `docker-compose.mysql.yml` **MySQL 服务:** @@ -65,8 +71,35 @@ ## 二、Kubernetes 部署 (`deploy/k8s/wayne-xinfra.yaml`) +```mermaid +graph TD + subgraph K8s["Kubernetes Cluster"] + Secret["Secret: xinfra-secret"] + CM["ConfigMap: xinfra-configmap"] + Harbor["Secret: harbor-registry"] + Redis["StatefulSet: xinfra-redis\n(1 replica, 2Gi)"] + Backend["Deployment: xinfra-backend\n(1 replica)"] + Frontend["Deployment: xinfra-frontend\n(1 replica)"] + SVC_BE["Service: xinfra-backend\nClusterIP:8083"] + SVC_FE["Service: xinfra-frontend\nNodePort:80→32002"] + end + + Secret --> Backend + CM --> Backend + Backend --> Redis + Frontend --> SVC_BE + SVC_FE --> Frontend + + style Redis fill:#e1f5fe + style Backend fill:#e8f5e9 + style Frontend fill:#fff3e0 +``` + 单一 YAML 文件,包含以下资源,均标注 `wayne-app: xinfra`, `wayne-ns: xinfra`: +!!! note "💡 K8s 部署" + 整个应用通过单一 YAML 文件部署到 K8s,使用 Wayne 平台管理。Redis 使用 StatefulSet 保证持久化,前后端使用 Deployment 支持滚动更新。前端通过 NodePort 32002 暴露到外部。 + ### 2.1 Secret: `xinfra-secret` (Opaque) | 键 | 说明 | @@ -158,13 +191,24 @@ ### 3.3 Job 依赖图 +```mermaid +graph TD + Prepare["prepare\nGo mod hash"] --> GoCache["go-mod-cache\n依赖缓存"] + GoCache --> Backend["backend-unit\ngo vet + test"] + FE["frontend-validation\nnpm test + build"] --> Integration["integration\n端到端测试"] + Backend --> Integration + Backend --> Coverage["coverage-upload\nCodecov"] + FE --> Coverage + Integration --> Coverage + + style Prepare fill:#e1f5fe + style Backend fill:#e8f5e9 + style FE fill:#fff3e0 + style Integration fill:#fce4ec ``` -prepare ──→ go-mod-cache ──→ backend-unit ──┐ - ├──→ coverage-upload -frontend-validation ────────────────────────┤ - │ -integration ────────────────────────────────┘ -``` + +!!! note "💡 CI 流水线" + 流水线采用 5 个 Job:`prepare` 计算 Go 模块 hash → `go-mod-cache` 缓存依赖 → `backend-unit` 并行跑后端单测 → `frontend-validation` 并行跑前端测试+构建 → `integration` 启动真实 MySQL 做端到端验证。最后 `coverage-upload` 汇总覆盖率上传 Codecov。 ### 3.4 Job 详情 diff --git a/docs/qiniu-cloud/resume-tech-points.md b/docs/qiniu-cloud/resume-tech-points.md index ebbdf3c..0407aa4 100644 --- a/docs/qiniu-cloud/resume-tech-points.md +++ b/docs/qiniu-cloud/resume-tech-points.md @@ -8,44 +8,68 @@ 基于 Patroni + etcd + HAProxy + Keepalived + pgBackRest 构建 3 节点共置高可用架构。通过 Keepalived unicast 模式实现 VIP 漂移,HAProxy 以 Patroni REST API `/primary` 健康检查实现读写分离路由;pgBackRest 双仓库(repo1/repo2 分布在不同节点)保障备份冗余。部署流水线经 preflight 静态预检(CPU/内存/磁盘/端口/L2 可达性/VIP 冲突检测)→ 3-Play 编排部署 → final_acceptance 验收(Patroni 健康/3 running + 1 primary/同步复制 2 streaming + 1 sync/etcd 3 members/HAPRoxy 端点/VIP 所有权)三阶段闭环,支持计划切换(patronictl switchover)、滚动重启、控制验收等运维操作。 +!!! note "💡 核心亮点" + 三阶段闭环部署(预检→部署→验收)+ VIP 漂移 + 读写分离 + 双仓库备份冗余,生产级高可用方案。 + --- ## 2. 实现 Vault Database Secrets Engine 全链路集成 对接 HashiCorp Vault 的 AppRole 认证 + Database Secrets Engine,实现数据库凭据全生命周期自动化。通过 `RegisterMySQLDatabaseConnection` 注册 MySQL 连接(mysql-database-plugin),`RegisterDatabaseStaticRole` 登记静态角色并校验 `skip_static_role_import_rotation` 是否生效——在密码仍被 MHA/Archery 等运行链路依赖时,拒绝静默降级为轮换模式,确保凭据安全。内置 token 自动续期(TTL 前 1 分钟刷新)和 401/403 请求重试机制,消除 Vault token 过期导致的间歇性故障。 +!!! note "💡 核心亮点" + `skip_static_role_import_rotation` 校验:当密码仍被运行链路依赖时,拒绝静默降级为轮换模式,保障凭据安全。 + --- ## 3. 构建多协议统一认证网关(SAML 2.0 + OAuth 2.0/OIDC + JWT) 从零实现 SAML 2.0 SP:AuthnRequest deflate+base64 编码 → HTTP-Redirect 绑定,SAMLResponse 解析支持加密断言解密(RSA-OAEP 密钥传输 + AES-128/192/256-CBC/GCM 数据加密),SP 元数据 XML 自动生成。同时实现完整 OAuth 2.0 Authorization Code 流程作为 OIDC Provider:OAuth Code 以 Redis SetNX+TTL 存储保证一次性消费,Token 端点按 client 差异化签发(Wayen/CloudDM: HS256 access_token,Archery: RS256 PlatformToken),JWKS 端点暴露 RSA 公钥。JWT 层设计四种 Claims 结构(访问令牌/OAuth Code/OIDC ID Token/平台令牌),支持 HS256/RS256 双算法,Redis 集中吊销。 +!!! note "💡 核心亮点" + 从零实现 SAML 2.0 SP + 完整 OAuth2/OIDC Provider + 四种 JWT Claims 结构,统一认证网关支持三种 SSO 协议。 + --- ## 4. 实现 Ansible MySQL 全生命周期自动化(11 个 Playbook) 覆盖 MySQL 从部署到销毁的完整链路:deploy(参数校验 → MHA 制品安装 → 原子二进制安装[flock 并发锁+SHA256 校验+aria2 多线程] → 账号配置[mktemp+chmod 600+trap 防泄露] → GTID 复制[Clone 全量克隆+server_uuid 重新生成+errant/missing GTID 校验] → MHA 配置 → 健康检查 → 注册回调)、precheck(Python 脚本结构化 JSON 输出)、failover(普通主从切换 + MHA masterha_master_switch 双模式)、config-apply(my.cnf 片段写入 + 逐台滚动重启 + SQL 执行 + root 密码轮换)、decommission(先停从库 → 主库设 read_only → 写下线标记)、rejoin(旧主 Clone 接收 + GTID 复制重建)、purge(校验下线标记 → 验证删除)。MHA 集成包含 deb 包修补(修复 MySQL 8.x 版本解析正则)、ed25519 集群独立 SSH 密钥、故障转移回调脚本。 +!!! note "💡 核心亮点" + 11 个 Playbook 覆盖 MySQL 全生命周期,原子二进制安装(flock+SHA256+aria2)+ GTID 复制校验 + MHA 故障转移回调。 + --- ## 5. 设计交付调度器状态机与幂等性保障 交付系统采用 16 状态状态机(DeliveryTask)+ 幂等键(IdempotencyKey)防重复提交。配额管理通过 ResourceQuota + ResourceReservation 实现业务线级资源预留与释放。PostgreSQL HA 操作引入 14 状态生命周期,支持 AWX Workflow Job 调度、preflight 预检、config 在线变更、control 操作(restart/rolling_restart/switchover)、cleanup 清理等完整运维操作。任务事件流通过 SSE(Server-Sent Events)实现实时进度推送,前端通过 `createTaskLogStream` 订阅。凭证揭示采用一次性消费模式(pending → revealed → expired),支持 JSON 和 XLSX 两种导出格式。 +!!! note "💡 核心亮点" + 16 状态状态机 + 幂等键防重复 + SSE 实时推送 + 凭证一次性揭示,交付调度器的可靠性设计。 + --- ## 6. 实现 Receptor 节点自动化供应系统(独立 Worker 进程) 独立运行的 Receptor Worker 进程,以可配置并发度(RECEPTOR_PROVISIONING_CONCURRENCY)执行节点供应循环。多阶段管线:pending → prechecking → registering_awx → preparing_artifacts → installing → checking_remote → checking_awx → attaching_instance_group → succeeded,失败分支覆盖 precheck_failed/awx_failed/artifact_failed/install_failed/mesh_unreachable/health_check_failed。SSH 凭据采用 PGP + AES 双层加密(随机 DataKey AES 加密私钥,PGP 公钥加密 DataKey)。制品下载支持多架构(amd64/arm64),内置 SHA256 校验。下线流程独立编排:decommissioning → awx_disabled → instance_group_detached → remote_uninstalling → certificate_invalidated → awx_cleaning。 +!!! note "💡 核心亮点" + 独立 Worker 进程 + 多阶段供应管线 + PGP+AES 双层加密 + 多架构制品支持,自动化节点生命周期管理。 + --- ## 7. 构建离线制品清单签名校验体系 实现 `xinfra.artifact-manifest.v1/v2` 清单 schema 的完整校验链:Ed25519 签名验证 + SHA256 digest 计算(排除 digest 和 signature 字段)+ source 前缀白名单 + 可达性检查。支持两种清单模式:Evidence Summary(校验 sha256 digest)和嵌入 Ed25519 签名的 manifest。独立 CLI 工具(`cmd/artifact-manifest`)支持 `--manifest`、`--expected-digest`、`--key-id`、`--public-key`、`--allowed-source-prefix`、`--reachable-source` 参数,校验结果输出 JSON,非 StatusReady 则 exit 2,可集成到 CI/CD 流水线作为门禁。同时实现不可变 APT 快照构建脚本:收集运行时包 → SHA256 校验 → 生成 Packages 索引 → GPG 签名(InRelease + Release.gpg)→ 上传 Nexus,配合幂等性校验脚本确保两次独立演练的 URI 集合和 SHA256 摘要完全一致。 +!!! note "💡 核心亮点" + Ed25519 签名 + SHA256 digest + 不可变 APT 快照,离线制品完整性校验的完整方案。 + --- ## 8. 实现 Wayne 服务间 HMAC-SHA256 签名与 RBAC 权限模型 服务间调用采用 HMAC-SHA256 签名方案:payload = `METHOD\nURI\nTIMESTAMP\nNONCE\nBODY_SHA256`,通过 `X-Wayne-Service`/`X-Wayne-Timestamp`/`X-Wayne-Nonce`/`X-Wayne-Signature` 四个 headers 传递,验签使用 `hmac.Equal` 常量时间比较防止时序攻击。RBAC 权限模型设计为三级架构:平台级(PlatformRoleBinding → platform_admin)、业务线级(BusinessLineUser owner/member + BusinessLinePermission 细粒度权限)、子系统级(Wayne Namespace Role Binding + Archery Resource/Permission Group)。前端实现四级路由守卫(platformPermission → businessLineMember → businessLineOwner → capability/capabilities),支持权限别名映射(如 `machine.view` → `machine.read` + `machine.credential.read`)。全链路审计日志异步写入,覆盖登录、业务线权限、子系统授权、服务交付四类操作。 + +!!! note "💡 核心亮点" + HMAC-SHA256 常量时间验签 + 三级 RBAC + 四级路由守卫 + 权限别名映射,完整的安全与权限体系。 diff --git a/docs/qiniu-cloud/security-auth-data.md b/docs/qiniu-cloud/security-auth-data.md index 2fdcce6..7857582 100644 --- a/docs/qiniu-cloud/security-auth-data.md +++ b/docs/qiniu-cloud/security-auth-data.md @@ -8,28 +8,26 @@ XINFRA 实现了多协议统一认证网关,支持本地登录、SAML 2.0 SSO、OAuth 2.0/OIDC 三种认证方式,并通过 JWT 实现会话管理。 +```mermaid +graph TD + subgraph "认证网关层" + A["本地登录\nPOST /login"] + B["SAML 2.0 SSO\nGET /login/internal-sso"] + C["OAuth 2.0 / OIDC\n/auth/oauth/*"] + end + + A --> JWT["JWT 签发/校验\nHS256/RS256"] + B --> JWT + C --> JWT + + JWT --> MW["AuthMiddleware\nBearer Token"] + + style JWT fill:#fff3e0 + style MW fill:#e8f5e9 ``` -┌─────────────────────────────────────────────────────────────┐ -│ 认证网关层 │ -│ ┌──────────┐ ┌──────────────┐ ┌──────────────────────┐ │ -│ │ 本地登录 │ │ SAML 2.0 SSO │ │ OAuth 2.0 / OIDC │ │ -│ │ POST / │ │ GET /login/ │ │ /auth/oauth/ │ │ -│ │ login │ │ internal-sso │ │ authorize/token/ │ │ -│ └────┬─────┘ └──────┬───────┘ │ jwks/userinfo │ │ -│ │ │ └──────────┬───────────┘ │ -│ └───────────────┼─────────────────────┘ │ -│ ▼ │ -│ ┌─────────────────┐ │ -│ │ JWT 签发/校验 │ │ -│ │ (HS256/RS256) │ │ -│ └────────┬────────┘ │ -│ ▼ │ -│ ┌─────────────────┐ │ -│ │ AuthMiddleware │ │ -│ │ (Bearer Token) │ │ -│ └─────────────────┘ │ -└─────────────────────────────────────────────────────────────┘ -``` + +!!! note "💡 统一认证网关" + 三种认证方式最终都汇聚到 JWT 签发/校验,后端通过统一的 `AuthMiddleware` 处理所有请求的认证。SSO 启用时本地登录自动禁用,保证认证入口收敛。 --- @@ -60,31 +58,28 @@ XINFRA 实现了多协议统一认证网关,支持本地登录、SAML 2.0 SSO ### 3.2 登录流程 +```mermaid +sequenceDiagram + participant U as 用户 + participant FE as 前端 + participant BE as 后端 + participant IDP as SAML IDP + + U->>FE: 点击 SSO 登录 + FE->>BE: GET /login/internal-sso + BE->>BE: BuildLoginRedirect() + BE->>BE: 构建 AuthnRequest (deflate+base64) + BE-->>FE: 302 重定向到 IDP + FE->>IDP: 用户在 IDP 认证 + IDP-->>BE: POST SAMLResponse 到 /saml/acs + BE->>BE: DecodeSAMLResponse() + BE->>BE: 解密断言 (RSA-OAEP + AES) + BE->>BE: 创建/更新用户 + 签发 JWT + BE-->>FE: 重定向回前端 (携带 sso_token) ``` -用户 → GET /auth/api/v1/login/internal-sso - ↓ - BuildLoginRedirect() - ↓ - 从 IDP 元数据获取 SSO URL - ↓ - 构建 AuthnRequest(deflate + base64 编码) - ↓ - HTTP-Redirect 绑定 URL → 重定向到 IDP - ↓ - 用户在 IDP 完成认证 - ↓ - IDP POST SAMLResponse 到 /auth/api/v1/saml/acs - ↓ - DecodeSAMLResponse() - ↓ - Base64 解码 → 提取 NameID 和属性 - ↓ - 支持加密断言解密(RSA-OAEP + AES-CBC/GCM) - ↓ - 创建/更新用户 + 签发 JWT - ↓ - 重定向回前端(携带 sso_token) -``` + +!!! note "💡 SAML 2.0 实现" + 完整实现 SAML 2.0 SP:AuthnRequest 构建(deflate + base64 编码)→ HTTP-Redirect 绑定 → IDP 认证 → SAMLResponse 解析。支持加密断言解密(RSA-OAEP 密钥传输 + AES-128/192/256-CBC/GCM 数据加密)。 ### 3.3 加密算法支持 @@ -134,14 +129,23 @@ XINFRA 实现了多协议统一认证网关,支持本地登录、SAML 2.0 SSO ### 4.3 授权码流程 +```mermaid +sequenceDiagram + participant FE as 前端 + participant BE as 后端 + participant Redis as Redis + + FE->>BE: GET /oauth/authorize?client_id=... + BE->>BE: 用户认证 + 生成 OAuth Code + BE->>Redis: SetNX + TTL 存储 Code + BE-->>FE: 302 redirect_uri?code=... + FE->>BE: POST /oauth/token (code) + BE->>Redis: 校验 + 消费 Code(一次性) + BE-->>FE: access_token + id_token ``` -1. 前端重定向到 /auth/oauth/authorize?client_id=...&redirect_uri=...&scope=...&state=...&nonce=... -2. 用户认证后,后端生成 OAuth Code(HS256 签名的 Claims) -3. OAuth Code 存储在 Redis(SetNX + TTL) -4. 重定向回 redirect_uri?code=...&state=... -5. 前端用 code 换取 token(POST /auth/oauth/token) -6. 后端校验 code → Redis 消费(一次性)→ 签发 access_token + id_token -``` + +!!! note "💡 OAuth2 授权码流程" + OAuth Code 使用 Redis SetNX + TTL 存储,保证一次性消费。Token 端点按 client 差异化签发:Wayen/CloudDM 使用 HS256 access_token,Archery 使用 RS256 PlatformToken。 ### 4.4 Token 签发 @@ -190,21 +194,33 @@ XINFRA 实现了多协议统一认证网关,支持本地登录、SAML 2.0 SSO ### 6.1 RBAC 架构 +```mermaid +graph TD + subgraph "平台级权限" + P1["PlatformRoleBinding\nUserID → Role (platform_admin)"] + end + + subgraph "业务线级权限" + B1["BusinessLineUser\nUserID → Role (owner/member)"] + B2["BusinessLinePermission\nUserID → Permission"] + end + + subgraph "子系统级权限" + S1["Wayne\nNamespace Role Binding"] + S2["Archery\nResource Group / Permission Group"] + end + + P1 --> B1 + B1 --> S1 + B1 --> S2 + + style P1 fill:#e1f5fe + style B1 fill:#fff3e0 + style B2 fill:#fff3e0 ``` -┌─────────────────────────────────────────────────┐ -│ 平台级权限 │ -│ PlatformRoleBinding: UserID → Role │ -│ (platform_admin) │ -├─────────────────────────────────────────────────┤ -│ 业务线级权限 │ -│ BusinessLineUser: UserID → Role (owner/member) │ -│ BusinessLinePermission: UserID → Permission │ -├─────────────────────────────────────────────────┤ -│ 子系统级权限 │ -│ Wayne: Namespace Role Binding │ -│ Archery: Resource Group / Permission Group │ -└─────────────────────────────────────────────────┘ -``` + +!!! note "💡 三级 RBAC" + 权限模型分为三级:**平台级**(platform_admin 管理员)→ **业务线级**(owner/member + 细粒度权限)→ **子系统级**(Wayne 命名空间角色 + Archery 资源组/权限组)。前端通过四级路由守卫实现权限控制。 ### 6.2 平台级角色 @@ -398,21 +414,25 @@ XINFRA 实现了多协议统一认证网关,支持本地登录、SAML 2.0 SSO ### 10.1 架构 +```mermaid +graph TD + subgraph VaultServer["Vault Server"] + KV["KV v2\n通用密钥"] + DB["Database Secrets Engine\n数据库凭据自动化"] + end + + AppRole["AppRole Auth"] --> KV + StaticRole["Static Role"] --> DB + + AppRole -->|"role_id + secret_id"| VaultServer + DB -->|"MySQL/PostgreSQL 连接"| DB + + style VaultServer fill:#e1f5fe + style AppRole fill:#e8f5e9 ``` -┌─────────────────────────────────────────────────┐ -│ Vault Server │ -│ ┌──────────────┐ ┌──────────────────────────┐ │ -│ │ KV v2 │ │ Database Secrets Engine │ │ -│ │ (通用密钥) │ │ (数据库凭据自动化) │ │ -│ └──────────────┘ └──────────────────────────┘ │ -└─────────────────────────────────────────────────┘ - ▲ ▲ - │ │ - ┌────┴────┐ ┌─────┴─────┐ - │ AppRole │ │ Static │ - │ Auth │ │ Role │ - └─────────┘ └───────────┘ -``` + +!!! note "💡 Vault 集成" + Vault 通过 AppRole 认证获取 token,支持自动续期(TTL 前 1 分钟刷新)和 401/403 请求重试。Database Secrets Engine 实现数据库凭据全生命周期自动化:连接注册 → Static Role 登记 → 凭据读取 → 清理。 ### 10.2 认证方式 @@ -583,3 +603,8 @@ METHOD\nURI\nTIMESTAMP\nNONCE\nBODY_SHA256 - 路由级权限控制(路由守卫四级检查) - API 级权限控制(AuthMiddleware + 业务逻辑校验) - 全链路审计日志 + +!!! note "💡 安全设计原则" + - **纵深防御:** 传输层(NodePort)→ 认证层(JWT/SAML/OAuth)→ 授权层(三级 RBAC)→ 审计层(全链路日志) + - **最小权限:** SSH 凭据 PGP 加密、交付凭据一次性揭示、Vault 自动轮换 + - **零信任:** OAuth Code 一次性消费、Token 吊销、常量时间签名验证防时序攻击