Class: Mongo::Crypt::AutoEncrypter Private

Inherits:
Object
  • Object
show all
Defined in:
lib/mongo/crypt/auto_encrypter.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

An AutoEcnrypter is an object that encapsulates the behavior of automatic encryption. It controls all resources associated with auto-encryption, including the libmongocrypt handle, key vault client object, mongocryptd client object, and encryption I/O.

The AutoEncrypter is kept as an instance on a Mongo::Client. Client objects with the same auto_encryption_options Hash may share AutoEncrypters.

Constant Summary collapse

DEFAULT_EXTRA_OPTIONS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

A Hash of default values for the :extra_options option

Options::Redacted.new({
  mongocryptd_uri: 'mongodb://localhost:27020',
  mongocryptd_bypass_spawn: false,
  mongocryptd_spawn_path: 'mongocryptd',
  mongocryptd_spawn_args: ['--idleShutdownTimeoutSecs=60'],
})

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ AutoEncrypter

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Set up encryption-related options and instance variables on the class that includes this module. Calls the same method on the Mongo::Crypt::Encrypter module.

Parameters:

  • options (Hash)

Options Hash (options):

  • :client (Mongo::Client)

    A client connected to the encrypted collection.

  • :key_vault_client (Mongo::Client | nil)

    A client connected to the MongoDB instance containing the encryption key vault; optional. If not provided, will default to :client option.

  • :key_vault_namespace (String)

    The namespace of the key vault in the format database.collection.

  • :schema_map (Hash | nil)

    The JSONSchema of the collection(s) with encrypted fields. This option is mutually exclusive with :schema_map_path.

  • :schema_map_path (String | nil)

    A path to a file contains the JSON schema of the collection that stores auto encrypted documents. This option is mutually exclusive with :schema_map.

  • :bypass_auto_encryption (Boolean | nil)

    When true, disables auto-encryption. Default is false.

  • :extra_options (Hash | nil)

    Options related to spawning mongocryptd. These are set to default values if no option is passed in.

  • :kms_providers (Hash)

    A hash of key management service configuration information. @see Mongo::Crypt::KMS::Credentials for list of options for every supported provider. @note There may be more than one KMS provider specified.

  • :kms_tls_options (Hash)

    TLS options to connect to KMS providers. Keys of the hash should be KSM provider names; values should be hashes of TLS connection options. The options are equivalent to TLS connection options of Mongo::Client. @see Mongo::Client#initialize for list of TLS options.

  • :encrypted_fields_map (Hash | nil)

    maps a collection namespace to an encryptedFields.

    • Note: If a collection is present on both the encryptedFieldsMap and schemaMap, an error will be raised.

  • :bypass_query_analysis (Boolean | nil)

    When true disables automatic analysis of outgoing commands.

  • :crypt_shared_lib_path (String | nil)

    Path that should be the used to load the crypt shared library. Providing this option overrides default crypt shared library load paths for libmongocrypt.

  • :crypt_shared_lib_required (Boolean | nil)

    Whether crypt shared library is required. If ‘true’, an error will be raised if a crypt_shared library cannot be loaded by libmongocrypt.

Raises:

  • (ArgumentError)

    If required options are missing or incorrectly formatted.



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/mongo/crypt/auto_encrypter.rb', line 93

def initialize(options)
  Crypt.validate_ffi!
  # Note that this call may eventually, via other method invocations,
  # create additional clients which have to be cleaned up.
  @options = set_default_options(options).freeze

  @crypt_handle = Crypt::Handle.new(
    Crypt::KMS::Credentials.new(@options[:kms_providers]),
    Crypt::KMS::Validations.validate_tls_options(@options[:kms_tls_options]),
    schema_map: @options[:schema_map],
    schema_map_path: @options[:schema_map_path],
    encrypted_fields_map: @options[:encrypted_fields_map],
    bypass_query_analysis: @options[:bypass_query_analysis],
    crypt_shared_lib_path: @options[:extra_options][:crypt_shared_lib_path],
    crypt_shared_lib_required: @options[:extra_options][:crypt_shared_lib_required],
  )

  @mongocryptd_options = @options[:extra_options].slice(
    :mongocryptd_uri,
    :mongocryptd_bypass_spawn,
    :mongocryptd_spawn_path,
    :mongocryptd_spawn_args
  )
  @mongocryptd_options[:mongocryptd_bypass_spawn] = @options[:bypass_auto_encryption] ||
    @options[:extra_options][:mongocryptd_bypass_spawn] ||
    @crypt_handle.crypt_shared_lib_available? ||
    @options[:extra_options][:crypt_shared_lib_required]

  unless @options[:extra_options][:crypt_shared_lib_required] || @crypt_handle.crypt_shared_lib_available? || @options[:bypass_query_analysis]
    @mongocryptd_client = Client.new(
      @options[:extra_options][:mongocryptd_uri],
      monitoring_io: @options[:client].options[:monitoring_io],
      populator_io: @options[:client].options[:populator_io],
      server_selection_timeout: 10,
      database: @options[:client].options[:database]
    )
  end

  begin
    @encryption_io = EncryptionIO.new(
      client: @options[:client],
      mongocryptd_client: @mongocryptd_client,
      key_vault_namespace: @options[:key_vault_namespace],
      key_vault_client: @key_vault_client,
      metadata_client: @metadata_client,
      mongocryptd_options: @mongocryptd_options
    )
  rescue
    begin
      @mongocryptd_client&.close
    rescue => e
      log_warn("Error closing mongocryptd client in auto encrypter's constructor: #{e.class}: #{e}")
      # Drop this exception so that the original exception is raised
    end
    raise
  end
rescue
  if @key_vault_client && @key_vault_client != options[:client] &&
    @key_vault_client.cluster != options[:client].cluster
  then
    begin
      @key_vault_client.close
    rescue => e
      log_warn("Error closing key vault client in auto encrypter's constructor: #{e.class}: #{e}")
      # Drop this exception so that the original exception is raised
    end
  end

  if @metadata_client && @metadata_client != options[:client] &&
    @metadata_client.cluster != options[:client].cluster
  then
    begin
      @metadata_client.close
    rescue => e
      log_warn("Error closing metadata client in auto encrypter's constructor: #{e.class}: #{e}")
      # Drop this exception so that the original exception is raised
    end
  end

  raise
end

Instance Attribute Details

#key_vault_clientObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



34
35
36
# File 'lib/mongo/crypt/auto_encrypter.rb', line 34

def key_vault_client
  @key_vault_client
end

#metadata_clientObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



35
36
37
# File 'lib/mongo/crypt/auto_encrypter.rb', line 35

def 
  @metadata_client
end

#mongocryptd_clientObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



33
34
35
# File 'lib/mongo/crypt/auto_encrypter.rb', line 33

def mongocryptd_client
  @mongocryptd_client
end

#optionsObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



36
37
38
# File 'lib/mongo/crypt/auto_encrypter.rb', line 36

def options
  @options
end

Instance Method Details

#closetrue

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Close the resources created by the AutoEncrypter.

Returns:

  • (true)

    Always true.



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/mongo/crypt/auto_encrypter.rb', line 215

def close
  @mongocryptd_client.close if @mongocryptd_client

  if @key_vault_client && @key_vault_client != options[:client] &&
    @key_vault_client.cluster != options[:client].cluster
  then
    @key_vault_client.close
  end

  if @metadata_client && @metadata_client != options[:client] &&
    @metadata_client.cluster != options[:client].cluster
  then
    @metadata_client.close
  end

  true
end

#decrypt(command, timeout_holder) ⇒ BSON::Document

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Decrypt a database command.

Parameters:

  • command (Hash)

    The command with encrypted fields.

Returns:

  • (BSON::Document)

    The decrypted command.



204
205
206
207
208
209
210
# File 'lib/mongo/crypt/auto_encrypter.rb', line 204

def decrypt(command, timeout_holder)
  AutoDecryptionContext.new(
    @crypt_handle,
    @encryption_io,
    command
  ).run_state_machine(timeout_holder)
end

#encrypt(database_name, command, timeout_holder) ⇒ BSON::Document

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Encrypt a database command.

Parameters:

  • database_name (String)

    The name of the database on which the command is being run.

  • command (Hash)

    The command to be encrypted.

Returns:

  • (BSON::Document)

    The encrypted command.



190
191
192
193
194
195
196
197
# File 'lib/mongo/crypt/auto_encrypter.rb', line 190

def encrypt(database_name, command, timeout_holder)
  AutoEncryptionContext.new(
    @crypt_handle,
    @encryption_io,
    database_name,
    command
  ).run_state_machine(timeout_holder)
end

#encrypt?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Whether this encrypter should perform encryption (returns false if the :bypass_auto_encryption option is set to true).

Returns:

  • (Boolean)

    Whether to perform encryption.



179
180
181
# File 'lib/mongo/crypt/auto_encrypter.rb', line 179

def encrypt?
  !@options[:bypass_auto_encryption]
end