{"id":31284867,"url":"https://github.com/metalcloud1/leakguard","last_synced_at":"2026-05-04T09:31:48.967Z","repository":{"id":312511131,"uuid":"1043927171","full_name":"MetalCloud1/LeakGuard","owner":"MetalCloud1","description":"🛡️ LeakGuard: Microservices for early detection of compromised passwords and sensitive data, with secure k-Anonymity checks, observability, and Docker-ready deployment.","archived":false,"fork":false,"pushed_at":"2025-08-31T05:37:58.000Z","size":450,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-31T07:17:00.027Z","etag":null,"topics":["ci-cd","data-protection","devops","docker","fastapi","grafana","haveibeenpwned","k-anonimity","leak-detection","loki","microservices","mocking","observability","password-security","posgresql","prometheus","pytest","python","security","security-testing"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MetalCloud1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-24T22:59:29.000Z","updated_at":"2025-08-31T05:38:01.000Z","dependencies_parsed_at":"2025-08-31T07:17:05.007Z","dependency_job_id":"95293ad4-acbb-4809-9124-0b3c5e31782a","html_url":"https://github.com/MetalCloud1/LeakGuard","commit_stats":null,"previous_names":["metalcloud1/leakguard"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/MetalCloud1/LeakGuard","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MetalCloud1%2FLeakGuard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MetalCloud1%2FLeakGuard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MetalCloud1%2FLeakGuard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MetalCloud1%2FLeakGuard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MetalCloud1","download_url":"https://codeload.github.com/MetalCloud1/LeakGuard/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MetalCloud1%2FLeakGuard/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276713376,"owners_count":25691389,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-24T02:00:09.776Z","response_time":97,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ci-cd","data-protection","devops","docker","fastapi","grafana","haveibeenpwned","k-anonimity","leak-detection","loki","microservices","mocking","observability","password-security","posgresql","prometheus","pytest","python","security","security-testing"],"created_at":"2025-09-24T07:34:27.516Z","updated_at":"2025-09-24T07:34:30.911Z","avatar_url":"https://github.com/MetalCloud1.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e🛡️ LeakGuard 🔐\u003c/h1\u003e\n\n\n*Quickly detect if your information (passwords, emails, etc.) has been compromised before it's too late.*\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Python-3.11%2B-3776AB?style=for-the-badge\u0026logo=python\u0026logoColor=white\"/\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Docker-Ready-2496ED?style=for-the-badge\u0026logo=docker\u0026logoColor=white\"/\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Status-Demo-FFA500?style=for-the-badge\u0026logo=githubactions\u0026logoColor=white\"/\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Template-MicroForge-2ecc71?style=for-the-badge\u0026logo=github\u0026logoColor=white\"/\u003e\n\u003c/p\u003e\n\n\n**Version 1.0 — demo release**  \n❗ Demo ready for testing. Production deployment optional and configurable.\n\n\n## 🔍 Project Overview\n\n**LeakGuard** is a set of microservices focused on **early leak detection**.  \nIt allows checking if passwords or other sensitive data appear in known breaches and sends alerts.  \nThis repo uses the **MicroForge** template to accelerate implementation and enforce best practices.\n\nMain components:\n\n- **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).\n- **Auth Service (`auth_service`)**: user management (registration, email verification, JWT, protected endpoints, rate-limiting).\n- **PostgreSQL**: user persistence in Docker container (used by `auth_service`).\n- **Observability**: Prometheus + Loki + Grafana for metrics, logs, and dashboards.\n- **Testing \u0026 CI**: `pytest` + `unittest.mock` for deterministic tests; linters and formatters in CI.\n\n---\n\n## 🏗️ Architecture (summary)\n\n1. Client → requests `/check-password` with Bearer token.\n2. `password_checker_service` validates the token via `auth_service` (`/users/me`).\n3. If the token is valid, queries **HIBP** using k-Anonymity (sends only first 5 chars of SHA-1).\n4. Responds `{ leaked: bool, times: int }`.\n5. Metrics and logs exported to Prometheus/Loki; dashboards in Grafana.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/diagrams/diagrams-svg-files/password-checker-architecture.svg\" width=\"600\" alt=\"Project Architecture\"/\u003e\n\u003c/p\u003e\n---\n\n## 📂 Repository Structure\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/diagrams/diagrams-svg-files/password-checker-architecture.svg\" width=\"600\" alt=\"password_checker_service_files\"/\u003e\n\u003c/p\u003e\n\n\n---\n\n## ⚡ Quick Start (local / demo)\n\n### Requirements\n- Docker \u0026 Docker Compose (recommended)\n- Python 3.11+\n- (Optional) `uvicorn` to run services individually\n\n### 1) Clone and run demo with Docker Compose\n\n```bash\ngit clone https://github.com/MetalCloud1/leakguard.git\ncd leakguard\n# Apply all namespaces\nkubectl apply -f auth_service/infra/k8s/dev/namespace-dev/\nkubectl apply -f monitoring-namespace.yaml\n```\n\nThis starts: `auth_service`, `password_checker_service`, Postgres (optional for auth), Prometheus, Loki, and Grafana.\n\n### 2) Run only `password_checker_service` locally\n\n```bash\ncd password_checker_service\npython -m venv .venv \u0026\u0026 source .venv/bin/activate\npip install -r requirements.txt -r requirements-test.txt\nuvicorn src_pcs.app:app --reload --port 8001\n```\n\nUseful endpoints:\n\n- `GET  http://localhost:8001/health`  \n- `POST http://localhost:8001/check-password`  \n\n`curl` example (requires valid token from `auth_service`):\n\n```bash\ncurl -sS -X POST http://localhost:8001/check-password \\\n  -H \"Authorization: Bearer \u003cYOUR_TOKEN\u003e\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"password\":\"123456\"}'\n```\n\nExample response:\n\n```json\n{\n  \"leaked\": true,\n  \"times\": 1000000\n}\n```\n\n---\n\n## 🧩 Configuration (environment variables)\n\nService configurable via 12-factor environment variables:\n\n- `AUTH_SERVICE_URL` — URL of authentication microservice (default `http://auth-service`).\n- `USE_HIBP` — `\"true\"` / `\"false\"`. If `false`, service responds with fallback (useful for tests).\n- `HIBP_TIMEOUT` — Timeout (seconds) for HIBP requests (default `5`).\n- `LOG_LEVEL` — Logging level (`INFO`, `DEBUG`, `WARNING`).\n- Standard Docker/Kubernetes vars (service names, networking).\n\n**Note:** HIBP `range` endpoint requires no API key; other endpoints (e.g., `breachedaccount`) do, use `.env` or GitHub Secrets.\n\n### Example `.env` (local)\n\n```\nAUTH_SERVICE_URL=http://localhost:8000\nUSE_HIBP=true\nHIBP_TIMEOUT=5\nLOG_LEVEL=INFO\n```\n\n---\n\n## ✅ Secure design: k-Anonymity\n\n- Service calculates SHA-1 of password locally.\n- Sends only the first 5 characters (`prefix`) to `https://api.pwnedpasswords.com/range/{prefix}`.\n- Receives list of suffixes and occurrences; compares suffix locally.\n- Never sends full password or hash externally.\n\n---\n\n## 🧪 Tests \u0026 best practices for CI\n\nTests in `tests/test_password_checker.py` cover:\n\n- `/health` endpoint (smoke test)\n- `/check-password` with valid token (mocking `decode_token_return_username` and `check_password_hibp`)\n- `/check-password` with invalid token (mocking `decode_token_return_username`)\n- Fallback (`USE_HIBP=false`) — ensures env variable is read dynamically\n\n### Run tests locally\n\n```bash\npytest -q\n```\n\n### Coverage and linters\n\n```bash\n# Coverage\npytest --cov=src --cov-report=term-missing\n\n# Lint / static analysis\nruff check .\nblack --check .\nmypy src\n```\n\n### Recommended mocking in tests\n- `decode_token_return_username` → avoids calling auth service.\n- `check_password_hibp` → avoids real HIBP requests in CI.\n- Avoid manipulating global vars at import time; read `USE_HIBP` per request or patch module var in tests.\n\n---\n\n## 🛠️ Implementation examples\n\n### Dynamic `USE_HIBP` reading\n\n```python\nuse_hibp = os.environ.get(\"USE_HIBP\", \"true\").lower() == \"true\"\nif use_hibp:\n    times = check_password_hibp(request.password)\nelse:\n    times = 0\n```\n\n### Mocking with pytest\n\n```python\n@patch(\"password_checker_service.src_pcs.app.decode_token_return_username\")\n@patch(\"password_checker_service.src_pcs.app.check_password_hibp\")\ndef test_check_password_with_hibp(mock_hibp, mock_decode):\n    mock_decode.return_value = \"testuser\"\n    mock_hibp.return_value = 1000000\n```\n\n---\n\n## 🛰️ Observability \u0026 monitoring\n\n- **Prometheus**: FastAPI metrics — latency, request count, errors\n- **Loki**: structured JSON logs for searching and correlation\n- **Grafana**: preconfigured dashboards:\n  - `API latency (p50/p95/p99)`\n  - `Requests per second`\n  - `Error rate (4xx vs 5xx)`\n  - `Auth failures` (invalid token count)\n\nScraping configuration in `docker-compose.demo.yml` and `prometheus/prometheus.yml`.\n\n---\n\n## 🔐 Security \u0026 legal notes\n\n- **Do not store passwords in plaintext** or user dumps in the repo.\n- HIBP used in read-only k-Anonymity mode — recommended way to check passwords.\n- Real account features (notifications, locks) require **explicit consent** and compliance (GDPR/LPD).\n- Use `GitHub Secrets` for sensitive CI/CD variables; do not commit `.env`.\n\n---\n\n## 🚀 Production deployment suggestions\n\n1. Containerize service (`Dockerfile`) and use `docker-compose` for staging.\n2. Deploy on Render, Railway, AWS ECS/Fargate, Google Cloud Run, or Kubernetes (EKS/GKE).\n3. Configure readiness/liveness probes and resource limits.\n4. Enable TLS/HTTPS and WAF if public.\n5. Set alerts in Grafana/Prometheus for high errors or request spikes.\n\n---\n\n## 🤝 Contribution \u0026 style guide\n\n- Open an issue for proposed changes or bugs\n- Submit PRs to `dev` branch\n- Follow conventions:\n  - `black` for formatting\n  - `ruff` for linting\n  - `mypy` for static typing\n  - Tests using `pytest` and mocks as needed\n- Maintain MicroForge attribution when using template\n\n---\n\n## 📄 License\n\nBased on **MicroForge** template by Gilbert Ramírez (`MetalCloud1`).  \n**License:** CC BY-NC-ND (see `LICENSE.md`).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmetalcloud1%2Fleakguard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmetalcloud1%2Fleakguard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmetalcloud1%2Fleakguard/lists"}