CP-11289 - Migrate CloudFront config to environment variables

Remove hardcoded CloudFront domains and key pair IDs from repository.
All CloudFront configuration now loaded from ENV variables for security:
- CF_URL: CloudFront distribution URL
- CF_KEY_PAIR_ID: CloudFront key pair identifier
- CF_KEY_SECRET: AWS Secrets Manager path for private key
- SECURED_STORAGE_BUCKET: S3 bucket name
- SECURED_STORAGE_REGION: AWS region

This prevents exposure of infrastructure identifiers in public repository.
Configuration should be set via cpdocuseal deployment module.
pull/544/head
Bernardo Anderson 2 months ago
parent d17d1c6561
commit 7ddafe0b13

@ -128,6 +128,40 @@ PRESIGNED_URLS_EXPIRE_MINUTES=240
# Default: INFO # Default: INFO
# AWS_SDK_LOG_LEVEL=INFO # AWS_SDK_LOG_LEVEL=INFO
# =============================================================================
# CLOUDFRONT SIGNED URLs (SECURED STORAGE)
# =============================================================================
# Optional: CloudFront distribution URL for secure document access
# Required for secured storage with signed URLs (production deployments)
# Format: https://your-cloudfront-domain.cloudfront.net
# SECURITY NOTE: Set via cpdocuseal deployment config, not committed to repo
# CF_URL=https://example.cloudfront.net
# Optional: CloudFront key pair ID for signing URLs
# Required when using CloudFront signed URLs for document access
# SECURITY NOTE: Set via cpdocuseal deployment config, not committed to repo
# CF_KEY_PAIR_ID=K1234567890ABC
# Optional: CloudFront private key secret path in AWS Secrets Manager
# The initializer will load the private key from this secret location
# Format: environment/cloudfront/private_key
# SECURITY NOTE: Set via cpdocuseal deployment config, not committed to repo
# CF_KEY_SECRET=production/cloudfront/private_key
# Optional: Secured storage bucket name (shared with ATS for compliance)
# Required when using secured CloudFront storage
# SECURITY NOTE: Set via cpdocuseal deployment config, not committed to repo
# SECURED_STORAGE_BUCKET=your-company-compliance-documents
# Optional: Secured storage region
# Default: us-east-1
# SECURED_STORAGE_REGION=us-east-1
# Optional: Disable secured storage in development
# Set to 'true' to use local disk storage instead of secured S3/CloudFront
# Only applies in development environment
# DOCUSEAL_DISABLE_SECURED_STORAGE=true
# ============================================================================= # =============================================================================
# EXAMPLE CONFIGURATIONS # EXAMPLE CONFIGURATIONS
# ============================================================================= # =============================================================================

@ -8,7 +8,7 @@
# name :string not null # name :string not null
# created_at :datetime not null # created_at :datetime not null
# updated_at :datetime not null # updated_at :datetime not null
# external_account_group_id :integer not null # external_account_group_id :string not null
# #
# Indexes # Indexes
# #

@ -13,7 +13,7 @@
# Indexes # Indexes
# #
# index_document_generation_events_on_submitter_id (submitter_id) # index_document_generation_events_on_submitter_id (submitter_id)
# index_document_generation_events_on_submitter_id_and_event_name (submitter_id,event_name) UNIQUE WHERE ((event_name)::text = ANY ((ARRAY['start'::character varying, 'complete'::character varying])::text[])) # index_document_generation_events_on_submitter_id_and_event_name (submitter_id,event_name) UNIQUE WHERE ((event_name)::text = ANY (ARRAY[('start'::character varying)::text, ('complete'::character varying)::text]))
# #
# Foreign Keys # Foreign Keys
# #

@ -20,7 +20,7 @@
# #
# index_email_events_on_account_id_and_event_datetime (account_id,event_datetime) # index_email_events_on_account_id_and_event_datetime (account_id,event_datetime)
# index_email_events_on_email (email) # index_email_events_on_email (email)
# index_email_events_on_email_event_types (email) WHERE ((event_type)::text = ANY ((ARRAY['bounce'::character varying, 'soft_bounce'::character varying, 'complaint'::character varying, 'soft_complaint'::character varying])::text[])) # index_email_events_on_email_event_types (email) WHERE ((event_type)::text = ANY (ARRAY[('bounce'::character varying)::text, ('soft_bounce'::character varying)::text, ('complaint'::character varying)::text, ('soft_complaint'::character varying)::text]))
# index_email_events_on_emailable (emailable_type,emailable_id) # index_email_events_on_emailable (emailable_type,emailable_id)
# index_email_events_on_message_id (message_id) # index_email_events_on_message_id (message_id)
# #

@ -47,15 +47,15 @@ class DocumentSecurityService
end end
def cloudfront_base_url def cloudfront_base_url
@cloudfront_base_url ||= Rails.configuration.x.compliance_storage&.dig(:cf_url) @cloudfront_base_url ||= ENV['CF_URL']
end end
def cloudfront_key_pair_id def cloudfront_key_pair_id
@cloudfront_key_pair_id ||= Rails.configuration.x.compliance_storage&.dig(:cf_key_pair) @cloudfront_key_pair_id ||= ENV['CF_KEY_PAIR_ID']
end end
def cloudfront_private_key def cloudfront_private_key
@cloudfront_private_key ||= ENV.fetch('SECURE_ATTACHMENT_PRIVATE_KEY', nil) @cloudfront_private_key ||= ENV['SECURE_ATTACHMENT_PRIVATE_KEY']
end end
end end
end end

@ -44,9 +44,6 @@ module DocuSeal
autoloaders.once.do_not_eager_load("#{Turbo::Engine.root}/app/channels") # https://github.com/hotwired/turbo-rails/issues/512 autoloaders.once.do_not_eager_load("#{Turbo::Engine.root}/app/channels") # https://github.com/hotwired/turbo-rails/issues/512
# DocuSeal compliance storage configuration (reuses ATS infrastructure)
config.x.compliance_storage = config_for(:compliance_storage)
ActiveSupport.run_load_hooks(:application_config, self) ActiveSupport.run_load_hooks(:application_config, self)
end end
end end

@ -3,7 +3,8 @@
require 'aws-sdk-secretsmanager' require 'aws-sdk-secretsmanager'
# Load CloudFront private key from AWS Secrets Manager (same as ATS) # Load CloudFront private key from AWS Secrets Manager (same as ATS)
key_secret = Rails.configuration.x.compliance_storage&.dig(:cf_key_secret) # Configuration loaded from environment variables (set in cpdocuseal deployment)
key_secret = ENV['CF_KEY_SECRET']
if key_secret.present? if key_secret.present?
begin begin

@ -851,8 +851,8 @@ module Submissions
return Rails.application.config.active_storage.service return Rails.application.config.active_storage.service
end end
# Use secured storage if compliance configuration is present # Use secured storage if CloudFront configuration is present (loaded from ENV)
if Rails.configuration.x.compliance_storage.present? if ENV['CF_URL'].present? && ENV['CF_KEY_PAIR_ID'].present?
'aws_s3_secured' 'aws_s3_secured'
else else
Rails.application.config.active_storage.service Rails.application.config.active_storage.service

@ -8,7 +8,7 @@
# name :string not null # name :string not null
# created_at :datetime not null # created_at :datetime not null
# updated_at :datetime not null # updated_at :datetime not null
# external_account_group_id :integer not null # external_account_group_id :string not null
# #
# Indexes # Indexes
# #

Loading…
Cancel
Save