1
2
3
4
5
6
7 package mongo
8
9 import (
10 "context"
11 "crypto/rand"
12 "encoding/base64"
13 "fmt"
14 "log"
15
16 "go.mongodb.org/mongo-driver/bson"
17 "go.mongodb.org/mongo-driver/bson/primitive"
18 "go.mongodb.org/mongo-driver/mongo/options"
19 )
20
21 func Example_clientSideEncryption() {
22
23
24 localKey := make([]byte, 96)
25 if _, err := rand.Read(localKey); err != nil {
26 log.Fatal(err)
27 }
28 kmsProviders := map[string]map[string]interface{}{
29 "local": {
30 "key": localKey,
31 },
32 }
33 keyVaultNamespace := "encryption.__keyVault"
34
35 uri := "mongodb://localhost:27017"
36 autoEncryptionOpts := options.AutoEncryption().
37 SetKeyVaultNamespace(keyVaultNamespace).
38 SetKmsProviders(kmsProviders)
39 clientOpts := options.Client().
40 ApplyURI(uri).
41 SetAutoEncryptionOptions(autoEncryptionOpts)
42 client, err := Connect(context.TODO(), clientOpts)
43 if err != nil {
44 log.Fatalf("Connect error: %v", err)
45 }
46 defer func() {
47 if err = client.Disconnect(context.TODO()); err != nil {
48 log.Fatalf("Disconnect error: %v", err)
49 }
50 }()
51
52 collection := client.Database("test").Collection("coll")
53 if err := collection.Drop(context.TODO()); err != nil {
54 log.Fatalf("Collection.Drop error: %v", err)
55 }
56
57 _, err = collection.InsertOne(
58 context.TODO(),
59 bson.D{{"encryptedField", "123456789"}})
60 if err != nil {
61 log.Fatalf("InsertOne error: %v", err)
62 }
63 res, err := collection.FindOne(context.TODO(), bson.D{}).Raw()
64 if err != nil {
65 log.Fatalf("FindOne error: %v", err)
66 }
67 fmt.Println(res)
68 }
69
70 func Example_clientSideEncryptionCreateKey() {
71 keyVaultNamespace := "encryption.__keyVault"
72 uri := "mongodb://localhost:27017"
73
74
75 var kmsProviders map[string]map[string]interface{}
76
77
78 clientEncryptionOpts := options.ClientEncryption().
79 SetKeyVaultNamespace(keyVaultNamespace).
80 SetKmsProviders(kmsProviders)
81 keyVaultClient, err := Connect(
82 context.TODO(),
83 options.Client().ApplyURI(uri))
84 if err != nil {
85 log.Fatalf("Connect error for keyVaultClient: %v", err)
86 }
87 clientEnc, err := NewClientEncryption(keyVaultClient, clientEncryptionOpts)
88 if err != nil {
89 log.Fatalf("NewClientEncryption error: %v", err)
90 }
91 defer func() {
92
93 if err = clientEnc.Close(context.TODO()); err != nil {
94 log.Fatalf("Close error: %v", err)
95 }
96 }()
97
98
99 dataKeyID, err := clientEnc.CreateDataKey(context.TODO(), "local")
100 if err != nil {
101 log.Fatalf("CreateDataKey error: %v", err)
102 }
103 dataKeyBase64 := base64.StdEncoding.EncodeToString(dataKeyID.Data)
104
105
106
107 schema := `{
108 "properties": {
109 "encryptedField": {
110 "encrypt": {
111 "keyId": [{
112 "$binary": {
113 "base64": "%s",
114 "subType": "04"
115 }
116 }],
117 "bsonType": "string",
118 "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
119 }
120 }
121 },
122 "bsonType": "object"
123 }`
124 schema = fmt.Sprintf(schema, dataKeyBase64)
125 var schemaDoc bson.Raw
126 err = bson.UnmarshalExtJSON([]byte(schema), true, &schemaDoc)
127 if err != nil {
128 log.Fatalf("UnmarshalExtJSON error: %v", err)
129 }
130
131
132 dbName := "test"
133 collName := "coll"
134 schemaMap := map[string]interface{}{
135 dbName + "." + collName: schemaDoc,
136 }
137 autoEncryptionOpts := options.AutoEncryption().
138 SetKmsProviders(kmsProviders).
139 SetKeyVaultNamespace(keyVaultNamespace).
140 SetSchemaMap(schemaMap)
141
142 clientOptions := options.Client().
143 ApplyURI(uri).
144 SetAutoEncryptionOptions(autoEncryptionOpts)
145 client, err := Connect(context.TODO(), clientOptions)
146 if err != nil {
147 log.Fatalf("Connect error for encrypted client: %v", err)
148 }
149 defer func() {
150 _ = client.Disconnect(context.TODO())
151 }()
152
153
154 }
155
156 func Example_explictEncryption() {
157
158
159 var localMasterKey []byte
160 kmsProviders := map[string]map[string]interface{}{
161 "local": {
162 "key": localMasterKey,
163 },
164 }
165
166
167
168 keyVaultDBName, keyVaultCollName := "encryption", "testKeyVault"
169 keyVaultNamespace := keyVaultDBName + "." + keyVaultCollName
170
171
172 client, err := Connect(
173 context.TODO(),
174 options.Client().ApplyURI("mongodb://localhost:27017"))
175 if err != nil {
176 panic(err)
177 }
178 defer func() { _ = client.Disconnect(context.TODO()) }()
179
180
181 coll := client.Database("test").Collection("coll")
182 _ = coll.Drop(context.TODO())
183
184
185 keyVaultColl := client.Database(keyVaultDBName).Collection(keyVaultCollName)
186 _ = keyVaultColl.Drop(context.TODO())
187
188 keyVaultIndex := IndexModel{
189 Keys: bson.D{{"keyAltNames", 1}},
190 Options: options.Index().
191 SetUnique(true).
192 SetPartialFilterExpression(bson.D{
193 {"keyAltNames", bson.D{
194 {"$exists", true},
195 }},
196 }),
197 }
198 _, err = keyVaultColl.Indexes().CreateOne(context.TODO(), keyVaultIndex)
199 if err != nil {
200 panic(err)
201 }
202
203
204
205
206
207 clientEncryptionOpts := options.ClientEncryption().
208 SetKmsProviders(kmsProviders).
209 SetKeyVaultNamespace(keyVaultNamespace)
210 clientEncryption, err := NewClientEncryption(client, clientEncryptionOpts)
211 if err != nil {
212 panic(err)
213 }
214 defer func() { _ = clientEncryption.Close(context.TODO()) }()
215
216
217 dataKeyOpts := options.DataKey().
218 SetKeyAltNames([]string{"go_encryption_example"})
219 dataKeyID, err := clientEncryption.CreateDataKey(
220 context.TODO(),
221 "local",
222 dataKeyOpts)
223 if err != nil {
224 panic(err)
225 }
226
227
228
229 rawValueType, rawValueData, err := bson.MarshalValue("123456789")
230 if err != nil {
231 panic(err)
232 }
233 rawValue := bson.RawValue{Type: rawValueType, Value: rawValueData}
234 encryptionOpts := options.Encrypt().
235 SetAlgorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").
236 SetKeyID(dataKeyID)
237 encryptedField, err := clientEncryption.Encrypt(
238 context.TODO(),
239 rawValue,
240 encryptionOpts)
241 if err != nil {
242 panic(err)
243 }
244
245
246 _, err = coll.InsertOne(
247 context.TODO(),
248 bson.D{{"encryptedField", encryptedField}})
249 if err != nil {
250 panic(err)
251 }
252 var foundDoc bson.M
253 err = coll.FindOne(context.TODO(), bson.D{}).Decode(&foundDoc)
254 if err != nil {
255 panic(err)
256 }
257
258
259 decrypted, err := clientEncryption.Decrypt(
260 context.TODO(),
261 foundDoc["encryptedField"].(primitive.Binary))
262 if err != nil {
263 panic(err)
264 }
265 fmt.Printf("Decrypted value: %s\n", decrypted)
266 }
267
268 func Example_explictEncryptionWithAutomaticDecryption() {
269
270
271
272
273
274 var localMasterKey []byte
275 kmsProviders := map[string]map[string]interface{}{
276 "local": {
277 "key": localMasterKey,
278 },
279 }
280
281
282
283 keyVaultDBName, keyVaultCollName := "encryption", "testKeyVault"
284 keyVaultNamespace := keyVaultDBName + "." + keyVaultCollName
285
286
287
288
289
290 autoEncryptionOpts := options.AutoEncryption().
291 SetKmsProviders(kmsProviders).
292 SetKeyVaultNamespace(keyVaultNamespace).
293 SetBypassAutoEncryption(true)
294 clientOpts := options.Client().
295 ApplyURI("mongodb://localhost:27017").
296 SetAutoEncryptionOptions(autoEncryptionOpts)
297 client, err := Connect(context.TODO(), clientOpts)
298 if err != nil {
299 panic(err)
300 }
301 defer func() { _ = client.Disconnect(context.TODO()) }()
302
303
304 coll := client.Database("test").Collection("coll")
305 _ = coll.Drop(context.TODO())
306
307
308 keyVaultColl := client.Database(keyVaultDBName).Collection(keyVaultCollName)
309 _ = keyVaultColl.Drop(context.TODO())
310
311 keyVaultIndex := IndexModel{
312 Keys: bson.D{{"keyAltNames", 1}},
313 Options: options.Index().
314 SetUnique(true).
315 SetPartialFilterExpression(bson.D{
316 {"keyAltNames", bson.D{
317 {"$exists", true},
318 }},
319 }),
320 }
321
322 _, err = keyVaultColl.Indexes().CreateOne(context.TODO(), keyVaultIndex)
323 if err != nil {
324 panic(err)
325 }
326
327
328
329
330
331 clientEncryptionOpts := options.ClientEncryption().
332 SetKmsProviders(kmsProviders).
333 SetKeyVaultNamespace(keyVaultNamespace)
334 clientEncryption, err := NewClientEncryption(client, clientEncryptionOpts)
335 if err != nil {
336 panic(err)
337 }
338 defer func() { _ = clientEncryption.Close(context.TODO()) }()
339
340
341 dataKeyOpts := options.DataKey().
342 SetKeyAltNames([]string{"go_encryption_example"})
343 dataKeyID, err := clientEncryption.CreateDataKey(
344 context.TODO(),
345 "local",
346 dataKeyOpts)
347 if err != nil {
348 panic(err)
349 }
350
351
352
353 rawValueType, rawValueData, err := bson.MarshalValue("123456789")
354 if err != nil {
355 panic(err)
356 }
357 rawValue := bson.RawValue{Type: rawValueType, Value: rawValueData}
358 encryptionOpts := options.Encrypt().
359 SetAlgorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").
360 SetKeyID(dataKeyID)
361 encryptedField, err := clientEncryption.Encrypt(
362 context.TODO(),
363 rawValue,
364 encryptionOpts)
365 if err != nil {
366 panic(err)
367 }
368
369
370
371 _, err = coll.InsertOne(
372 context.TODO(),
373 bson.D{{"encryptedField", encryptedField}})
374 if err != nil {
375 panic(err)
376 }
377 var foundDoc bson.M
378 err = coll.FindOne(context.TODO(), bson.D{}).Decode(&foundDoc)
379 if err != nil {
380 panic(err)
381 }
382 fmt.Printf("Decrypted document: %v\n", foundDoc)
383 }
384
View as plain text