fhurau/distributed-auth-platform

GitHub: fhurau/distributed-auth-platform

一个基于 Spring Boot、Next.js 和 Keycloak 构建的本地全栈应用安全演示平台,完整展示身份认证、对象级授权、审计日志和安全 CI/CD 等企业级安全控制措施。

Stars: 0 | Forks: 0

# 分布式-auth-platform distributed-auth-platform 是一个本地作品集应用程序,用于演示 使用 Next.js、Spring Boot、PostgreSQL 和 Keycloak 构建的全栈系统中的 安全控制。 该演示包含使用 PKCE 的 OAuth2/OIDC 登录、项目 CRUD、对象级 授权、审计日志、受控文档上传/下载、 Swagger/OpenAPI、安全标头以及 GitHub Actions 安全检查。 ![distributed-auth-platform 仪表板](https://static.pigsec.cn/wp-content/uploads/repos/cas/74/74693eb7d4cd421ef582695f078f784e8e523ed31a0edb6992cbb204ef692b1c.png) ## 快速开始 前置条件:带有 Docker Compose 的 Docker Desktop,以及 Windows PowerShell 5.1 或 PowerShell 7。 从全新的克隆开始: ``` Copy-Item .env.example .env docker compose up -d --build ``` 示例环境值仅供本地演示使用。在隔离的本地机器之外使用本 仓库之前,请更改 `.env` 中的 PostgreSQL 和 Keycloak 管理员密码。 容器启动完成后,打开: - Frontend: [http://localhost:3000](http://localhost:3000) - Swagger UI: [http://localhost:8080/swagger-ui.html](http://localhost:8080/swagger-ui.html) - Keycloak: [http://localhost:8081](http://localhost:8081) - Prometheus: [http://localhost:9090](http://localhost:9090) - Grafana: [http://localhost:3001](http://localhost:3001) (`.env` 中的 `admin` / `GRAFANA_ADMIN_PASSWORD`) 运行自动审查检查: ``` powershell -ExecutionPolicy Bypass -File .\scripts\smoke-test.ps1 ``` [冒烟测试脚本](scripts/smoke-test.ps1)验证身份验证、 对象级授权、文档限制和审计日志访问。它 使用临时数据,即使在检查失败后也会进行清理,不会打印任何 token 或 密码,并且当控制行为与预期不符时以非零状态退出。 Keycloak 仅在 `securetask` realm 不存在时才导入它。 如果存在较旧的本地 realm,请删除本地 Docker 卷,并 仅在允许删除本地演示数据时才重新启动。 ## 架构 ``` flowchart LR Browser[Browser] -->|OIDC Authorization Code + PKCE| Keycloak[Keycloak] Browser -->|Bearer token| Frontend[Next.js frontend / API proxy] Frontend -->|Bearer token| Backend[Spring Boot API] Backend -->|Validate JWT/JWKS| Keycloak Backend -->|Audit events| Kafka[(Kafka)] Kafka -->|Consume| Backend Backend -->|Cache, token blacklist, rate limits| Redis[(Redis)] Backend -->|JPA/Flyway| Postgres[(PostgreSQL)] Keycloak -->|Realm/user data| Postgres Prometheus[Prometheus] -->|Scrape /actuator/prometheus| Backend Grafana[Grafana] -->|Query| Prometheus ``` 后端既向 Kafka 发布消息,也从中消费消息:服务将 `AuditEvent` 发布到 `audit-events` topic,而不是直接写入审计行, 同一应用程序中的消费者读取该 topic 并 执行向 PostgreSQL 的实际写入(原因请参阅 [基于 Kafka 的审计事件流处理](docs/05-audit-logging.md))。 Redis 支持三个独立的功能——项目列表缓存、JWT 撤销黑名单和每用户速率限制器——而不是单一的缓存 层。 指标:后端在 `/actuator/prometheus` 暴露 Prometheus 格式的指标 (未经身份验证——请参阅 [本地演示限制](#local-demo-limitations));Prometheus 每 15 秒抓取一次;Grafana 的 "distributed-auth-platform Backend Overview" 仪表板(启动时从 [`infra/grafana/provisioning/dashboards/backend-overview.json`](infra/grafana/provisioning/dashboards/backend-overview.json) 自动配置,而非手动构建)显示请求速率、p95 延迟和错误 率。每个后端日志行都是结构化的 JSON(Elastic Common Schema),并 将 `X-Correlation-ID` 请求标头作为 `correlationId` 字段携带,因此 即使在并发流量下,也可以通过该 ID 追踪单个请求的日志行。 ## Kubernetes(演示) **本节是可选的,尝试运行该项目时不需要。** 上面的 docker-compose 是在本地运行 distributed-auth-platform 唯一受支持的方式。 [`deploy/k8s/`](deploy/k8s/) 下的清单文件是为了演示 部署就绪情况——即相同的容器可以在真实的 编排器下运行,并具备健康探针、启动顺序和服务发现—— 而不是作为第二种开发依赖。 [安全工作流](.github/workflows/security-ci.yml) 中的 GitHub Actions `deploy` 作业 在每次推送/PR 时自动证明这一点:它构建后端和前端镜像, 在 runner 上启动一个一次性的 [kind](https://kind.sigs.k8s.io/)(Kubernetes-in-Docker) 集群,将镜像加载到其中(无需 registry、无需云 账户、无需任何凭据),应用 `deploy/k8s/` 中的每个清单文件, 等待所有 pod 就绪,并通过 `kubectl port-forward` 对 后端健康端点和前端进行冒烟测试。 集群和镜像在作业完成时会被丢弃。 与 compose 设置相比已知的、有意的简化(所有这些 都是因为这是一个演示,而不是生产环境的清单集合): - 没有 `Secret` 对象——每个值都是已经在 `.env.example` 中 有意提交的演示凭据,为简单起见保存在 `ConfigMap` 中。 真正的部署应该使用 `Secret` 或外部密钥管理器。 - 没有 `PersistentVolumeClaim`——Postgres 和 Redis 数据在 pod 重启后不会保留。对于每次 CI 运行或本地演示 会话都会重新创建的集群来说没有问题;对于任何需要保留数据的情况则不合适。 - 前端的 `NEXT_PUBLIC_*` 值在 `docker build` 时被固化到镜像中(这是 Next.js 的限制,而不是 Kubernetes 的限制)——仅更改 `deploy/k8s/frontend/configmap.yaml` 无效;必须使用匹配的 `--build-arg` 值重新构建 镜像。 - `deploy/k8s/ingress.yaml` 需要一个 ingress controller(例如 `ingress-nginx`),而 kind 默认不安装它。CI 的冒烟测试 使用 `kubectl port-forward` 代替,这证明了相同的 Service 到 Pod 的路由,且设置要少得多;Ingress 清单 是为在本地安装 controller 的任何人提供的。 要在本地使用 [kind](https://kind.sigs.k8s.io/) 和 [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) 自行运行: ``` kind create cluster --name securetask docker build -t securetask-backend:local ./backend docker build ` --build-arg NEXT_PUBLIC_KEYCLOAK_URL=http://localhost:8081 ` --build-arg NEXT_PUBLIC_KEYCLOAK_REALM=securetask ` --build-arg NEXT_PUBLIC_KEYCLOAK_CLIENT_ID=securetask-frontend ` --build-arg NEXT_PUBLIC_API_PROXY_PATH=/api/backend ` -t securetask-frontend:local ./frontend kind load docker-image securetask-backend:local --name securetask kind load docker-image securetask-frontend:local --name securetask kubectl apply -f deploy/k8s/namespace.yaml kubectl create configmap keycloak-realm-import -n securetask ` --from-file=infra/keycloak/realms/securetask-realm.json ` --dry-run=client -o yaml | kubectl apply -f - kubectl apply -R -f deploy/k8s/ kubectl -n securetask rollout status deployment/backend kubectl -n securetask port-forward svc/frontend 3000:3000 ``` 如果清单的 `image:` 字段(`securetask-backend:ci` / `securetask-frontend:ci`)与上面的标签不匹配,请编辑 `deploy/k8s/backend/deployment.yaml` 和 `deploy/k8s/frontend/deployment.yaml` 改为 `:local`,或者将您的本地构建标记为 `:ci`。 ## 演示凭据 这些账户和密码是为本地演示有意提交的。 请勿在共享或生产环境中重复使用它们。 | 账户 | 密码 | 角色 | 演示内容 | | --- | --- | --- | --- | | `user1@example.com` | `User123!` | `USER` | 项目所有权和文档处理 | | `user2@example.com` | `User123!` | `USER` | 拒绝跨用户访问 | | `admin@example.com` | `Admin123!` | `ADMIN` | 管理项目和审计访问 | | `auditor@example.com` | `Auditor123!` | `AUDITOR` | 只读审计审查 | | `manager@example.com` | `Manager123!` | `MANAGER` | 附加演示角色 | ## 演示流程 1. 以 `user1@example.com` 身份登录,创建一个项目,并上传允许的 `.txt`、`.pdf`、`.png`、`.jpg` 或 `.jpeg` 文档。 2. 登出并以 `user2@example.com` 身份登录。尝试访问 user1 的 项目的请求将被拒绝,并返回 `403 Forbidden`。 3. 以 `admin@example.com` 或 `auditor@example.com` 身份登录,并在 审计日志页面上查看记录的事件。 4. 运行冒烟测试,以非交互方式重复执行核心的正面和负面安全检查。 ![项目详情和文档上传](https://static.pigsec.cn/wp-content/uploads/repos/cas/d1/d16954550d739429c04b98bbd8ca2e9e2f1ec913fa41e35d7e712e9bac38ef1e.png) ![审计日志审查](https://static.pigsec.cn/wp-content/uploads/repos/cas/fa/fa24d60069a29f7f5aaf833184e4b7d12fa7205a20b8ac3e7fb3bfb3a6914825.png) ## 安全设计 - 浏览器使用公共的 `securetask-frontend` OIDC 客户端,采用 Authorization Code Flow 和 S256 PKCE。 - Access token 保留在内存中,不存储在 `localStorage` 中。 - 后端验证 bearer JWT,并独立于前端强制执行项目所有权和 基于角色的访问。 - 上传限制为 5 MB,通过扩展名进行限制,以随机化 名称存储,并检查是否存在路径遍历。 - 审计记录排除了密码、token、密钥、文件内容和完整的 请求体。 - 仅限本地的 `securetask-smoke-test` Keycloak 客户端与 浏览器客户端分离。`securetask-frontend` 仍然禁用 直接访问授权。 - 前端和后端响应包含与 localhost 兼容的安全标头 基线。CSP 并非有意呈现为生产级别。 详细设计和限制: - [架构](docs/01-architecture.md) - [威胁模型](docs/02-threat-model.md) - [安全控制](docs/03-security-controls.md) - [OWASP Top 10 2025 和 API Security Top 10 2023 映射](docs/04-owasp-mapping.md) - [审计日志](docs/05-audit-logging.md) - [安全权衡](docs/06-security-tradeoffs.md) - [AppSec 演示场景](docs/07-demo-scenarios.md) - [MVP 项目计划](docs/00-project-plan.md) ## 审查清单 - [ ] 使用 `.env.example` 从全新的克隆开始。 - [ ] 确认前端将登录重定向到本地的 Keycloak realm。 - [ ] 完成 user1/user2 对象授权演示。 - [ ] 以 ADMIN 或 AUDITOR 身份审查审计事件。 - [ ] 在 [Swagger UI](http://localhost:8080/swagger-ui.html) 中检查受保护的操作。 - [ ] 运行 [`scripts/smoke-test.ps1`](scripts/smoke-test.ps1) 并确认所有检查通过。 - [ ] 审查 [AppSec 文档](docs/01-architecture.md)。 - [ ] 检查 [GitHub Actions 安全工作流](.github/workflows/security-ci.yml)。 ## 安全 CI [安全工作流](.github/workflows/security-ci.yml) 在推送到 `main`、Pull Request 和手动调度时运行。它使用免费工具,并且 不会部署到真实的基础设施——仅在 runner 本地使用一个一次性的 `kind` 集群: - Java 21 上的 Maven 后端测试 - Node.js 上的前端锁定安装、lint 和生产构建 - Gitleaks 密钥扫描 - Trivy 高/严重级别依赖项扫描 - Actionlint 工作流验证 - Kubernetes 部署演示:构建两个镜像,将 [`deploy/k8s/`](deploy/k8s/) 应用到 `kind` 集群,并对其进行冒烟测试(请参阅 上面的 [Kubernetes(演示)](#kubernetes-demonstration)) ## 本地演示限制 本仓库演示的是控制措施;它不是生产部署 蓝图。 - 服务使用普通的 HTTP 和特定于 localhost 的源。 - 演示凭据和冒烟测试密码授权客户端特意 仅限本地使用。 - 密钥通过本地 `.env` 文件提供,而不是使用密钥 管理器。 - 上传的文件使用本地文件系统存储,没有恶意软件扫描。 - PostgreSQL 和 Keycloak 使用面向开发的 Docker 配置运行。 - CSP 允许 localhost 前端、Keycloak 和 Swagger UI 所需的源;生产环境应使用 HTTPS 和特定于部署的、 基于 nonce/hash 的策略。 - 审计日志没有外部保留、警报或防篡改存储。 - `/actuator/prometheus` 未经身份验证(与 健康端点一起被允许),以便本地 Prometheus 可以在没有抓取凭据的情况下抓取它; 真正的部署会将其置于网络策略或仅限抓取的 token 之后,而不是公开暴露它。 - Prometheus 和 Grafana 在没有配置持久存储或警报规则 的情况下运行——指标在容器重新创建时重置,并且没有 alertmanager。 - 可用性、备份和密钥轮换控制超出了本演示的 范围。 ## 仓库布局 ``` backend/ Spring Boot resource server frontend/ Next.js TypeScript application infra/keycloak/ Local Keycloak realm import infra/prometheus/ Prometheus scrape config infra/grafana/ Grafana datasource/dashboard provisioning deploy/k8s/ Kubernetes manifests (deployment-readiness demo, see above) scripts/ Reviewer smoke test docs/ Architecture and AppSec documentation .github/workflows Security CI ```
标签:域名枚举, 子域名突变, 搜索引擎查询, 测试用例, 版权保护, 自定义请求头