security: rotate bootstrap and clean workspace
This commit is contained in:
@@ -6,18 +6,35 @@
|
||||
# @RELATION: DEPENDS_ON -> backend.src.core.database
|
||||
# @RELATION: DEPENDS_ON -> backend.src.models.llm
|
||||
|
||||
from typing import List, Optional
|
||||
from typing import List, Optional, TYPE_CHECKING
|
||||
from sqlalchemy.orm import Session
|
||||
from ..models.llm import LLMProvider
|
||||
from ..plugins.llm_analysis.models import LLMProviderConfig
|
||||
from ..core.logger import belief_scope, logger
|
||||
from cryptography.fernet import Fernet
|
||||
import os
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..plugins.llm_analysis.models import LLMProviderConfig
|
||||
|
||||
# [DEF:_require_fernet_key:Function]
|
||||
# @TIER: CRITICAL
|
||||
# @PURPOSE: Load and validate the Fernet key used for secret encryption.
|
||||
# @PRE: ENCRYPTION_KEY environment variable must be set to a valid Fernet key.
|
||||
# @POST: Returns validated key bytes ready for Fernet initialization.
|
||||
def _require_fernet_key() -> bytes:
|
||||
raw_key = os.getenv("ENCRYPTION_KEY", "").strip()
|
||||
if not raw_key:
|
||||
raise RuntimeError("ENCRYPTION_KEY must be set to a valid Fernet key")
|
||||
|
||||
key = raw_key.encode()
|
||||
Fernet(key)
|
||||
return key
|
||||
# [/DEF:_require_fernet_key:Function]
|
||||
|
||||
# [DEF:EncryptionManager:Class]
|
||||
# @TIER: CRITICAL
|
||||
# @PURPOSE: Handles encryption and decryption of sensitive data like API keys.
|
||||
# @INVARIANT: Uses a secret key from environment or a default one (fallback only for dev).
|
||||
# @INVARIANT: Uses only a validated secret key from environment.
|
||||
#
|
||||
# @TEST_CONTRACT: EncryptionManagerModel ->
|
||||
# {
|
||||
@@ -33,10 +50,10 @@ import os
|
||||
class EncryptionManager:
|
||||
# [DEF:EncryptionManager.__init__:Function]
|
||||
# @PURPOSE: Initialize the encryption manager with a Fernet key.
|
||||
# @PRE: ENCRYPTION_KEY env var must be set or use default dev key.
|
||||
# @PRE: ENCRYPTION_KEY env var must be set to a valid Fernet key.
|
||||
# @POST: Fernet instance ready for encryption/decryption.
|
||||
def __init__(self):
|
||||
self.key = os.getenv("ENCRYPTION_KEY", "REMOVED_HISTORICAL_SECRET_DO_NOT_USE").encode()
|
||||
self.key = _require_fernet_key()
|
||||
self.fernet = Fernet(self.key)
|
||||
# [/DEF:EncryptionManager.__init__:Function]
|
||||
|
||||
@@ -97,7 +114,7 @@ class LLMProviderService:
|
||||
# @PURPOSE: Creates a new LLM provider with encrypted API key.
|
||||
# @PRE: config must contain valid provider configuration.
|
||||
# @POST: New provider created and persisted to database.
|
||||
def create_provider(self, config: LLMProviderConfig) -> LLMProvider:
|
||||
def create_provider(self, config: "LLMProviderConfig") -> LLMProvider:
|
||||
with belief_scope("create_provider"):
|
||||
encrypted_key = self.encryption.encrypt(config.api_key)
|
||||
db_provider = LLMProvider(
|
||||
@@ -119,7 +136,7 @@ class LLMProviderService:
|
||||
# @PURPOSE: Updates an existing LLM provider.
|
||||
# @PRE: provider_id must exist, config must be valid.
|
||||
# @POST: Provider updated and persisted to database.
|
||||
def update_provider(self, provider_id: str, config: LLMProviderConfig) -> Optional[LLMProvider]:
|
||||
def update_provider(self, provider_id: str, config: "LLMProviderConfig") -> Optional[LLMProvider]:
|
||||
with belief_scope("update_provider"):
|
||||
db_provider = self.get_provider(provider_id)
|
||||
if not db_provider:
|
||||
@@ -180,4 +197,4 @@ class LLMProviderService:
|
||||
|
||||
# [/DEF:LLMProviderService:Class]
|
||||
|
||||
# [/DEF:backend.src.services.llm_provider:Module]
|
||||
# [/DEF:backend.src.services.llm_provider:Module]
|
||||
|
||||
Reference in New Issue
Block a user