Class: LLM::Bedrock::Signature Private

Inherits:
Object
  • Object
show all
Defined in:
lib/llm/providers/bedrock/signature.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Signs HTTP requests and headers with AWS Signature V4.

Returns the signed headers as a Hash through #to_h, ready to merge into a Net::HTTPRequest or other HTTP client. Everything else is private.

Uses only Ruby’s stdlib (openssl, digest) with no external deps.

Examples:

signature = LLM::Bedrock::Signature.new(
  credentials: LLM::Object.from(
    access_key_id: ENV["AWS_ACCESS_KEY_ID"],
    secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"],
    aws_region: "us-east-1",
    host: "bedrock-runtime.us-east-1.amazonaws.com",
    session_token: nil
  ),
  method: "POST",
  path: "/model/anthropic.claude-3/converse",
  body: '{"messages":[...]}'
)
signature.sign!(req)

Constant Summary collapse

SERVICE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

"bedrock"

Instance Method Summary collapse

Constructor Details

#initialize(credentials:, method:, path:, body:, query: nil) ⇒ Signature

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Signature.

Parameters:

  • credentials (LLM::Object)

    AWS signing credentials and host

  • method (String)

    HTTP method (“POST”, “GET”, etc.)

  • path (String)

    Request path (e.g. “/model/…/converse”)

  • body (String)

    Raw request body

  • query (String, nil) (defaults to: nil)

    Canonical query string



41
42
43
44
45
46
47
# File 'lib/llm/providers/bedrock/signature.rb', line 41

def initialize(credentials:, method:, path:, body:, query: nil)
  @credentials = credentials
  @method = method
  @path = path
  @query = query
  @body = body
end

Instance Method Details

#sign!(req) ⇒ Net::HTTPRequest

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • req (Net::HTTPRequest)

Returns:

  • (Net::HTTPRequest)


94
95
96
97
# File 'lib/llm/providers/bedrock/signature.rb', line 94

def sign!(req)
  to_h.each { |k, v| req[k] = v }
  req
end

#to_hHash{String => String}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the signed headers as a plain Hash.

Call this once per request and merge the result into your HTTP headers. Each call recomputes the signature with the current time, so call it immediately before sending.

Returns:

  • (Hash{String => String})


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/llm/providers/bedrock/signature.rb', line 57

def to_h
  now = Time.now.utc
  amz_date = now.strftime("%Y%m%dT%H%M%SZ")
  date_stamp = now.strftime("%Y%m%d")
  payload_hash = Digest::SHA256.hexdigest(@body)
  headers = {
    "X-Amz-Date" => amz_date,
    "X-Amz-Content-Sha256" => payload_hash,
    "Content-Type" => "application/json",
    "Host" => @credentials.host
  }
  headers["X-Amz-Security-Token"] = @credentials.session_token if @credentials.session_token
  signed_headers = build_signed_headers
  canonical_headers = build_canonical_headers(headers, signed_headers)
  canonical_uri = build_canonical_uri
  canonical_query = build_canonical_query
  canonical_request = build_canonical_request(
    canonical_uri, canonical_query, canonical_headers, signed_headers, payload_hash
  )
  credential_scope = "#{date_stamp}/#{@credentials.aws_region}/#{SERVICE}/aws4_request"
  string_to_sign = build_string_to_sign(
    amz_date, credential_scope, canonical_request
  )
  signing_key = derive_signing_key(date_stamp)
  signature = OpenSSL::HMAC.hexdigest(
    "sha256", signing_key, string_to_sign
  )
  headers["Authorization"] =
    "AWS4-HMAC-SHA256 " \
    "Credential=#{@credentials.access_key_id}/#{credential_scope}, " \
    "SignedHeaders=#{signed_headers}, Signature=#{signature}"
  headers
end