123456789_123456789_123456789_123456789_123456789_

Class: Mongo::Crypt::KMS::Azure::CredentialsRetriever Private

Do not use. This class is for internal use only.
Relationships & Source Files
Inherits: Object
Defined in: lib/mongo/crypt/kms/azure/credentials_retriever.rb

Overview

This class retrieves ::Mongo::Crypt::KMS::Azure credentials using ::Mongo::Crypt::KMS::Azure metadata host. This should be used when the driver is used on the ::Mongo::Crypt::KMS::Azure environment.

Constant Summary

Class Method Summary

Class Method Details

.do_request(uri, req, timeout_holder) ⇒ Net::HTTPResponse (private)

Performs a request to ::Mongo::Crypt::KMS::Azure metadata host.

Parameters:

Returns:

  • (Net::HTTPResponse)

    Response object.

Raises:

[ GitHub ]

  
# File 'lib/mongo/crypt/kms/azure/credentials_retriever.rb', line 116

def self.do_request(uri, req, timeout_holder)
  timeout_holder&.check_timeout!
  timeout = timeout_holder&.remaining_timeout_sec || 10
  exception_class = if timeout_holder&.csot?
                      Error::TimeoutError
                    else
                      nil
                    end
  ::Timeout.timeout(timeout, exception_class) do
    Net::HTTP.start(uri.hostname, uri.port, use_ssl: false) do |http|
      http.request(req)
    end
  end
rescue ::Timeout::Error, IOError, SystemCallError, SocketError => e
  raise KMS::CredentialsNotFound,
        "Could not receive Azure metadata response; #{e.class}: #{e.message}"
end

.fetch_access_token(extra_headers: {}, metadata_host: nil, timeout_holder: nil) ⇒ KMS::Azure::AccessToken

Fetches Azure credentials from ::Mongo::Crypt::KMS::Azure metadata host.

Parameters:

  • extra_headers (Hash)

    Extra headers to be passed to the request. This is used for testing.

  • metadata_host (String | nil)

    ::Mongo::Crypt::KMS::Azure metadata host. This is used for testing.

  • timeout_holder (CsotTimeoutHolder | nil)

    CSOT timeout.

Returns:

Raises:

[ GitHub ]

  
# File 'lib/mongo/crypt/kms/azure/credentials_retriever.rb', line 44

def self.fetch_access_token(extra_headers: {}, metadata_host: nil, timeout_holder: nil)
  uri, req = prepare_request(extra_headers, )
  parsed_response = fetch_response(uri, req, timeout_holder)
  Azure::AccessToken.new(
    parsed_response.fetch('access_token'),
    Integer(parsed_response.fetch('expires_in'))
  )
rescue KeyError, ArgumentError => e
  raise KMS::CredentialsNotFound,
        "Azure metadata response is invalid: '#{parsed_response}'; #{e.class}: #{e.message}"
end

.fetch_response(uri, req, timeout_holder) ⇒ Hash (private)

Fetches response from ::Mongo::Crypt::KMS::Azure metadata host.

Parameters:

Returns:

  • (Hash)

    Parsed response.

Raises:

[ GitHub ]

  
# File 'lib/mongo/crypt/kms/azure/credentials_retriever.rb', line 92

def self.fetch_response(uri, req, timeout_holder)
  resp = do_request(uri, req, timeout_holder)
  if resp.code != '200'
    raise KMS::CredentialsNotFound,
          "Azure metadata host responded with code #{resp.code}"
  end
  JSON.parse(resp.body)
rescue JSON::ParserError => e
  raise KMS::CredentialsNotFound,
        "Azure metadata response is invalid: '#{resp.body}'; #{e.class}: #{e.message}"
end

.prepare_request(extra_headers, metadata_host) ⇒ Array<URI, Net::HTTP::Get> (private)

Prepares a request to ::Mongo::Crypt::KMS::Azure metadata host.

Parameters:

  • extra_headers (Hash)

    Extra headers to be passed to the request. This is used for testing.

  • metadata_host (String | nil)

    ::Mongo::Crypt::KMS::Azure metadata host. This is used for testing.

Returns:

[ GitHub ]

  
# File 'lib/mongo/crypt/kms/azure/credentials_retriever.rb', line 64

def self.prepare_request(extra_headers, )
  host =  || DEFAULT_HOST
  host = DEFAULT_HOST if host.empty?
  uri = URI("http://#{host}/metadata/identity/oauth2/token")
  uri.query = ::URI.encode_www_form(
    'api-version' => '2018-02-01',
    'resource' => 'https://vault.azure.net'
  )
  req = Net::HTTP::Get.new(uri)
  req['Metadata'] = 'true'
  req['Accept'] = 'application/json'
  extra_headers.each { |k, v| req[k] = v }
  [uri, req]
end