-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathBatchGetItemTransform.dfy
84 lines (75 loc) · 4.07 KB
/
BatchGetItemTransform.dfy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
include "DynamoDbMiddlewareSupport.dfy"
module BatchGetItemTransform {
import opened DdbMiddlewareConfig
import opened DynamoDbMiddlewareSupport
import opened Wrappers
import DDB = ComAmazonawsDynamodbTypes
import opened AwsCryptographyDbEncryptionSdkDynamoDbTransformsTypes
import EncTypes = AwsCryptographyDbEncryptionSdkDynamoDbItemEncryptorTypes
import Seq
import SortedSets
method Input(config: Config, input: BatchGetItemInputTransformInput)
returns (output: Result<BatchGetItemInputTransformOutput, Error>)
ensures output.Success? && output.value.transformedInput == input.sdkInput
{
return Success(BatchGetItemInputTransformOutput(transformedInput := input.sdkInput));
}
method {:vcs_split_on_every_assert} Output(config: Config, input: BatchGetItemOutputTransformInput)
returns (output: Result<BatchGetItemOutputTransformOutput, Error>)
requires ValidConfig?(config)
ensures ValidConfig?(config)
modifies ModifiesConfig(config)
ensures output.Success? ==> SameOption(input.sdkOutput.Responses, output.value.transformedOutput.Responses)
ensures output.Success? && input.sdkOutput.Responses.Some? ==>
&& output.value.transformedOutput.Responses.Some?
// true but expensive -- input.sdkOutput.Responses.value.Keys == output.value.transformedOutput.Responses.value.Keys
{
if NoMap(input.sdkOutput.Responses) {
return Success(BatchGetItemOutputTransformOutput(transformedOutput := input.sdkOutput));
}
var tableNames := input.sdkOutput.Responses.value.Keys;
var tableNamesSeq := SortedSets.ComputeSetToSequence(tableNames);
ghost var tableNamesSet' := tableNames;
var i := 0;
var result := map[];
while i < |tableNamesSeq|
invariant tableNamesSet' <= input.sdkOutput.Responses.value.Keys
// true but expensive -- invariant result.Keys + tableNames == input.sdkOutput.Responses.value.Keys
{
var tableName := tableNamesSeq[i];
var responses := input.sdkOutput.Responses.value[tableName];
if tableName in config.tableEncryptionConfigs {
var tableConfig := config.tableEncryptionConfigs[tableName];
var decryptedItem : DDB.ItemList := [];
for x := 0 to |responses| {
//= specification/dynamodb-encryption-client/ddb-sdk-integration.md#decrypt-after-batchgetitem
//# For each list item under each key in `Responses`,
//# if there is a configured Item Encryptor with [DynamoDB Table Name](./ddb-item-encryptor.md#dynamodb-table-name) equal to the key,
//# that Item Encryptor MUST perform [Decrypt Item](./decrypt-item.md) where the input
//# [DynamoDB Item](./decrypt-item.md#dynamodb-item)
//# is the `Item` field in the original response.
var decryptRes := tableConfig.itemEncryptor.DecryptItem(EncTypes.DecryptItemInput(encryptedItem:=responses[x]));
//= specification/dynamodb-encryption-client/ddb-sdk-integration.md#decrypt-after-batchgetitem
//# If any [Decrypt Item](./decrypt-item.md) operation fails,
//# BatchGetItem MUST yield an error.
var decrypted :- MapError(decryptRes);
//= specification/dynamodb-encryption-client/ddb-sdk-integration.md#decrypt-after-batchgetitem
//# Beacons MUST be [removed](ddb-support.md#removebeacons) from the result.
var item :- RemoveBeacons(tableConfig, decrypted.plaintextItem);
//= specification/dynamodb-encryption-client/ddb-sdk-integration.md#decrypt-after-batchgetitem
//# Each of these items on the original response MUST be replaced
//# with a value that is equivalent to
//# this result.
decryptedItem := decryptedItem + [item];
}
result := result + map[tableName := decryptedItem];
} else {
result := result + map[tableName := responses];
}
i := i + 1;
}
return Success(BatchGetItemOutputTransformOutput(transformedOutput := input.sdkOutput.(Responses := Some(result))));
}
}