mano8/security-tests-m8

GitHub: mano8/security-tests-m8

面向 FastAPI M8 微服务堆栈的可复用实时安全测试套件,以 pytest 插件与 CLI 双模式验证认证、授权、JWT、速率限制等 API 安全机制在真实运行环境中的有效性。

Stars: 2 | Forks: 0

# security-tests-m8 ![CI/CD](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg) [![PyPI version](https://img.shields.io/pypi/v/security-tests-m8)](https://pypi.org/project/security-tests-m8/) [![Python](https://img.shields.io/pypi/pyversions/security-tests-m8)](https://pypi.org/project/security-tests-m8/) [![PyPI Downloads](https://static.pepy.tech/personalized-badge/security-tests-m8?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/security-tests-m8) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/a412ae6b7fc443de829514a6c62ee5d4)](https://app.codacy.com/gh/mano8/security-tests-m8/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) [![codecov](https://codecov.io/gh/mano8/security-tests-m8/graph/badge.svg?token=8M408KN18A)](https://codecov.io/gh/mano8/security-tests-m8) [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/mano8/security-tests-m8/blob/main/LICENSE) 用于 FastAPI M8 认证和服务堆栈的可重用实时安全测试。 ## 目录 - [摘要](#summary) - [环境要求](#requirements) - [安装](#install) - [快速开始:CLI](#quick-start-cli) - [破坏性与非破坏性测试](#destructive-vs-non-destructive-tests) - [快速开始:pytest](#quick-start-pytest) - [工作原理](#how-it-works) - [配置](#configuration) - [环境变量](#environment-variables) - [选择 Env 文件](#choosing-an-env-file) - [部署环境预检](#deployment-env-preflight) - [CLI 与 pytest 模式](#cli-vs-pytest-mode) - [单服务用法](#single-service-usage) - [多服务用法](#multi-service-usage) - [可用测试套件](#available-suites) - [完整的认证服务示例](#full-auth-service-example) - [Pytest 标记](#pytest-markers) - [暴露的 Fixtures](#exposed-fixtures) - [实时堆栈注意事项](#notes-for-live-stacks) - [开发](#development) - [示例](#examples) ## 摘要 `security-tests-m8` 是一个 pytest 插件,同时包含一组可重用的测试套件类。它允许任何 FastAPI M8 项目运行最初为 `fa-auth-m8` 编写的相同实时安全检查,而无需在不同仓库之间复制测试文件。 它针对 **任何 issuer 为 `fa-auth-m8` 且下游服务基于 `fastapi-m8` 构建的 Docker Compose(或远程)堆栈** —— 而不仅仅是加固的参考堆栈。`hardened_m8` 部署只是贯穿本 README 使用的示例;只需更改配置,即可将相同的套件指向最小化、预发布或生产堆栈。该插件会在收集阶段探测实时堆栈,并自动跳过不适用于检测到的算法、token 模式或可用组件的检查(参见 [工作原理](#how-it-works))。 使用它来测试: - JWT 结构和 token 伪造保护 - RS256、ES256 和 HS256 算法行为 - 无状态、有状态和混合 token 模式 - 登录滥用、授权、IDOR、CORS、cookies、headers、metrics、健康检查、私有 API、头像、API keys 和速率限制 - 一个或多个下游 FastAPI M8 服务中的受保护 endpoint 这些测试针对真实的实时堆栈运行。它们不会 mock 你的认证服务。你只需将该包指向你正在运行的认证 URL、管理员凭据和可选的服务 URL,然后在你自己的测试文件中继承所需的套件类即可。 ## 环境要求 - Python 3.11 或更高版本 - `pytest` - 正在运行的 FastAPI M8 认证堆栈 - 一个可以通过 `/login/access-token` 登录的专用纯测试超级用户 - 用于受保护 endpoint 测试的可选下游 FastAPI M8 服务 URL ## 安装 从本仓库安装: ``` pip install -e . ``` 从其他项目安装(或更新到最新版本),在测试环境中安装该包: ``` pip install --upgrade security-tests-m8 ``` 该包通过 `pytest11` 入口点将自己注册为 pytest 插件,因此安装后会自动提供 fixtures 和标记。 ## 快速开始:CLI 对于常规的堆栈验证,请为测试运行器创建一个专用的实时测试 env 文件。在诸如 `/workspace/fa-auth-m8/examples/docker_compose/hardened_m8` 的堆栈目录下,创建一个包含 `LIVE_TEST_*` 值的 `test.env` 文件,替换掉所有的占位符密钥值,然后运行: ``` security-tests-m8 preflight --deployment-root . security-tests-m8 run --env-file test.env ``` `security-tests-m8 run` 在内部保留 pytest 作为执行引擎,但它会为你创建临时的包测试模块。默认情况下,它运行 `-m "live and not destructive"`,这样重复的 CLI 运行就不会有意改变登录锁定、会话或速率限制状态。你仍然可以在 `--` 之后传递 pytest 选择标志: ``` security-tests-m8 run --env-file test.env -- -ra security-tests-m8 run --env-file test.env --include-destructive security-tests-m8 run --env-file test.env -- -m live_asymmetric -ra ``` 常用命令: ``` security-tests-m8 run security-tests-m8 run --env-file test.env security-tests-m8 preflight security-tests-m8 preflight --deployment-root . security-tests-m8 scan-env --deployment-root . security-tests-m8 list-suites ``` ## 破坏性与非破坏性测试 非破坏性测试设计为对于重复的常规验证运行是安全的。它们读取实时 endpoint,检查 token 结构,验证访问控制,检查 headers/cookies,并避免有意消耗锁定或撤销状态。CLI 的 `run` 命令默认使用 `-m "live and not destructive"` 模式。 破坏性测试会有意改变实时的认证、会话、API-key、撤销或速率限制状态,以证明堆栈在遭受攻击时的行为。它们可能会触发登录锁定、撤销会话或 token、消耗速率限制计数器、创建或修改测试用户/API keys,或者导致后续测试失败,直到堆栈状态过期或被重置。仅当这种副作用是可以接受时才运行它们。 推荐的常规运行: ``` security-tests-m8 run --env-file test.env ``` 包含大量变更操作的完整运行: ``` security-tests-m8 run --env-file test.env --include-destructive pytest --live-env-file test.env --pyargs security_tests_m8.full_security -m live ``` 等效的非破坏性 pytest 运行: ``` pytest --live-env-file test.env --pyargs security_tests_m8.full_security -m "live and not destructive" ``` ## 快速开始:pytest 当你需要自定义本地测试、本地套件子类或直接使用 pytest 标记选择时,请使用 pytest 模式: ``` pytest --live-env-file test.env --pyargs security_tests_m8.full_security pytest --live-env-file test.env tests/live pytest --live-env-file test.env --pyargs security_tests_m8.full_security -m live_deployment ``` 该包通过 `pytest11` 入口点将自己注册为 pytest 插件。`--live-env-file` 会加载与 CLI 模式相同的实时测试 env 文件,而 `--live-env-override` 允许文件中的值替换现有的进程环境变量。 对于自定义的本地测试,请创建一个导入已打包套件的文件: ``` from security_tests_m8.full_security import * # noqa: F403 ``` ## 工作原理 该包包含三个部分: 1. 配置存储在进程级别的 `LiveTestConfig` 中。你可以通过 `security_tests_m8.configure(...)` 或环境变量来设置它。 2. pytest 插件暴露了诸如 `admin_token`、`admin_headers`、`regular_user`、`stack_config`、`service_base_url` 和 `service_url` 等 fixtures。 3. 套件类包含实际的测试。你的项目导入一个套件并继承它,这会使 pytest 在你的项目中收集这些测试。 当 `fail_fast_preflight=True` 时,插件会在收集之前检查认证健康状况、已配置的服务可用性、专用测试超级用户登录以及引导超级用户的滥用情况。如果堆栈不可用或凭据错误,pytest 会在整套测试触发锁定之前退出。 在收集阶段,插件会探测已配置的认证堆栈,并自动跳过与当前部署不匹配的测试。例如,在 HS256 堆栈上会跳过仅适用于 RS256 的测试,如果 Redis 不可用,则会跳过有状态的 Redis 检查。 ## 配置 你可以使用 Python 进行配置: ``` from pathlib import Path from security_tests_m8 import configure configure( auth_base_url="http://localhost:9000/user", admin_email="admin@example.com", admin_password="changethis", service_base_url="http://localhost:9000/fastapi", timeout=10, repo_root=Path(__file__).parents[2], deployment_root=Path(__file__).parents[2] / "examples/docker_compose/hardened_m8", public_base_url="https://localhost:4430", public_tls_verify=False, private_api_secret="changethis", private_api_client_id="media-service", refresh_secret_key="changethis", ) ``` 或者使用由 CLI `run`、pytest `--live-env-file` 或 `configure_from_env()` 加载的实时测试 env 文件: ``` LIVE_TEST_AUTH_BASE=http://localhost:9000/user LIVE_TEST_INTERNAL_AUTH_BASE=http://localhost:9000/user LIVE_TEST_AUTH_HEALTH_URL=http://localhost:9000/user/health/ LIVE_TEST_ADMIN_EMAIL=tester@example.com LIVE_TEST_ADMIN_PASSWORD=change-this-test-password LIVE_TEST_SVC_BASE=http://localhost:9000/fastapi LIVE_TEST_TIMEOUT=10 LIVE_TEST_FAIL_FAST_PREFLIGHT=true LIVE_TEST_FORBID_BOOTSTRAP_SUPERUSER=true LIVE_TEST_DEPLOYMENT_ROOT=/path/to/repo/examples/docker_compose/hardened_m8 LIVE_TEST_PUBLIC_BASE=https://localhost:4430 LIVE_TEST_PUBLIC_TLS_VERIFY=false ``` 对于使用自签名 Traefik 证书的本地 HTTPS 堆栈,设置 `LIVE_TEST_PUBLIC_TLS_VERIFY=false` 以禁用对配置的 实时测试目标 URL 的验证,或者将其设置为证书包路径,例如 `/path/to/hardened_m8/traefik/certs/local.crt`。 ### 环境变量 | 变量 | 用途 | 默认值 | | --- | --- | --- | | `LIVE_TEST_AUTH_BASE` | 认证服务的 Base URL | `http://localhost:9000/user` | | `LIVE_TEST_INTERNAL_AUTH_BASE` | 暴露 `/private/*` 的内部服务间入口。加固堆栈在公共边缘屏蔽 `/private` (Traefik → 404),因此 F06 针对每个消费者的旧版结构检查以此 URL 为目标。未设置时回退到 `LIVE_TEST_AUTH_BASE` | 未设置 | | `LIVE_TEST_AUTH_HEALTH_URL` | 用于就绪状态和堆栈检测的可选私有/内部认证健康检查 URL | 未设置 | | `LIVE_TEST_ADMIN_EMAIL` | 管理员登录邮箱 | `admin@example.com` | | `LIVE_TEST_ADMIN_PASSWORD` | 管理员登录密码 | `changethis` | | `LIVE_TEST_SVC_BASE` | 单个/默认下游服务 URL | 未设置 | | `LIVE_TEST_SVC_BASES` | 命名服务 URL 的 JSON 对象 | `{}` | | `LIVE_TEST_DEFAULT_SVC` | `LIVE_TEST_SVC_BASES` 中的默认服务名称 | 未设置 | | `LIVE_TEST_TIMEOUT` | 请求超时时间(秒) | `10` | | `LIVE_TEST_REPO_ROOT` | 用于发现已提交 JWT 密钥的仓库根目录 | 未设置 | | `LIVE_TEST_DEPLOYMENT_ROOT` | `DeploymentPreflightSuite` 使用的 Compose 部署目录 | 未设置 | | `LIVE_TEST_PUBLIC_BASE` | 用于公共/私有路由检查的公共 HTTPS 入口 | `https://localhost:4430` | | `LIVE_TEST_PUBLIC_TLS_VERIFY` | 配置的实时测试 HTTPS 目标 URL 的 TLS 验证设置;对于本地自签名堆栈,请使用 `false` 或 CA 证书包路径 | `true` | | `LIVE_TEST_PRIVATE_API_SECRET` | 用于私有 API 测试的 Secret header 值 (`X-Internal-Token`) | 未设置 | | `LIVE_TEST_PRIVATE_API_CLIENT_ID` | fa-auth-m8 >= 1.0.0 issuer 的消费者 ID (`X-Internal-Client`);对于旧版的单密钥堆栈请保持未设置状态 | 未设置 | | `LIVE_TEST_HEALTH_DETAIL_CREDENTIAL` | 解锁深层 `/health` 基础架构详情(token 模式、Redis/DB)的专用凭据 (`X-Internal-Token`);对于旧版堆栈,回退到 `LIVE_TEST_PRIVATE_API_SECRET` | 未设置 | | `LIVE_TEST_REFRESH_SECRET_KEY` | refresh/cookie 测试使用的 Refresh-token secret | 未设置 | | `LIVE_TEST_FAIL_FAST_PREFLIGHT` | 如果认证、服务或凭据不可用,在收集前中止 | `false` | | `LIVE_TEST_FORBID_BOOTSTRAP_SUPERUSER` | 拒绝将来自 `auth.env` 的 `FIRST_SUPERUSER` 作为测试账户 | `true` | | `LIVE_TEST_PROTECTED_ENDPOINTS` | 服务名称到受保护 endpoint 数组的 JSON 对象 | `{}` | ## 选择 Env 文件 `test.env` 用于配置测试运行器。它应该包含 `LIVE_TEST_*` 值,例如 `LIVE_TEST_AUTH_BASE`、`LIVE_TEST_ADMIN_EMAIL`、`LIVE_TEST_ADMIN_PASSWORD`、`LIVE_TEST_SVC_BASES` 和 `LIVE_TEST_DEPLOYMENT_ROOT`。`LIVE_TEST_PRIVATE_API_SECRET` 和 `LIVE_TEST_REFRESH_SECRET_KEY` 是可选的自愿启用值;仅当你希望进行 Secret 暴露检查(即使用真实的堆栈 secret 伪造请求)时才设置它们。 部署环境变量文件用于配置堆栈本身。诸如 `.env`、`auth.env`、`api.env`、`media.env`、`grafana/.env` 等文件,以及部署根目录下任何非示例的 `*.env` 文件,都会被部署预检扫描。诸如 `.env.example`、`auth.env.example`、`api.env.example`、`media.env.example`、`grafana/.env.example` 和 `test.env.example` 等示例/模板文件将被有意忽略。如果你将 `test.env` 放在部署根目录下,请不要在其中留下诸如 `changethis` 之类的占位符值,因为预检会报告它们。 ## 部署环境预检 部署预检扫描程序会检查 compose env 文件和内联的 compose `environment:` 值中是否存在占位符密钥、重复的高价值密钥、不安全的生产设置、默认凭据,以及加固/生产堆栈中未固定版本的镜像。 ``` security-tests-m8 preflight --deployment-root . security-tests-m8 preflight --env-file test.env security-tests-m8 preflight --deployment-root . --strict-warnings ``` 它会打印出所扫描的准确 env 和 compose 文件、所有发现的问题、明确的 PASS/FAIL 结果、产生该结果的原因,以及需要采取的操作。当没有错误时它退出代码为 `0`,当存在错误时退出代码为 `1`。警告会被打印出来,但只有在使用--strict-warnings` 时才会使命令失败。 ## CLI 与 pytest 模式 CLI 模式对于非高级用户来说是最简单的路径:指向一个 env 文件并运行打包的套件,而无需添加本地的 pytest 文件。它默认排除 `destructive` 测试;当你有意希望获得包含大量变更操作的全面覆盖时,请使用 `--include-destructive`。对于希望进行自定义测试、自定义套件子类、特定项目的 fixtures 或直接使用 pytest 标记表达式的团队来说,Pytest 模式是合适的选择。 两种模式都使用相同的配置模型和相同的可重用套件。 ## 单服务用法 对于只有一个下游服务的项目,请配置 `service_base_url`,并针对你要验证的每个受保护 endpoint 继承 `ProtectedEndpointSuite`。 ``` from security_tests_m8 import configure configure( auth_base_url="http://localhost:9000/user", service_base_url="http://localhost:9000/fastapi", admin_email="admin@example.com", admin_password="change-me", ) ``` ``` from security_tests_m8.suites import ProtectedEndpointSuite class TestCategories(ProtectedEndpointSuite): endpoint = "/category/" class TestDashboardActivity(ProtectedEndpointSuite): endpoint = "/dashboard/users/activity/" ``` 每个受保护的 endpoint 套件会检查: - 缺少 token 会被拒绝,返回 `401` 或 `403` - 无效的 bearer token 会被拒绝,返回 `401` 或 `403` - 有效的管理员 access token 会被接受,返回 `200` ## 多服务用法 对于包含多个 FastAPI M8 服务的堆栈,请配置一个命名的 URL 映射。 ``` from security_tests_m8 import configure configure( auth_base_url="http://localhost:9000/user", service_base_urls={ "catalog": "http://localhost:9000/catalog", "orders": "http://localhost:9000/orders", "billing": "http://localhost:9000/billing", }, default_service="catalog", admin_email="admin@example.com", admin_password="change-me", ) ``` 同样的设置也可以通过 shell 提供: ``` export LIVE_TEST_SVC_BASES='{"catalog":"http://localhost:9000/catalog","orders":"http://localhost:9000/orders","billing":"http://localhost:9000/billing"}' export LIVE_TEST_DEFAULT_SVC="catalog" ``` 然后为每个测试类选择服务: ``` from security_tests_m8.suites import ProtectedEndpointSuite class TestCatalogCategories(ProtectedEndpointSuite): service = "catalog" endpoint = "/category/" class TestOrderList(ProtectedEndpointSuite): service = "orders" endpoint = "/orders/" ``` 如果某个套件指定了一个未配置的服务,setup 将会失败,并列出已知的明确服务名称列表。 ## 可用测试套件 通用认证与 HTTP 安全套件: - `AuthAttackSuite` - `JWTStructuralSuite` - `AuthorizationSuite` - `RateLimitingSuite` - `CORSSuite` - `PrivateAPISuite` - `MetricsAPISuite` - `HealthAPISuite` - `AvatarUrlSuite` - `InfoDisclosureSuite` - `SecurityHeadersSuite` - `CookieSecuritySuite` - `ApiKeySuite` Token 模式套件: - `StatelessContractSuite` - `StatefulRevocationSuite` - `StatefulAccessRevocationSuite` - `HybridContractSuite` JWT 算法套件: - `AsymmetricJWTSuite` - `JWKSSuite` - `CrossServiceTokenSuite` - `HS256Suite` - `HS256WeakKeySuite` 通用服务与部署套件: - `ProtectedEndpointSuite` - `ConfiguredProtectedEndpointsSuite` - `ServiceInfoDisclosureSuite` - `ConfiguredServiceInfoDisclosureSuite` - `DeploymentPreflightSuite` ## 完整的认证服务示例 ``` from security_tests_m8.suites import ( ApiKeySuite, AsymmetricJWTSuite, AuthAttackSuite, AuthorizationSuite, AvatarUrlSuite, CookieSecuritySuite, CORSSuite, CrossServiceTokenSuite, HealthAPISuite, HS256Suite, HS256WeakKeySuite, HybridContractSuite, InfoDisclosureSuite, JWKSSuite, JWTStructuralSuite, MetricsAPISuite, PrivateAPISuite, RateLimitingSuite, SecurityHeadersSuite, StatefulAccessRevocationSuite, StatefulRevocationSuite, StatelessContractSuite, ) class TestAuthAttacks(AuthAttackSuite): pass class TestJWTStructure(JWTStructuralSuite): pass class TestAuthorization(AuthorizationSuite): pass class TestRateLimiting(RateLimitingSuite): pass class TestCORS(CORSSuite): pass class TestPrivateAPI(PrivateAPISuite): pass class TestMetrics(MetricsAPISuite): pass class TestHealth(HealthAPISuite): pass class TestAvatarUrls(AvatarUrlSuite): pass class TestInfoDisclosure(InfoDisclosureSuite): pass class TestSecurityHeaders(SecurityHeadersSuite): pass class TestCookieSecurity(CookieSecuritySuite): pass class TestApiKeys(ApiKeySuite): pass class TestStatelessMode(StatelessContractSuite): pass class TestStatefulRevocation(StatefulRevocationSuite): pass class TestStatefulAccessRevocation(StatefulAccessRevocationSuite): pass class TestHybridMode(HybridContractSuite): pass class TestAsymmetricJWT(AsymmetricJWTSuite): pass class TestJWKS(JWKSSuite): pass class TestCrossServiceTokens(CrossServiceTokenSuite): pass class TestHS256(HS256Suite): pass class TestHS256WeakKeys(HS256WeakKeySuite): pass ``` ## Pytest 标记 该插件注册了以下标记: - `live` - `live_security` - `live_asymmetric` - `live_hs256` - `live_stateful` - `live_stateless` - `live_hybrid` - `live_deployment` - `require_algorithm(*names)` - `require_token_mode(*names)` - `require_redis` - `destructive` 常用命令: ``` pytest tests/live -m live pytest tests/live -m "live and not destructive" pytest tests/live -m live_asymmetric pytest tests/live -m live_hs256 pytest tests/live -m live_stateful pytest tests/live -m live_stateless pytest tests/live -m live_hybrid ``` ## 暴露的 Fixtures 在安装了该包之后,消费者测试中可以使用以下 fixtures: - `stack_config` - `admin_token` - `admin_headers` - `admin_login` - `regular_user` — 作用于会话级别;创建一个一次性的 `redteam_@redteam-test.com` 非超级用户,并在会话结束时(尽最大努力,通过管理员账户)将其删除 - `live_jwks_keys` - `committed_key_forge` - `public_key_pem` - `asymmetric_key_pem` - `service_base_urls` - `service_base_url` - `service_url` 示例: ``` def test_custom_protected_route(service_url, admin_headers): import requests response = requests.get( f"{service_url('catalog')}/category/", headers=admin_headers, timeout=10, ) assert response.status_code == 200 ``` ## 实时堆栈注意事项 - 测试使用配置的专用纯测试超级用户来创建 token,并且对于某些套件,还会创建一个临时的普通用户。 - **一次性 `redteam_*` 用户。** `regular_user` fixture 会在每个会话中创建一个普通(非超级)用户账户,使用格式为 `redteam_@redteam-test.com` 的随机邮箱(密码为 `RedTeam!Pass99`),用于证明普通用户无法提升权限或访问仅限管理员的 routes。该 fixture **会在会话结束时通过管理员账户删除该用户**,因此常规运行不会留下长期存在的测试身份。删除操作是尽最大努力的:如果在运行 teardown 时堆栈不可达,该账户可能会残留,并且可以手动清理(通过 `redteam_*@redteam-test.com` 模式进行过滤)。你配置的专用**超级用户**绝不会由套件创建或删除——它必须事先存在,并由你自行管理。 - 不要使用堆栈的引导超级用户(`FIRST_SUPERUSER`)作为实时测试账户。在启用了 fail-fast 预检的情况下,该包默认会拒绝此配置。 - 一些测试被标记为 `destructive`,因为它们会执行撤销、速率限制、API key 变更或其他实时状态更改操作。CLI `run` 默认排除这些测试;传递 `--include-destructive` 以运行它们。 - 当算法和特定 token 模式的测试与检测到的堆栈不匹配时,它们会被自动跳过。 - `repo_root` 或 `LIVE_TEST_REPO_ROOT` 仅在尝试将实时 JWKS keys 与已提交的私钥进行比较的测试中才需要。 - `deployment_root` 或 `LIVE_TEST_DEPLOYMENT_ROOT` 启用用于 compose env/镜像检查的 Python 部署预检套件。 - `public_tls_verify=False` 对于使用自签名证书的本地 HTTPS 堆栈很有用。 - `LIVE_TEST_PRIVATE_API_SECRET` 和 `LIVE_TEST_REFRESH_SECRET_KEY` 是可选启用的检查。将它们留空以跳过这些检查,或者将它们设置为目标堆栈中的真实值。 - `LIVE_TEST_PRIVATE_API_CLIENT_ID` 是作为 `X-Internal-Client` 与 `X-Internal-Token` 一起发送的每个消费者的 ID,以便私有 API 探测能够针对基于每个消费者的 issuer (fa-auth-m8 >= 1.0.0,无共享密钥回退) 进行认证。将其与 `LIVE_TEST_PRIVATE_API_SECRET` 一起设置也可启用 F06 旧版检测检查(已废弃的、仅包含 `X-Internal-Token` 的结构必须被拒绝并返回 401)。对于旧版的单密钥堆栈,请将其留空。 - `LIVE_TEST_INTERNAL_AUTH_BASE` 是暴露 `/private/*` 的内部服务间入口。加固堆栈在公共边缘屏蔽 `/private` (Traefik → 404),因此 F06 旧版结构拒绝只能在内部入口上观察到。当 `LIVE_TEST_AUTH_BASE` 指向公共边缘时,将其设置为该 URL(例如 `http://localhost:9000/user`);未设置时它将回退到 `LIVE_TEST_AUTH_BASE`,这对于那些 Base 能直接到达私有 routes 的简单堆栈来说是正确的。 - `LIVE_TEST_HEALTH_DETAIL_CREDENTIAL` 解锁用于堆栈检测以及 token 模式/信息泄露套件的深层 `/health` 基础架构详情响应体(token 模式、Redis/DB 可达性、降级模式)。fa-auth-m8 >= 1.0.0 将该详情限制在与 `PRIVATE_API_SECRET` 解耦的专用凭据之后(方案 9.3),并通过 `X-Internal-Token` 发送。将其设置为堆栈的 `HEALTH_DETAIL_CREDENTIAL`,以便那些依赖健康状态的测试可以读取所需内容;仅在旧版堆栈(仍然将其复用于健康检查门控)时,探测才会回退到 `LIVE_TEST_PRIVATE_API_SECRET`。 ## 开发 安装带有开发依赖的包: ``` pip install -e ".[dev]" ``` 运行本地单元测试: ``` pytest ``` 根据需要使用你的项目工具运行格式化和 linting。该包使用来自 `pyproject.toml` 的 Ruff 设置。 ## 示例 在 [`examples/hardened_m8_full_security/`](examples/hardened_m8_full_security/) 中提供了一个可直接运行的完整安全测试示例。 此示例针对 `fa-auth-m8` 加固的 Docker Compose 堆栈运行完整的可重用套件: - 被测试的 compose 堆栈:[`mano8/fa-auth-m8/examples/docker_compose/hardened_m8`](https://github.com/mano8/fa-auth-m8/tree/main/examples/docker_compose/hardened_m8) - 本地工作区路径:`/workspace/fa-auth-m8/examples/docker_compose/hardened_m8` - 本仓库中的示例:[`mano8/security-tests-m8/examples/hardened_m8_full_security`](https://github.com/mano8/security-tests-m8/tree/main/examples/hardened_m8_full_security) 加固堆栈使用 RS256 access token、有状态 token 模式、由 Redis 支持的撤销机制、PostgreSQL、Traefik、Prometheus、Grafana,以及暴露在 `/fastapi` 的示例 `fastapi_full` 消费者。该示例需要一个专用的纯测试超级用户。CLI 模式加载通过 `--env-file` 传递的文件;本地 pytest 示例通过 `tests/live/conftest.py` 从其自身目录加载 `.env`。 `hardened_m8` 仅作为参考目标。只需调整配置(认证/服务 URL、受保护的 endpoint、部署根目录和 TLS 设置),该示例即可针对**任何使用 `fa-auth-m8` 作为 issuer 且使用基于 `fastapi-m8` 的消费者的 compose 堆栈**运行 —— 无论是最小化、预发布还是生产环境。该示例的两个随时可适配的副本位于它们所测试的堆栈旁边: - [`fa-auth-m8/examples/docker_compose/shared_live_tests`](https://github.com/mano8/fa-auth-m8/tree/main/examples/docker_compose/shared_live_tests) - [`media-service-m8/docker_compose/shared_live_tests`](https://github.com/mano8/media-service-m8/tree/main/docker_compose/shared_live_tests)
标签:API安全, JSON输出, Python, 安全测试, 安全规则引擎, 攻击性安全, 无后门, 版权保护, 逆向工具