Initial commit: Agentic OS troubleshooting platform
Self-hosted, Docker-based agentic troubleshooting platform: FastAPI backend + LangGraph agent, Next.js UI, tiered LLM routing (local Ollama -> Gemini -> DeepSeek -> OpenRouter), MCP server manager, encrypted device credentials, RBAC, audit log, project-memory + Obsidian integrations, and editable troubleshooting decision rules tuned for the GeneseasX vessel stack. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
38
backend/app/core/crypto.py
Normal file
38
backend/app/core/crypto.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""Symmetric encryption of device credentials at rest (Fernet)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import hashlib
|
||||
|
||||
from cryptography.fernet import Fernet, InvalidToken
|
||||
|
||||
from app.config import settings
|
||||
|
||||
|
||||
def _fernet() -> Fernet:
|
||||
key = settings.credential_encryption_key
|
||||
if not key:
|
||||
# Derive a stable (but weak) key from SECRET_KEY so dev works without extra config.
|
||||
digest = hashlib.sha256(settings.secret_key.encode()).digest()
|
||||
key = base64.urlsafe_b64encode(digest).decode()
|
||||
try:
|
||||
return Fernet(key)
|
||||
except (ValueError, TypeError):
|
||||
# Treat provided value as raw material and derive a valid Fernet key
|
||||
digest = hashlib.sha256(key.encode()).digest()
|
||||
return Fernet(base64.urlsafe_b64encode(digest))
|
||||
|
||||
|
||||
def encrypt_secret(plaintext: str | None) -> str | None:
|
||||
if not plaintext:
|
||||
return None
|
||||
return _fernet().encrypt(plaintext.encode()).decode()
|
||||
|
||||
|
||||
def decrypt_secret(token: str | None) -> str | None:
|
||||
if not token:
|
||||
return None
|
||||
try:
|
||||
return _fernet().decrypt(token.encode()).decode()
|
||||
except InvalidToken:
|
||||
return None
|
||||
Reference in New Issue
Block a user