module Shrine::Plugins::Lambda::AttacherClassMethods

Public Instance Methods

lambda_authorize(headers, body) click to toggle source

Parses the payload of the Lambda request to the `callbackUrl` and loads the Shrine Attacher from the received context. Fetches the signing key from the attacher's record metadata and uses it for calculating the signature of the received from Lambda request. Then it compares the calculated and received signatures, returning an error if the signatures mismatch.

If the signatures are equal, it returns the attacher and the hash of the parsed result from Lambda, else - it returns false. @param [Hash] headers from the Lambda request @option headers [String] 'User-Agent' The AWS Lambda function user agent @option headers [String] 'Content-Type' 'application/json' @option headers [String] 'Host' @option headers [String] 'X-Amz-Date' The AWS Lambda function user agent @option headers [String] 'Authorization' The AWS authorization string @param [String] body of the Lambda request @return [Array] Shrine Attacher and the Lambda result (the request body parsed to a hash) if signature in

received headers matches locally computed AWS signature

@return [false] if signature in received headers does't match locally computed AWS signature

# File lib/shrine/plugins/shrine-lambda.rb, line 82
def lambda_authorize(headers, body)
  result = JSON.parse(body)
  attacher = load(result.delete('context'))
  incoming_auth_header = auth_header_hash(headers['Authorization'])

  signer = build_signer(
    incoming_auth_header['Credential'].split('/'),
    JSON.parse(attacher.record.__send__(:"#{attacher.data_attribute}") || '{}').dig('metadata', 'key') || 'key',
    headers['x-amz-security-token']
  )
  signature = signer.sign_request(http_method: 'PUT',
                                  url:         Shrine.opts[:callback_url],
                                  headers:     { 'X-Amz-Date' => headers['X-Amz-Date'] },
                                  body:        body)
  calculated_signature = auth_header_hash(signature.headers['authorization'])['Signature']
  return false if incoming_auth_header['Signature'] != calculated_signature

  [attacher, result]
end
lambda_process(data) click to toggle source

Loads the attacher from the data, and triggers its instance AWS Lambda processing method. Intended to be used in a background job.

# File lib/shrine/plugins/shrine-lambda.rb, line 58
def lambda_process(data)
  attacher = load(data)
  attacher.lambda_process(data)
  attacher
end

Private Instance Methods

auth_header_hash(header) click to toggle source

@param [String] header is the `Authorization` header string @return [Hash] the `Authorization` header string transformed into a Hash

# File lib/shrine/plugins/shrine-lambda.rb, line 118
def auth_header_hash(header)
  auth_header = header.split(/ |, |=/)
  auth_header.shift
  Hash[*auth_header]
end
build_signer(headers, secret_access_key, security_token = nil) click to toggle source
# File lib/shrine/plugins/shrine-lambda.rb, line 104
def build_signer(headers, secret_access_key, security_token = nil)
  Aws::Sigv4::Signer.new(
    service:               headers[3],
    region:                headers[2],
    access_key_id:         headers[0],
    secret_access_key:     secret_access_key,
    session_token:         security_token,
    apply_checksum_header: false,
    unsigned_headers:      %w[content-length user-agent x-amzn-trace-id]
  )
end