diff --git a/.env.example b/.env.example index 56568fc88..548bd1971 100644 --- a/.env.example +++ b/.env.example @@ -103,7 +103,8 @@ POSTHOG_HOST= # Active Record Encryption Keys (Optional) # These keys are used to encrypt sensitive data like API keys in the database. -# If not provided, they will be automatically generated based on your SECRET_KEY_BASE. +# For managed mode: Set these environment variables to provide encryption keys. +# For self-hosted mode: If not provided, they will be automatically generated based on your SECRET_KEY_BASE. # You can generate your own keys by running: rails db:encryption:init # ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY= # ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY= diff --git a/charts/sure/README.md b/charts/sure/README.md index a1dfb8903..6a004d153 100644 --- a/charts/sure/README.md +++ b/charts/sure/README.md @@ -533,9 +533,9 @@ ingress: secretName: finance-tls ``` -## Boot-required secrets (self-hosted) +## Boot-required secrets -In self-hosted mode the Rails initializer for Active Record Encryption loads on boot. To prevent boot crashes, ensure the following environment variables are present for ALL workloads (web, worker, migrate job/initContainer, CronJobs, and the SimpleFin backfill job): +The Rails initializer for Active Record Encryption loads on boot. To prevent boot crashes, ensure the following environment variables are present for ALL workloads (web, worker, migrate job/initContainer, CronJobs, and the SimpleFin backfill job): - `SECRET_KEY_BASE` - `ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY` @@ -552,7 +552,7 @@ rails: enabled: true # set to false to skip injecting the three AR encryption env vars ``` -Note: Even if `simplefin.encryption.enabled=false`, the app initializer expects these env vars to exist in self-hosted mode. +Note: In self-hosted mode, if these env vars are not provided, they will be automatically generated from `SECRET_KEY_BASE`. In managed mode, these env vars must be explicitly provided via environment variables or Rails credentials. ## Advanced environment variable injection diff --git a/config/initializers/active_record_encryption.rb b/config/initializers/active_record_encryption.rb index 30d771531..0c6da99ef 100644 --- a/config/initializers/active_record_encryption.rb +++ b/config/initializers/active_record_encryption.rb @@ -1,25 +1,33 @@ -# Auto-generate Active Record encryption keys for self-hosted instances -# This ensures encryption works out of the box without manual setup -if Rails.application.config.app_mode.self_hosted? && !Rails.application.credentials.active_record_encryption.present? - # Check if keys are provided via environment variables - primary_key = ENV["ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY"] - deterministic_key = ENV["ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY"] - key_derivation_salt = ENV["ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT"] +# Configure Active Record encryption keys +# Priority order: +# 1. Environment variables (works for both managed and self-hosted modes) +# 2. Auto-generation from SECRET_KEY_BASE (self-hosted only, if credentials not present) +# 3. Rails credentials (fallback, handled in application.rb) - # If any key is missing, generate all of them based on SECRET_KEY_BASE - if primary_key.blank? || deterministic_key.blank? || key_derivation_salt.blank? - # Use SECRET_KEY_BASE as the seed for deterministic key generation - # This ensures keys are consistent across container restarts - secret_base = Rails.application.secret_key_base +# Check if keys are provided via environment variables +primary_key = ENV["ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY"] +deterministic_key = ENV["ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY"] +key_derivation_salt = ENV["ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT"] - # Generate deterministic keys from the secret base - primary_key = Digest::SHA256.hexdigest("#{secret_base}:primary_key")[0..63] - deterministic_key = Digest::SHA256.hexdigest("#{secret_base}:deterministic_key")[0..63] - key_derivation_salt = Digest::SHA256.hexdigest("#{secret_base}:key_derivation_salt")[0..63] - end +# If all environment variables are present, use them (works for both managed and self-hosted) +if primary_key.present? && deterministic_key.present? && key_derivation_salt.present? + Rails.application.config.active_record.encryption.primary_key = primary_key + Rails.application.config.active_record.encryption.deterministic_key = deterministic_key + Rails.application.config.active_record.encryption.key_derivation_salt = key_derivation_salt +elsif Rails.application.config.app_mode.self_hosted? && !Rails.application.credentials.active_record_encryption.present? + # For self-hosted instances without credentials or env vars, auto-generate keys + # Use SECRET_KEY_BASE as the seed for deterministic key generation + # This ensures keys are consistent across container restarts + secret_base = Rails.application.secret_key_base + + # Generate deterministic keys from the secret base + primary_key = Digest::SHA256.hexdigest("#{secret_base}:primary_key")[0..63] + deterministic_key = Digest::SHA256.hexdigest("#{secret_base}:deterministic_key")[0..63] + key_derivation_salt = Digest::SHA256.hexdigest("#{secret_base}:key_derivation_salt")[0..63] # Configure Active Record encryption Rails.application.config.active_record.encryption.primary_key = primary_key Rails.application.config.active_record.encryption.deterministic_key = deterministic_key Rails.application.config.active_record.encryption.key_derivation_salt = key_derivation_salt end +# If none of the above conditions are met, credentials from application.rb will be used