module Citadel::S3

Simple read-only S3 client.

@since 1.0.0 @api private

Public Instance Methods

get(bucket:, path:, access_key_id:, secret_access_key:, token: nil, region: nil) click to toggle source

Get an object from S3.

@param bucket [String] Name of the bucket to use. @param path [String] Path to the object. @param access_key_id [String] AWS access key ID. @param secret_access_key [String] AWS secret access key. @param token [String, nil] AWS IAM token. @param region [String] S3 bucket region. @return [Net::HTTPResponse]

# File lib/citadel/s3.rb, line 51
def get(bucket:, path:, access_key_id:, secret_access_key:, token: nil, region: nil)
  region ||= 'us-east-1' # Most buckets.
  path = path[1..-1] if path[0] == '/'
  now = Time.now().utc.strftime('%a, %d %b %Y %H:%M:%S GMT')

  string_to_sign = "GET\n\n\n#{now}\n"
  string_to_sign << "x-amz-security-token:#{token}\n" if token
  string_to_sign << "/#{bucket}/#{path}"

  signed = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), secret_access_key, string_to_sign)
  signed_base64 = Base64.encode64(signed)

  headers = {
    'date' => now,
    'authorization' => "AWS #{access_key_id}:#{signed_base64}",
  }
  headers['x-amz-security-token'] = token if token

  hostname = case region
  when 'us-east-1'
    's3.amazonaws.com'
  else
    "s3-#{region}.amazonaws.com"
  end

  begin
    Chef::HTTP.new("https://#{hostname}").get("#{bucket}/#{path}", headers)
  rescue Net::HTTPServerException => e
    raise CitadelError.new("Unable to download #{path}: #{e}")
  end
end