Skip to content

CXX-2517 Add support for Range Explicit Encryption #955

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 17 commits into from
Apr 17, 2023

Conversation

eramongodb
Copy link
Contributor

Description

Resolves CXX-2517. Verified by this patch.

Test Spec Files

Relevant legacy CSE test files are already synced as part of #953.

Files under https://github.com/mongodb/specifications/tree/c94fefe3e14d163bedcab75a761bc14a77ec689f/source/client-side-encryption/etc/data required by Range Explicit Encryption prose tests were added to the data/client_side_encryption/explicit_encryption directory. The encryptedFields-Range-<Type>.json are not required (used to generate other test files) and were thus excluded.

Interface Changes

ClientEncryption.encryptExpression()

A straightforward addition to the client_encryption class' interface as required by CXX-2517.

RangeOpts

A new options::range class was added corresponding to the new RangeOpts class.

RangePreview Options

The options::encrypt::encryption_algorithm and options::encrypt::encryption_query_type were updated to support the Range algorithm.

EncryptOpts.rangeOpts

Added range_opts() accessors to options::encrypt that depend on the new options::range class.

The options::encrypt::convert() function was updated to call relevant client_encryption_encrypt_range_opts_*() functions for the appropriate options in options::range.

Note a new potential error_code::k_invalid_parameter exception was introduced to validate that min and max are either both set or both unset to satisfy mongoc_client_encryption_encrypt_range_opts_set_min_max. This may be removed once CDRIVER-4610 is resolved.

Range Explicit Encryption Prose Tests

A new test case was added corresponding to Prose Test 22: Range Explicit Encryption. The structure of the test is as follows (pseudocode):

enum struct RangeFieldType : int {
    DecimalNoPrecision,
    DecimalPrecision,
    DoubleNoPrecision,
    DoublePrecision,
    Date,
    Int,
    Long,
};

TEST_CASE("Range Explicit Encryption", ...) {
  // Run condition checks.

  for (auto field_type : RangeFieldTypes) {
    DYNAMIC_SECTION("Field Type - " << field_type) {
      // Setup

      SECTION("Case 1") { ... }
      SECTION("Case 2") { ... }
      // ...
    }
  }
}

The RangeFieldType enumeration is used to define and iterate over the supported types to be tested while ensuring fields and values have the appropriate corresponding types (e.g. via to_type_str, to_field_value, and to_range_opts).

The range_explicit_encryption_setup function is used to encapsulate common setup routines, returning range_explicit_encryption_objects containing the entities required by the following test cases.

The field_type_values struct is used to define common field values (0, 6, 30, and 200 with the appropriate type corresponding to the RangeFieldType being tested) used by multiple test cases as a convenience.

Miscellaneous

Public Technical Preview Warnings

Documentation was updated to mark Public Technical Preview notes for Queryable Encryption as Doxygen warnings. Their scope (entities which the warning is being applied to) was also reduced to only the relevant entities as applicable.

fprintf in run_encryption_tests_in_file

Some stray fprintf that were being unconditionally printed by run_encryption_tests_in_file were replaced with UNSCOPED_INFO so they are only emitted when necessary.

file.is_open()

A minor change to improve context should the REQUIRES assertion fail.

Member Order in options::encrypt

The key_id function was relocated (both in header and source) to match the pattern of the rest of the member functions.

RAII Helpers

The options/encrypt.cpp and private/client_encryption.hh files were refactored to remove all instances of raw owning pointers in the implementation.

Notable patterns include:

scoped_bson_value

A helper class similar to scoped_bson_t that wraps bson_value_t. Given its limited use, it is currently defined (note: twice) in options/encrypt.cpp and private/client_encryption.hh. It may be worth eventually extracting this helper into a proper a proper component (probably under src/mongocxx/private?), but that work has been deferred for now.

Deleter and std::unique_ptr

Raw owning pointers with corresponding cleanup routines replaced with std::unique_ptr that define custom deleters. This fixes potential leaks when unexpected exceptions may be thrown by sub-operations (e.g. by calls to make_document() or doc.get_<type>()) before cleanup is invoked.

Temporary Objects

Thanks to scoped_bson_value (as well as scoped_bson_t), the following frequent pattern:

template <typename T>
void example(const T& param) {
  bson_value_t value;
  convert_to_libbson(param, &value);
  libmongoc::some_func(&value);
  bson_value_destroy(&value);
}

has been refactored to:

template <typename T>
void example(const T& param) {
  libmongoc::some_func(scoped_bson_value(param).get());
}

@eramongodb eramongodb self-assigned this Apr 13, 2023
Copy link
Collaborator

@kevinAlbs kevinAlbs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addition of RAII types seems helpful and less error prone. TIL about DYNAMIC_SECTION.

LGTM with minor comments addressed.

@eramongodb
Copy link
Contributor Author

Latest changes verified by this patch.

Realized I missed the addition of a clause specifying DecimalNoPrecision tests should only be run against replica sets. Added the skip condition accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants