Endpoint Monitor
A typed, unauthenticated FastAPI service that keeps endpoint monitor definitions in concurrency-safe process-local memory and checks HTTP(S) targets on demand. It measures total latency, records the final HTTP status, follows bounded redirects, emits redacted JSON events, and rejects SSRF destinations at every hop.
Security and operational boundaries
The service is deliberately unauthenticated; expose it only on a trusted network. It rejects credentials in URLs and rejects every DNS result set containing a non-global address (loopback, RFC1918/private, link-local, reserved, multicast, or unspecified). Approved DNS answers are pinned into the actual connection resolver, closing the resolution/connection DNS-rebinding gap. Redirects receive the same checks. Response bodies are never consumed.
State is process-local and ephemeral. Restarting loses all monitors, and multiple workers would each have divergent state. Run exactly one worker, as the supplied commands do. Use a persistent shared store before scaling horizontally.
Layout
See docs/service-design.md for the complete contract. Application modules are under app/, tests under tests/, and validation evidence/checklists in docs/verification.md.
Local development
Python 3.12 is required.
python -m venv .venv
. .venv/bin/activate
python -m pip install -e '.[dev]'
ruff format --check .
ruff check .
mypy app
pytest
uvicorn app.main:app --host 127.0.0.1 --port 8000 --workers 1
No test performs a real outbound request; checker transport and resolution are mocked.
API examples
curl -s http://127.0.0.1:8000/healthz
curl -s -X POST http://127.0.0.1:8000/v1/monitors \
-H 'content-type: application/json' \
-d '{"name":"example","url":"https://example.com/health"}'
curl -s http://127.0.0.1:8000/v1/monitors
curl -s -X POST http://127.0.0.1:8000/v1/monitors/MONITOR_UUID/check
curl -s http://127.0.0.1:8000/v1/monitors/MONITOR_UUID/status
curl -s -X PATCH http://127.0.0.1:8000/v1/monitors/MONITOR_UUID \
-H 'content-type: application/json' -d '{"name":"renamed"}'
curl -i -X DELETE http://127.0.0.1:8000/v1/monitors/MONITOR_UUID
Interactive OpenAPI documentation is at /docs. up means 200–399, down means 400–599, error means checking could not safely produce an HTTP response, and unknown means never checked.
Configuration
All settings are validated at startup.
| Variable | Default | Bounds |
|---|---|---|
MONITOR_APP_NAME |
endpoint-monitor |
string |
MONITOR_LOG_LEVEL |
INFO |
logging level |
MONITOR_REQUEST_TIMEOUT_SECONDS |
5 |
>0, <=30 |
MONITOR_CONNECT_TIMEOUT_SECONDS |
2 |
>0, <=10 |
MONITOR_MAX_REDIRECTS |
5 |
0–10 |
Container
docker build -t endpoint-monitor:local .
docker run --rm -p 8000:8000 endpoint-monitor:local
# or
docker compose up --build
The image uses a slim runtime, a non-root user, one Uvicorn worker, and an internal health check. Smoke test it with:
curl --fail http://127.0.0.1:8000/healthz
curl --fail http://127.0.0.1:8000/readyz
Logs contain JSON application events with query values replaced by REDACTED; Uvicorn access logging is disabled in the container so raw query strings are not reintroduced there.