Skip to content

Commit

Permalink
Merge pull request #94 from tablecheck/merge-crypt
Browse files Browse the repository at this point in the history
Merge crypt changes (no squash)
  • Loading branch information
johnnyshields authored Apr 22, 2023
2 parents 34151e4 + a9def39 commit a10a6c3
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 51 deletions.
32 changes: 26 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
${{matrix.gemfile || 'Gemfile'}}
mongodb-${{matrix.mongodb || '6.0'}}
${{matrix.topology || 'server'}}
${{matrix.fle && 'fle=' || ''}}${{matrix.fle || ''}}
${{matrix.os || 'ubuntu-20.04'}}"
env:
CI: true
Expand Down Expand Up @@ -55,15 +56,15 @@ jobs:
- ruby: ruby-3.1
gemfile: gemfiles/rails_6.1.gemfile
mongodb: '5.0'
topology: server
topology: sharded_cluster
- ruby: ruby-3.0
gemfile: gemfiles/rails_6.1.gemfile
mongodb: '4.4'
topology: server
- ruby: ruby-3.0
gemfile: gemfiles/rails_6.0.gemfile
mongodb: '4.4'
topology: server
topology: replica_set
- ruby: ruby-2.7
gemfile: gemfiles/rails_6.0.gemfile
mongodb: '4.4'
Expand All @@ -78,7 +79,7 @@ jobs:
- ruby: ruby-3.0
gemfile: gemfiles/driver_stable.gemfile
mongodb: '5.0'
topology: replica_set
topology: sharded_cluster
- ruby: ruby-2.7
gemfile: gemfiles/driver_min.gemfile
mongodb: '4.4'
Expand All @@ -105,11 +106,27 @@ jobs:
mongodb: '5.0'
topology: server

# Field-Level Encryption
# TODO: support LIBMONGOCRYPT via path
- ruby: ruby-3.2
gemfile: gemfiles/rails_7.0.gemfile
mongodb: '6.0'
topology: sharded_cluster
fle: helper
- ruby: ruby-3.1
gemfile: gemfiles/rails_6.1.gemfile
mongodb: '6.0'
topology: replica_set
fle: helper
- ruby: ruby-2.7
gemfile: gemfiles/rails_6.0.gemfile
mongodb: '6.0'
topology: server
fle: helper

steps:
- name: repo checkout
uses: actions/checkout@v2
with:
submodules: recursive
uses: actions/checkout@v3
- id: start-mongodb
name: start mongodb
uses: mongodb-labs/drivers-evergreen-tools@master
Expand All @@ -120,17 +137,20 @@ jobs:
uses: ruby/setup-ruby@v1
env:
BUNDLE_GEMFILE: "${{matrix.gemfile || 'Gemfile'}}"
FLE: "${{matrix.fle || ''}}"
with:
ruby-version: "${{matrix.ruby}}"
bundler: 2
- name: bundle
run: bundle install --jobs 4 --retry 3
env:
BUNDLE_GEMFILE: "${{matrix.gemfile || 'Gemfile'}}"
FLE: "${{matrix.fle || ''}}"
- name: test
timeout-minutes: 60
continue-on-error: "${{matrix.experimental || false}}"
run: bundle exec rake spec
env:
BUNDLE_GEMFILE: "${{matrix.gemfile || 'Gemfile'}}"
FLE: "${{matrix.fle || ''}}"
MONGODB_URI: "${{steps.start-mongodb.outputs.cluster-uri}}"
41 changes: 32 additions & 9 deletions lib/mongoid/clients/factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,8 @@ def create_client(configuration)
hosts = config.delete(:hosts)
opts = config.delete(:options) || {}

if opts[:auto_encryption_options]
if opts[:auto_encryption_options].key?(:schema_map)
Mongoid.logger.warn(
'The :schema_map is configured in the :auto_encryption_options for the client; ' \
'encryption setting in Mongoid documents will be ignored.'
)
else
opts[:auto_encryption_options][:schema_map] = Mongoid.config.encryption_schema_map(database)
end
if opts.key?(:auto_encryption_options)
opts[:auto_encryption_options] = build_auto_encryption_options(opts, database)
end

default_logger.warn("Unknown config options detected: #{config}.") unless config.empty?
Expand All @@ -87,6 +80,36 @@ def create_client(configuration)
end
end

# Build auto encryption options for the client based on the options
# provided in the Mongoid client configuration and the encryption
# schema map for the database.
#
# @param [ Hash ] opts Options from the Mongoid client configuration.
# @param [ String ] database Database name to use for encryption schema map.
#
# @return [ Hash | nil ] Auto encryption options for the client.
#
# @api private
def build_auto_encryption_options(opts, database)
return nil unless opts[:auto_encryption_options]

opts[:auto_encryption_options].dup.tap do |auto_encryption_options|
if auto_encryption_options.key?(:schema_map)
default_logger.warn(
'The :schema_map is configured in the :auto_encryption_options for the client; ' \
'encryption setting in Mongoid documents will be ignored.'
)
else
auto_encryption_options[:schema_map] = Mongoid.config.encryption_schema_map(database)
end
if auto_encryption_options.key?(:key_vault_client)
auto_encryption_options[:key_vault_client] = Mongoid::Clients.with_name(
auto_encryption_options[:key_vault_client]
)
end
end
end

MONGOID_WRAPPING_LIBRARY = {
name: 'Mongoid',
version: VERSION
Expand Down
20 changes: 10 additions & 10 deletions lib/mongoid/contextual/mongo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ class Mongo
# @attribute [r] view The Mongo collection view.
attr_reader :view

# Run an explain on the criteria.
#
# @example Explain the criteria.
# Band.where(name: "Depeche Mode").explain
#
# @param [ Hash ] options customizable options (See Mongo::Collection::View::Explainable)
#
# @return [ Hash ] The explain result.
def_delegator :view, :explain

# Get the number of documents matching the query.
#
# @example Get the number of matching documents.
Expand Down Expand Up @@ -176,16 +186,6 @@ def exists?(id_or_conditions = :none)
end
end

# Run an explain on the criteria.
#
# @example Explain the criteria.
# Band.where(name: "Depeche Mode").explain
#
# @return [ Hash ] The explain result.
def explain
view.explain
end

# Execute the find and modify command, used for MongoDB's
# $findAndModify.
#
Expand Down
4 changes: 3 additions & 1 deletion spec/integration/encryption_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
let(:config) do
{
default: { hosts: SpecConfig.instance.addresses, database: database_id },
key_vault: { hosts: SpecConfig.instance.addresses, database: :key_vault },
encrypted: {
hosts: SpecConfig.instance.addresses,
database: database_id,
options: {
auto_encryption_options: {
key_vault_client: :key_vault,
kms_providers: kms_providers,
key_vault_namespace: key_vault_namespace,
extra_options: extra_options
Expand All @@ -31,11 +33,11 @@
end

around do |example|
key_vault_client[key_vault_collection].drop
Mongoid.default_client[Crypt::Patient.collection_name].drop
existing_key_id = Crypt::Patient.encrypt_metadata[:key_id]
Crypt::Patient.set_key_id(data_key_id)
Mongoid::Config.send(:clients=, config)
Mongoid::Clients.with_name(:key_vault)[key_vault_collection].drop
Crypt::Patient.store_in(client: :encrypted)

example.run
Expand Down
80 changes: 56 additions & 24 deletions spec/mongoid/clients/factory_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -249,26 +249,6 @@
restore_config_clients
include_context 'with encryption'

let(:config) do
{
default: { hosts: SpecConfig.instance.addresses, database: database_id },
encrypted: {
hosts: SpecConfig.instance.addresses,
database: database_id,
options: {
auto_encryption_options: {
kms_providers: kms_providers,
key_vault_namespace: key_vault_namespace,
extra_options: extra_options
}
}
}
}
end
let(:client) do
described_class.create(:encrypted)
end

before do
Mongoid::Config.send(:clients=, config)
key_vault_client[key_vault_collection].drop
Expand All @@ -278,12 +258,64 @@
client.close
end

it 'returns a client' do
expect(client).to be_a(Mongo::Client)
let(:client) do
described_class.create(:encrypted)
end

it 'sets schema_map for the client' do
expect(client.options[:auto_encryption_options][:schema_map]).to_not be_nil
context 'when no key vault client is provided' do
let(:config) do
{
default: { hosts: SpecConfig.instance.addresses, database: database_id },
encrypted: {
hosts: SpecConfig.instance.addresses,
database: database_id,
options: {
auto_encryption_options: {
kms_providers: kms_providers,
key_vault_namespace: key_vault_namespace,
extra_options: extra_options
}
}
}
}
end

it 'returns a client' do
expect(client).to be_a(Mongo::Client)
end

it 'sets schema_map for the client' do
expect(client.options[:auto_encryption_options][:schema_map]).to_not be_nil
end
end

context 'when a key vault client is provided' do
let(:config) do
{
default: { hosts: SpecConfig.instance.addresses, database: database_id },
key_vault: { hosts: SpecConfig.instance.addresses, database: database_id },
encrypted: {
hosts: SpecConfig.instance.addresses,
database: database_id,
options: {
auto_encryption_options: {
key_vault_client: :key_vault,
kms_providers: kms_providers,
key_vault_namespace: key_vault_namespace,
extra_options: extra_options
}
}
}
}
end

it 'returns a client' do
expect(client).to be_a(Mongo::Client)
end

it 'sets key_vault_client option for the client' do
expect(client.options[:auto_encryption_options][:key_vault_client]).to eq(Mongoid::Clients.with_name(:key_vault))
end
end
end
end
Expand Down
11 changes: 10 additions & 1 deletion spec/mongoid/contextual/mongo_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1571,7 +1571,16 @@
end

it 'returns the criteria explain path' do
expect(context.explain).to_not be_empty
explain = context.explain
expect(explain).to_not be_empty
expect(explain.keys).to include('queryPlanner', 'executionStats', 'serverInfo')
end

it 'respects options passed to explain' do
explain = context.explain(verbosity: :query_planner)
expect(explain).to_not be_empty
expect(explain.keys).to include('queryPlanner', 'serverInfo')
expect(explain.keys).to_not include('executionStats')
end
end

Expand Down

0 comments on commit a10a6c3

Please sign in to comment.