NikaNats/Sentinel

GitHub: NikaNats/Sentinel

Sentinel是一款基于.NET 10的零信任API安全框架。

Stars: 0 | Forks: 0

# 哨兵 Sentinel 是一个以安全为重点的 ASP.NET Core Web API,它强制执行与 FAPI 2.0 基线和高级强化目标一致的发送者约束令牌验证模式。 当前实现提供: - DPoP 访问令牌处理,包括证明验证和nonce发行 - 支持Redis的访问令牌jti和DPoP证明jti的重放检测 - ACR和基于作用域的授权要求 - 对cnf.x5t#S256绑定的令牌进行mTLS证书绑定检查 - 严格的JWT算法约束和零时钟偏移生存期验证 - 安全遥测、安全头、速率限制和结构化错误处理 ## 规范和交付工件 - 规范:[SPEC-0001 - 用户身份验证和令牌发行](./.specify/specs/SPEC-0001-auth-token-issuance.md) - 实施计划:[PLAN-0001 - 身份验证实施](./.specify/plans/PLAN-0001-auth-implementation.md) - 任务分解:[TASK-0001 - 身份验证实施任务](./.specify/tasks/TASK-0001-auth-implementation.md) ## 综合文档套件 **适用于所有受众的生产级文档。** 从[文档索引](./docs/README.md)开始。 | 文档 | 受众 | 目的 | |----------|----------|---------| | [ARCHITECTURE.md](./docs/ARCHITECTURE.md) | 架构师、工程师 | 10个架构决策记录(ADRs)解释DPoP、重放缓存、速率限制、nonce管理、中间件排序、幂等性和运营设计 | | [SDK_LESS_INTEGRATION_GUIDE.md](./docs/SDK_LESS_INTEGRATION_GUIDE.md) | 客户端开发者 | 完整的HTTP/REST集成指南,包括5种语言(JS、Python、Java、C#、Go)的DPoP证明生成和完整的端到端示例 | | [LIVING_THREAT_MODEL.md](./docs/LIVING_THREAT_MODEL.md) | 安全团队、审计员 | 7个类别中21个已识别的威胁,包括缓解分析、可能性×影响矩阵和剩余风险评估 | | [SRE_SOC_RUNBOOKS.md](./docs/SRE_SOC_RUNBOOKS.md) | SRE、SOC、值班 | 监控、警报、事件响应程序、故障排除指南和维护清单,包括bash/PowerShell命令 | | [COMPLIANCE_AUDIT_MATRIX.md](./docs/COMPLIANCE_AUDIT_MATRIX.md) | 合规性、审计员 | 合规性框架映射(OAuth 2.0、JWT、DPoP RFC 9449、FAPI 2.0 基线)以及40多个审计清单项 | | [OPENAPI_3_1.yaml](./docs/OPENAPI_3_1.yaml) | API消费者 | 正式的OpenAPI 3.1规范;用于SDK生成和API网关集成的机器可读API合同 | | [BUILD_CONFIGURATION_GUIDE.md](./docs/BUILD_CONFIGURATION_GUIDE.md) | 开发者、DevOps | Directory.Build.props解释、构建工作流、代码分析策略、AOT/可重用性以及故障排除 | **按角色快速入门:** - **客户端开发者:** 从[SDK_LESS_INTEGRATION_GUIDE.md](./docs/SDK_LESS_INTEGRATION_GUIDE.md)和[OPENAPI_3_1.yaml](./docs/OPENAPI_3_1.yaml)开始 - **SRE / 运营:** 从[SRE_SOC_RUNBOOKS.md](./docs/SRE_SOC_RUNBOOKS.md)开始 - **安全 / 合规性:** 从[LIVING_THREAT_MODEL.md](./docs/LIVING_THREAT_MODEL.md)和[COMPLIANCE_AUDIT_MATRIX.md](./docs/COMPLIANCE_AUDIT_MATRIX.md)开始 - **架构师 / 首席工程师:** 从[ARCHITECTURE.md](./docs/ARCHITECTURE.md)开始 - **开发者 / DevOps:** 从[BUILD_CONFIGURATION_GUIDE.md](./docs/BUILD_CONFIGURATION_GUIDE.md)开始 ## 实施状态 | 区域 | 状态 | 备注 | |---|---|---| | API主机和中间件管道 | 实现 | 安全中间件链和集中异常处理是活动的 | | JWT验证和策略授权 | 实现 | 发行者、受众、生存期、算法验证、ACR和作用域强制执行 | | DPoP证明验证 | 实现 | htm、htu、iat窗口、typ、alg、jwk、cnf.jkt检查;符合RFC 9449的nonce挑战-响应 | | 重放保护 | 实现 | 原子Redis支持的jti缓存(SET NX),失败关闭行为,60秒TTL与令牌生存期对齐 | | DPoP nonce管理 | 实现 | 每个JWK指纹旋转nonce;原子比较-删除事务防止消费竞争;在陈旧/已消费不匹配时挑战发行新鲜nonce | | mTLS令牌绑定 | 实现 | cnf.x5t#S256与提供的客户端证书哈希值比较;可选的第二因素 | | 速率限制 | 实现 | 双分区链式强制执行:身份分区(sub+client_id或匿名时的per-IP)和始终存在的IP分区;429响应包括Retry-After头 | | 幂等性强制执行 | 实现 | 注销幂等性具有状态机(IN_PROGRESS→409,COMPLETED→204) | | 会话管理 | 实现 | 刷新令牌轮换;注销时会话黑名单;TTL与Keycloak(默认8小时)对齐 | | OpenTelemetry和度量端点 | 实现 | 跟踪、度量计数器/直方图、Prometheus抓取端点;安全事件遥测 | | 集成和单元测试 | 实现 | 50/50测试通过,具有完整的场景覆盖 | | 全OAuth PAR和PKCE编排端点集 | 计划/外部化 | Keycloak驱动的流程编排仍然是基础设施和客户端驱动的 | ## 架构概述 ### 运行时管道 API管道以防御深度序列应用控制: 1. 全局异常处理和问题详情格式化 2. 安全响应头强化(HSTS、CSP、frame-deny、no-sniff、cache-control) 3. 全局固定窗口速率限制器(per-identity + per-IP双分区) 4. JWT身份验证(发行者、受众、生存期、算法验证) 5. 速率限制器评估(两个分区都必须有可用配额) 6. DPoP验证中间件(证明结构、签名、htm/htu绑定、nonce验证) 7. mTLS证书绑定中间件(可选cnf.x5t#S256验证) 8. ACR存在验证中间件 9. 授权策略强制执行(作用域、每个端点的ACR要求) 10. 控制器端点执行 11. 响应头(DPoP-Nonce用于下一个请求轮换) 12. Prometheus抓取端点(/metrics) ### 核心安全组件 - **DPoP验证器**强制执行RFC 9449合规性:验证证明签名、类型、算法、htm/htu绑定、iat新鲜度(±60秒)、jti证明重放通过原子Redis缓存、以及每个指纹的nonce消费 - **重放缓存**存储JWT jti和证明jti,使用原子SET NX(When.NotExists)语义;Redis不可用时返回503失败关闭 - **nonce存储**管理每个JWK指纹旋转nonce;原子比较-删除事务防止消费竞争;在陈旧/已消费不匹配时挑战发行新鲜nonce - **速率限制器**实现双分区链式强制执行:身份分区(sub+client_id或匿名时的per-IP)和始终存在的IP分区;429响应包括Retry-After头 - **安全事件发射器**生成具有关联ID的结构化OpenTelemetry Activity事件,用于SIEM切换 - **ACR和作用域授权处理程序**在端点级别使用声明验证应用细粒度策略检查 ## 仓库布局 ``` Sentinel/ |- Sentinel.slnx |- Directory.Build.props ← Centralized build config (all projects inherit) |- docker-compose.yml |- Makefile |- docs/ | |- README.md ← Documentation index | |- ARCHITECTURE.md ← ADRs (10 decisions) | |- SDK_LESS_INTEGRATION_GUIDE.md ← Client integration (5 languages) | |- LIVING_THREAT_MODEL.md ← Security threat analysis (21 threats) | |- SRE_SOC_RUNBOOKS.md ← Operational procedures | |- COMPLIANCE_AUDIT_MATRIX.md ← Regulatory framework mapping | |- OPENAPI_3_1.yaml ← API specification (OpenAPI) | |- BUILD_CONFIGURATION_GUIDE.md ← Build config explanation & workflow |- artifacts/ ← Centralized build output (bin/obj) | |- bin/ | |- obj/ |- infra/ | |- keycloak/ | |- realms/ | |- sentinel.json |- .github/ | |- workflows/ | |- agents/ | |- prompts/ |- .specify/ | |- specs/ | |- plans/ | |- tasks/ |- src/ | |- Sentinel.Domain/ | |- Sentinel.Application/ | |- Sentinel.Infrastructure/ | |- Sentinel.AspNetCore/ |- tests/ | |- Sentinel.Tests/ | |- Integration/ | |- Unit/ |- artifacts/ ← Build output (bin/obj centralized) ``` ## 技术堆栈 | 组件 | 版本 | 用途 | |---|---|---| | .NET SDK | 11.0 preview | 构建 和 运行时 | | ASP.NET Core | 11.0 preview packages | API框架和中间件 | | Keycloak | 26.1 image in compose | 授权服务器和领域管理 | | Redis | 7.4 alpine | 重放缓存后端存储 | | OpenTelemetry | 1.13 to 1.14 packages | 跟踪、度量、导出器集成 | | xUnit + Testcontainers | 当前项目引用 | 单元和集成验证 | ## 先决条件 - Windows、Linux或macOS开发环境 - 安装.NET 11 SDK预览版 - Docker Desktop或Docker Engine - 可选:Trivy进行镜像漏洞扫描 ## 构建配置 **Directory.Build.props**为所有项目提供集中配置: | 功能 | 设置 | 目的 | |---------|---------|---------| | **工件布局** | `UseArtifactsOutput: true` | 中心化的bin/obj → artifacts/文件夹(无树污染) | | **框架** | `TargetFramework: net11.0` | .NET 11预览(最新) | | **代码分析** | `AnalysisLevel: latest-all` | 严格的代码质量检查(尽早捕捉问题) | | **警告作为错误** | 发布/CI仅限 | 零警告策略;在CI阶段强制执行 | | **AOT兼容性** | 可用于可执行文件 | 本地AOT就绪;修剪安全的代码分析 | | **安全** | NuGetAudit、ControlFlowGuard | 阻止易受攻击的包;启用控制流保护 | | **可重用构建** | `Deterministic: true` | 开发机二进制文件 = CI二进制文件(无差异) | | **语言** | `Nullable: enable`、`ImplicitUsings: enable` | 现代C#,具有严格的空安全 | | **锁文件** | `RestorePackagesWithLockFile: true` | 冻结的传递依赖关系以实现可重用性 | 所有项目自动继承这些设置;仅在必要时在单个.csproj中进行覆盖。 ## 快速入门 交互式API参考(仅限开发): http://localhost:5260/scalar ### 1. 还原、构建、测试 ``` dotnet restore Sentinel.slnx --locked-mode dotnet build Sentinel.slnx -c Release dotnet test Sentinel.slnx ``` ### 2. 使用Docker Compose启动本地基础设施和API ``` docker-compose up --build -d ``` 服务: - Keycloak:https://localhost:8443 和 http://localhost:8080 - Redis:localhost:6379 - Sentinel API:http://localhost:5260 ### 3. 直接运行API(不使用Compose) ``` cd src/Sentinel.AspNetCore dotnet run ``` ### 4. 停止本地堆栈 ``` docker-compose down -v ``` ## 强名称签名(混合模型) Sentinel强制对所有程序集执行强名称签名。本地开发使用`PublicSign`与`Sentinel.public.snk`(已提交到源代码控制)当私有密钥不可用或在不支持Windows的系统上构建时,而CI/CD发布构建执行完整的签名,通过注入通过机密注入的私有密钥。 为了防止在积极本地开发期间`InternalsVisibleTo`与未签名的测试项目之间的加密冲突,仅在官方发布打包期间条件性地启用程序集签名。 ### 生成强名称密钥(本地安全管理员) ``` sn -k Sentinel.snk ``` ### 提取公钥(用于PublicSign场景) ``` sn -p Sentinel.snk Sentinel.public.snk ``` ### 使用强名称签名编译和打包 要构建和打包带有强名称签名的生产NuGet库,请传递SignSentinelRelease=true属性: ``` dotnet pack Sentinel.slnx -c Release -p:SignSentinelRelease=true -o ./artifacts ``` ### CI/CD安全签名(GitHub Actions) 1. 将base64编码的Sentinel.snk存储在GitHub Secrets中(例如 SENTINEL_SNK_BASE64)。 2. 在.github/workflows/security-pipeline.yml中,在构建之前将机密解码到工作区: ``` - name: Restore strong-name key (Staging/Release Only) if: ${{ secrets.SENTINEL_SNK_BASE64 != '' }} shell: bash run: echo "$SENTINEL_SNK_BASE64" | base64 -d > Sentinel.snk env: SENTINEL_SNK_BASE64: ${{ secrets.SENTINEL_SNK_BASE64 }} ``` 这使私有密钥不在源代码控制中,同时确保发布构建得到完全签名。 ## Make目标 ``` make build # locked restore + release build make test # run all tests make mutation # run mutation tests for DPoP-critical paths make lint # dotnet format verification make sec-scan # build image + trivy scan (critical/high) make up # docker-compose up --build -d make down # docker-compose down -v make all # build + lint + test + sec-scan ``` ## 变异测试(安全网关) 变异测试通过Stryker.NET配置为DPoP关键代码路径: ``` dotnet tool restore dotnet stryker --config-file stryker-config.json ``` 基线网关阈值: - break: 70 - low: 70 - high: 85 ## 配置参考 所需的最小密钥: | 密钥 | 目的 | 示例 | |---|---|---| | ConnectionStrings:Redis | 重放缓存后端 | localhost:6379 | | Keycloak:Authority | 令牌发行者权威 | https://localhost:8443/realms/sentinel | | Keycloak:Audience | 期望的访问令牌受众 | sentinel-api | | Keycloak:RequireHttpsMetadata | Dev元数据通过HTTP切换 | false(仅限开发) | | FeatureFlags:Auth:DpopFlow | 功能切换占位符 | true | 注意: - 生产部署应保留HTTPS元数据要求。 - Redis可用性是安全边界的一部分;当Redis不可用时,服务降级为失败关闭(返回503服务不可用),阻止所有受保护资源访问,直到Redis恢复。 ## API表面 ### 受保护端点 - GET /v1/Profile 要求: - 通过带有DPoP方案的Authorization头传递经过身份验证的JWT - DPoP头中的匹配DPoP证明 - 满足策略ReadProfile: - 作用域包括profile - acr声明符合最小acr2 示例响应模型: ``` { "sub": "subject-id", "displayName": "display name", "roles": ["user"] } ``` ## 安全控制 实现了RFC 9449(DPoP)+ FAPI 2.0基线强化控制: **JWT验证:** - 发行者和受众是必需的;与Keycloak领域配置进行验证 - 生存期是必需的,具有零时钟偏移容差 - 签名令牌是必需的;算法白名单限制为ES256、RS256、PS256 - JTI(JWT ID)重放检测:存储在Redis缓存,TTL与令牌生存期匹配(60秒) - 重复JTI拒绝:返回503服务不可用(失败关闭) **DPoP证明验证(RFC 9449):** - 令牌和证明格式验证 - 类型必须是`dpop+jwt`;算法限制为ES256、RS256、PS256 - 内嵌的公共JWK是必需的;拒绝私钥材料 - 签名与内嵌的JWK进行验证 - `htm`(HTTP方法)和`htu`(HTTP URI)绑定强制执行并与请求进行比较 - `iat`新鲜度窗口强制执行(±60秒时钟偏移容差) - 访问令牌`cnf.jkt`必须与证明JWK指纹匹配(S256) - 证明JTI重放通过原子Redis SET NX(When.NotExists)缓存阻止 - 证明声明中必需每个JWK指纹的nonce - 通过Redis事务比较-删除原子消费nonce(防止重用) **nonce挑战-响应(RFC 9449 §4.3):** - 服务器发行的nonce包含在`DPoP-Nonce`响应头中 - nonce与客户端的JWK指纹绑定;每个身份的nonce序列 - nonce生存期:60秒;过期触发挑战重新发行 - 初始未经过身份验证的请求返回400 Bad Request + nonce挑战 - 客户端在下一个证明中包含nonce;服务器在消费之前进行验证 - 陈旧/已消费nonce触发新的挑战发行,带有新鲜nonce - 客户端必须从每个响应头中更新缓存的nonce **访问令牌重放防御:** - JTI声明是必需的并强制执行 - 在令牌生存期内(60秒)重复JTI被拒绝 - Redis故障触发失败关闭行为(503服务不可用) **mTLS发送者约束(可选):** - `cnf.x5t#S256`与提供的客户端证书SHA-256哈希值进行比较 - 启用可选的第二因素绑定(mTLS + DPoP) **速率限制:** - 双分区链式强制执行: - **身份分区**:如果经过身份验证则为`{sub}:{client_id}`;如果匿名则为`{remote_ip}` - **IP分区**:始终`{remote_ip}`(分层防御) - 两个分区都必须有可用配额;如果任一耗尽则返回429 Too Many Requests - 每个身份配额:10-20 req/min(可配置;身份验证端点较低) - 每个IP配额:100 req/min(可配置;匿名隔离) - 逐步降级:429响应包括`Retry-After`头 **会话管理:** - 刷新令牌轮换在每次刷新时强制执行 - 检测到刷新令牌重用;第二次使用触发会话黑名单并强制重新身份验证 - 注销时进行会话黑名单;TTL与Keycloak `SsoSessionMaxLifespanSeconds`(默认8小时)对齐 - 注销时强制执行幂等性:需要`Idempotency-Key`头 - 幂等性状态机:IN_PROGRESS(409)与COMPLETED(204)的区别 - 支持后端通道注销(Keycloak发起的会话终止) **HTTP响应强化:** - HSTS(HTTP Strict-Transport-Security):最大1年max-age - CSP(Content-Security-Policy):限制内联脚本、外部资源 - X-Content-Type-Options:nosniff(防止MIME类型嗅探) - X-Frame-Options:DENY(防止点击劫持) - X-XSS-Protection:1;mode=block(浏览器XSS过滤器) - Referrer-Policy:strict-origin-when-cross-origin - Permissions-Policy:限制API功能 - Cache-Control:no-store,must-revalidate(防止缓存敏感响应) - 删除服务器和X
标签:API安全, DPoP, FAPI 2.0, JSON输出, JWT算法, ML-DSA签名, .NET开发, SD-JWT, Streamlit, 多人体追踪, 多因素认证, 威胁模型, 安全文档, 安全策略, 安全运营, 实时信号, 开发者指南, 扫描框架, 提示词设计, 搜索引擎查询, 架构设计, 用户代理, 访问控制, 证书绑定, 量子安全, 错误处理, 零信任安全