Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions BFF_AUTHENTICATION_DOCS_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ All authentication configuration now uses `AUTH_*` parameters. **Deprecated `OID
- **AUTH_OIDC_VERIFY_SSL**: Whether to verify SSL certificates for OIDC requests (default: `true`)
- **AUTH_OIDC_VERIFY_SIGNATURE**: Whether to verify OIDC token signatures (default: `true`)
- **AUTH_SESSION_TTL_HOURS**: Session duration in hours (default: `24`)
- **AUTH_KEY_VERSIONS_TO_KEEP**: Number of encryption key versions to retain during rotation (default: `3`)
- **AUTH_SYNC_DOMAINS**: Optional comma-separated list of additional domains for cookie sync
- **AUTH_SESSION_TABLE_NAME**: DynamoDB table name for authentication sessions (default: `mlspace-auth-sessions`)
- **AUTH_TOKEN_ENCRYPTION_KEY_SECRET_NAME**: Secrets Manager secret name for token encryption keys (default: `mlspace/auth/token-encryption-keys`)
Expand Down Expand Up @@ -130,6 +131,7 @@ frontend/docs/admin-guide/
- **AUTH_OIDC_VERIFY_SSL**: Whether to verify SSL certificates (default: `true`)
- **AUTH_OIDC_VERIFY_SIGNATURE**: Whether to verify OIDC token signatures (default: `true`)
- **AUTH_SESSION_TTL_HOURS**: Session duration configuration (default: `24`)
- **AUTH_KEY_VERSIONS_TO_KEEP**: Number of encryption key versions to retain during rotation (default: `3`)
- **AUTH_SYNC_DOMAINS**: Multi-domain cookie synchronization
- **AUTH_SESSION_TABLE_NAME**: DynamoDB table name for sessions
- **AUTH_TOKEN_ENCRYPTION_KEY_SECRET_NAME**: Versioned token encryption keys (rotatable)
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ If the config-helper doesn't provide the level of customization you need for you
| AUTH_OIDC_VERIFY_SIGNATURE | Whether or not the lambda authorizer should verify the JWT token signature | `true` |
| AUTH_OIDC_USE_PKCE | Whether to use PKCE (Proof Key for Code Exchange) for OIDC authentication | `false` |
| AUTH_SESSION_TTL_HOURS | The time-to-live (TTL) in hours for authentication sessions | `24` |
| AUTH_KEY_VERSIONS_TO_KEEP | Number of encryption key versions to retain during key rotation | `3` |
| AUTH_SYNC_DOMAINS | Comma-separated list of domains to sync authentication state across | - |
| ADDITIONAL_LAMBDA_ENVIRONMENT_VARS | A map of key value pairs which will be set as environment variables on every MLSpace lambda | `{}` |
| RESOURCE_TERMINATION_INTERVAL | Interval (in minutes) to run the resource termination cleanup lambda | `60` |
Expand Down
30 changes: 25 additions & 5 deletions backend/src/ml_space_lambda/auth/utils/key_rotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import json
import logging
import os
from typing import Dict, Optional

import boto3
Expand All @@ -41,6 +42,20 @@
logger.setLevel(level=logging.INFO)


def _get_default_keep_versions() -> int:
"""
Get the default number of key versions to keep from environment variable.

Returns:
Number of versions to keep (default: 3)
"""
try:
return int(os.environ.get("AUTH_KEY_VERSIONS_TO_KEEP", "3"))
except ValueError:
logger.warning("Invalid AUTH_KEY_VERSIONS_TO_KEEP value, using default: 3")
return 3


def initialize_state_encryption_key(secret_arn: str) -> Dict:
"""
Initialize state encryption key secret with versioned structure.
Expand Down Expand Up @@ -129,7 +144,7 @@ def rotate_state_encryption_key(
secret_arn: str,
version_stage: str = SecretsManagerStage.PENDING,
version_token: Optional[str] = None,
keep_versions: int = 3,
keep_versions: Optional[int] = None,
) -> KeyRotationResult:
"""
Rotate state encryption key for AWS Secrets Manager rotation protocol.
Expand All @@ -139,15 +154,18 @@ def rotate_state_encryption_key(

Args:
secret_arn: AWS Secrets Manager ARN for state encryption key
token: Version stage (AWSPENDING for new version)
keep_versions: Number of recent versions to keep after rotation
version_stage: Version stage (AWSPENDING for new version)
version_token: Version token for the rotation
keep_versions: Number of recent versions to keep after rotation (uses AUTH_KEY_VERSIONS_TO_KEEP env var if not specified)

Returns:
KeyRotationResult with rotation details

Raises:
Exception: If rotation fails
"""
if keep_versions is None:
keep_versions = _get_default_keep_versions()
try:
secrets_client = boto3.client("secretsmanager")

Expand Down Expand Up @@ -205,7 +223,7 @@ def rotate_token_encryption_key(
secret_arn: str,
version_stage: str = SecretsManagerStage.PENDING,
version_token: Optional[str] = None,
keep_versions: int = 3,
keep_versions: Optional[int] = None,
) -> KeyRotationResult:
"""
Rotate token encryption key for AWS Secrets Manager rotation protocol.
Expand All @@ -217,14 +235,16 @@ def rotate_token_encryption_key(
secret_arn: AWS Secrets Manager ARN for token encryption key
version_stage: Version stage (AWSPENDING for new version)
version_token: Version token (normally from ClientRequestToken)
keep_versions: Number of recent versions to keep after rotation
keep_versions: Number of recent versions to keep after rotation (uses AUTH_KEY_VERSIONS_TO_KEEP env var if not specified)

Returns:
KeyRotationResult with rotation details

Raises:
Exception: If rotation fails
"""
if keep_versions is None:
keep_versions = _get_default_keep_versions()
try:
secrets_client = boto3.client("secretsmanager")

Expand Down
22 changes: 20 additions & 2 deletions backend/src/ml_space_lambda/auth/utils/rotation_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"""

import logging
import os
from enum import StrEnum
from typing import Any, Dict, Optional

Expand All @@ -39,6 +40,20 @@
logger.setLevel(level=logging.INFO)


def _get_keep_versions() -> int:
"""
Get the number of key versions to keep from environment variable.

Returns:
Number of versions to keep (default: 3)
"""
try:
return int(os.environ.get("AUTH_KEY_VERSIONS_TO_KEEP", "3"))
except ValueError:
logger.warning("Invalid AUTH_KEY_VERSIONS_TO_KEEP value, using default: 3")
return 3


class RotationStep(StrEnum):
"""AWS Secrets Manager rotation steps."""

Expand Down Expand Up @@ -86,12 +101,15 @@ def _handle_create_secret_step(secret_name: str, key_type: str, version_token: O
Args:
secret_name: Secret ARN
key_type: Type of key being rotated
version_token: Version token for the rotation
"""
keep_versions = _get_keep_versions()

# Create new key version
if key_type == KeyType.STATE:
result = rotate_state_encryption_key(secret_name, version_token=version_token, keep_versions=3)
result = rotate_state_encryption_key(secret_name, version_token=version_token, keep_versions=keep_versions)
else: # token
result = rotate_token_encryption_key(secret_name, version_token=version_token, keep_versions=3)
result = rotate_token_encryption_key(secret_name, version_token=version_token, keep_versions=keep_versions)


def _handle_set_secret_step(secret_name: str) -> None:
Expand Down
Loading