1
2
3
4
5
6
7 package unified
8
9 import (
10 "context"
11 "errors"
12 "fmt"
13
14 "go.mongodb.org/mongo-driver/bson"
15 "go.mongodb.org/mongo-driver/bson/primitive"
16 "go.mongodb.org/mongo-driver/mongo"
17 "go.mongodb.org/mongo-driver/mongo/options"
18 "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
19 )
20
21
22 func parseDataKeyOptions(opts bson.Raw) (*options.DataKeyOptions, error) {
23 elems, err := opts.Elements()
24 if err != nil {
25 return nil, err
26 }
27 dko := options.DataKey()
28 for _, elem := range elems {
29 key := elem.Key()
30 val := elem.Value()
31 switch key {
32 case "masterKey":
33 masterKey := make(map[string]interface{})
34 if err := val.Unmarshal(&masterKey); err != nil {
35 return nil, fmt.Errorf("error unmarshaling 'masterKey': %w", err)
36 }
37 dko.SetMasterKey(masterKey)
38 case "keyAltNames":
39 keyAltNames := []string{}
40 if err := val.Unmarshal(&keyAltNames); err != nil {
41 return nil, fmt.Errorf("error unmarshaling 'keyAltNames': %w", err)
42 }
43 dko.SetKeyAltNames(keyAltNames)
44 case "keyMaterial":
45 bin := primitive.Binary{}
46 if err := val.Unmarshal(&bin); err != nil {
47 return nil, fmt.Errorf("error unmarshaling 'keyMaterial': %w", err)
48 }
49 dko.SetKeyMaterial(bin.Data)
50 default:
51 return nil, fmt.Errorf("unrecognized DataKeyOptions arg: %q", key)
52 }
53 }
54 return dko, nil
55 }
56
57
58
59 func executeAddKeyAltName(ctx context.Context, operation *operation) (*operationResult, error) {
60 cee, err := entities(ctx).clientEncryption(operation.Object)
61 if err != nil {
62 return nil, err
63 }
64
65 var id primitive.Binary
66 var keyAltName string
67
68 elems, err := operation.Arguments.Elements()
69 if err != nil {
70 return nil, err
71 }
72 for _, elem := range elems {
73 key := elem.Key()
74 val := elem.Value()
75
76 switch key {
77 case "id":
78 subtype, data := val.Binary()
79 id = primitive.Binary{Subtype: subtype, Data: data}
80 case "keyAltName":
81 keyAltName = val.StringValue()
82 default:
83 return nil, fmt.Errorf("unrecognized AddKeyAltName arg: %q", key)
84 }
85 }
86
87 res, err := cee.AddKeyAltName(ctx, id, keyAltName).Raw()
88
89
90 if errors.Is(err, mongo.ErrNoDocuments) {
91 err = nil
92 }
93 return newDocumentResult(res, err), nil
94 }
95
96
97 func executeCreateDataKey(ctx context.Context, operation *operation) (*operationResult, error) {
98 cee, err := entities(ctx).clientEncryption(operation.Object)
99 if err != nil {
100 return nil, err
101 }
102
103 var kmsProvider string
104 var dko *options.DataKeyOptions
105
106 elems, err := operation.Arguments.Elements()
107 if err != nil {
108 return nil, err
109 }
110 for _, elem := range elems {
111 key := elem.Key()
112 val := elem.Value()
113
114 switch key {
115 case "kmsProvider":
116 kmsProvider = val.StringValue()
117 case "opts":
118 dko, err = parseDataKeyOptions(val.Document())
119 if err != nil {
120 return nil, err
121 }
122 default:
123 return nil, fmt.Errorf("unrecognized CreateDataKey arg: %q", key)
124 }
125 }
126 if kmsProvider == "" {
127 return nil, newMissingArgumentError("kmsProvider")
128 }
129
130 bin, err := cee.CreateDataKey(ctx, kmsProvider, dko)
131 if bin.Data != nil {
132 bsonType, bsonData, err := bson.MarshalValue(bin)
133 if err != nil {
134 return nil, err
135 }
136 return newValueResult(bsonType, bsonData, err), nil
137 }
138 return newErrorResult(err), nil
139 }
140
141
142
143 func executeDeleteKey(ctx context.Context, operation *operation) (*operationResult, error) {
144 cee, err := entities(ctx).clientEncryption(operation.Object)
145 if err != nil {
146 return nil, err
147 }
148
149 var id primitive.Binary
150
151 elems, err := operation.Arguments.Elements()
152 if err != nil {
153 return nil, err
154 }
155 for _, elem := range elems {
156 key := elem.Key()
157 val := elem.Value()
158
159 switch key {
160 case "id":
161 subtype, data := val.Binary()
162 id = primitive.Binary{Subtype: subtype, Data: data}
163 default:
164 return nil, fmt.Errorf("unrecognized DeleteKey arg: %q", key)
165 }
166 }
167
168 res, err := cee.DeleteKey(ctx, id)
169 raw := emptyCoreDocument
170 if res != nil {
171 raw = bsoncore.NewDocumentBuilder().
172 AppendInt64("deletedCount", res.DeletedCount).
173 Build()
174 }
175 return newDocumentResult(raw, err), nil
176 }
177
178
179 func executeGetKeyByAltName(ctx context.Context, operation *operation) (*operationResult, error) {
180 cee, err := entities(ctx).clientEncryption(operation.Object)
181 if err != nil {
182 return nil, err
183 }
184
185 var keyAltName string
186
187 elems, err := operation.Arguments.Elements()
188 if err != nil {
189 return nil, err
190 }
191 for _, elem := range elems {
192 key := elem.Key()
193 val := elem.Value()
194
195 switch key {
196 case "keyAltName":
197 keyAltName = val.StringValue()
198 default:
199 return nil, fmt.Errorf("unrecognized GetKeyByAltName arg: %q", key)
200 }
201 }
202
203 res, err := cee.GetKeyByAltName(ctx, keyAltName).Raw()
204
205
206 if errors.Is(err, mongo.ErrNoDocuments) {
207 err = nil
208 }
209 return newDocumentResult(res, err), nil
210 }
211
212
213
214 func executeGetKey(ctx context.Context, operation *operation) (*operationResult, error) {
215 cee, err := entities(ctx).clientEncryption(operation.Object)
216 if err != nil {
217 return nil, err
218 }
219
220 var id primitive.Binary
221
222 elems, err := operation.Arguments.Elements()
223 if err != nil {
224 return nil, err
225 }
226 for _, elem := range elems {
227 key := elem.Key()
228 val := elem.Value()
229
230 switch key {
231 case "id":
232 subtype, data := val.Binary()
233 id = primitive.Binary{Subtype: subtype, Data: data}
234 default:
235 return nil, fmt.Errorf("unrecognized GetKey arg: %q", key)
236 }
237 }
238
239 res, err := cee.GetKey(ctx, id).Raw()
240
241
242 if errors.Is(err, mongo.ErrNoDocuments) {
243 err = nil
244 }
245 return newDocumentResult(res, err), nil
246 }
247
248
249
250 func executeGetKeys(ctx context.Context, operation *operation) (*operationResult, error) {
251 cee, err := entities(ctx).clientEncryption(operation.Object)
252 if err != nil {
253 return nil, err
254 }
255 cursor, err := cee.GetKeys(ctx)
256 if err != nil {
257 return newErrorResult(err), nil
258 }
259 var docs []bson.Raw
260 if err := cursor.All(ctx, &docs); err != nil {
261 return newErrorResult(err), nil
262 }
263 return newCursorResult(docs), nil
264 }
265
266
267 func executeRemoveKeyAltName(ctx context.Context, operation *operation) (*operationResult, error) {
268 cee, err := entities(ctx).clientEncryption(operation.Object)
269 if err != nil {
270 return nil, err
271 }
272
273 var id primitive.Binary
274 var keyAltName string
275
276 elems, err := operation.Arguments.Elements()
277 if err != nil {
278 return nil, err
279 }
280 for _, elem := range elems {
281 key := elem.Key()
282 val := elem.Value()
283
284 switch key {
285 case "id":
286 subtype, data := val.Binary()
287 id = primitive.Binary{Subtype: subtype, Data: data}
288 case "keyAltName":
289 keyAltName = val.StringValue()
290 default:
291 return nil, fmt.Errorf("unrecognized RemoveKeyAltName arg: %q", key)
292 }
293 }
294
295 res, err := cee.RemoveKeyAltName(ctx, id, keyAltName).Raw()
296
297
298 if errors.Is(err, mongo.ErrNoDocuments) {
299 err = nil
300 }
301 return newDocumentResult(res, err), nil
302 }
303
304
305
306 func parseRewrapManyDataKeyOptions(opts bson.Raw) (*options.RewrapManyDataKeyOptions, error) {
307 elems, err := opts.Elements()
308 if err != nil {
309 return nil, err
310 }
311 rmdko := options.RewrapManyDataKey()
312 for _, elem := range elems {
313 key := elem.Key()
314 val := elem.Value()
315 switch key {
316 case "provider":
317 rmdko.SetProvider(val.StringValue())
318 case "masterKey":
319 rmdko.SetMasterKey(val.Document())
320 default:
321 return nil, fmt.Errorf("unrecognized RewrapManyDataKeyOptions arg: %q", key)
322 }
323 }
324 return rmdko, nil
325 }
326
327
328
329 func rewrapManyDataKeyResultsOpResult(result *mongo.RewrapManyDataKeyResult) (*operationResult, error) {
330 raw := bsoncore.NewDocumentBuilder()
331 if res := result.BulkWriteResult; res != nil {
332 rawUpsertedIDs := emptyDocument
333 var marshalErr error
334 if res.UpsertedIDs != nil {
335 rawUpsertedIDs, marshalErr = bson.Marshal(res.UpsertedIDs)
336 if marshalErr != nil {
337 return nil, fmt.Errorf("error marshalling UpsertedIDs map to BSON: %w", marshalErr)
338 }
339 }
340 bulkWriteResult := bsoncore.NewDocumentBuilder()
341 bulkWriteResult.
342 AppendInt64("insertedCount", res.InsertedCount).
343 AppendInt64("deletedCount", res.DeletedCount).
344 AppendInt64("matchedCount", res.MatchedCount).
345 AppendInt64("modifiedCount", res.ModifiedCount).
346 AppendInt64("upsertedCount", res.UpsertedCount).
347 AppendDocument("upsertedIds", rawUpsertedIDs)
348 raw.AppendDocument("bulkWriteResult", bulkWriteResult.Build())
349 }
350 return newDocumentResult(raw.Build(), nil), nil
351 }
352
353
354 func executeRewrapManyDataKey(ctx context.Context, operation *operation) (*operationResult, error) {
355 cee, err := entities(ctx).clientEncryption(operation.Object)
356 if err != nil {
357 return nil, err
358 }
359
360 var filter bson.Raw
361 var rmdko *options.RewrapManyDataKeyOptions
362
363 elems, err := operation.Arguments.Elements()
364 if err != nil {
365 return nil, err
366 }
367
368 for _, elem := range elems {
369 key := elem.Key()
370 val := elem.Value()
371
372 switch key {
373 case "filter":
374 filter = val.Document()
375 case "opts":
376 rmdko, err = parseRewrapManyDataKeyOptions(val.Document())
377 if err != nil {
378 return nil, err
379 }
380 default:
381 return nil, fmt.Errorf("unrecognized RewrapManyDataKey arg: %q", key)
382 }
383 }
384
385 if filter == nil {
386 return nil, newMissingArgumentError("filter")
387 }
388
389 result, err := cee.RewrapManyDataKey(ctx, filter, rmdko)
390 if err != nil {
391 return newErrorResult(err), nil
392 }
393 return rewrapManyDataKeyResultsOpResult(result)
394 }
395
View as plain text