From ccd66036a00ca11687c6d668a707d16ddfc2786e Mon Sep 17 00:00:00 2001 From: matt-domsch-sp Date: Mon, 25 Nov 2024 17:34:16 +0000 Subject: [PATCH] Add fog_aws_fips config option, tests This adds the [:fog_aws_fips] option, default false. When true, it causes the default endpoint hostname to be changed from `s3` to `s3-fips`. --- lib/carrierwave/storage/fog.rb | 7 +++-- lib/carrierwave/uploader/configuration.rb | 2 ++ spec/storage/fog_helper.rb | 38 ++++++++++++++++++++++- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/lib/carrierwave/storage/fog.rb b/lib/carrierwave/storage/fog.rb index 8a1d290cd..94a1bd8a1 100644 --- a/lib/carrierwave/storage/fog.rb +++ b/lib/carrierwave/storage/fog.rb @@ -18,6 +18,8 @@ module Storage # [:fog_use_ssl_for_aws] (optional) #public_url will use https for the AWS generated URL] # [:fog_aws_accelerate] (optional) #public_url will use s3-accelerate subdomain # instead of s3, defaults to false + # [:fog_aws_fips] (optional) #public_url will use s3-fips subdomain + # instead of s3, defaults to false # # # AWS credentials contain the following keys: @@ -163,7 +165,6 @@ def connection class File DEFAULT_S3_REGION = 'us-east-1'.freeze - AWS_FIPS_REGIONS = %w(us-east-1 us-east-2 us-west-1 us-west-2 us-gov-east-1 us-gov-west-1 ca-central-1 ca-west-1).freeze include CarrierWave::Utilities::Uri include CarrierWave::Utilities::FileName @@ -383,9 +384,11 @@ def public_url # To use the virtual-hosted style, the bucket name needs to be representable as a subdomain use_virtual_hosted_style = @uploader.fog_directory.to_s =~ subdomain_regex && !(protocol == 'https' && @uploader.fog_directory =~ /\./) + return nil if !use_virtual_hosted_style && @uploader.fog_aws_fips # FIPS Endpoints can only be used with Virtual Hosted-Style addressing. + region = @uploader.fog_credentials[:region].to_s regional_host = 's3.amazonaws.com' # used for DEFAULT_S3_REGION or no region set - if ENV['AWS_USE_FIPS_ENDPOINT'] == 'true' && AWS_FIPS_REGIONS.include?(region) + if @uploader.fog_aws_fips regional_host = "s3-fips.#{region}.amazonaws.com" # https://aws.amazon.com/compliance/fips/ elsif ![DEFAULT_S3_REGION, ''].include?(region) regional_host = "s3.#{region}.amazonaws.com" diff --git a/lib/carrierwave/uploader/configuration.rb b/lib/carrierwave/uploader/configuration.rb index dce36306e..216c5cf15 100644 --- a/lib/carrierwave/uploader/configuration.rb +++ b/lib/carrierwave/uploader/configuration.rb @@ -35,6 +35,7 @@ module Configuration add_config :fog_authenticated_url_expiration add_config :fog_use_ssl_for_aws add_config :fog_aws_accelerate + add_config :fog_aws_fips # Mounting add_config :ignore_integrity_errors @@ -197,6 +198,7 @@ def reset_config config.fog_authenticated_url_expiration = 600 config.fog_use_ssl_for_aws = true config.fog_aws_accelerate = false + config.fog_aws_fips = false config.store_dir = 'uploads' config.cache_dir = 'uploads/tmp' config.delete_tmp_file_after_storage = true diff --git a/spec/storage/fog_helper.rb b/spec/storage/fog_helper.rb index 48cf0b20d..f41a79c3a 100644 --- a/spec/storage/fog_helper.rb +++ b/spec/storage/fog_helper.rb @@ -526,7 +526,8 @@ def check_file nil => 's3.amazonaws.com', 'us-east-1' => 's3.amazonaws.com', 'us-east-2' => 's3.us-east-2.amazonaws.com', - 'eu-central-1' => 's3.eu-central-1.amazonaws.com' + 'eu-central-1' => 's3.eu-central-1.amazonaws.com', + 'us-gov-west-1' => 's3.us-gov-west-1.amazonaws.com' }.each do |region, expected_host| it "should use a #{expected_host} hostname when using path style for access #{region} region" do allow(@uploader).to receive(:fog_use_ssl_for_aws).and_return(true) @@ -539,6 +540,23 @@ def check_file end end + context 'when the directory is not a valid subdomain and :fog_aws_fips' do + [ + 'us-east-1', + 'us-east-2', + 'us-gov-west-1' + ].each do |region| + it "public_url should be nil" do + allow(@uploader).to receive(:fog_use_ssl_for_aws).and_return(true) + allow(@uploader).to receive(:fog_directory).and_return('foo.bar') + allow(@uploader).to receive(:fog_aws_fips).and_return(true) + allow(@uploader).to receive(:fog_credentials).and_return(@uploader.fog_credentials.merge(region: region)) + + expect(@fog_file.public_url).to be_nil + end + end + end + context 'when the directory is a valid subdomain' do { nil => 'foobar.s3.amazonaws.com', @@ -557,6 +575,24 @@ def check_file end end + context 'when the directory is a valid subdomain and :fog_aws_fips' do + { + 'us-east-1' => 'foobar.s3-fips.us-east-1.amazonaws.com', + 'us-east-2' => 'foobar.s3-fips.us-east-2.amazonaws.com', + 'eu-central-1' => 'foobar.s3-fips.eu-central-1.amazonaws.com', # Carrierwave shouldn't know which regions are FIPS-capable + 'us-gov-west-1' => 'foobar.s3-fips.us-gov-west-1.amazonaws.com' + }.each do |region, expected_host| + it "should use a #{expected_host} hostname when using path style for access #{region} region" do + allow(@uploader).to receive(:fog_use_ssl_for_aws).and_return(true) + allow(@uploader).to receive(:fog_directory).and_return('foobar') + allow(@uploader).to receive(:fog_aws_fips).and_return(true) + allow(@uploader).to receive(:fog_credentials).and_return(@uploader.fog_credentials.merge(region: region)) + + expect(@fog_file.public_url).to include("https://#{expected_host}/") + end + end + end + it "should use https as a default protocol" do expect(@uploader.fog_use_ssl_for_aws).to be true expect(@fog_file.public_url).to start_with 'https://'