feat: Implement initial schema and add various API, service, and management command enhancements across the application.

This commit is contained in:
pacnpal
2026-01-01 15:13:01 -05:00
parent c95f99ca10
commit b243b17af7
413 changed files with 11164 additions and 17433 deletions

View File

@@ -31,17 +31,13 @@ logger = logging.getLogger("security")
# =============================================================================
# Enable secret rotation checking (set to True in production)
SECRET_ROTATION_ENABLED = config(
"SECRET_ROTATION_ENABLED", default=False, cast=bool
)
SECRET_ROTATION_ENABLED = config("SECRET_ROTATION_ENABLED", default=False, cast=bool)
# Secret version for tracking rotations
SECRET_KEY_VERSION = config("SECRET_KEY_VERSION", default="1")
# Secret expiry warning threshold (days before expiry to start warning)
SECRET_EXPIRY_WARNING_DAYS = config(
"SECRET_EXPIRY_WARNING_DAYS", default=30, cast=int
)
SECRET_EXPIRY_WARNING_DAYS = config("SECRET_EXPIRY_WARNING_DAYS", default=30, cast=int)
# =============================================================================
# Required Secrets Registry
@@ -104,10 +100,7 @@ def validate_secret_strength(name: str, value: str, min_length: int = 10) -> boo
return False
if len(value) < min_length:
logger.error(
f"Secret '{name}' is too short ({len(value)} chars, "
f"minimum {min_length})"
)
logger.error(f"Secret '{name}' is too short ({len(value)} chars, " f"minimum {min_length})")
return False
# Check for placeholder values
@@ -123,9 +116,7 @@ def validate_secret_strength(name: str, value: str, min_length: int = 10) -> boo
value_lower = value.lower()
for pattern in placeholder_patterns:
if pattern in value_lower:
logger.warning(
f"Secret '{name}' appears to contain a placeholder value"
)
logger.warning(f"Secret '{name}' appears to contain a placeholder value")
return False
return True
@@ -148,9 +139,7 @@ def validate_secret_key(secret_key: str) -> bool:
bool: True if valid, False otherwise
"""
if len(secret_key) < 50:
logger.error(
f"SECRET_KEY is too short ({len(secret_key)} chars, minimum 50)"
)
logger.error(f"SECRET_KEY is too short ({len(secret_key)} chars, minimum 50)")
return False
has_upper = any(c.isupper() for c in secret_key)
@@ -159,10 +148,7 @@ def validate_secret_key(secret_key: str) -> bool:
has_special = any(not c.isalnum() for c in secret_key)
if not all([has_upper, has_lower, has_digit, has_special]):
logger.warning(
"SECRET_KEY should contain uppercase, lowercase, digits, "
"and special characters"
)
logger.warning("SECRET_KEY should contain uppercase, lowercase, digits, " "and special characters")
# Don't fail, just warn - some generated keys may not have all
return True
@@ -193,7 +179,7 @@ def get_secret(
value = config(name, default=default)
except UndefinedValueError:
if required:
raise ValueError(f"Required secret '{name}' is not set")
raise ValueError(f"Required secret '{name}' is not set") from None
return default
if value and min_length > 0 and not validate_secret_strength(name, value, min_length):
@@ -231,7 +217,7 @@ def validate_required_secrets(raise_on_error: bool = False) -> list[str]:
msg = f"Required secret '{name}' is not set: {rules['description']}"
errors.append(msg)
if raise_on_error:
raise ValueError(msg)
raise ValueError(msg) from None
return errors
@@ -257,9 +243,7 @@ def check_secret_expiry() -> list[str]:
version = int(SECRET_KEY_VERSION)
# If version is very old, suggest rotation
if version < 2:
warnings_list.append(
"SECRET_KEY version is old. Consider rotating secrets."
)
warnings_list.append("SECRET_KEY version is old. Consider rotating secrets.")
except ValueError:
pass
@@ -316,8 +300,7 @@ class EnvironmentSecretProvider(SecretProvider):
def set_secret(self, name: str, value: str) -> bool:
"""Environment variables are read-only at runtime."""
logger.warning(
f"Cannot set secret '{name}' in environment provider. "
"Update your .env file or environment variables."
f"Cannot set secret '{name}' in environment provider. " "Update your .env file or environment variables."
)
return False
@@ -385,4 +368,4 @@ def run_startup_validation() -> None:
raise ValueError("SECRET_KEY does not meet security requirements")
except UndefinedValueError:
if not debug_mode:
raise ValueError("SECRET_KEY is required in production")
raise ValueError("SECRET_KEY is required in production") from None