class Mongo::Crypt::Binding
A Ruby binding for the libmongocrypt C library
@api private
Constants
- MIN_LIBMONGOCRYPT_VERSION
Minimum version of libmongocrypt required by this version of the driver. An attempt to use the driver with any previous version of libmongocrypt will cause a `LoadError`.
@api private
Public Class Methods
Raise a Mongo::Error::CryptError based on the status of the underlying mongocrypt_ctx_t object.
@return [ nil ] Always nil.
# File lib/mongo/crypt/binding.rb, line 1756 def self.check_ctx_status(context) if block_given? do_raise = !yield else do_raise = true end if do_raise status = Status.new mongocrypt_ctx_status(context.ctx_p, status.ref) status.raise_crypt_error end end
If the provided block returns false, raise a CryptError with the status information from the provided KmsContext object.
@param [ Mongo::Crypt::KmsContext ] kms_context
@raise [ Mongo::Error::CryptError ] If the provided block returns false
# File lib/mongo/crypt/binding.rb, line 1098 def self.check_kms_ctx_status(kms_context) unless yield status = Status.new mongocrypt_kms_ctx_status(kms_context.kms_ctx_p, status.ref) status.raise_crypt_error(kms: true) end end
Raise a Mongo::Error::CryptError based on the status of the underlying mongocrypt_t object.
@return [ nil ] Always nil.
# File lib/mongo/crypt/binding.rb, line 1743 def self.check_status(handle) unless yield status = Status.new mongocrypt_status(handle.ref, status.ref) status.raise_crypt_error end end
Initialize the Context to create a data key
@param [ Mongo::Crypt::Context ] context
@raise [ Mongo::Error::CryptError ] If initialization fails
# File lib/mongo/crypt/binding.rb, line 616 def self.ctx_datakey_init(context) check_ctx_status(context) do mongocrypt_ctx_datakey_init(context.ctx_p) end end
Initialize the Context for auto-decryption
@param [ Mongo::Crypt::Context ] context @param [ BSON::Document ] command A BSON document to decrypt
@raise [ Mongo::Error::CryptError ] If initialization fails
# File lib/mongo/crypt/binding.rb, line 777 def self.ctx_decrypt_init(context, command) validate_document(command) data = command.to_bson.to_s Binary.wrap_string(data) do |data_p| check_ctx_status(context) do mongocrypt_ctx_decrypt_init(context.ctx_p, data_p) end end end
Initialize the Context for auto-encryption
@param [ Mongo::Crypt::Context ] context @param [ String ] db_name The name of the database against which the
encrypted command is being performed
@param [ Hash ] command The command to be encrypted
@raise [ Mongo::Error::CryptError ] If initialization fails
# File lib/mongo/crypt/binding.rb, line 683 def self.ctx_encrypt_init(context, db_name, command) validate_document(command) data = command.to_bson.to_s Binary.wrap_string(data) do |data_p| check_ctx_status(context) do mongocrypt_ctx_encrypt_init(context.ctx_p, db_name, -1, data_p) end end end
Initialize the Context for explicit decryption
@param [ Mongo::Crypt::Context ] context @param [ Hash ] doc A BSON document to decrypt
@raise [ Mongo::Error::CryptError ] If initialization fails
# File lib/mongo/crypt/binding.rb, line 807 def self.ctx_explicit_decrypt_init(context, doc) validate_document(doc) data = doc.to_bson.to_s Binary.wrap_string(data) do |data_p| check_ctx_status(context) do mongocrypt_ctx_explicit_decrypt_init(context.ctx_p, data_p) end end end
Initialize the Context for explicit expression encryption.
@param [ Mongo::Crypt::Context ] context @param [ Hash ] doc A BSON document to encrypt
@raise [ Mongo::Error::CryptError ] If initialization fails
# File lib/mongo/crypt/binding.rb, line 751 def self.ctx_explicit_encrypt_expression_init(context, doc) validate_document(doc) data = doc.to_bson.to_s Binary.wrap_string(data) do |data_p| check_ctx_status(context) do mongocrypt_ctx_explicit_encrypt_expression_init(context.ctx_p, data_p) end end end
Initialize the Context for explicit encryption
@param [ Mongo::Crypt::Context ] context @param [ Hash ] doc A BSON document to encrypt
@raise [ Mongo::Error::CryptError ] If initialization fails
# File lib/mongo/crypt/binding.rb, line 717 def self.ctx_explicit_encrypt_init(context, doc) validate_document(doc) data = doc.to_bson.to_s Binary.wrap_string(data) do |data_p| check_ctx_status(context) do mongocrypt_ctx_explicit_encrypt_init(context.ctx_p, data_p) end end end
Finalize the state machine represented by the Context
@param [ Mongo::Crypt::Context ] context
@raise [ Mongo::Error::CryptError ] If the state machine is not successfully
finalized
# File lib/mongo/crypt/binding.rb, line 1144 def self.ctx_finalize(context) binary = Binary.new check_ctx_status(context) do mongocrypt_ctx_finalize(context.ctx_p, binary.ref) end # TODO since the binary references a C pointer, and ByteBuffer is # written in C in MRI, we could omit a copy of the data by making # ByteBuffer reference the string that is owned by libmongocrypt. BSON::Document.from_bson(BSON::ByteBuffer.new(binary.to_s), mode: :bson) end
Indicate to libmongocrypt that it will receive no more KMS replies.
@param [ Mongo::Crypt::Context ] context
@raise [ Mongo::Error::CryptError ] If the operation is unsuccessful
# File lib/mongo/crypt/binding.rb, line 1121 def self.ctx_kms_done(context) check_ctx_status(context) do mongocrypt_ctx_kms_done(context.ctx_p) end end
Feed a response from the driver back to libmongocrypt
@param [ Mongo::Crypt::Context ] context @param [ BSON::Document ] doc The document representing the response
@raise [ Mongo::Error::CryptError ] If the response is not fed successfully
# File lib/mongo/crypt/binding.rb, line 888 def self.ctx_mongo_feed(context, doc) validate_document(doc) data = doc.to_bson.to_s Binary.wrap_string(data) do |data_p| check_ctx_status(context) do mongocrypt_ctx_mongo_feed(context.ctx_p, data_p) end end end
Returns a BSON::Document representing an operation that the driver must perform on behalf of libmongocrypt to get the information it needs in order to continue with encryption/decryption (for example, a filter for a key vault query).
@param [ Mongo::Crypt::Context ] context
@raise [ Mongo::Crypt ] If there is an error getting the operation @return [ BSON::Document ] The operation that the driver must perform
# File lib/mongo/crypt/binding.rb, line 859 def self.ctx_mongo_op(context) binary = Binary.new check_ctx_status(context) do mongocrypt_ctx_mongo_op(context.ctx_p, binary.ref) end # TODO since the binary references a C pointer, and ByteBuffer is # written in C in MRI, we could omit a copy of the data by making # ByteBuffer reference the string that is owned by libmongocrypt. BSON::Document.from_bson(BSON::ByteBuffer.new(binary.to_s), mode: :bson) end
Return a new KmsContext object needed by a Context object.
@param [ Mongo::Crypt::Context ] context
@return [ Mongo::Crypt::KmsContext | nil ] The KmsContext needed to
fetch an AWS master key or nil, if no KmsContext is needed
# File lib/mongo/crypt/binding.rb, line 920 def self.ctx_next_kms_ctx(context) kms_ctx_p = mongocrypt_ctx_next_kms_ctx(context.ctx_p) if kms_ctx_p.null? nil else KmsContext.new(kms_ctx_p) end end
Call in response to the MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS state to set per-context KMS provider settings. These follow the same format as `mongocrypt_setopt_kms_providers“. If no keys are present in the BSON input, the KMS provider settings configured for the mongocrypt_t at initialization are used.
@param [ Mongo::Crypt::Context ] context Encryption context. @param [ BSON::Document ] kms_providers BSON document mapping
the KMS provider names to credentials.
@raise [ Mongo::Error::CryptError ] If the option is not set successfully.
# File lib/mongo/crypt/binding.rb, line 1622 def self.ctx_provide_kms_providers(context, kms_providers) validate_document(kms_providers) data = kms_providers.to_bson.to_s Binary.wrap_string(data) do |data_p| check_ctx_status(context) do mongocrypt_ctx_provide_kms_providers(context.ctx_p, data_p) end end end
Initialize a context to rewrap datakeys.
@param [ Mongo::Crypt::Context ] context @param [ BSON::Document ] filter BSON Document
that represents filter to use for the find command on the key vault collection to retrieve datakeys to rewrap.
@return [ Boolean ] Whether the initialization was successful.
# File lib/mongo/crypt/binding.rb, line 647 def self.ctx_rewrap_many_datakey_init(context, filter) filter_data = filter.to_bson.to_s Binary.wrap_string(filter_data) do |data_p| check_ctx_status(context) do mongocrypt_ctx_rewrap_many_datakey_init(context.ctx_p, data_p) end end end
Set the algorithm on the context
@param [ Mongo::Crypt::Context ] context @param [ String ] name The algorithm name. Valid values are:
- "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" - "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
@raise [ Mongo::Error::CryptError ] If the operation failed
# File lib/mongo/crypt/binding.rb, line 560 def self.ctx_setopt_algorithm(context, name) check_ctx_status(context) do mongocrypt_ctx_setopt_algorithm(context.ctx_p, name, -1) end end
Set options for explicit encryption with the “rangePreview” algorithm.
@note The RangePreview algorithm is experimental only. It is not intended for public use.
@param [ Mongo::Crypt::Context ] context @param [ Hash ] opts options
@raise [ Mongo::Error::CryptError ] If the operation failed
# File lib/mongo/crypt/binding.rb, line 1729 def self.ctx_setopt_algorithm_range(context, opts) validate_document(opts) data = opts.to_bson.to_s Binary.wrap_string(data) do |data_p| check_ctx_status(context) do mongocrypt_ctx_setopt_algorithm_range(context.ctx_p, data_p) end end end
Set the contention factor used for explicit encryption. The contention factor is only used for indexed FLE 2 encryption.
@param [ Mongo::Crypt::Context ] context Explicit encryption context. @param [ Integer ] factor Contention factor used for explicit encryption.
@raise [ Mongo::Error::CryptError ] If the operation failed.
# File lib/mongo/crypt/binding.rb, line 1692 def self.ctx_setopt_contention_factor(context, factor) check_ctx_status(context) do mongocrypt_ctx_setopt_contention_factor(context.ctx_p, factor) end end
Set multiple alternate key names on data key creation
@param [ Mongo::Crypt::Context ] context A DataKeyContext @param [ Array ] key_alt_names An array of alternate key names as strings
@raise [ Mongo::Error::CryptError ] If any of the alternate names are
not valid UTF8 strings
# File lib/mongo/crypt/binding.rb, line 491 def self.ctx_setopt_key_alt_names(context, key_alt_names) key_alt_names.each do |key_alt_name| key_alt_name_bson = { :keyAltName => key_alt_name }.to_bson.to_s Binary.wrap_string(key_alt_name_bson) do |key_alt_name_p| check_ctx_status(context) do mongocrypt_ctx_setopt_key_alt_name(context.ctx_p, key_alt_name_p) end end end end
Set key encryption key document for creating a data key.
@param [ Mongo::Crypt::Context ] context @param [ BSON::Document ] key_document BSON document representing the key
encryption key document with an additional "provider" field.
@raise [ Mongo::Error::CryptError ] If the operation failed
# File lib/mongo/crypt/binding.rb, line 589 def self.ctx_setopt_key_encryption_key(context, key_document) validate_document(key_document) data = key_document.to_bson.to_s Binary.wrap_string(data) do |data_p| check_ctx_status(context) do mongocrypt_ctx_setopt_key_encryption_key(context.ctx_p, data_p) end end end
Sets the key id option on an explicit encryption context.
@param [ Mongo::Crypt::Context ] context Explicit encryption context @param [ String ] key_id The key id
@raise [ Mongo::Error::CryptError ] If the operation failed
# File lib/mongo/crypt/binding.rb, line 458 def self.ctx_setopt_key_id(context, key_id) Binary.wrap_string(key_id) do |key_id_p| check_ctx_status(context) do mongocrypt_ctx_setopt_key_id(context.ctx_p, key_id_p) end end end
Set set a custom key material to use for
encrypting data.
@param [ Mongo::Crypt::Context ] context A DataKeyContext @param [ BSON::Binary ] key_material 96 bytes of custom key material
@raise [ Mongo::Error::CryptError ] If the key material is not 96 bytes.
# File lib/mongo/crypt/binding.rb, line 526 def self.ctx_setopt_key_material(context, key_material) data = {'keyMaterial' => key_material}.to_bson.to_s Binary.wrap_string(data) do |data_p| check_ctx_status(context) do mongocrypt_ctx_setopt_key_material(context.ctx_p, data_p) end end end
Set the query type to use for FLE 2 explicit encryption. The query type is only used for indexed FLE 2 encryption.
@param [ Mongo::Crypt::Context ] context Explicit encryption context. @param [ String ] :mongocrypt_query_type query_type Type of the query.
@raise [ Mongo::Error::CryptError ] If the operation failed.
# File lib/mongo/crypt/binding.rb, line 1660 def self.ctx_setopt_query_type(context, query_type) check_ctx_status(context) do mongocrypt_ctx_setopt_query_type(context.ctx_p, query_type, -1) end end
Initialize the Mongo::Crypt::Handle object
@param [ Mongo::Crypt::Handle ] handle
@raise [ Mongo::Error::CryptError ] If initialization fails
# File lib/mongo/crypt/binding.rb, line 398 def self.init(handle) check_status(handle) do mongocrypt_init(handle.ref) end end
Get the number of bytes needed by the KmsContext.
@param [ Mongo::Crypt::KmsContext ] kms_context
@return [ Integer ] The number of bytes needed
# File lib/mongo/crypt/binding.rb, line 1054 def self.kms_ctx_bytes_needed(kms_context) mongocrypt_kms_ctx_bytes_needed(kms_context.kms_ctx_p) end
Get the hostname with which to connect over TLS to get information about the AWS master key.
@param [ Mongo::Crypt::KmsContext ] kms_context
@raise [ Mongo::Error::CryptError ] If the response is not fed successfully
@return [ String | nil ] The hostname, or nil if none exists
# File lib/mongo/crypt/binding.rb, line 1030 def self.kms_ctx_endpoint(kms_context) ptr = FFI::MemoryPointer.new(:pointer, 1) check_kms_ctx_status(kms_context) do mongocrypt_kms_ctx_endpoint(kms_context.kms_ctx_p, ptr) end str_ptr = ptr.read_pointer str_ptr.null? ? nil : str_ptr.read_string.force_encoding('UTF-8') end
Feed replies from the KMS back to libmongocrypt.
@param [ Mongo::Crypt::KmsContext ] kms_context @param [ String ] bytes The data to feed to libmongocrypt
@raise [ Mongo::Error::CryptError ] If the response is not fed successfully
# File lib/mongo/crypt/binding.rb, line 1074 def self.kms_ctx_feed(kms_context, bytes) check_kms_ctx_status(kms_context) do Binary.wrap_string(bytes) do |bytes_p| mongocrypt_kms_ctx_feed(kms_context.kms_ctx_p, bytes_p) end end end
Get the KMS provider identifier associated with this KMS request.
This is used to conditionally configure TLS connections based on the KMS request. It is useful for KMIP, which authenticates with a client certificate.
@param [ FFI::Pointer ] kms Pointer mongocrypt_kms_ctx_t object.
@returns [ Symbol | nil ] KMS provider identifier.
# File lib/mongo/crypt/binding.rb, line 961 def self.kms_ctx_get_kms_provider(kms_context) len_ptr = FFI::MemoryPointer.new(:uint32, 1) provider = mongocrypt_kms_ctx_get_kms_provider( kms_context.kms_ctx_p, len_ptr ) if len_ptr.nil? nil else len = if BSON::Environment.jruby? # JRuby FFI implementation does not have `read(type)` method, but it # has this `get_uint32`. len_ptr.get_uint32 else # For MRI we use a documented `read` method - https://www.rubydoc.info/github/ffi/ffi/FFI%2FPointer:read len_ptr.read(:uint32) end provider.read_string(len).to_sym end end
Get the HTTP message needed to fetch the AWS KMS master key from a KmsContext object.
@param [ Mongo::Crypt::KmsContext ] kms_context
@raise [ Mongo::Error::CryptError ] If the response is not fed successfully
@return [ String ] The HTTP message
# File lib/mongo/crypt/binding.rb, line 1001 def self.kms_ctx_message(kms_context) binary = Binary.new check_kms_ctx_status(kms_context) do mongocrypt_kms_ctx_message(kms_context.kms_ctx_p, binary.ref) end return binary.to_s end
Given a string representing a version number, parses it into a Gem::Version object. This handles the case where the string is not in a format supported by Gem::Version by doing some custom parsing.
@param [ String ] version String representing a version number.
@return [ Gem::Version ] the version number
@raise [ ArgumentError ] if the string cannot be parsed.
@api private
# File lib/mongo/crypt/binding.rb, line 107 def self.parse_version(version) Gem::Version.new(version) rescue ArgumentError match = version.match(/\A(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)?(-[A-Za-z\+\d]+)?\z/) raise ArgumentError.new("Malformed version number string #{version}") if match.nil? Gem::Version.new( [ match[:major], match[:minor], match[:patch] ].join('.') ) end
Set a crypto hook for the AES256-CTR operations.
@param [ Mongo::Crypt::Handle ] handle @param [ Method ] aes_encrypt_cb An AES-CTR encryption method @param [ Method ] aes_decrypt_cb A AES-CTR decryption method
@raise [ Mongo::Error::CryptError ] If the callbacks aren't set successfully
# File lib/mongo/crypt/binding.rb, line 1440 def self.setopt_aes_256_ctr(handle, aes_ctr_encrypt_cb, aes_ctr_decrypt_cb) check_status(handle) do mongocrypt_setopt_aes_256_ctr(handle.ref, aes_ctr_encrypt_cb, aes_ctr_decrypt_cb, nil ) end end
Opt-into skipping query analysis.
If opted in:
-
The csfle shared library will not attempt to be loaded.
-
A mongocrypt_ctx_t will never enter the MONGOCRYPT_CTX_NEED_MARKINGS state.
@param [ Mongo::Crypt::Handle ] handle
# File lib/mongo/crypt/binding.rb, line 1407 def self.setopt_bypass_query_analysis(handle) mongocrypt_setopt_bypass_query_analysis(handle.ref) end
Set a crypto hook for the RSASSA-PKCS1-v1_5 algorithm with
a SHA-256 hash oh the Handle.
@param [ Mongo::Crypt::Handle ] handle @param [ Method ] rsaes_pkcs_signature_cb A RSASSA-PKCS1-v1_5 signing method.
@raise [ Mongo::Error::CryptError ] If the callbacks aren't set successfully
# File lib/mongo/crypt/binding.rb, line 1332 def self.setopt_crypto_hook_sign_rsaes_pkcs1_v1_5( handle, rsaes_pkcs_signature_cb ) check_status(handle) do mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5( handle.ref, rsaes_pkcs_signature_cb, nil ) end end
Set crypto callbacks on the Handle
@param [ Mongo::Crypt::Handle ] handle @param [ Method ] aes_encrypt_cb An AES encryption method @param [ Method ] aes_decrypt_cb A AES decryption method @param [ Method ] random_cb A method that returns a string of random bytes @param [ Method ] hmac_sha_512_cb A HMAC SHA-512 method @param [ Method ] hmac_sha_256_cb A HMAC SHA-256 method @param [ Method ] hmac_hash_cb A SHA-256 hash method
@raise [ Mongo::Error::CryptError ] If the callbacks aren't set successfully
# File lib/mongo/crypt/binding.rb, line 1294 def self.setopt_crypto_hooks(handle, aes_encrypt_cb, aes_decrypt_cb, random_cb, hmac_sha_512_cb, hmac_sha_256_cb, hmac_hash_cb ) check_status(handle) do mongocrypt_setopt_crypto_hooks(handle.ref, aes_encrypt_cb, aes_decrypt_cb, random_cb, hmac_sha_512_cb, hmac_sha_256_cb, hmac_hash_cb, nil ) end end
Set a local EncryptedFieldConfigMap for encryption.
@param [ Mongo::Crypt::Handle ] handle @param [ BSON::Document ] efc_map A BSON document representing
the EncryptedFieldConfigMap supplied by the user. The keys are collection namespaces and values are EncryptedFieldConfigMap documents.
@raise [ Mongo::Error::CryptError ] If the operation failed.
# File lib/mongo/crypt/binding.rb, line 1375 def self.setopt_encrypted_field_config_map(handle, efc_map) validate_document(efc_map) data = efc_map.to_bson.to_s Binary.wrap_string(data) do |data_p| check_status(handle) do mongocrypt_setopt_encrypted_field_config_map( handle.ref, data_p ) end end end
Set KMS providers options on the Mongo::Crypt::Handle object
@param [ Mongo::Crypt::Handle ] handle @param [ BSON::Document ] kms_providers BSON document mapping
the KMS provider names to credentials.
@raise [ Mongo::Error::CryptError ] If the option is not set successfully
# File lib/mongo/crypt/binding.rb, line 348 def self.setopt_kms_providers(handle, kms_providers) validate_document(kms_providers) data = kms_providers.to_bson.to_s Binary.wrap_string(data) do |data_p| check_status(handle) do mongocrypt_setopt_kms_providers(handle.ref, data_p) end end end
Set the logger callback function on the Mongo::Crypt::Handle object
@param [ Mongo::Crypt::Handle ] handle @param [ Method ] log_callback
@raise [ Mongo::Error::CryptError ] If the callback is not set successfully
# File lib/mongo/crypt/binding.rb, line 318 def self.setopt_log_handler(handle, log_callback) check_status(handle) do mongocrypt_setopt_log_handler(handle, log_callback, nil) end end
Set schema map on the Mongo::Crypt::Handle object
@param [ Mongo::Crypt::Handle ] handle @param [ BSON::Document ] schema_map_doc The schema map as a
BSON::Document object
@raise [ Mongo::Error::CryptError ] If the schema map is not set successfully
# File lib/mongo/crypt/binding.rb, line 375 def self.setopt_schema_map(handle, schema_map_doc) validate_document(schema_map_doc) data = schema_map_doc.to_bson.to_s Binary.wrap_string(data) do |data_p| check_status(handle) do mongocrypt_setopt_schema_map(handle.ref, data_p) end end end
Opt-into handling the MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS state.
If set, before entering the MONGOCRYPT_CTX_NEED_KMS state, contexts may enter the MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS state and then wait for credentials to be supplied through `mongocrypt_ctx_provide_kms_providers`.
A context will only enter MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS if an empty document was set for a KMS provider in `mongocrypt_setopt_kms_providers`.
@param [ Mongo::Crypt::Handle ] handle
# File lib/mongo/crypt/binding.rb, line 1586 def self.setopt_use_need_kms_credentials_state(handle) mongocrypt_setopt_use_need_kms_credentials_state(handle.ref) end
Checks that the specified data is a Hash before serializing it to BSON to prevent errors from libmongocrypt
@note All BSON::Document instances are also Hash instances
@param [ Object ] data The data to be passed to libmongocrypt
@raise [ Mongo::Error::CryptError ] If the data is not a Hash
# File lib/mongo/crypt/binding.rb, line 1779 def self.validate_document(data) return if data.is_a?(Hash) if data.nil? message = "Attempted to pass nil data to libmongocrypt. " + "Data must be a Hash" else message = "Attempted to pass invalid data to libmongocrypt: #{data} " + "Data must be a Hash" end raise Error::CryptError.new(message) end
Validates if provided version of libmongocrypt is valid, i.e. equal or greater than minimum required version. Raises a LoadError if not.
@param [ String ] lmc_version String representing libmongocrypt version.
@raise [ LoadError ] if given version is lesser than minimum required version.
@api private
# File lib/mongo/crypt/binding.rb, line 130 def self.validate_version(lmc_version) if (actual_version = parse_version(lmc_version)) < MIN_LIBMONGOCRYPT_VERSION raise LoadError, "libmongocrypt version #{MIN_LIBMONGOCRYPT_VERSION} or above is required, " + "but version #{actual_version} was found." end end