Files
DECNET/tests/api/test_schemathesis_ttp.py
anti 9a31d0e50c feat(ttp): E.3.17 worker registration + scoped schemathesis suite
Wires decnet-ttp as a first-class worker:

* `decnet ttp` CLI command (master-only via MASTER_ONLY_COMMANDS)
* deploy/decnet-ttp.service.j2 systemd unit (After= identity / intel
  / reuse-correlator workers; ProtectHome=read-only since
  FilesystemRuleStore only reads ./rules/ttp/)
* deploy/decnet.target Wants= chain extended with decnet-ttp.service
* `ttp` was already in web/worker_registry.KNOWN_WORKERS

tests/api/test_schemathesis_ttp.py: TTP-routes-only schemathesis
suite, filtered via the OpenAPI tags=["TTP Tagging"] annotation
shared by the eight TTP routes. Reuses the live uvicorn subprocess
the wider test_schemathesis spawns; max_examples=400 keeps the
focused gate fast for E.3.13–E.3.16 iteration.

wiki-checkout/Service-Bus.md committed in its own repo: ttp.tagged
and ttp.rule.fired.<id> flipped from "reserved (TTP worker)" to
"decnet.ttp.worker" now that the worker publishes them.
2026-05-01 21:26:46 -04:00

88 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Schemathesis contract tests scoped to the TTP Tagging API surface.
E.3.17 of ``development/TTP_TAGGING.md``. The full ``test_schemathesis``
suite fuzzes every endpoint with ``max_examples=3000`` — slow and
overkill when iterating on TTP-routes-only changes (E.3.13E.3.16).
This file filters by the OpenAPI ``tags=["TTP Tagging"]`` annotation
the eight TTP routes carry, runs against the same live uvicorn
subprocess the wider suite spins up, and applies the same check
battery so a 4xx-shape regression on a TTP route fails here without
waiting on the rest of the API.
Routes covered (all decorated ``tags=["TTP Tagging"]``):
* ``GET /api/v1/ttp/techniques``
* ``GET /api/v1/ttp/by-identity/{identity_uuid}``
* ``GET /api/v1/ttp/by-attacker/{attacker_uuid}``
* ``GET /api/v1/ttp/by-campaign/{campaign_uuid}``
* ``GET /api/v1/ttp/by-session/{session_id}``
* ``GET /api/v1/ttp/rules``
* ``POST /api/v1/ttp/rules/{rule_id}/state``
* ``DELETE /api/v1/ttp/rules/{rule_id}/state``
* ``GET /api/v1/ttp/export/navigator``
* ``GET /api/v1/ttp/export/navigator/identity/{identity_uuid}``
"""
from __future__ import annotations
import pytest
import schemathesis as st
from hypothesis import HealthCheck, Verbosity, settings
from tests.api.test_schemathesis import (
ALL_CHECKS,
AUTH_CHECKS,
LIVE_SERVER_URL,
before_call as _shared_before_call, # noqa: F401 (registers @st.hook)
)
# Reuse the schema fetched against the same uvicorn subprocess started
# by ``test_schemathesis``. Filtering by tag keeps the TTP suite a
# fast, focused contract gate without re-spinning the server.
TTP_SCHEMA = st.openapi.from_url(
f"{LIVE_SERVER_URL}/openapi.json",
).include(tag="TTP Tagging")
@pytest.mark.fuzz
@TTP_SCHEMA.parametrize()
@settings(
max_examples=400,
deadline=None,
verbosity=Verbosity.normal,
suppress_health_check=[
HealthCheck.filter_too_much,
HealthCheck.too_slow,
HealthCheck.data_too_large,
],
)
def test_ttp_schema_compliance(case):
"""Per-TTP-route schema compliance — valid + invalid inputs."""
case.call_and_validate(checks=ALL_CHECKS)
@pytest.mark.fuzz
@TTP_SCHEMA.parametrize()
@settings(
max_examples=120,
deadline=None,
verbosity=Verbosity.normal,
suppress_health_check=[
HealthCheck.filter_too_much,
HealthCheck.too_slow,
],
)
def test_ttp_auth_enforcement(case):
"""Every TTP route rejects requests without a Bearer token (401).
The mutation endpoints additionally require ``admin`` (server-side
``require_admin``); the authless probe doesn't distinguish 401 vs
403 here — the ``ignored_auth`` check just asserts that an absent
token never lands the request inside the handler with a usable
identity.
"""
case.headers = {
k: v for k, v in (case.headers or {}).items()
if k.lower() != "authorization"
}
case.call_and_validate(checks=AUTH_CHECKS)