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 1757 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 1099 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 1744 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 617 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 778 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 684 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 808 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 752 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 718 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 1145 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 1122 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 889 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 860 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 921 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 1623 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 648 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 561 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 1730 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 1693 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 492 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 590 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 459 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 527 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 1661 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 399 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 1055 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 1031 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 1075 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 962 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 1002 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 108 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 1441 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 1408 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 1333 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 1295 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 1376 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 349 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 319 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 376 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 1587 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 1780 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 131 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