Skip to content

RUBY-2832 Fix FLE problems on JRuby #2392

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion lib/mongo/crypt/binding.rb
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,14 @@ def self.kms_ctx_get_kms_provider(kms_context)
if len_ptr.nil?
nil
else
len = len_ptr.read(:uint32)
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
Expand Down
79 changes: 38 additions & 41 deletions spec/integration/client_side_encryption/custom_endpoint_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@
)
end

let(:master_key_template) do
{
region: "us-east-1",
key: "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"
}
end

let(:data_key_id) do
client_encryption.create_data_key('aws', master_key: master_key)
end
Expand All @@ -51,85 +58,75 @@

context 'with region and key options' do
let(:master_key) do
{
region: "us-east-1",
key: "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"
}
master_key_template
end

it_behaves_like 'a functioning data key'
end

context 'with region, key, and endpoint options' do
let(:master_key) do
{
region: "us-east-1",
key: "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
endpoint: "kms.us-east-1.amazonaws.com"
}
master_key_template.merge({endpoint: "kms.us-east-1.amazonaws.com"})
end

it_behaves_like 'a functioning data key'
end

context 'with region, key, and endpoint with valid port' do
let(:master_key) do
{
region: "us-east-1",
key: "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
endpoint: "kms.us-east-1.amazonaws.com:443"
}
master_key_template.merge({endpoint: "kms.us-east-1.amazonaws.com:443"})
end

it_behaves_like 'a functioning data key'
end

shared_examples 'raising a KMS error' do
it 'throws an exception' do
expect do
data_key_id
end.to raise_error(Mongo::Error::KmsError, error_regex)
end
end

context 'with region, key, and endpoint with invalid port' do
let(:master_key) do
{
region: "us-east-1",
key: "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
endpoint: "kms.us-east-1.amazonaws.com:12345"
}
master_key_template.merge({endpoint: "kms.us-east-1.amazonaws.com:12345"})
end

it 'throws an exception' do
expect do
data_key_id
end.to raise_error(Mongo::Error::KmsError, /Connection refused/)
let(:error_regex) do
if BSON::Environment.jruby?
/Bad file descriptor/
else
/Connection refused/
end
end

it_behaves_like 'raising a KMS error'
end


context 'with region, key, and endpoint with invalid region' do
let(:master_key) do
{
region: "us-east-1",
key: "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
endpoint: "kms.us-east-2.amazonaws.com"
}
master_key_template.merge({endpoint: "kms.us-east-2.amazonaws.com"})
end

it 'throws an exception' do
expect do
data_key_id
end.to raise_error(Mongo::Error::KmsError, /us-east-1/)
let(:error_regex) do
/us-east-1/
end

it_behaves_like 'raising a KMS error'
end

context 'with region, key, and endpoint at incorrect domain' do
let(:master_key) do
{
region: "us-east-1",
key: "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
endpoint: "example.com"
}
master_key_template.merge({endpoint: "example.com"})
end

it 'throws an exception' do
expect do
data_key_id
end.to raise_error(Mongo::Error::KmsError, /parse error/)
let(:error_regex) do
/parse error/
end

it_behaves_like 'raising a KMS error'
end
end
end
85 changes: 54 additions & 31 deletions spec/integration/client_side_encryption/kms_tls_options_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -200,18 +200,21 @@

# We do noy use shared examples for AWS because of the way we pass endpoint.
context 'AWS' do
let(:master_key_template) do
{
region: "us-east-1",
key: "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
}
end

context 'with no client certificate' do
it 'TLS handshake failed' do
expect do
client_encryption_no_client_cert.create_data_key(
'aws',
{
master_key: {
region: "us-east-1",
key: "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
endpoint: "127.0.0.1:8002",
}
}
master_key: master_key_template.merge({endpoint: "127.0.0.1:8002"})
}
)
end.to raise_error(Mongo::Error::KmsError, /(SocketError|ECONNRESET)/)
end
Expand All @@ -223,48 +226,52 @@
client_encryption_with_tls.create_data_key(
'aws',
{
master_key: {
region: "us-east-1",
key: "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
endpoint: "127.0.0.1:8002",
}
master_key: master_key_template.merge({endpoint: "127.0.0.1:8002"})
}
)
end.to raise_error(Mongo::Error::KmsError, /libmongocrypt error code/)
end
end

context 'with no expired server certificate' do
context 'with expired server certificate' do
let(:error_regex) do
if BSON::Environment.jruby?
/certificate verify failed/
else
/certificate has expired/
end
end

it 'TLS handshake failed' do
expect do
client_encryption_expired.create_data_key(
'aws',
{
master_key: {
region: "us-east-1",
key: "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
endpoint: "127.0.0.1:8000",
}
}
master_key: master_key_template.merge({endpoint: "127.0.0.1:8000"})
}
)
end.to raise_error(Mongo::Error::KmsError, /certificate has expired/)
end.to raise_error(Mongo::Error::KmsError, error_regex)
end
end

context 'with server certificate with invalid hostname' do
let(:error_regex) do
if BSON::Environment.jruby?
/TLS handshake failed due to a hostname mismatch/
else
/certificate verify failed/
end
end

it 'TLS handshake failed' do
expect do
client_encryption_invalid_hostname.create_data_key(
'aws',
{
master_key: {
region: "us-east-1",
key: "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
endpoint: "127.0.0.1:8001",
}
}
master_key: master_key_template.merge({endpoint: "127.0.0.1:8001"})
}
)
end.to raise_error(Mongo::Error::KmsError, /certificate verify failed/)
end.to raise_error(Mongo::Error::KmsError, error_regex)
end
end
end
Expand Down Expand Up @@ -296,29 +303,45 @@
end
end

context 'with no expired server certificate' do
context 'with expired server certificate' do
let(:error_regex) do
if BSON::Environment.jruby?
/certificate verify failed/
else
/certificate has expired/
end
end

it 'TLS handshake failed' do
expect do
client_encryption_expired.create_data_key(
kms_provider,
{
master_key: master_key
}
}
)
end.to raise_error(Mongo::Error::KmsError, /certificate has expired/)
end.to raise_error(Mongo::Error::KmsError, error_regex)
end
end

context 'with server certificate with invalid hostname' do
let(:error_regex) do
if BSON::Environment.jruby?
/TLS handshake failed due to a hostname mismatch/
else
/certificate verify failed/
end
end

it 'TLS handshake failed' do
expect do
client_encryption_invalid_hostname.create_data_key(
kms_provider,
{
master_key: master_key
}
}
)
end.to raise_error(Mongo::Error::KmsError, /certificate verify failed/)
end.to raise_error(Mongo::Error::KmsError, error_regex)
end
end
end
Expand Down
51 changes: 37 additions & 14 deletions spec/integration/client_side_encryption/kms_tls_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,24 +44,47 @@
}
}
)
end.to raise_error(Mongo::Error::KmsError, /certificate verify failed \(certificate has expired\)/)
end.to raise_error(Mongo::Error::KmsError, /certificate verify failed/)
end
end

context 'Invalid Hostname in KMS Certificate' do
it 'raises an error when creating data key' do
expect do
client_encryption.create_data_key(
'aws',
{
master_key: {
region: "us-east-1",
key: "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
endpoint: "127.0.0.1:8001",
}
}
)
end.to raise_error(Mongo::Error::KmsError, /certificate verify failed/)
context 'MRI' do
require_mri

it 'raises an error when creating data key' do
expect do
client_encryption.create_data_key(
'aws',
{
master_key: {
region: "us-east-1",
key: "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
endpoint: "127.0.0.1:8001",
}
}
)
end.to raise_error(Mongo::Error::KmsError, /certificate verify failed/)
end
end

context 'JRuby' do
require_jruby

it 'raises an error when creating data key' do
expect do
client_encryption.create_data_key(
'aws',
{
master_key: {
region: "us-east-1",
key: "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
endpoint: "127.0.0.1:8001",
}
}
)
end.to raise_error(Mongo::Error::KmsError, /hostname mismatch/)
end
end
end

Expand Down
7 changes: 5 additions & 2 deletions spec/lite_spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,17 @@ class ExampleTimeout < StandardError; end
end

if SpecConfig.instance.ci? && !%w(1 true yes).include?(ENV['INTERACTIVE']&.downcase)
# Allow a max of 30 seconds per test.
# Tests should take under 10 seconds ideally but it seems
# we have some that run for more than 10 seconds in CI.
config.around(:each) do |example|
timeout = if %w(1 true yes).include?(ENV['STRESS']&.downcase)
210
else
45
if BSON::Environment.jruby?
90
else
45
end
end
TimeoutInterrupt.timeout(timeout, ExampleTimeout) do
example.run
Expand Down