123456789_123456789_123456789_123456789_123456789_

Class: Mongo::Crypt::Context Private

Do not use. This class is for internal use only.
Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Subclasses:
Mongo::Crypt::AutoDecryptionContext, Mongo::Crypt::AutoEncryptionContext, Mongo::Crypt::DataKeyContext, Mongo::Crypt::ExplicitDecryptionContext, Mongo::Crypt::ExplicitEncryptionContext, Mongo::Crypt::ExplicitEncryptionExpressionContext, Mongo::Crypt::RewrapManyDataKeyContext
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Forwardable
Inherits: Object
Defined in: lib/mongo/crypt/context.rb

Overview

A wrapper around mongocrypt_ctx_t, which manages the state machine for encryption and decription.

This class is a superclass that defines shared methods amongst contexts that are initialized for different purposes (e.g. data key creation, encryption, explicit encryption, etc.)

Class Method Summary

Instance Attribute Summary

  • #ctx_p readonly Internal use only

Instance Method Summary

Instance Attribute Details

#ctx_p (readonly)

[ GitHub ]

  
# File 'lib/mongo/crypt/context.rb', line 56

attr_reader :ctx_p

Instance Method Details

#azure_access_token(timeout_holder) ⇒ String (private)

Returns an Azure access token, retrieving it if necessary.

Returns:

  • (String)

    An Azure access token.

Raises:

[ GitHub ]

  
# File 'lib/mongo/crypt/context.rb', line 226

def azure_access_token(timeout_holder)
  if @cached_azure_token.nil? || @cached_azure_token.expired?
    @cached_azure_token = KMS::Azure::CredentialsRetriever.fetch_access_token(timeout_holder: timeout_holder)
  end
  @cached_azure_token.access_token
rescue KMS::CredentialsNotFound => e
  raise Error::CryptError.new(
    "Could not locate Azure credentials: #{e.class}: #{e.message}"
  )
end

#feed_kms (private)

[ GitHub ]

  
# File 'lib/mongo/crypt/context.rb', line 142

def feed_kms
  while (kms_context = Binding.ctx_next_kms_ctx(self)) do
    begin
      delay = Binding.kms_ctx_usleep(kms_context)
      sleep(delay / 1_000_000.0) unless delay.nil?
      provider = Binding.kms_ctx_get_kms_provider(kms_context)
      tls_options = @mongocrypt_handle.kms_tls_options(provider)
      @encryption_io.feed_kms(kms_context, tls_options)
    rescue Error::KmsError => e
      if e.network_error?
        if Binding.kms_ctx_fail(kms_context)
          next
        else
          raise
        end
      else
        raise
      end
    end
  end
  Binding.ctx_kms_done(self)
end

#gcp_access_token(timeout_holder) ⇒ String (private)

Retrieves a GCP access token.

Returns:

  • (String)

    A GCP access token.

Raises:

[ GitHub ]

  
# File 'lib/mongo/crypt/context.rb', line 212

def gcp_access_token(timeout_holder)
  KMS::GCP::CredentialsRetriever.fetch_access_token(timeout_holder)
rescue KMS::CredentialsNotFound => e
  raise Error::CryptError.new(
    "Could not locate GCP credentials: #{e.class}: #{e.message}"
  )
end

#mongocrypt_done (private)

Indicate that state machine is done feeding I/O responses back to libmongocrypt

[ GitHub ]

  
# File 'lib/mongo/crypt/context.rb', line 166

def mongocrypt_done
  Binding.mongocrypt_ctx_mongo_done(ctx_p)
end

#mongocrypt_feed(doc) ⇒ BSON::Document (private)

Feeds the result of a ::Mongo operation back to libmongocrypt.

Parameters:

  • doc (Hash)

    BSON document to feed.

Returns:

  • (BSON::Document)

    BSON document containing the result.

[ GitHub ]

  
# File 'lib/mongo/crypt/context.rb', line 175

def mongocrypt_feed(doc)
  Binding.ctx_mongo_feed(self, doc)
end

#provide_collection_info(timeout_ms) (private)

[ GitHub ]

  
# File 'lib/mongo/crypt/context.rb', line 123

def provide_collection_info(timeout_ms)
  filter = Binding.ctx_mongo_op(self)

  result = @encryption_io.collection_info(@db_name, filter, timeout_ms: timeout_ms)
  mongocrypt_feed(result) if result

  mongocrypt_done
end

#provide_keys(timeout_ms) (private)

[ GitHub ]

  
# File 'lib/mongo/crypt/context.rb', line 132

def provide_keys(timeout_ms)
  filter = Binding.ctx_mongo_op(self)

  @encryption_io.find_keys(filter, timeout_ms: timeout_ms).each do |key|
    mongocrypt_feed(key) if key
  end

  mongocrypt_done
end

#provide_markings(timeout_ms) (private)

[ GitHub ]

  
# File 'lib/mongo/crypt/context.rb', line 114

def provide_markings(timeout_ms)
  cmd = Binding.ctx_mongo_op(self)

  result = @encryption_io.mark_command(cmd, timeout_ms: timeout_ms)
  mongocrypt_feed(result)

  mongocrypt_done
end

#retrieve_kms_credentials(timeout_holder) ⇒ Crypt::KMS::Credentials (private)

Retrieves KMS credentials for providers that are configured for automatic credentials retrieval.

Parameters:

Returns:

[ GitHub ]

  
# File 'lib/mongo/crypt/context.rb', line 186

def retrieve_kms_credentials(timeout_holder)
  providers = {}
  if kms_providers.aws&.empty?
    begin
      aws_credentials = Mongo::Auth::Aws::CredentialsRetriever.new.credentials(timeout_holder)
    rescue Auth::Aws::CredentialsNotFound
      raise Error::CryptError.new(
        "Could not locate AWS credentials (checked environment variables, ECS and EC2 metadata)"
      )
    end
    providers[:aws] = aws_credentials.to_h
  end
  if kms_providers.gcp&.empty?
    providers[:gcp] = { access_token: gcp_access_token(timeout_holder) }
  end
  if kms_providers.azure&.empty?
    providers[:azure] = { access_token: azure_access_token(timeout_holder) }
  end
  KMS::Credentials.new(providers)
end

#run_state_machine(timeout_holder) ⇒ BSON::Document

Runs the mongocrypt_ctx_t state machine and handles all I/O on behalf of

This method is not currently unit tested. It is integration tested in spec/integration/explicit_encryption_spec.rb

Parameters:

Returns:

  • (BSON::Document)

    A BSON document representing the outcome of the state machine. Contents can differ depending on how the context was initialized..

Raises:

[ GitHub ]

  
# File 'lib/mongo/crypt/context.rb', line 80

def run_state_machine(timeout_holder)
  while true
    timeout_ms = timeout_holder.remaining_timeout_ms!
    case state
    when :error
      Binding.check_ctx_status(self)
    when :ready
      # Finalize the state machine and return the result as a BSON::Document
      return Binding.ctx_finalize(self)
    when :done
      return nil
    when :need_mongo_keys
      provide_keys(timeout_ms)
    when :need_mongo_collinfo
      provide_collection_info(timeout_ms)
    when :need_mongo_markings
      provide_markings(timeout_ms)
    when :need_kms
      feed_kms
    when :need_kms_credentials
      Binding.ctx_provide_kms_providers(
        self,
        retrieve_kms_credentials(timeout_holder).to_document
      )
    else
      raise Error::CryptError.new(
        "State #{state} is not supported by Mongo::Crypt::Context"
      )
    end
  end
end

#stateSymbol

Returns the state of the mongocrypt_ctx_t

Returns:

  • (Symbol)

    The context state

[ GitHub ]

  
# File 'lib/mongo/crypt/context.rb', line 61

def state
  Binding.mongocrypt_ctx_state(@ctx_p)
end