Files
mimic/backend/app/services/crypto.py
Knacky 9a9c98beab feat(backend): c2 crypto + config CRUD + adapter scaffolding (sprint 8 M1)
- Add Fernet crypto service (MIMIC_ENCRYPTION_KEY env, C2Disabled on absent key)
- Add Alembic migration 0006: c2_config + c2_task tables with cascade FKs
- Add C2Config and C2Task SQLAlchemy models
- Add C2Adapter ABC with dataclasses (C2Health, C2Callback, C2TaskStatus, C2TaskPage)
- Add FakeAdapter (deterministic in-memory, MIMIC_C2_ADAPTER=fake)
- Add MythicAdapter scaffold: test_connection() live, M2+ raise NotImplementedError
- Add decode_response_text() helper for base64/binary Mythic responses
- Add GET/PUT/DELETE/POST-test /api/engagements/<id>/c2-config endpoints
- RBAC: admin+redteam OK, SOC 403; 503 guard when encryption key absent
- Token never returned in API responses; stored Fernet-encrypted only
- 42 new tests (300 total, 258 baseline preserved green)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 19:20:52 +02:00

41 lines
1.2 KiB
Python

"""Fernet-based encryption service for sensitive fields.
Key is read from the MIMIC_ENCRYPTION_KEY env var (Fernet base64-urlsafe 32-byte key).
When the key is absent the service raises C2Disabled so callers can return 503.
The key is never logged or returned in any response.
"""
from __future__ import annotations
import os
from cryptography.fernet import Fernet, InvalidToken
class C2Disabled(Exception):
"""Raised when MIMIC_ENCRYPTION_KEY is not set."""
def _get_fernet() -> Fernet:
key = os.environ.get("MIMIC_ENCRYPTION_KEY")
if not key:
raise C2Disabled("C2 disabled: MIMIC_ENCRYPTION_KEY not set")
return Fernet(key.encode() if isinstance(key, str) else key)
def encrypt(plaintext: str) -> str:
"""Encrypt *plaintext* and return a Fernet token (str)."""
f = _get_fernet()
return f.encrypt(plaintext.encode()).decode()
def decrypt(ciphertext: str) -> str:
"""Decrypt a Fernet token and return the plaintext string."""
f = _get_fernet()
try:
return f.decrypt(ciphertext.encode()).decode()
except InvalidToken as exc:
raise ValueError("Invalid ciphertext") from exc
__all__ = ["C2Disabled", "encrypt", "decrypt"]