Class: Mongo::Crypt::EncryptionIO Private

Inherits:
Object
  • Object
show all
Defined in:
build/ruby-driver-v2.18/lib/mongo/crypt/encryption_io.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.

A class that implements I/O methods between the driver and the MongoDB server or mongocryptd.

Constant Summary collapse

SOCKET_TIMEOUT =

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.

Timeout used for TLS socket connection, reading, and writing. There is no specific timeout written in the spec. See SPEC-1394 for a discussion and updates on what this timeout should be.

10

Instance Method Summary collapse

Constructor Details

#initialize(client: nil, mongocryptd_client: nil, key_vault_namespace:, key_vault_client:, metadata_client:, mongocryptd_options: {}) ⇒ EncryptionIO

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.

Note:

When being used for auto encryption, all arguments are required. When being used for explicit encryption, only the key_vault_namespace and key_vault_client arguments are required.

Note:

This class expects that the key_vault_client and key_vault_namespace options are not nil and are in the correct format.

Creates a new EncryptionIO object with information about how to connect to the key vault.

Parameters:

  • client (Mongo::Client) (defaults to: nil)

    The client used to connect to the collection that stores the encrypted documents, defaults to nil.

  • mongocryptd_client (Mongo::Client) (defaults to: nil)

    The client connected to mongocryptd, defaults to nil.

  • key_vault_client (Mongo::Client)

    The client connected to the key vault collection.

  • metadata_client (Mongo::Client | nil)

    The client to be used to obtain collection metadata.

  • key_vault_namespace (String)

    The key vault namespace in the format db_name.collection_name.

  • mongocryptd_options (Hash) (defaults to: {})

    Options related to mongocryptd.

Options Hash (mongocryptd_options:):

  • :mongocryptd_bypass_spawn (Boolean)
  • :mongocryptd_spawn_path (String)
  • :mongocryptd_spawn_args (Array<String>)


57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'build/ruby-driver-v2.18/lib/mongo/crypt/encryption_io.rb', line 57

def initialize(
  client: nil, mongocryptd_client: nil, key_vault_namespace:,
  key_vault_client:, metadata_client:, mongocryptd_options: {}
)
  validate_key_vault_client!(key_vault_client)
  validate_key_vault_namespace!(key_vault_namespace)

  @client = client
  @mongocryptd_client = mongocryptd_client
  @key_vault_db_name, @key_vault_collection_name = key_vault_namespace.split('.')
  @key_vault_client = key_vault_client
  @metadata_client = 
  @options = mongocryptd_options
end

Instance Method Details

#add_key_alt_name(id, key_alt_name) ⇒ Object

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.

Adds a key_alt_name to the key_alt_names array of the key document in the key vault collection with the given id.



163
164
165
166
167
168
# File 'build/ruby-driver-v2.18/lib/mongo/crypt/encryption_io.rb', line 163

def add_key_alt_name(id, key_alt_name)
  key_vault_collection.find_one_and_update(
    { _id: id },
    { '$addToSet' => { keyAltNames: key_alt_name } },
  )
end

#collection_info(db_name, filter) ⇒ Hash

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.

Get collection info for a collection matching the provided filter

Parameters:

  • filter (Hash)

Returns:

  • (Hash)

    The collection information



96
97
98
99
100
101
102
# File 'build/ruby-driver-v2.18/lib/mongo/crypt/encryption_io.rb', line 96

def collection_info(db_name, filter)
  unless @metadata_client
    raise ArgumentError, 'collection_info requires metadata_client to have been passed to the constructor, but it was not'
  end

  @metadata_client.use(db_name).database.list_collections(filter: filter).first
end

#delete_key(id) ⇒ Object

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.

Removes the key document with the given id from the key vault collection.



172
173
174
# File 'build/ruby-driver-v2.18/lib/mongo/crypt/encryption_io.rb', line 172

def delete_key(id)
  key_vault_collection.delete_one(_id: id)
end

#feed_kms(kms_context, tls_options) ⇒ Object

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.

Get information about the remote KMS encryption key and feed it to the the KmsContext object

Parameters:

  • kms_context (Mongo::Crypt::KmsContext)

    A KmsContext object corresponding to one remote KMS data key. Contains information about the endpoint at which to establish a TLS connection and the message to send on that connection.

  • tls_options. (Hash)

    TLS options to connect to KMS provider. The options are same as for Mongo::Client.



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'build/ruby-driver-v2.18/lib/mongo/crypt/encryption_io.rb', line 139

def feed_kms(kms_context, tls_options)
  with_ssl_socket(kms_context.endpoint, tls_options) do |ssl_socket|
    Timeout.timeout(SOCKET_TIMEOUT, Error::SocketTimeoutError,
      'Socket write operation timed out'
    ) do
      ssl_socket.syswrite(kms_context.message)
    end

    bytes_needed = kms_context.bytes_needed
    while bytes_needed > 0 do
      bytes = Timeout.timeout(SOCKET_TIMEOUT, Error::SocketTimeoutError,
        'Socket read operation timed out'
      ) do
        ssl_socket.sysread(bytes_needed)
      end

      kms_context.feed(bytes)
      bytes_needed = kms_context.bytes_needed
    end
  end
end

#find_keys(filter) ⇒ Array<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.

Query for keys in the key vault collection using the provided filter

Parameters:

  • filter (Hash)

Returns:

  • (Array<BSON::Document>)

    The query results



78
79
80
# File 'build/ruby-driver-v2.18/lib/mongo/crypt/encryption_io.rb', line 78

def find_keys(filter)
  key_vault_collection.find(filter).to_a
end

#get_key(id) ⇒ Object

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.

Finds a single key document with the given id.



177
178
179
# File 'build/ruby-driver-v2.18/lib/mongo/crypt/encryption_io.rb', line 177

def get_key(id)
  key_vault_collection.find(_id: id).first
end

#get_key_by_alt_name(key_alt_name) ⇒ Object

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.

Returns a key document in the key vault collection with the given key_alt_name.



183
184
185
# File 'build/ruby-driver-v2.18/lib/mongo/crypt/encryption_io.rb', line 183

def get_key_by_alt_name(key_alt_name)
  key_vault_collection.find(keyAltNames: key_alt_name).first
end

#get_keysObject

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.

Finds all documents in the key vault collection.



188
189
190
# File 'build/ruby-driver-v2.18/lib/mongo/crypt/encryption_io.rb', line 188

def get_keys
  key_vault_collection.find
end

#insert_data_key(document) ⇒ Mongo::Operation::Insert::Result

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.

Insert a document into the key vault collection

Parameters:

  • document (Hash)

Returns:



87
88
89
# File 'build/ruby-driver-v2.18/lib/mongo/crypt/encryption_io.rb', line 87

def insert_data_key(document)
  key_vault_collection.insert_one(document)
end

#mark_command(cmd) ⇒ Hash

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.

Send the command to mongocryptd to be marked with intent-to-encrypt markings

Parameters:

  • cmd (Hash)

Returns:

  • (Hash)

    The marked command



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'build/ruby-driver-v2.18/lib/mongo/crypt/encryption_io.rb', line 109

def mark_command(cmd)
  unless @mongocryptd_client
    raise ArgumentError, 'mark_command requires mongocryptd_client to have been passed to the constructor, but it was not'
  end

  # Ensure the response from mongocryptd is deserialized with { mode: :bson }
  # to prevent losing type information in commands
  options = { execution_options: { deserialize_as_bson: true } }

  begin
    response = @mongocryptd_client.database.command(cmd, options)
  rescue Error::NoServerAvailable => e
    raise e if @options[:mongocryptd_bypass_spawn]

    spawn_mongocryptd
    response = @mongocryptd_client.database.command(cmd, options)
  end

  return response.first
end

#remove_key_alt_name(id, key_alt_name) ⇒ Object

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.

Removes a key_alt_name from the key_alt_names array of the key document in the key vault collection with the given id.



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'build/ruby-driver-v2.18/lib/mongo/crypt/encryption_io.rb', line 194

def remove_key_alt_name(id, key_alt_name)
  key_vault_collection.find_one_and_update(
    { _id: id },
    [
      {
        '$set' => {
          keyAltNames: {
            '$cond' => [
              { '$eq' => [ '$keyAltNames', [ key_alt_name ] ] },
              '$$REMOVE',
              {
                '$filter' => {
                  input: '$keyAltNames',
                  cond: { '$ne' =>  [ '$$this', key_alt_name ] }
                }
              }
            ]
          }
        }
      }
    ]
  )
end

#update_data_keys(updates) ⇒ BulkWrite::Result

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.

Apply given requests to the key vault collection using bulk write.

Parameters:

  • requests (Array<Hash>)

    The bulk write requests.

Returns:



223
224
225
# File 'build/ruby-driver-v2.18/lib/mongo/crypt/encryption_io.rb', line 223

def update_data_keys(updates)
  key_vault_collection.bulk_write(updates)
end