Class: Google::Auth::ExternalAccount::AwsRequestSigner

Inherits:
Object
  • Object
show all
Defined in:
lib/googleauth/external_account/aws_credentials.rb

Overview

Implements an AWS request signer based on the AWS Signature Version 4 signing process. https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html

Instance Method Summary collapse

Constructor Details

#initialize(region_name) ⇒ AwsRequestSigner

Instantiates an AWS request signer used to compute authenticated signed requests to AWS APIs based on the AWS Signature Version 4 signing process.

Parameters:

  • region_name (string)

    The AWS region to use.



264
265
266
# File 'lib/googleauth/external_account/aws_credentials.rb', line 264

def initialize region_name
  @region_name = region_name
end

Instance Method Details

#generate_signed_request(aws_credentials, original_request) ⇒ Hash

Generates an AWS signature version 4 signed request.

Creates a signed request following the AWS Signature Version 4 process, which provides secure authentication for AWS API calls. The process includes creating canonical request strings, calculating signatures using the AWS credentials, and building proper authorization headers.

For detailed information on the signing process, see: https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html

Parameters:

  • aws_credentials (Hash)

    The AWS security credentials with the following keys: @option aws_credentials [String] :access_key_id The AWS access key ID @option aws_credentials [String] :secret_access_key The AWS secret access key @option aws_credentials [String, nil] :session_token Optional AWS session token

  • original_request (Hash)

    The request to sign with the following keys: @option original_request [String] :url The AWS service URL (must be HTTPS) @option original_request [String] :method The HTTP method (GET, POST, etc.) @option original_request [Hash, nil] :headers Optional request headers @option original_request [String, nil] :data Optional request payload

Returns:

  • (Hash)

    The signed request with the following keys:

    • :url - The original URL as a string
    • :headers - A hash of headers with the authorization header added
    • :method - The HTTP method
    • :data - The request payload (if present)

Raises:



296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/googleauth/external_account/aws_credentials.rb', line 296

def generate_signed_request aws_credentials, original_request
  uri = Addressable::URI.parse original_request[:url]
  unless uri.hostname && uri.scheme == "https"
    # NOTE: We use AwsCredentials name but can't access its principal since AwsRequestSigner
    # is a separate class and not a credential object with access to the audience
    raise CredentialsError.with_details(
      "Invalid AWS service URL",
      credential_type_name: AwsCredentials.name,
      principal: "aws"
    )
  end
  service_name = uri.host.split(".").first

  datetime = Time.now.utc.strftime "%Y%m%dT%H%M%SZ"
  date = datetime[0, 8]

  headers = aws_headers aws_credentials, original_request, datetime

  request_payload = original_request[:data] || ""
  content_sha256 = sha256_hexdigest request_payload

  canonical_req = canonical_request original_request[:method], uri, headers, content_sha256
  sts = string_to_sign datetime, canonical_req, service_name

  # Authorization header requires everything else to be properly setup in order to be properly
  # calculated.
  headers["Authorization"] = build_authorization_header headers, sts, aws_credentials, service_name, date

  {
    url: uri.to_s,
    headers: headers,
    method: original_request[:method],
    data: (request_payload unless request_payload.empty?)
  }.compact
end