|
1 | 1 | .. _scala-encrypt: |
2 | 2 |
|
3 | | -====================== |
4 | | -Client-Side Encryption |
5 | | -====================== |
6 | | - |
7 | | -.. facet:: |
8 | | - :name: genre |
9 | | - :values: reference |
10 | | - |
11 | | -.. meta:: |
12 | | - :keywords: code example, encrypt data, decrypt data |
13 | | - |
14 | | -.. contents:: On this page |
15 | | - :local: |
16 | | - :backlinks: none |
17 | | - :depth: 2 |
18 | | - :class: singlecol |
19 | | - |
20 | | -Starting in v4.2, MongoDB supports client-side encryption. Client-side |
21 | | -encryption allows administrators and developers to encrypt specific data |
22 | | -fields in addition to providing other MongoDB encryption features. |
23 | | - |
24 | | -With field-level encryption, developers can encrypt fields on the client-side |
25 | | -without any server-side configuration or directives. Client-side field |
26 | | -level encryption supports workloads where applications must guarantee |
27 | | -that unauthorized parties, including server administrators, cannot |
28 | | -read the encrypted data. |
29 | | - |
30 | | -.. include:: /includes/obs-note.rst |
31 | | - |
32 | | -Installation |
33 | | ------------- |
34 | | - |
35 | | -The recommended way to get started using field-level encryption in |
36 | | -your project is by using a dependency management system. Field-level |
37 | | -encryption requires additional packages in addition to the |
38 | | -driver. |
39 | | - |
40 | | -.. include:: /includes/install-note.rst |
41 | | - |
42 | | -libmongocrypt |
43 | | -~~~~~~~~~~~~~ |
44 | | - |
45 | | -There is a separate JAR file containing ``libmongocrypt`` bindings. |
46 | | - |
47 | | -.. tabs:: |
48 | | - |
49 | | - .. tab:: Maven |
50 | | - :tabid: maven-installation |
51 | | - |
52 | | - If you are using `Maven <https://maven.apache.org/>`__ to manage your |
53 | | - packages, add the following entry to your ``pom.xml`` dependencies list: |
54 | | - |
55 | | - .. code-block:: xml |
56 | | - |
57 | | - <dependencies> |
58 | | - <dependency> |
59 | | - <groupId>org.mongodb</groupId> |
60 | | - <artifactId>mongodb-crypt</artifactId> |
61 | | - <version>1.2.1</version> |
62 | | - </dependency> |
63 | | - </dependencies> |
64 | | - |
65 | | - .. tab:: Gradle |
66 | | - :tabid: gradle-installation |
67 | | - |
68 | | - If you are using `Gradle <https://gradle.org/>`__ to manage your |
69 | | - packages, add the following entry to your dependencies list: |
70 | | - |
71 | | - .. code-block:: scala |
72 | | - |
73 | | - dependencies { |
74 | | - implementation 'org.mongodb:mongodb-crypt:1.2.1' |
75 | | - } |
76 | | - |
77 | | -mongocryptd Configuration |
78 | | -~~~~~~~~~~~~~~~~~~~~~~~~~ |
79 | | - |
80 | | -The ``libmongocrypt`` bindings require the ``mongocryptd`` daemon/process to be |
81 | | -running. A specific daemon/process URI can be configured in the |
82 | | -``AutoEncryptionSettings`` class by setting ``mongocryptdURI`` in the |
83 | | -``extraOptions`` setting. |
84 | | - |
85 | | -Examples |
86 | | --------- |
87 | | - |
88 | | -Auto Encryption and Decryption |
89 | | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
90 | | - |
91 | | -The following example is a sample app that assumes the key and schema have |
92 | | -already been created in MongoDB. The example uses a local key, but you |
93 | | -can also use the AWS/Azure/GCP Key Management Service. The data in |
94 | | -the ``encryptedField`` field is automatically encrypted on the insert |
95 | | -and decrypted when using find on the client side. |
96 | | - |
97 | | -The code example is from the `ClientSideEncryptionSimpleTour.scala |
98 | | -<{+driver-source-gh+}/blob/master/driver-scala/src/integration/scala/tour/ClientSideEncryptionSimpleTour.scala>`__ |
99 | | -file in the driver source code GitHub repository. |
100 | | - |
101 | | -.. code-block:: scala |
102 | | - |
103 | | - import java.security.SecureRandom |
104 | | - |
105 | | - import org.mongodb.scala.{AutoEncryptionSettings, Document, MongoClient, MongoClientSettings} |
106 | | - import tour.Helpers._ |
107 | | - |
108 | | - import scala.collection.JavaConverters._ |
109 | | - |
110 | | - object ClientSideEncryptionSimpleTour { |
111 | | - |
112 | | - def main(args: Array[String]): Unit = { |
113 | | - val localMasterKey = new Array[Byte](96) |
114 | | - new SecureRandom().nextBytes(localMasterKey) |
115 | | - |
116 | | - val kmsProviders = Map("local" -> Map[String, AnyRef]("key" -> localMasterKey).asJava).asJava |
117 | | - |
118 | | - val keyVaultNamespace = "admin.datakeys" |
119 | | - |
120 | | - val autoEncryptionSettings = AutoEncryptionSettings.builder() |
121 | | - .keyVaultNamespace(keyVaultNamespace).kmsProviders(kmsProviders).build() |
122 | | - |
123 | | - val clientSettings = MongoClientSettings.builder() |
124 | | - .autoEncryptionSettings(autoEncryptionSettings).build() |
125 | | - |
126 | | - val mongoClient = MongoClient(clientSettings) |
127 | | - val collection = mongoClient.getDatabase("test").getCollection("coll") |
128 | | - |
129 | | - collection.drop().headResult() |
130 | | - |
131 | | - collection.insertOne(Document("encryptedField" -> "123456789")).headResult() |
132 | | - |
133 | | - collection.find().first().printHeadResult() |
134 | | - |
135 | | - // release resources |
136 | | - mongoClient.close() |
137 | | - } |
138 | | - } |
139 | | - |
140 | | -.. note:: |
141 | | - |
142 | | - Automatic encryption is an **enterprise only** feature. |
143 | | - |
144 | | -Specify a Data Encryption Key and Encrypted Fields |
145 | | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
146 | | - |
147 | | -The following example shows how to configure the |
148 | | -``AutoEncryptionSettings`` instance to create a new key and set the |
149 | | -JSON schema map. |
150 | | - |
151 | | -The code example is from the `ClientSideEncryptionAutoEncryptionSettingsTour.scala |
152 | | -<{+driver-source-gh+}/blob/master/driver-scala/src/integration/scala/tour/ClientSideEncryptionAutoEncryptionSettingsTour.scala>`__ |
153 | | -file in the driver source code GitHub repository. |
154 | | - |
155 | | -.. code-block:: scala |
156 | | - |
157 | | - import java.security.SecureRandom |
158 | | - import java.util.Base64 |
159 | | - |
160 | | - import scala.collection.JavaConverters._ |
161 | | - import org.mongodb.scala._ |
162 | | - import org.mongodb.scala.bson.BsonDocument |
163 | | - import org.mongodb.scala.model.vault.DataKeyOptions |
164 | | - import org.mongodb.scala.vault.ClientEncryptions |
165 | | - import tour.Helpers._ |
166 | | - |
167 | | - ... |
168 | | - |
169 | | - val keyVaultNamespace = "admin.datakeys" |
170 | | - |
171 | | - val clientEncryptionSettings = ClientEncryptionSettings.builder() |
172 | | - .keyVaultMongoClientSettings( |
173 | | - MongoClientSettings.builder().applyConnectionString(ConnectionString("mongodb://localhost")).build()) |
174 | | - .keyVaultNamespace(keyVaultNamespace).kmsProviders(kmsProviders).build() |
175 | | - |
176 | | - val clientEncryption = ClientEncryptions.create(clientEncryptionSettings) |
177 | | - |
178 | | - val dataKey = clientEncryption.createDataKey("local", DataKeyOptions()).headResult() |
179 | | - |
180 | | - val base64DataKeyId = Base64.getEncoder.encodeToString(dataKey.getData) |
181 | | - val dbName = "test" |
182 | | - val collName = "coll" |
183 | | - val autoEncryptionSettings = AutoEncryptionSettings.builder() |
184 | | - .keyVaultNamespace(keyVaultNamespace) |
185 | | - .kmsProviders(kmsProviders) |
186 | | - .schemaMap(Map(s"$dbName.$collName" -> BsonDocument( |
187 | | - s"""{ |
188 | | - properties: { |
189 | | - encryptedField: { |
190 | | - encrypt: { |
191 | | - keyId: [{ |
192 | | - "$$binary": { |
193 | | - "base64": "$base64DataKeyId", |
194 | | - "subType": "04" |
195 | | - } |
196 | | - }], |
197 | | - bsonType: "string", |
198 | | - algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" |
199 | | - } |
200 | | - } |
201 | | - }, |
202 | | - bsonType: "object" |
203 | | - }""")).asJava) |
204 | | - .build() |
205 | | - |
206 | | -Explicit Encryption and Decryption |
207 | | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
208 | | - |
209 | | -Explicit encryption and decryption is a MongoDB community feature and |
210 | | -does not use the ``mongocryptd`` process. Explicit encryption is |
211 | | -provided by the ``ClientEncryption`` class. |
212 | | - |
213 | | -The code example is from the `ClientSideEncryptionExplicitEncryptionAndDecryptionTour.scala |
214 | | -<{+driver-source-gh+}/blob/master/driver-scala/src/integration/scala/tour/ClientSideEncryptionExplicitEncryptionAndDecryptionTour.scala>`__ |
215 | | -file in the driver source code GitHub repository. |
216 | | - |
217 | | -.. code-block:: scala |
218 | | - |
219 | | - // This would have to be the same master key as was used to create the encryption key |
220 | | - val localMasterKey = new Array[Byte](96) |
221 | | - new SecureRandom().nextBytes(localMasterKey) |
222 | | - |
223 | | - val kmsProviders = Map("local" -> Map[String, AnyRef]("key" -> localMasterKey).asJava).asJava |
224 | | - |
225 | | - val keyVaultNamespace = new MongoNamespace("encryption.testKeyVault") |
226 | | - |
227 | | - val clientSettings = MongoClientSettings.builder().build() |
228 | | - val mongoClient = MongoClient(clientSettings) |
229 | | - |
230 | | - // Set up the key vault for this example |
231 | | - val keyVaultCollection = mongoClient.getDatabase(keyVaultNamespace.getDatabaseName) |
232 | | - .getCollection(keyVaultNamespace.getCollectionName) |
233 | | - keyVaultCollection.drop().headResult() |
234 | | - |
235 | | - // Ensure that two data keys cannot share the same keyAltName. |
236 | | - keyVaultCollection.createIndex(Indexes.ascending("keyAltNames"), new IndexOptions().unique(true) |
237 | | - .partialFilterExpression(Filters.exists("keyAltNames"))) |
238 | | - |
239 | | - val collection = mongoClient.getDatabase("test").getCollection("coll") |
240 | | - collection.drop().headResult() |
241 | | - |
242 | | - // Create the ClientEncryption instance |
243 | | - val clientEncryptionSettings = ClientEncryptionSettings |
244 | | - .builder() |
245 | | - .keyVaultMongoClientSettings( |
246 | | - MongoClientSettings.builder() |
247 | | - .applyConnectionString(ConnectionString("mongodb://localhost")).build() |
248 | | - ) |
249 | | - .keyVaultNamespace(keyVaultNamespace.getFullName) |
250 | | - .kmsProviders(kmsProviders) |
251 | | - .build() |
252 | | - |
253 | | - val clientEncryption = ClientEncryptions.create(clientEncryptionSettings) |
254 | | - |
255 | | - val dataKeyId = clientEncryption.createDataKey("local", DataKeyOptions()).headResult() |
256 | | - |
257 | | - // Explicitly encrypt a field |
258 | | - val encryptedFieldValue = clientEncryption.encrypt(BsonString("123456789"), |
259 | | - EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId)) |
260 | | - .headResult() |
261 | | - |
262 | | - collection.insertOne(Document("encryptedField" -> encryptedFieldValue)).headResult() |
263 | | - |
264 | | - val doc = collection.find.first().headResult() |
265 | | - println(doc.toJson()) |
266 | | - |
267 | | - // Explicitly decrypt the field |
268 | | - println( |
269 | | - clientEncryption.decrypt(doc.get[BsonBinary]("encryptedField").get).headResult() |
270 | | - ) |
271 | | - |
272 | | -Explicit Encryption and Auto Decryption |
273 | | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
274 | | - |
275 | | -Although automatic encryption requires MongoDB 4.2 enterprise or a |
276 | | -MongoDB 4.2 Atlas cluster, automatic decryption is supported for all |
277 | | -users. To configure automatic decryption without automatic encryption, |
278 | | -set ``bypassAutoEncryption(true)``. |
279 | | - |
280 | | -The code example is from the `ClientSideEncryptionExplicitEncryptionOnlyTour.scala |
281 | | -<{+driver-source-gh+}/blob/master/driver-scala/src/integration/scala/tour/ClientSideEncryptionExplicitEncryptionOnlyTour.scala>`__ |
282 | | -file in the driver source code GitHub repository. |
283 | | - |
284 | | -.. code-block:: scala |
285 | | - |
286 | | - ... |
287 | | - val clientSettings = MongoClientSettings.builder() |
288 | | - .autoEncryptionSettings(AutoEncryptionSettings.builder() |
289 | | - .keyVaultNamespace(keyVaultNamespace.getFullName) |
290 | | - .kmsProviders(kmsProviders) |
291 | | - .bypassAutoEncryption(true) |
292 | | - .build()) |
293 | | - .build() |
294 | | - val mongoClient = MongoClient(clientSettings) |
295 | | - |
296 | | - ... |
297 | | - |
298 | | - // Explicitly encrypt a field |
299 | | - val encryptedFieldValue = clientEncryption.encrypt(BsonString("123456789"), |
300 | | - EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId)) |
301 | | - .headResult() |
302 | | - |
303 | | - collection.insertOne(Document("encryptedField" -> encryptedFieldValue)).headResult() |
304 | | - |
305 | | - val doc = collection.find.first().headResult() |
306 | | - println(doc.toJson()) |
| 3 | +.. sharedinclude:: dbx/encrypt-fields.rst |
| 4 | + |
| 5 | + .. replacement:: driver-specific-content |
| 6 | + |
| 7 | + .. important:: Compatible Encryption Library Version |
| 8 | + |
| 9 | + The {+driver-short+} uses the `mongodb-crypt |
| 10 | + <https://mvnrepository.com/artifact/org.mongodb/mongodb-crypt>`__ |
| 11 | + encryption library for in-use encryption. This driver version |
| 12 | + is compatible with ``mongodb-crypt`` v{+mongocrypt-version+}. |
| 13 | + |
| 14 | + Select from the following :guilabel:`Maven` and |
| 15 | + :guilabel:`sbt` tabs to see how to add the ``mongodb-crypt`` |
| 16 | + dependency to your project by using the specified manager: |
| 17 | + |
| 18 | + .. tabs:: |
| 19 | + |
| 20 | + .. tab:: Maven |
| 21 | + :tabid: maven-dependency |
| 22 | + |
| 23 | + .. include:: /includes/security/crypt-maven-versioned.rst |
| 24 | + |
| 25 | + .. tab:: sbt |
| 26 | + :tabid: sbt-dependency |
| 27 | + |
| 28 | + .. include:: /includes/security/crypt-sbt-versioned.rst |
0 commit comments