Quickly detect if your information (passwords, emails, etc.) has been compromised before it's too late.
Version 1.0 β demo release
β Demo ready for testing. Production deployment optional and configurable.
LeakGuard is a set of microservices focused on early leak detection.
It allows checking if passwords or other sensitive data appear in known breaches and sends alerts.
This repo uses the MicroForge template to accelerate implementation and enforce best practices.
Main components:
- Password Checker Service (
password_checker_service): FastAPI app that checks passwords against the Have I Been Pwned (HIBP) public API using k-Anonymity (safe: full hash never sent). - Auth Service (
auth_service): user management (registration, email verification, JWT, protected endpoints, rate-limiting). - PostgreSQL: user persistence in Docker container (used by
auth_service). - Observability: Prometheus + Loki + Grafana for metrics, logs, and dashboards.
- Testing & CI:
pytest+unittest.mockfor deterministic tests; linters and formatters in CI.
- Client β requests
/check-passwordwith Bearer token. password_checker_servicevalidates the token viaauth_service(/users/me).- If the token is valid, queries HIBP using k-Anonymity (sends only first 5 chars of SHA-1).
- Responds
{ leaked: bool, times: int }. - Metrics and logs exported to Prometheus/Loki; dashboards in Grafana.
- Docker & Docker Compose (recommended)
- Python 3.11+
- (Optional)
uvicornto run services individually
git clone https://github.com/MetalCloud1/leakguard.git
cd leakguard
# Apply all namespaces
kubectl apply -f auth_service/infra/k8s/dev/namespace-dev/
kubectl apply -f monitoring-namespace.yamlThis starts: auth_service, password_checker_service, Postgres (optional for auth), Prometheus, Loki, and Grafana.
cd password_checker_service
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt -r requirements-test.txt
uvicorn src_pcs.app:app --reload --port 8001Useful endpoints:
GET http://localhost:8001/healthPOST http://localhost:8001/check-password
curl example (requires valid token from auth_service):
curl -sS -X POST http://localhost:8001/check-password \
-H "Authorization: Bearer <YOUR_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"password":"123456"}'Example response:
{
"leaked": true,
"times": 1000000
}Service configurable via 12-factor environment variables:
AUTH_SERVICE_URLβ URL of authentication microservice (defaulthttp://auth-service).USE_HIBPβ"true"/"false". Iffalse, service responds with fallback (useful for tests).HIBP_TIMEOUTβ Timeout (seconds) for HIBP requests (default5).LOG_LEVELβ Logging level (INFO,DEBUG,WARNING).- Standard Docker/Kubernetes vars (service names, networking).
Note: HIBP range endpoint requires no API key; other endpoints (e.g., breachedaccount) do, use .env or GitHub Secrets.
AUTH_SERVICE_URL=http://localhost:8000
USE_HIBP=true
HIBP_TIMEOUT=5
LOG_LEVEL=INFO
- Service calculates SHA-1 of password locally.
- Sends only the first 5 characters (
prefix) tohttps://api.pwnedpasswords.com/range/{prefix}. - Receives list of suffixes and occurrences; compares suffix locally.
- Never sends full password or hash externally.
Tests in tests/test_password_checker.py cover:
/healthendpoint (smoke test)/check-passwordwith valid token (mockingdecode_token_return_usernameandcheck_password_hibp)/check-passwordwith invalid token (mockingdecode_token_return_username)- Fallback (
USE_HIBP=false) β ensures env variable is read dynamically
pytest -q# Coverage
pytest --cov=src --cov-report=term-missing
# Lint / static analysis
ruff check .
black --check .
mypy srcdecode_token_return_usernameβ avoids calling auth service.check_password_hibpβ avoids real HIBP requests in CI.- Avoid manipulating global vars at import time; read
USE_HIBPper request or patch module var in tests.
use_hibp = os.environ.get("USE_HIBP", "true").lower() == "true"
if use_hibp:
times = check_password_hibp(request.password)
else:
times = 0@patch("password_checker_service.src_pcs.app.decode_token_return_username")
@patch("password_checker_service.src_pcs.app.check_password_hibp")
def test_check_password_with_hibp(mock_hibp, mock_decode):
mock_decode.return_value = "testuser"
mock_hibp.return_value = 1000000- Prometheus: FastAPI metrics β latency, request count, errors
- Loki: structured JSON logs for searching and correlation
- Grafana: preconfigured dashboards:
API latency (p50/p95/p99)Requests per secondError rate (4xx vs 5xx)Auth failures(invalid token count)
Scraping configuration in docker-compose.demo.yml and prometheus/prometheus.yml.
- Do not store passwords in plaintext or user dumps in the repo.
- HIBP used in read-only k-Anonymity mode β recommended way to check passwords.
- Real account features (notifications, locks) require explicit consent and compliance (GDPR/LPD).
- Use
GitHub Secretsfor sensitive CI/CD variables; do not commit.env.
- Containerize service (
Dockerfile) and usedocker-composefor staging. - Deploy on Render, Railway, AWS ECS/Fargate, Google Cloud Run, or Kubernetes (EKS/GKE).
- Configure readiness/liveness probes and resource limits.
- Enable TLS/HTTPS and WAF if public.
- Set alerts in Grafana/Prometheus for high errors or request spikes.
- Open an issue for proposed changes or bugs
- Submit PRs to
devbranch - Follow conventions:
blackfor formattingrufffor lintingmypyfor static typing- Tests using
pytestand mocks as needed
- Maintain MicroForge attribution when using template
Based on MicroForge template by Gilbert RamΓrez (MetalCloud1).
License: CC BY-NC-ND (see LICENSE.md).