Skip to content

Commit

Permalink
(DOCSP-33831): C++: Add docs for encryption and metadata encryption (#…
Browse files Browse the repository at this point in the history
…3073)

## Pull Request Info

### Jira

- https://jira.mongodb.org/browse/DOCSP-33831

### Staged Changes

- [Encrypt a
Realm](https://preview-mongodbdacharyc.gatsbyjs.io/realm/DOCSP-33831/sdk/cpp/realm-files/encrypt-a-realm/):
New page based on similar pages in other SDKs
- [Connect to App
Services](https://preview-mongodbdacharyc.gatsbyjs.io/realm/DOCSP-33831/sdk/cpp/app-services/connect-to-app/#encrypt-app-metadata):
Add a section about encrypting metadata. Update custom HTTP section for
deprecated `realm::App(...)`

### Reminder Checklist

If your PR modifies the docs, you might need to also update some
corresponding
pages. Check if completed or N/A.

- [x] Create Jira ticket for corresponding docs-app-services update(s),
if any
- [x] Checked/updated Admin API
- [x] Checked/updated CLI reference

### Review Guidelines


[REVIEWING.md](https://github.com/mongodb/docs-realm/blob/master/REVIEWING.md)

---------

Co-authored-by: cbullinger <[email protected]>
  • Loading branch information
dacharyc and cbullinger authored Nov 9, 2023
1 parent 30e51bd commit a308b56
Show file tree
Hide file tree
Showing 12 changed files with 327 additions and 9 deletions.
1 change: 1 addition & 0 deletions examples/cpp/beta/local/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ add_executable(examples-beta-local
crud.cpp
filter-data.cpp
notifications.cpp
realm-files.cpp
relationships.cpp
supported-types.cpp
threading.cpp
Expand Down
70 changes: 70 additions & 0 deletions examples/cpp/beta/local/realm-files.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include <catch2/catch_test_macros.hpp>
#include <cpprealm/sdk.hpp>
#include <cpprealm/experimental/sdk.hpp>

using namespace realm::experimental;

struct Dog {
std::string name;
int64_t age;
};
REALM_SCHEMA(Dog, name, age)

TEST_CASE("Encrypt a realm example", "[write]") {
auto relative_realm_path_directory = "beta_encrypt-realm/";
std::filesystem::create_directories(relative_realm_path_directory);
std::filesystem::path path = std::filesystem::current_path().append(relative_realm_path_directory);
path = path.append("encrypted");
path = path.replace_extension("realm");
// :snippet-start: beta-open-encrypted-realm
// Check if we already have a key stored in the platform's secure storage.
// If we don't, generate a new one.
// Use your preferred method to generate a key. This example key is
// NOT representative of a secure encryption key. It only exists to
// illustrate the form your key might take.
std::array<char, 64> exampleKey = {
0,0,0,0,0,0,0,0,
1,1,0,0,0,0,0,0,
2,2,0,0,0,0,0,0,
3,3,0,0,0,0,0,0,
4,4,0,0,0,0,0,0,
5,5,0,0,0,0,0,0,
6,6,0,0,0,0,0,0,
7,7,0,0,0,0,0,0
};

// Store the key securely to be used next time we want to open the database.
// We don't illustrate this here because it varies depending on the platform.

// Create a database configuration.
auto config = realm::db_config();
config.set_path(path); // :remove:
// Set the encryption key in your config.
config.set_encryption_key(exampleKey);

// Open or create a realm with the config containing the encryption key.
auto realm = db(config);
// :snippet-end:

auto dog = Dog {
.name = "Maui",
.age = 3
};

realm.write([&] {
realm.add(std::move(dog));
});

auto managedDogs = realm.objects<Dog>();
auto specificDog = managedDogs[0];
REQUIRE(specificDog.name == "Maui");
REQUIRE(specificDog.age == static_cast<long long>(3));
REQUIRE(managedDogs.size() == 1);

realm.write([&] {
realm.remove(specificDog);
});

auto managedDogsAfterDelete = realm.objects<Dog>();
REQUIRE(managedDogsAfterDelete.size() == 0);
}
2 changes: 1 addition & 1 deletion examples/cpp/beta/sync/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ FetchContent_Declare(
FetchContent_Declare(
cpprealm
GIT_REPOSITORY https://github.com/realm/realm-cpp.git
GIT_TAG v0.3.0-preview
GIT_TAG v0.4.0-preview
)

FetchContent_MakeAvailable(Catch2 cpprealm)
Expand Down
90 changes: 89 additions & 1 deletion examples/cpp/beta/sync/app.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include <catch2/catch_test_macros.hpp>
#include <cpprealm/sdk.hpp>
#include <cpprealm/experimental/sdk.hpp>

using namespace realm::experimental;

static const std::string APP_ID = "cpp-tester-uliix";

Expand All @@ -8,7 +11,7 @@ TEST_CASE("test custom headers compile", "[realm][sync]") {
std::map<std::string, std::string> customHttpHeaders;
customHttpHeaders.emplace("CUSTOM_HEADER_NAME", "CUSTOM_HEADER_VALUE");

auto app = realm::App(APP_ID, std::nullopt, std::nullopt, customHttpHeaders);
auto app = realm::App(realm::App::configuration({APP_ID, std::nullopt, std::nullopt, customHttpHeaders}));
// :snippet-end:

app.get_sync_manager().set_log_level(realm::logger::level::warn);
Expand All @@ -25,3 +28,88 @@ TEST_CASE("test custom headers compile", "[realm][sync]") {
user.log_out().get();
REQUIRE(user.access_token().empty());
}

struct Beta_FlexibleSync_Dog {
realm::experimental::primary_key<realm::object_id> _id{realm::object_id::generate()};
std::string name;
int64_t age;
};
REALM_SCHEMA(Beta_FlexibleSync_Dog, _id, name, age)

TEST_CASE("test metadata encryption", "[realm][sync]") {
// :snippet-start: encrypt-metadata
// Check if we already have a key stored in the platform's secure storage.
// If we don't, generate a new one.
// Use your preferred method to generate a key. This example key is
// NOT representative of a secure encryption key. It only exists to
// illustrate the form your key might take.
std::array<char, 64> exampleKey = {
0,0,0,0,0,0,0,0,
1,1,0,0,0,0,0,0,
2,2,0,0,0,0,0,0,
3,3,0,0,0,0,0,0,
4,4,0,0,0,0,0,0,
5,5,0,0,0,0,0,0,
6,6,0,0,0,0,0,0,
7,7,0,0,0,0,0,0
};

// Create and populate an App configuration.
auto appConfig = realm::App::configuration();
appConfig.app_id = APP_ID;
// Specify the metadata key.
appConfig.metadata_encryption_key = exampleKey;

// Use the configuration when you open the app.
auto app = realm::App(appConfig);
// :snippet-end:

// The code from here down isn't relevant to the example - just confirming
// we can open and write to a realm whose metadata is encrypted.
app.get_sync_manager().set_log_level(realm::logger::level::warn);

auto user = app.login(realm::App::credentials::anonymous()).get();
REQUIRE(user.is_logged_in());

auto syncConfig = user.flexible_sync_configuration();

auto syncedRealm = realm::experimental::db(syncConfig);

syncedRealm.subscriptions().update([](realm::mutable_sync_subscription_set &subs) {
subs.add<Beta_FlexibleSync_Dog>("puppies", [](auto &obj) {
return obj.age < 3;
});
}).get();

auto objectId = realm::object_id::generate();
auto maui = Beta_FlexibleSync_Dog();
maui._id = objectId;
maui.name = "Maui";
maui.age = 2;

syncedRealm.write([&] {
syncedRealm.add(std::move(maui));
});

auto syncSession = syncedRealm.get_sync_session();
syncSession->wait_for_upload_completion().get();

auto dogs = syncedRealm.objects<Beta_FlexibleSync_Dog>();
REQUIRE(dogs.size() == 1);
auto dogsNamedMaui = dogs.where([](auto &dog) {
return dog.name == "Maui";
});
auto persistedMaui = dogsNamedMaui[0];

syncedRealm.write([&] {
syncedRealm.remove(persistedMaui);
});

auto managedDogsAfterDelete = syncedRealm.objects<Beta_FlexibleSync_Dog>();
REQUIRE(managedDogsAfterDelete.size() == 0);

syncSession->wait_for_upload_completion().get();

user.log_out().get();
REQUIRE(user.access_token().empty());
}
24 changes: 24 additions & 0 deletions source/examples/generated/cpp/app.snippet.encrypt-metadata.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Check if we already have a key stored in the platform's secure storage.
// If we don't, generate a new one.
// Use your preferred method to generate a key. This example key is
// NOT representative of a secure encryption key. It only exists to
// illustrate the form your key might take.
std::array<char, 64> exampleKey = {
0,0,0,0,0,0,0,0,
1,1,0,0,0,0,0,0,
2,2,0,0,0,0,0,0,
3,3,0,0,0,0,0,0,
4,4,0,0,0,0,0,0,
5,5,0,0,0,0,0,0,
6,6,0,0,0,0,0,0,
7,7,0,0,0,0,0,0
};

// Create and populate an App configuration.
auto appConfig = realm::App::configuration();
appConfig.app_id = APP_ID;
// Specify the metadata key.
appConfig.metadata_encryption_key = exampleKey;

// Use the configuration when you open the app.
auto app = realm::App(appConfig);
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
std::map<std::string, std::string> customHttpHeaders;
customHttpHeaders.emplace("CUSTOM_HEADER_NAME", "CUSTOM_HEADER_VALUE");

auto app = realm::App(APP_ID, std::nullopt, std::nullopt, customHttpHeaders);
auto app = realm::App(realm::App::configuration({APP_ID, std::nullopt, std::nullopt, customHttpHeaders}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Check if we already have a key stored in the platform's secure storage.
// If we don't, generate a new one.
// Use your preferred method to generate a key. This example key is
// NOT representative of a secure encryption key. It only exists to
// illustrate the form your key might take.
std::array<char, 64> exampleKey = {
0,0,0,0,0,0,0,0,
1,1,0,0,0,0,0,0,
2,2,0,0,0,0,0,0,
3,3,0,0,0,0,0,0,
4,4,0,0,0,0,0,0,
5,5,0,0,0,0,0,0,
6,6,0,0,0,0,0,0,
7,7,0,0,0,0,0,0
};

// Store the key securely to be used next time we want to open the database.
// We don't illustrate this here because it varies depending on the platform.

// Create a database configuration.
auto config = realm::db_config();
// Set the encryption key in your config.
config.set_encryption_key(exampleKey);

// Open or create a realm with the config containing the encryption key.
auto realm = db(config);
2 changes: 1 addition & 1 deletion source/sdk/cpp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ C++ SDK Preview
Install Realm </sdk/cpp/install>
Quick Start </sdk/cpp/quick-start>
Model Data </sdk/cpp/model-data>
Configure & Open a Realm </sdk/cpp/realm-files/configure-and-open-a-realm>
Realm Files </sdk/cpp/realm-files>
CRUD </sdk/cpp/crud/>
React to Changes </sdk/cpp/react-to-changes>
Application Services </sdk/cpp/application-services>
Expand Down
32 changes: 29 additions & 3 deletions source/sdk/cpp/app-services/connect-to-app.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,14 @@ Access the App Client
Set Custom HTTP Headers
-----------------------

.. versionadded:: v0.3.0-preview
.. versionchanged:: v0.4.0-preview replaces deprecated realm::App(...) with realm::App(const realm::App::configuration&)

If you use App Services or Device Sync with a proxy setup, you may need
to set custom HTTP headers. The Realm C++ SDK supports setting custom
HTTP headers on the ``App``, and on the ``flexible_sync_configuration()``.
HTTP headers on the :cpp-sdk:`App <structrealm_1_1App_1_1configuration.html>`
and on the ``flexible_sync_configuration()``.

When you initialize the ``App``, pass in a map of string header keys
When you initialize the App configuration, pass in a map of string header keys
and values.

.. literalinclude:: /examples/generated/cpp/app.snippet.set-custom-headers-for-app.cpp
Expand All @@ -65,3 +66,28 @@ these custom headers.
If you want to use custom headers with Device Sync, you must
additionally :ref:`set the headers on the Flexible Sync configuration
<cpp-set-custom-headers-using-synced-realm>`.

.. _cpp-encrypt-app-metadata:

Encrypt App Metadata
--------------------

.. versionadded:: v0.4.0-preview

When you connect to App Services, Realm creates additional metadata files
on a device. For more information about these metadata files, refer to
:ref:`cpp-realm-database`.

You can encrypt the metadata that App Services stores on client devices,
similar to :ref:`encrypting the realm <cpp-encrypt-a-realm>`.

On Apple devices, the metadata is encrypted by default. To disable this,
add ``REALM_DISABLE_METADATA_ENCRYPTION`` to your environment variables.

To enable metadata encryption on other platforms, you must set a
``metadata_encryption_key`` on your
:cpp-sdk:`realm::App::configuration <structrealm_1_1App_1_1configuration.html>`.

.. literalinclude:: /examples/generated/cpp/app.snippet.encrypt-metadata.cpp
:language: cpp
:emphasize-lines: 20-21
2 changes: 0 additions & 2 deletions source/sdk/cpp/realm-database.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
.. _cpp-realm-database:


=======================
Realm - C++ SDK Preview
=======================


.. contents:: On this page
:local:
:backlinks: none
Expand Down
11 changes: 11 additions & 0 deletions source/sdk/cpp/realm-files.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.. _cpp-realms:

=======================================
Work with Realm Files - C++ SDK Preview
=======================================

.. toctree::
:titlesonly:

Configure & Open a Realm </sdk/cpp/realm-files/configure-and-open-a-realm>
Encrypt a Realm </sdk/cpp/realm-files/encrypt-a-realm>
Loading

0 comments on commit a308b56

Please sign in to comment.