From ac476917a51dfc7814b4ad02b07d0b2f376d098c Mon Sep 17 00:00:00 2001 From: dustins Date: Sat, 24 Jan 2026 03:16:38 +0000 Subject: [PATCH 1/2] Updating version for hotfix v1.7.1 --- frontend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/package.json b/frontend/package.json index 95845d4c..9414cee9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "@amzn/mlspace", "homepage": "/Prod", - "version": "1.7", + "version": "1.7.1", "main": "dist/lib/index.js", "types": "dist/types/index.d.ts", "private": true, From 191349f05a97224b9f80fa45d68aeb945c743d88 Mon Sep 17 00:00:00 2001 From: Dustin Sweigart Date: Mon, 26 Jan 2026 14:55:56 +0000 Subject: [PATCH 2/2] updated documentation --- BFF_AUTHENTICATION_DOCS_README.md | 2 + README.md | 1 + .../auth/utils/key_rotation.py | 30 +- .../auth/utils/rotation_handlers.py | 22 +- docs/BFF_AUTHENTICATION_KEY_ROTATION.md | 289 ------------------ .../auth-configuration-reference.md | 10 + frontend/docs/admin-guide/custom-domain.md | 51 +++- frontend/docs/admin-guide/install.md | 1 + frontend/src/contexts/AuthContext.tsx | 2 - lib/constants.ts | 1 + lib/constructs/api/authConstruct.ts | 1 + lib/constructs/auth/authSecretsConstruct.ts | 6 +- lib/utils/configTypes.ts | 3 + 13 files changed, 115 insertions(+), 304 deletions(-) delete mode 100644 docs/BFF_AUTHENTICATION_KEY_ROTATION.md diff --git a/BFF_AUTHENTICATION_DOCS_README.md b/BFF_AUTHENTICATION_DOCS_README.md index b86cab8d..46c38438 100644 --- a/BFF_AUTHENTICATION_DOCS_README.md +++ b/BFF_AUTHENTICATION_DOCS_README.md @@ -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`) @@ -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) diff --git a/README.md b/README.md index 3c2be5eb..0b4d911a 100644 --- a/README.md +++ b/README.md @@ -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` | diff --git a/backend/src/ml_space_lambda/auth/utils/key_rotation.py b/backend/src/ml_space_lambda/auth/utils/key_rotation.py index 13be3558..bd5716d6 100644 --- a/backend/src/ml_space_lambda/auth/utils/key_rotation.py +++ b/backend/src/ml_space_lambda/auth/utils/key_rotation.py @@ -23,6 +23,7 @@ import json import logging +import os from typing import Dict, Optional import boto3 @@ -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. @@ -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. @@ -139,8 +154,9 @@ 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 @@ -148,6 +164,8 @@ def rotate_state_encryption_key( Raises: Exception: If rotation fails """ + if keep_versions is None: + keep_versions = _get_default_keep_versions() try: secrets_client = boto3.client("secretsmanager") @@ -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. @@ -217,7 +235,7 @@ 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 @@ -225,6 +243,8 @@ def rotate_token_encryption_key( Raises: Exception: If rotation fails """ + if keep_versions is None: + keep_versions = _get_default_keep_versions() try: secrets_client = boto3.client("secretsmanager") diff --git a/backend/src/ml_space_lambda/auth/utils/rotation_handlers.py b/backend/src/ml_space_lambda/auth/utils/rotation_handlers.py index fc65327c..9361c42c 100644 --- a/backend/src/ml_space_lambda/auth/utils/rotation_handlers.py +++ b/backend/src/ml_space_lambda/auth/utils/rotation_handlers.py @@ -22,6 +22,7 @@ """ import logging +import os from enum import StrEnum from typing import Any, Dict, Optional @@ -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.""" @@ -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: diff --git a/docs/BFF_AUTHENTICATION_KEY_ROTATION.md b/docs/BFF_AUTHENTICATION_KEY_ROTATION.md deleted file mode 100644 index 797593f6..00000000 --- a/docs/BFF_AUTHENTICATION_KEY_ROTATION.md +++ /dev/null @@ -1,289 +0,0 @@ -# Enhanced Authentication Key Rotation Guide - -This document provides comprehensive guidance for managing encryption key rotation in the MLSpace enhanced authentication system. - -## Overview - -The enhanced authentication system uses two types of encryption keys: - -1. **Token Encryption Keys** - Encrypt IdP tokens stored in sessions (high impact) -2. **State Encryption Keys** - Encrypt CSRF state parameters during login flow (low impact) - -## Key Rotation Strategy - -### Hybrid Approach - -We implement a **hybrid key rotation strategy** that balances security with operational simplicity: - -- **Token Keys**: Versioned with automated rotation (zero downtime) -- **State Keys**: Simple deploy-time generation (minimal impact) - -### Impact Assessment - -| Key Type | Rotation Impact | Affected Users | Duration | -|----------|----------------|----------------|----------| -| Token Keys | Zero downtime | None | N/A | -| State Keys | Minimal | Users actively logging in | 1-2 minutes | - -## Token Key Rotation (Automated) - -### Architecture - -Token encryption uses a **versioned key system** that supports graceful rotation: - -- **Encryption**: Always uses the latest key version -- **Decryption**: Can decrypt with any available key version -- **Storage**: AWS Secrets Manager with versioned JSON structure -- **Rotation**: Automated via EventBridge + Lambda (90-day schedule) - -### Key Structure - -```json -{ - "current_version": 2, - "keys": { - "1": "base64-encoded-key-v1", - "2": "base64-encoded-key-v2" - }, - "key_type": "token", - "rotation_date": "2024-01-15T10:30:00Z", - "rotated_by": "key_rotation_manager" -} -``` - -### Automated Rotation - -**Schedule**: Every 90 days via EventBridge rule - -**Process**: -1. Generate new 32-byte encryption key -2. Increment version number -3. Add new key to versioned structure -4. Update Secrets Manager -5. New sessions use latest key -6. Existing sessions continue with their original key - -**Zero Impact**: Users experience no disruption during rotation. - -### Key Cleanup - -Old key versions are automatically retained for backward compatibility and cleaned up during rotation based on the configured retention policy (default: 3 versions). - -### Monitoring Token Key Rotation - -Monitor rotation through CloudWatch Logs and AWS Secrets Manager console: - -- **CloudWatch Logs**: Check `/aws/lambda/mlspace-key-rotation` log group -- **Secrets Manager Console**: View rotation configuration and history -- **CloudWatch Metrics**: Monitor rotation success/failure rates - -## State Key Rotation (Deploy-Time) - -### Architecture - -State encryption uses a **simple Fernet key** that can be regenerated as needed: - -- **Generation**: Initialization script creates key using `create_state_encryption_key()` -- **Storage**: AWS Secrets Manager (simple string value) -- **Rotation**: Regenerate via initialization script -- **Impact**: Only affects users actively logging in (1-2 minutes) -- **Rotation**: Automatic via configured rotation schedule - -## Deployment Configuration - -### CDK Integration - -The `AuthSecretsConstruct` creates the secrets with placeholder values: - -```typescript -// In your CDK stack -const authSecrets = new AuthSecretsConstruct(this, 'AuthSecrets', { - encryptionKey: kmsKey, // Optional: Use customer-managed KMS key - enableTokenKeyRotation: true, // Enable automated rotation - tokenKeyRotationSchedule: Schedule.rate(Duration.days(90)), // Optional: Custom schedule -}); -``` - -### Key Initialization - -After CDK deployment, run the initialization script to populate secrets with proper keys: - -```bash -# Initialize both state and token encryption keys -python3 scripts/initialize-auth-keys.py -``` - -**What the script does:** -- Generates proper Fernet key for state encryption using `create_state_encryption_key()` -- Generates versioned token encryption key using `create_encryption_key()` -- Stores keys in the correct format expected by the authentication system - -### Environment Variables - -Lambda functions receive these environment variables: - -```bash -# Token encryption (versioned) -AUTH_TOKEN_ENCRYPTION_KEY_SECRET_NAME=mlspace/auth/token-encryption-keys - -# State encryption (simple) -AUTH_STATE_ENCRYPTION_KEY_SECRET_NAME=mlspace/auth/state-encryption-key -``` - -### Configuration Files - -**lib/config.json**: -```json -{ - "AUTH_TOKEN_ENCRYPTION_KEY_SECRET_NAME": "mlspace/auth/token-encryption-keys", - "AUTH_STATE_ENCRYPTION_KEY_SECRET_NAME": "mlspace/auth/state-encryption-key" -} -``` - -## Security Considerations - -### Key Generation - -- **Token Keys**: 32-byte cryptographically secure random keys -- **State Keys**: Fernet-compatible keys (32-byte base64-encoded) -- **Entropy**: All keys use `os.urandom()` for cryptographic randomness - -### Access Control - -**IAM Permissions**: -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "secretsmanager:GetSecretValue", - "secretsmanager:UpdateSecret" - ], - "Resource": [ - "arn:aws:secretsmanager:*:*:secret:mlspace/auth/*" - ] - } - ] -} -``` - -### Encryption at Rest - -- **Secrets Manager**: Encrypted with AWS managed keys or customer-managed KMS keys -- **DynamoDB**: Session data encrypted at rest -- **Application-Level**: Tokens encrypted before storage in DynamoDB - -## Troubleshooting - -### Token Key Rotation Issues - -**Problem**: Rotation Lambda fails -- Check CloudWatch Logs for the `/aws/lambda/mlspace-key-rotation` log group -- Review CloudWatch metrics for rotation failures -- Verify IAM permissions for the rotation Lambda function - -**Problem**: Sessions become invalid after rotation -- This should not happen with versioned keys -- Check that `VersionedTokenEncryption` is being used -- Verify key versions are properly stored - -### State Key Rotation Issues - -**Problem**: Users can't log in after deployment -- Expected behavior during state key rotation -- Users should retry login after 1-2 minutes -- Check that new state key was generated properly - -**Problem**: State key generation fails -- Check CloudWatch logs for the rotation Lambda function -- Verify the rotation schedule is configured correctly in AWS Secrets Manager - -### Key Validation - -Verify key structure using AWS Secrets Manager console or by checking CloudWatch logs for the rotation Lambda function. - -## Migration from Legacy Keys - -The system now uses versioned keys by default. If migrating from a legacy deployment: - -1. **Backup existing keys** using AWS Secrets Manager console or CLI -2. **Deploy updated infrastructure** with versioned key support -3. **Initialize secrets** using the initialization script -4. **Verify rotation schedule** is configured correctly - -### Rollback Plan - -If issues occur during migration: - -1. **Check CloudWatch logs** for rotation Lambda errors -2. **Verify secret structure** matches expected versioned format -3. **Contact support** if issues persist - -## Best Practices - -### Rotation Schedule - -- **Token Keys**: Every 90 days (automated via AWS Secrets Manager) -- **State Keys**: Every 90 days (automated via AWS Secrets Manager) - -### Monitoring - -- **CloudWatch Alarms**: Monitor rotation Lambda failures -- **Session Metrics**: Track session creation/expiration rates -- **Error Rates**: Monitor authentication error rates during rotation - -### Testing - -- **Pre-Production**: Test rotation in staging environment -- **Load Testing**: Verify rotation works under load -- **Rollback Testing**: Practice emergency rollback procedures - -### Documentation - -- **Runbooks**: Document rotation procedures for operations team -- **Incident Response**: Include key rotation in security incident procedures -- **Change Management**: Include rotation schedule in change calendar - -## Emergency Procedures - -### Key Compromise Response - -If keys are compromised: - -1. **Trigger immediate rotation**: Use AWS Secrets Manager console to trigger rotation immediately -2. **Monitor rotation completion**: Check CloudWatch logs for rotation Lambda execution -3. **Invalidate sessions if necessary**: Consider clearing the session table for critical security incidents - -### Key Recovery - -If rotation fails and keys are lost: - -1. **Check CloudTrail** for key modification events -2. **Restore from backup** if available -3. **Generate new keys** and accept that existing sessions will be invalidated -4. **Notify users** of required re-authentication - -## Compliance and Auditing - -### Audit Trail - -All key operations are logged: -- **CloudTrail**: Secrets Manager API calls -- **Lambda Logs**: Rotation operation details -- **EventBridge**: Scheduled rotation events - -### Compliance Requirements - -- **Key Rotation**: Automated 90-day rotation meets most compliance requirements -- **Access Logging**: All key access is logged and auditable -- **Encryption**: Keys encrypted at rest and in transit -- **Separation of Duties**: Rotation is automated, reducing human access - -### Reporting - -Monitor rotation history through: -- **CloudWatch Logs Insights**: Query rotation events in the Lambda log group -- **AWS Secrets Manager Console**: View rotation history for each secret -- **CloudTrail**: Audit all Secrets Manager API calls \ No newline at end of file diff --git a/frontend/docs/admin-guide/auth-configuration-reference.md b/frontend/docs/admin-guide/auth-configuration-reference.md index 75477ca0..17dc88c5 100644 --- a/frontend/docs/admin-guide/auth-configuration-reference.md +++ b/frontend/docs/admin-guide/auth-configuration-reference.md @@ -121,6 +121,15 @@ The deprecated `OIDC_*` configuration parameters (such as `OIDC_URL`, `OIDC_CLIE - **Example**: `"mlspace/auth/state-encryption-key"` - **Notes**: Used for encrypting OAuth state parameter; automatically created during deployment +### AUTH_KEY_VERSIONS_TO_KEEP +- **Type**: Number +- **Required**: No +- **Default**: `3` +- **Range**: `1` to `10` (recommended) +- **Description**: Number of encryption key versions to retain during key rotation +- **Example**: `3` +- **Notes**: Ensures backward compatibility for active sessions during key rotation. Should be set such that `AUTH_KEY_VERSIONS_TO_KEEP × rotation_interval > AUTH_SESSION_TTL_HOURS`. For example, with 90-day rotation and 24-hour sessions, keeping 3 versions provides 270 days of backward compatibility. + ## Environment-Specific Examples ### Development Environment (Minimal) @@ -165,6 +174,7 @@ The deprecated `OIDC_*` configuration parameters (such as `OIDC_URL`, `OIDC_CLIE 1. **AUTH_SYNC_DOMAINS**: Not currently used; reserved for future functionality 2. **AUTH_OIDC_USE_PKCE**: Must be boolean (true/false) +3. **AUTH_KEY_VERSIONS_TO_KEEP**: Must be positive integer between 1 and 10 (recommended) 4. **AUTH_OIDC_VERIFY_SSL**: Must be boolean (true/false); should be true in production 5. **AUTH_OIDC_VERIFY_SIGNATURE**: Must be boolean (true/false); should be true in production 6. **AUTH_OIDC_CLIENT_SECRET_NAME**: Must be valid Secrets Manager secret name if specified diff --git a/frontend/docs/admin-guide/custom-domain.md b/frontend/docs/admin-guide/custom-domain.md index 4d73472c..41d1ea78 100644 --- a/frontend/docs/admin-guide/custom-domain.md +++ b/frontend/docs/admin-guide/custom-domain.md @@ -69,9 +69,50 @@ If you're keeping the stage name in your path (e.g., `https://mlspace.mycompany. The `homepage` value should match the base path where your application will be served. This affects how static assets are referenced. ::: -### Step 3: Deploy CDK Changes +### Step 3: Configure Documentation Base Path (Optional) -Deploy your updated {{ $params.APPLICATION_NAME }} stack: +If you're changing the base path for your application, you should also update the documentation site configuration: + +1. Open `frontend/docs/.vitepress/config.mts` + +2. Update the `base` parameter (around line 65): + +```typescript +export default defineConfig({ + title: `${APPLICATION_NAME} Documentation`, + description: 'A collaborative data science environment', + outDir: '../public/docs', + base: process.env.DOCS_BASE_PATH || '/docs/', // Update this line + themeConfig: { + // ... + } +}) +``` + +**Examples**: +- For root path: `base: '/docs/'` (default) +- For stage path: `base: '/Prod/docs/'` +- Using environment variable: `base: process.env.DOCS_BASE_PATH || '/docs/'` + +::: tip +The `base` value determines where the documentation site assets are served from. It should match your application's base path plus `/docs/`. +::: + +### Step 4: Build Frontend and Deploy CDK Changes + +After making configuration changes, you need to rebuild the frontend application before deploying: + +1. Navigate to the frontend directory and build the application: + +```bash +cd frontend +npm run build +cd .. +``` + +This will generate a production-optimized build of the web application with your updated configuration. + +2. Deploy your updated {{ $params.APPLICATION_NAME }} stack: ```bash cdk deploy --all @@ -82,7 +123,7 @@ This will update the application configuration to use your custom domain for: - API endpoint references in the frontend - Session management -### Step 4: Create API Gateway Custom Domain +### Step 5: Create API Gateway Custom Domain After deploying the CDK changes, you must manually configure the API Gateway custom domain and API mapping. @@ -129,7 +170,7 @@ aws apigateway create-base-path-mapping \ --base-path '' # Leave empty for root path, or use 'Prod' for /Prod path ``` -### Step 5: Configure DNS +### Step 6: Configure DNS Create a DNS record pointing your custom domain to the API Gateway domain name: @@ -171,7 +212,7 @@ If using Route 53, you can create an A record with an alias: - **API Gateway endpoint**: Select your custom domain 5. Click **Create records** -### Step 6: Verify Configuration +### Step 7: Verify Configuration 1. Wait for DNS propagation (typically 5-15 minutes, but can take up to 48 hours) diff --git a/frontend/docs/admin-guide/install.md b/frontend/docs/admin-guide/install.md index 0b4ab603..acbe0037 100644 --- a/frontend/docs/admin-guide/install.md +++ b/frontend/docs/admin-guide/install.md @@ -1640,6 +1640,7 @@ Use the MLSpace Config Wizard by running `npm run config` and select "Advanced C | `AUTH_OIDC_VERIFY_SSL` | Whether to verify SSL certificates when making requests to the OIDC provider. Should be `true` in production | `true` | | `AUTH_OIDC_VERIFY_SIGNATURE` | Whether to verify OIDC token signatures. Should be `true` in production | `true` | | `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. Should be set such that `AUTH_KEY_VERSIONS_TO_KEEP × rotation_interval > AUTH_SESSION_TTL_HOURS` | `3` | | `AUTH_SYNC_DOMAINS` | **Not currently needed.** Reserved for future multi-domain cookie sync functionality | - | | `ADDITIONAL_LAMBDA_ENVIRONMENT_VARS` | A map of key-value pairs which will be set as environment variables on every {{ $params.APPLICATION_NAME }} lambda | `{}` | | `RESOURCE_TERMINATION_INTERVAL` | Interval (in minutes) to run the resource termination cleanup lambda | `60` | diff --git a/frontend/src/contexts/AuthContext.tsx b/frontend/src/contexts/AuthContext.tsx index 5aa84253..15556cdb 100644 --- a/frontend/src/contexts/AuthContext.tsx +++ b/frontend/src/contexts/AuthContext.tsx @@ -123,7 +123,6 @@ export const AuthProvider: React.FC = ({ const checkAuthStatusRef = useRef<() => void>(); const checkAuthStatus = useCallback(async () => { - console.log('checking auth status'); const wasAuthenticated = state.status === 'authenticated'; try { @@ -183,7 +182,6 @@ export const AuthProvider: React.FC = ({ // Periodic session validation useEffect(() => { - console.log('reset periodic refresh'); const interval = setInterval(checkAuthStatus, checkInterval); return () => clearInterval(interval); }, [checkInterval, checkAuthStatus]); diff --git a/lib/constants.ts b/lib/constants.ts index 5e29e022..01eefab1 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -142,6 +142,7 @@ export const AUTH_SESSION_TTL_HOURS = 24; // Session duration in hours // Encryption configuration export const AUTH_TOKEN_ENCRYPTION_KEY_SECRET_NAME = 'mlspace/auth/token-encryption-keys'; // Versioned secret for token encryption keys (rotatable) export const AUTH_STATE_ENCRYPTION_KEY_SECRET_NAME = 'mlspace/auth/state-encryption-key'; // Simple secret for state encryption key (deploy-time generated) +export const AUTH_KEY_VERSIONS_TO_KEEP = 3; // Number of key versions to retain during rotation // Legacy OIDC configuration (deprecated - maintained for backward compatibility during migration) // Use AUTH_OIDC_URL, AUTH_OIDC_CLIENT_ID, and other AUTH_* constants instead diff --git a/lib/constructs/api/authConstruct.ts b/lib/constructs/api/authConstruct.ts index 4ff6091d..f2b55a5b 100644 --- a/lib/constructs/api/authConstruct.ts +++ b/lib/constructs/api/authConstruct.ts @@ -46,6 +46,7 @@ export class AuthApiConstruct extends Construct { AUTH_SESSION_TTL_HOURS: props.mlspaceConfig.AUTH_SESSION_TTL_HOURS.toString(), AUTH_TOKEN_ENCRYPTION_KEY_SECRET_NAME: props.mlspaceConfig.AUTH_TOKEN_ENCRYPTION_KEY_SECRET_NAME, AUTH_STATE_ENCRYPTION_KEY_SECRET_NAME: props.mlspaceConfig.AUTH_STATE_ENCRYPTION_KEY_SECRET_NAME, + AUTH_KEY_VERSIONS_TO_KEEP: String(props.mlspaceConfig.AUTH_KEY_VERSIONS_TO_KEEP), NEW_USERS_SUSPENDED: props.mlspaceConfig.NEW_USERS_SUSPENDED ? 'True' : 'False', WEB_CUSTOM_DOMAIN_NAME: props.mlspaceConfig.WEB_CUSTOM_DOMAIN_NAME || '' }; diff --git a/lib/constructs/auth/authSecretsConstruct.ts b/lib/constructs/auth/authSecretsConstruct.ts index ea275ca0..01b82e93 100644 --- a/lib/constructs/auth/authSecretsConstruct.ts +++ b/lib/constructs/auth/authSecretsConstruct.ts @@ -97,6 +97,7 @@ export class AuthSecretsConstruct extends Construct { layers: props.layers, environment: { STATE_ENCRYPTION_SECRET_ARN: this.stateEncryptionSecret.secretArn, + AUTH_KEY_VERSIONS_TO_KEEP: String(props.config.AUTH_KEY_VERSIONS_TO_KEEP), }, vpc: props.vpc, securityGroups: props.securityGroups, @@ -138,6 +139,7 @@ export class AuthSecretsConstruct extends Construct { layers: props.layers, environment: { TOKEN_ENCRYPTION_SECRET_ARN: this.tokenEncryptionSecret.secretArn, + AUTH_KEY_VERSIONS_TO_KEEP: String(props.config.AUTH_KEY_VERSIONS_TO_KEEP), }, vpc: props.vpc, securityGroups: props.securityGroups, @@ -171,7 +173,7 @@ export class AuthSecretsConstruct extends Construct { * Create manual initialization functions for secrets. * These can be invoked on-demand to initialize secrets with proper key structures. */ - public createManualInitializationFunctions (): { stateInit: IFunction; tokenInit: IFunction } { + public createManualInitializationFunctions (config: MLSpaceConfig): { stateInit: IFunction; tokenInit: IFunction } { const stateInitFunction = new Function(this, 'ManualStateInitFunction', { runtime: Runtime.PYTHON_3_11, code: Code.fromAsset('backend/src'), @@ -180,6 +182,7 @@ export class AuthSecretsConstruct extends Construct { memorySize: 256, environment: { STATE_ENCRYPTION_SECRET_ARN: this.stateEncryptionSecret.secretArn, + AUTH_KEY_VERSIONS_TO_KEEP: String(config.AUTH_KEY_VERSIONS_TO_KEEP), }, }); @@ -191,6 +194,7 @@ export class AuthSecretsConstruct extends Construct { memorySize: 256, environment: { TOKEN_ENCRYPTION_SECRET_ARN: this.tokenEncryptionSecret.secretArn, + AUTH_KEY_VERSIONS_TO_KEEP: String(config.AUTH_KEY_VERSIONS_TO_KEEP), }, }); diff --git a/lib/utils/configTypes.ts b/lib/utils/configTypes.ts index 34ff44dc..067f06e0 100644 --- a/lib/utils/configTypes.ts +++ b/lib/utils/configTypes.ts @@ -33,6 +33,7 @@ import { AUTH_SESSION_TTL_HOURS, AUTH_STATE_ENCRYPTION_KEY_SECRET_NAME, AUTH_SYNC_DOMAINS, + AUTH_KEY_VERSIONS_TO_KEEP, AWS_ACCOUNT, AWS_REGION, BACKGROUND_REFRESH_INTERVAL, @@ -142,6 +143,7 @@ export type MLSpaceConfig = { AUTH_SESSION_TTL_HOURS: number, AUTH_TOKEN_ENCRYPTION_KEY_SECRET_NAME: string, AUTH_STATE_ENCRYPTION_KEY_SECRET_NAME: string, + AUTH_KEY_VERSIONS_TO_KEEP: number, // Other properties not handled in config.json SYSTEM_TAG: string, IAM_RESOURCE_PREFIX: string, @@ -250,6 +252,7 @@ export function generateConfig (accountId?: string) { AUTH_SESSION_TTL_HOURS: AUTH_SESSION_TTL_HOURS, AUTH_TOKEN_ENCRYPTION_KEY_SECRET_NAME: AUTH_TOKEN_ENCRYPTION_KEY_SECRET_NAME, AUTH_STATE_ENCRYPTION_KEY_SECRET_NAME: AUTH_STATE_ENCRYPTION_KEY_SECRET_NAME, + AUTH_KEY_VERSIONS_TO_KEEP: AUTH_KEY_VERSIONS_TO_KEEP, // Other properties not prompted for in config-helper SYSTEM_TAG: SYSTEM_TAG, IAM_RESOURCE_PREFIX: IAM_RESOURCE_PREFIX,