class Aws::Plugins::S3RequestSigner::BucketSigningErrorHandler

This handler detects when a request fails because signature version 4 is required but not used. It follows up by making a request to determine the correct region, then finally a version 4 signed request against the regional endpoint.

Constants

SIGV4_MSG

Public Instance Methods

call(context) click to toggle source
# File lib/aws-sdk-core/plugins/s3_request_signer.rb, line 148
def call(context)
  response = @handler.call(context)
  handle_region_errors(response)
end

Private Instance Methods

detect_region_and_retry(resp) click to toggle source
# File lib/aws-sdk-core/plugins/s3_request_signer.rb, line 187
def detect_region_and_retry(resp)
  context = resp.context
  updgrade_to_v4(context, 'us-east-1')
  resp = @handler.call(context)
  if resp.successful?
    resp
  else
    actual_region = region_from_location_header(context)
    updgrade_to_v4(context, actual_region)
    log_warning(context, actual_region)
    @handler.call(context)
  end
end
extract_body_region_and_retry(context) click to toggle source
# File lib/aws-sdk-core/plugins/s3_request_signer.rb, line 176
def extract_body_region_and_retry(context)
  actual_region = region_from_body(context)
  updgrade_to_v4(context, actual_region)
  log_warning(context, actual_region)
  @handler.call(context)
end
handle_region_errors(response) click to toggle source
# File lib/aws-sdk-core/plugins/s3_request_signer.rb, line 155
def handle_region_errors(response)
  if sigv4_required_error?(response)
    detect_region_and_retry(response)
  elsif wrong_sigv4_region?(response)
    extract_body_region_and_retry(response.context)
  else
    response
  end
end
log_warning(context, actual_region) click to toggle source
# File lib/aws-sdk-core/plugins/s3_request_signer.rb, line 215
def log_warning(context, actual_region)
  S3::BUCKET_REGIONS[context.params[:bucket]] = actual_region
  msg = "S3 client configured for #{context.config.region.inspect} " +
    "but the bucket #{context.params[:bucket].inspect} is in " +
    "#{actual_region.inspect}; Please configure the proper region " +
    "to avoid multiple unecessary redirects and signing attempts\n"
  if logger = context.config.logger
    logger.warn(msg)
  else
    warn(msg)
  end
end
region_from_body(context) click to toggle source
# File lib/aws-sdk-core/plugins/s3_request_signer.rb, line 183
def region_from_body(context)
  context.http_response.body_contents.match(/<Region>(.+?)<\/Region>/)[1]
end
region_from_location_header(context) click to toggle source
# File lib/aws-sdk-core/plugins/s3_request_signer.rb, line 210
def region_from_location_header(context)
  location = context.http_response.headers['location']
  location.match(/s3[.-](.+?)\.amazonaws\.com/)[1]
end
sigv4_required_error?(resp) click to toggle source
# File lib/aws-sdk-core/plugins/s3_request_signer.rb, line 165
def sigv4_required_error?(resp)
  resp.context.http_response.status_code == 400 &&
  resp.context.http_response.body_contents.match(SIGV4_MSG) &&
  resp.context.http_response.body.respond_to?(:truncate)
end
updgrade_to_v4(context, region) click to toggle source
# File lib/aws-sdk-core/plugins/s3_request_signer.rb, line 201
def updgrade_to_v4(context, region)
  context.http_response.body.truncate(0)
  context.http_request.headers.delete('authorization')
  context.http_request.headers.delete('x-amz-security-token')
  context.http_request.endpoint.host = new_hostname(context, region)
  signer = Signers::V4.new(context.config.credentials, 's3', region)
  signer.sign(context.http_request)
end
wrong_sigv4_region?(resp) click to toggle source
# File lib/aws-sdk-core/plugins/s3_request_signer.rb, line 171
def wrong_sigv4_region?(resp)
  resp.context.http_response.status_code == 400 &&
  resp.context.http_response.body_contents.match(/<Region>.+?<\/Region>/)
end