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 AutoEncrypter 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.



87
88
89
90
91
92
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
# File 'lib/mongo/crypt/auto_encrypter.rb', line 87

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],
    disable_crypt_shared_lib_search: @options[:extra_options][:disable_crypt_shared_lib_search]
  )

  @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 StandardError
    begin
      @mongocryptd_client&.close
    rescue StandardError => 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 StandardError
  if @key_vault_client && @key_vault_client != options[:client] &&
     @key_vault_client.cluster != options[:client].cluster
    begin
      @key_vault_client.close
    rescue StandardError => 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
    begin
      @metadata_client.close
    rescue StandardError => 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.



30
31
32
# File 'lib/mongo/crypt/auto_encrypter.rb', line 30

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.



30
31
32
# File 'lib/mongo/crypt/auto_encrypter.rb', line 30

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.



30
31
32
# File 'lib/mongo/crypt/auto_encrypter.rb', line 30

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.



30
31
32
# File 'lib/mongo/crypt/auto_encrypter.rb', line 30

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.



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/mongo/crypt/auto_encrypter.rb', line 208

def close
  @mongocryptd_client.close if @mongocryptd_client

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

  if @metadata_client && @metadata_client != options[:client] &&
     @metadata_client.cluster != options[:client].cluster
    @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.



197
198
199
200
201
202
203
# File 'lib/mongo/crypt/auto_encrypter.rb', line 197

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.



183
184
185
186
187
188
189
190
# File 'lib/mongo/crypt/auto_encrypter.rb', line 183

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.



172
173
174
# File 'lib/mongo/crypt/auto_encrypter.rb', line 172

def encrypt?
  !@options[:bypass_auto_encryption]
end