Skip to content

Commit 23c8a18

Browse files
authored
chore: do not add beacons when FORCE_PLAINTEXT_WRITE is used. (#1232)
* chore: respect FORCE_PLAINTEXT_WRITE when using multi-tenant and search config
1 parent 3aa25d0 commit 23c8a18

File tree

7 files changed

+113
-40
lines changed

7 files changed

+113
-40
lines changed

DynamoDbEncryption/dafny/DynamoDbEncryptionTransforms/src/BatchWriteItemTransform.dfy

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ module BatchWriteItemTransform {
3232
//= specification/dynamodb-encryption-client/ddb-sdk-integration.md#encrypt-before-batchwriteitem
3333
//# If the table name does not refer to an [encrypted-table](#encrypted-table),
3434
//# the list of operations MUST be unchanged.
35-
if tableName in config.tableEncryptionConfigs {
35+
if !IsPlainWrite(config, tableName) {
3636
var tableConfig := config.tableEncryptionConfigs[tableName];
3737
var encryptedItems : seq<DDB.WriteRequest> := [];
3838
for x := 0 to |writeRequests|

DynamoDbEncryption/dafny/DynamoDbEncryptionTransforms/src/DdbMiddlewareConfig.dfy

+9-1
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,17 @@ module DdbMiddlewareConfig {
1616
partitionKeyName: string,
1717
sortKeyName: Option<string>,
1818
itemEncryptor: DynamoDbItemEncryptor.DynamoDbItemEncryptorClient,
19-
search : Option<SearchableEncryptionInfo.ValidSearchInfo>
19+
search : Option<SearchableEncryptionInfo.ValidSearchInfo>,
20+
plaintextOverride: AwsCryptographyDbEncryptionSdkDynamoDbTypes.PlaintextOverride
2021
)
2122

23+
// return true if records written to the table should NOT be encrypted or otherwise modified
24+
predicate method IsPlainWrite(config : Config, tableName : string)
25+
{
26+
|| tableName !in config.tableEncryptionConfigs
27+
|| config.tableEncryptionConfigs[tableName].plaintextOverride == AwsCryptographyDbEncryptionSdkDynamoDbTypes.PlaintextOverride.FORCE_PLAINTEXT_WRITE_ALLOW_PLAINTEXT_READ
28+
}
29+
2230
predicate ValidTableConfig?(config: TableConfig) {
2331
var encryptorConfig := config.itemEncryptor.config;
2432
&& config.logicalTableName == encryptorConfig.logicalTableName

DynamoDbEncryption/dafny/DynamoDbEncryptionTransforms/src/Index.dfy

+2-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,8 @@ module
199199
partitionKeyName := inputConfig.partitionKeyName,
200200
sortKeyName := inputConfig.sortKeyName,
201201
itemEncryptor := itemEncryptor,
202-
search := search
202+
search := search,
203+
plaintextOverride := inputConfig.plaintextOverride.UnwrapOr(AwsCryptographyDbEncryptionSdkDynamoDbTypes.PlaintextOverride.FORBID_PLAINTEXT_WRITE_FORBID_PLAINTEXT_READ)
203204
);
204205

205206
internalConfigs := internalConfigs[tableName := internalConfig];

DynamoDbEncryption/dafny/DynamoDbEncryptionTransforms/src/PutItemTransform.dfy

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ module PutItemTransform {
2626
ensures output.Success? && input.sdkInput.TableName !in config.tableEncryptionConfigs ==>
2727
output.value.transformedInput == input.sdkInput
2828

29-
ensures output.Success? && input.sdkInput.TableName in config.tableEncryptionConfigs ==>
29+
ensures output.Success? && !IsPlainWrite(config, input.sdkInput.TableName) ==>
3030
&& var tableConfig := config.tableEncryptionConfigs[input.sdkInput.TableName];
3131
//= specification/dynamodb-encryption-client/ddb-sdk-integration.md#encrypt-before-putitem
3232
//= type=implication
@@ -55,7 +55,7 @@ module PutItemTransform {
5555
input.sdkInput.ExpressionAttributeValues).Success?
5656

5757
{
58-
if input.sdkInput.TableName !in config.tableEncryptionConfigs {
58+
if IsPlainWrite(config, input.sdkInput.TableName) {
5959
return Success(PutItemInputTransformOutput(transformedInput := input.sdkInput));
6060
}
6161
var tableConfig := config.tableEncryptionConfigs[input.sdkInput.TableName];

DynamoDbEncryption/dafny/DynamoDbEncryptionTransforms/src/TransactWriteItemsTransform.dfy

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ module TransactWriteItemsTransform {
7575
item.Update.value.ExpressionAttributeValues);
7676
}
7777

78-
if item.Put.Some? && item.Put.value.TableName in config.tableEncryptionConfigs {
78+
if item.Put.Some? && !IsPlainWrite(config, item.Put.value.TableName) {
7979
var tableConfig := config.tableEncryptionConfigs[item.Put.value.TableName];
8080

8181
//= specification/dynamodb-encryption-client/ddb-sdk-integration.md#encrypt-before-transactwriteitems

DynamoDbEncryption/dafny/DynamoDbEncryptionTransforms/test/PutItemTransform.dfy

+45-18
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,14 @@ module PutItemTransformTest {
99
import opened TestFixtures
1010
import DDB = ComAmazonawsDynamodbTypes
1111
import AwsCryptographyDbEncryptionSdkDynamoDbTransformsTypes
12+
import opened AwsCryptographyDbEncryptionSdkDynamoDbTypes
1213

1314
method {:test} TestPutItemInputPassthrough() {
1415
var middlewareUnderTest := TestFixtures.GetDynamoDbEncryptionTransforms();
1516
var tableName := GetTableName("no_such_table");
1617
var input := DDB.PutItemInput(
1718
TableName := tableName,
18-
Item := map[],
19-
Expected := None(),
20-
ReturnValues := None(),
21-
ReturnConsumedCapacity := None(),
22-
ReturnItemCollectionMetrics := None(),
23-
ConditionalOperator := None(),
24-
ConditionExpression := None(),
25-
ExpressionAttributeNames := None(),
26-
ExpressionAttributeValues := None()
19+
Item := map[]
2720
);
2821
var transformed := middlewareUnderTest.PutItemInputTransform(
2922
AwsCryptographyDbEncryptionSdkDynamoDbTransformsTypes.PutItemInputTransformInput(
@@ -35,6 +28,48 @@ module PutItemTransformTest {
3528
expect_equal("PutItemInput", transformed.value.transformedInput, input);
3629
}
3730

31+
const BasicItem : DDB.AttributeMap := map["bar" := DDB.AttributeValue.S("baz")]
32+
33+
method TestPutItemInputMultiFail(plaintextOverride : Option<AwsCryptographyDbEncryptionSdkDynamoDbTypes.PlaintextOverride>) {
34+
var middlewareUnderTest := TestFixtures.GetDynamoDbEncryptionTransformsMutli(plaintextOverride);
35+
var tableName := GetTableName("foo");
36+
var input := DDB.PutItemInput(
37+
TableName := tableName,
38+
Item := BasicItem
39+
);
40+
var transformed := middlewareUnderTest.PutItemInputTransform(
41+
AwsCryptographyDbEncryptionSdkDynamoDbTransformsTypes.PutItemInputTransformInput(
42+
sdkInput := input
43+
)
44+
);
45+
expect transformed.Failure?;
46+
expect transformed.error == AwsCryptographyDbEncryptionSdkDynamoDbTransformsTypes.DynamoDbEncryptionTransformsException(
47+
message := "In multi-tenant mode, keyProviderId must be aws-kms-hierarchy");
48+
}
49+
50+
method {:test} TestPutItemInputMulti() {
51+
TestPutItemInputMultiFail(None);
52+
TestPutItemInputMultiFail(Some(PlaintextOverride.FORBID_PLAINTEXT_WRITE_FORBID_PLAINTEXT_READ));
53+
TestPutItemInputMultiFail(Some(PlaintextOverride.FORBID_PLAINTEXT_WRITE_ALLOW_PLAINTEXT_READ));
54+
}
55+
56+
method {:test} TestPutItemInputMultiForceAllow() {
57+
var middlewareUnderTest := TestFixtures.GetDynamoDbEncryptionTransformsMutli(
58+
Some(PlaintextOverride.FORCE_PLAINTEXT_WRITE_ALLOW_PLAINTEXT_READ)
59+
);
60+
var tableName := GetTableName("foo");
61+
var input := DDB.PutItemInput(
62+
TableName := tableName,
63+
Item := BasicItem
64+
);
65+
var transformed := middlewareUnderTest.PutItemInputTransform(
66+
AwsCryptographyDbEncryptionSdkDynamoDbTransformsTypes.PutItemInputTransformInput(
67+
sdkInput := input
68+
)
69+
);
70+
expect transformed.Success?;
71+
}
72+
3873
method {:test} TestPutItemOutputPassthrough() {
3974
var middlewareUnderTest := TestFixtures.GetDynamoDbEncryptionTransforms();
4075
var output := DDB.PutItemOutput(
@@ -45,15 +80,7 @@ module PutItemTransformTest {
4580
var tableName := GetTableName("no_such_table");
4681
var input := DDB.PutItemInput(
4782
TableName := tableName,
48-
Item := map[],
49-
Expected := None(),
50-
ReturnValues := None(),
51-
ReturnConsumedCapacity := None(),
52-
ReturnItemCollectionMetrics := None(),
53-
ConditionalOperator := None(),
54-
ConditionExpression := None(),
55-
ExpressionAttributeNames := None(),
56-
ExpressionAttributeValues := None()
83+
Item := map[]
5784
);
5885
var transformed := middlewareUnderTest.PutItemOutputTransform(
5986
AwsCryptographyDbEncryptionSdkDynamoDbTransformsTypes.PutItemOutputTransformInput(

DynamoDbEncryption/dafny/DynamoDbEncryptionTransforms/test/TestFixtures.dfy

+53-16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33
include "../src/Index.dfy"
4+
include "../../DynamoDbEncryption/test/BeaconTestFixtures.dfy"
45

56
module TestFixtures {
67
import opened Wrappers
@@ -9,6 +10,7 @@ module TestFixtures {
910
import opened AwsCryptographyDbEncryptionSdkDynamoDbTransformsTypes
1011
import opened AwsCryptographyDbEncryptionSdkDynamoDbItemEncryptorTypes
1112
import opened AwsCryptographyDbEncryptionSdkDynamoDbTypes
13+
import opened BeaconTestFixtures
1214
import DynamoDbEncryptionTransforms
1315
import DynamoDbItemEncryptor
1416
import AwsCryptographyMaterialProvidersTypes
@@ -122,11 +124,7 @@ module TestFixtures {
122124
attributeActionsOnEncrypt := config.attributeActionsOnEncrypt,
123125
allowedUnsignedAttributes := config.allowedUnsignedAttributes,
124126
allowedUnsignedAttributePrefix := config.allowedUnsignedAttributePrefix,
125-
keyring := Some(keyring),
126-
cmm := None(),
127-
algorithmSuiteId := None(),
128-
legacyOverride := None(),
129-
plaintextOverride := None()
127+
keyring := Some(keyring)
130128
);
131129
var encryptor2 : IDynamoDbItemEncryptorClient :- expect DynamoDbItemEncryptor.DynamoDbItemEncryptor(encryptorConfig);
132130
assert encryptor2 is DynamoDbItemEncryptor.DynamoDbItemEncryptorClient;
@@ -184,10 +182,7 @@ module TestFixtures {
184182
{
185183
var matProv :- expect MaterialProviders.MaterialProviders(MaterialProviders.DefaultMaterialProvidersConfig());
186184
var keyringInput := AwsCryptographyMaterialProvidersTypes.CreateAwsKmsMultiKeyringInput(
187-
generator := Some(PUBLIC_US_WEST_2_KMS_TEST_KEY),
188-
kmsKeyIds := None(),
189-
clientSupplier := None(),
190-
grantTokens := None()
185+
generator := Some(PUBLIC_US_WEST_2_KMS_TEST_KEY)
191186
);
192187
keyring :- expect matProv.CreateAwsKmsMultiKeyring(keyringInput);
193188
}
@@ -216,7 +211,7 @@ module TestFixtures {
216211
ensures fresh(encryption.Modifies)
217212
{
218213
var keyring := GetKmsKeyring();
219-
var encryption2 : IDynamoDbEncryptionTransformsClient :- expect DynamoDbEncryptionTransforms.DynamoDbEncryptionTransforms(
214+
encryption :- expect DynamoDbEncryptionTransforms.DynamoDbEncryptionTransforms(
220215
DynamoDbTablesEncryptionConfig(
221216
tableEncryptionConfigs := map[
222217
"foo" := DynamoDbTableEncryptionConfig(
@@ -232,17 +227,59 @@ module TestFixtures {
232227
allowedUnsignedAttributes := Some(["plain"]),
233228
allowedUnsignedAttributePrefix := None(),
234229
algorithmSuiteId := None(),
230+
keyring := Some(keyring)
231+
)
232+
]
233+
)
234+
);
235+
assume {:axiom} fresh(encryption.Modifies);
236+
}
237+
238+
// type AttributeActions = map<ComAmazonawsDynamodbTypes.AttributeName, AwsCryptographyDbEncryptionSdkStructuredEncryptionTypes.CryptoAction>
239+
240+
const MultiActions : AttributeActions :=
241+
map[
242+
"bar" := SE.SIGN_ONLY,
243+
"std2" := SE.ENCRYPT_AND_SIGN,
244+
"std4" := SE.ENCRYPT_AND_SIGN,
245+
"std6" := SE.ENCRYPT_AND_SIGN,
246+
"Name" := SE.ENCRYPT_AND_SIGN,
247+
"Title" := SE.ENCRYPT_AND_SIGN,
248+
"TooBad" := SE.ENCRYPT_AND_SIGN,
249+
"Year" := SE.SIGN_ONLY,
250+
"Date" := SE.SIGN_ONLY,
251+
"TheKeyField" := SE.SIGN_ONLY
252+
]
253+
254+
method GetDynamoDbEncryptionTransformsMutli(plaintextOverride : Option<AwsCryptographyDbEncryptionSdkDynamoDbTypes.PlaintextOverride>)
255+
returns (encryption: DynamoDbEncryptionTransforms.DynamoDbEncryptionTransformsClient)
256+
ensures encryption.ValidState()
257+
ensures fresh(encryption)
258+
ensures fresh(encryption.Modifies)
259+
{
260+
var keyring := GetKmsKeyring();
261+
var beacons := GetLotsaBeaconsMulti();
262+
var search := SearchConfig (
263+
versions := [beacons],
264+
writeVersion := 1
265+
);
266+
encryption :- expect DynamoDbEncryptionTransforms.DynamoDbEncryptionTransforms(
267+
DynamoDbTablesEncryptionConfig(
268+
tableEncryptionConfigs := map[
269+
"foo" := DynamoDbTableEncryptionConfig(
270+
logicalTableName := "foo",
271+
partitionKeyName := "bar",
272+
sortKeyName := None(),
273+
attributeActionsOnEncrypt := MultiActions,
274+
allowedUnsignedAttributes := Some(["plain"]),
235275
keyring := Some(keyring),
236-
cmm := None(),
237-
search := None,
238-
legacyOverride := None,
239-
plaintextOverride := None
276+
search := Some(search),
277+
plaintextOverride := plaintextOverride
240278
)
241279
]
242280
)
243281
);
244-
assert encryption2 is DynamoDbEncryptionTransforms.DynamoDbEncryptionTransformsClient;
245-
encryption := encryption2 as DynamoDbEncryptionTransforms.DynamoDbEncryptionTransformsClient;
246282
assume {:axiom} fresh(encryption.Modifies);
247283
}
284+
248285
}

0 commit comments

Comments
 (0)