class Mongo::Crypt::Context
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.)
@api private
Attributes
Public Class Methods
Create a new Context object
@param [ Mongo::Crypt::Handle ] mongocrypt_handle A handle to libmongocrypt
used to create a new context object.
@param [ ClientEncryption::IO ] io An instance of the IO class
that implements driver I/O methods required to run the state machine.
# File lib/mongo/crypt/context.rb, line 40 def initialize(mongocrypt_handle, io) @mongocrypt_handle = mongocrypt_handle # Ideally, this level of the API wouldn't be passing around pointer # references between objects, so this method signature is subject to change. # FFI::AutoPointer uses a custom release strategy to automatically free # the pointer once this object goes out of scope @ctx_p = FFI::AutoPointer.new( Binding.mongocrypt_ctx_new(@mongocrypt_handle.ref), Binding.method(:mongocrypt_ctx_destroy) ) @encryption_io = io @cached_azure_token = nil end
Public Instance Methods
Runs the mongocrypt_ctx_t state machine and handles all I/O on behalf of libmongocrypt
@return [ BSON::Document ] A BSON document representing the outcome
of the state machine. Contents can differ depending on how the context was initialized..
@raise [ Error::CryptError ] If the state machine enters the
:error state
This method is not currently unit tested. It is integration tested in spec/integration/explicit_encryption_spec.rb
# File lib/mongo/crypt/context.rb, line 77 def run_state_machine while true 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 filter = Binding.ctx_mongo_op(self) @encryption_io.find_keys(filter).each do |key| mongocrypt_feed(key) if key end mongocrypt_done when :need_mongo_collinfo filter = Binding.ctx_mongo_op(self) result = @encryption_io.collection_info(@db_name, filter) mongocrypt_feed(result) if result mongocrypt_done when :need_mongo_markings cmd = Binding.ctx_mongo_op(self) result = @encryption_io.mark_command(cmd) mongocrypt_feed(result) mongocrypt_done when :need_kms while kms_context = Binding.ctx_next_kms_ctx(self) do 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) end Binding.ctx_kms_done(self) when :need_kms_credentials Binding.ctx_provide_kms_providers( self, retrieve_kms_credentials.to_document ) else raise Error::CryptError.new( "State #{state} is not supported by Mongo::Crypt::Context" ) end end end
Returns the state of the mongocrypt_ctx_t
@return [ Symbol ] The context state
# File lib/mongo/crypt/context.rb, line 61 def state Binding.mongocrypt_ctx_state(@ctx_p) end
Private Instance Methods
Returns an Azure access token, retrieving it if necessary.
@return [ String ] An Azure access token.
@raise [ Error::CryptError ] If the Azure access token could not be
retrieved.
# File lib/mongo/crypt/context.rb, line 191 def azure_access_token if @cached_azure_token.nil? || @cached_azure_token.expired? @cached_azure_token = KMS::Azure::CredentialsRetriever.fetch_access_token end @cached_azure_token.access_token rescue KMS::CredentialsNotFound => e raise Error::CryptError.new( "Could not locate Azure credentials: #{e.class}: #{e.message}" ) end
Retrieves a GCP access token.
@return [ String ] A GCP access token.
@raise [ Error::CryptError ] If the GCP access token could not be
# File lib/mongo/crypt/context.rb, line 177 def gcp_access_token KMS::GCP::CredentialsRetriever.fetch_access_token rescue KMS::CredentialsNotFound => e raise Error::CryptError.new( "Could not locate GCP credentials: #{e.class}: #{e.message}" ) end
Indicate that state machine is done feeding I/O responses back to libmongocrypt
# File lib/mongo/crypt/context.rb, line 133 def mongocrypt_done Binding.mongocrypt_ctx_mongo_done(ctx_p) end
Retrieves KMS credentials for providers that are configured for automatic credentials retrieval.
@return [ Crypt::KMS::Credentials ] Credentials for the configured
KMS providers.
# File lib/mongo/crypt/context.rb, line 151 def retrieve_kms_credentials providers = {} if kms_providers.aws&.empty? begin aws_credentials = Mongo::Auth::Aws::CredentialsRetriever.new.credentials 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 } end if kms_providers.azure&.empty? providers[:azure] = { access_token: azure_access_token } end KMS::Credentials.new(providers) end