Skip to content

Commit ae00d3a

Browse files
committed
feat: allow indirect attribute names with MultiKeyStore
1 parent 808a5b4 commit ae00d3a

File tree

3 files changed

+129
-2
lines changed

3 files changed

+129
-2
lines changed

DynamoDbEncryption/dafny/DynamoDbEncryption/src/FilterExpr.dfy

+1-1
Original file line numberDiff line numberDiff line change
@@ -1533,7 +1533,7 @@ module DynamoDBFilterExpr {
15331533
else
15341534
var name := if names.Some? && attr.value.s in names.value then names.value[attr.value.s] else attr.value.s;
15351535
var keyIdField := bv.keySource.keyLoc.keyName;
1536-
if keyIdField == attr.value.s then
1536+
if keyIdField == name then
15371537
Some(value)
15381538
else
15391539
KeyIdFromPart(bv, keyIdField, attr.value.s, value)

DynamoDbEncryption/dafny/DynamoDbEncryption/test/BeaconTestFixtures.dfy

+63-1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,29 @@ module BeaconTestFixtures {
141141
return store;
142142
}
143143

144+
method GetMultiKeyStore() returns (output : SI.ValidStore)
145+
ensures fresh(output.Modifies)
146+
{
147+
var kmsClient :- expect KMS.KMSClient();
148+
var ddbClient :- expect DDBC.DynamoDBClient();
149+
var kmsConfig := KTypes.KMSConfiguration.kmsKeyArn(
150+
"arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126"
151+
);
152+
var keyStoreConfig := KTypes.KeyStoreConfig(
153+
id := None,
154+
kmsConfiguration := kmsConfig,
155+
logicalKeyStoreName := "KeyStoreDdbTable",
156+
grantTokens := None,
157+
ddbTableName := "KeyStoreDdbTable",
158+
ddbClient := Some(ddbClient),
159+
kmsClient := Some(kmsClient)
160+
);
161+
162+
var store :- expect KeyStore.KeyStore(keyStoreConfig);
163+
return store;
164+
}
165+
166+
144167
method GetEmptyBeacons() returns (output : BeaconVersion)
145168
ensures output.keyStore.ValidState()
146169
ensures fresh(output.keyStore.Modifies)
@@ -177,6 +200,24 @@ module BeaconTestFixtures {
177200
);
178201
}
179202

203+
method GetLotsaBeaconsMulti() returns (output : BeaconVersion)
204+
ensures output.keyStore.ValidState()
205+
ensures fresh(output.keyStore.Modifies)
206+
ensures output.version == 1
207+
{
208+
var store := GetMultiKeyStore();
209+
return BeaconVersion (
210+
version := 1,
211+
keyStore := store,
212+
keySource := multi(MultiKeyStore(keyFieldName := "TheKeyField", cacheTTL := 42)),
213+
standardBeacons := [std2, std4, std6, NameTitleBeacon, NameB, TitleB],
214+
compoundBeacons := Some([NameTitle, YearName, Mixed, JustSigned]),
215+
virtualFields := Some([NameTitleField]),
216+
encryptedParts := None,
217+
signedParts := None
218+
);
219+
}
220+
180221
const EmptyTableConfig := DynamoDbTableEncryptionConfig (
181222
logicalTableName := "Foo",
182223
partitionKeyName := "foo",
@@ -200,7 +241,8 @@ module BeaconTestFixtures {
200241
"Title" := SE.ENCRYPT_AND_SIGN,
201242
"TooBad" := SE.ENCRYPT_AND_SIGN,
202243
"Year" := SE.SIGN_ONLY,
203-
"Date" := SE.SIGN_ONLY
244+
"Date" := SE.SIGN_ONLY,
245+
"TheKeyField" := SE.SIGN_ONLY
204246
]
205247
)
206248

@@ -223,6 +265,26 @@ module BeaconTestFixtures {
223265
return SI.KeySource(client, version.keyStore, SI.LiteralLoc(keys), cache, 0);
224266
}
225267

268+
datatype KeyLocation =
269+
| LiteralLoc (keys: HmacKeyMap)
270+
| SingleLoc (keyId: string)
271+
| MultiLoc (keyName : string, deleteKey : bool)
272+
273+
method GetMultiSource(keyName : string, version : BeaconVersion) returns (output : SI.KeySource)
274+
requires version.keyStore.ValidState()
275+
ensures output.ValidState()
276+
ensures version.keyStore == output.store
277+
ensures fresh(output.client.Modifies)
278+
{
279+
var client :- expect Primitives.AtomicPrimitives();
280+
var mpl :- expect MaterialProviders.MaterialProviders();
281+
var input := MPT.CreateCryptographicMaterialsCacheInput(
282+
cache := MPT.Default(Default := MPT.DefaultCache(entryCapacity := 3))
283+
);
284+
var cache :- expect mpl.CreateCryptographicMaterialsCache(input);
285+
return SI.KeySource(client, version.keyStore, SI.MultiLoc(keyName, false), cache, 0);
286+
}
287+
226288
const SimpleItem : DDB.AttributeMap := map[
227289
"std2" := Std2String,
228290
"std4" := Std4String,

DynamoDbEncryption/dafny/DynamoDbEncryption/test/DDBSupport.dfy

+65
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,69 @@ module TestDDBSupport {
3232
expect newItem == SimpleItem + expectedNew;
3333
}
3434

35+
function method DS(x : string) : DDB.AttributeValue
36+
{
37+
DDB.AttributeValue.S(x)
38+
}
39+
40+
method {:test} TestMulti() {
41+
var version := GetLotsaBeaconsMulti();
42+
var src := GetMultiSource("TheKeyField", version);
43+
var bv :- expect ConvertVersionWithSource(FullTableConfig, version, src);
44+
var search := SI.SearchInfo([bv], 0);
45+
var expressionAttributeValues : map<string, AttributeValue> := map[
46+
":value" := DS("0ad21413-51aa-42e1-9c3d-6a4b1edf7e10")
47+
];
48+
var queryInput := DDB.QueryInput (
49+
TableName := "SomeTable",
50+
ExpressionAttributeValues := Some(expressionAttributeValues),
51+
KeyConditionExpression := Some("TheKeyField = :value")
52+
);
53+
var result :- expect QueryInputForBeacons(Some(search), FullTableConfig.attributeActionsOnEncrypt, queryInput);
54+
55+
expressionAttributeValues := map[
56+
":value" := DS("0ad21413-51aa-42e1-9c3d-6a4b1edf7e10"),
57+
":other" := DS("junk")
58+
];
59+
queryInput := DDB.QueryInput (
60+
TableName := "foo",
61+
ExpressionAttributeValues := Some(expressionAttributeValues),
62+
KeyConditionExpression := Some("TheKeyField = :value AND std2 = :other")
63+
);
64+
result :- expect QueryInputForBeacons(Some(search), FullTableConfig.attributeActionsOnEncrypt, queryInput);
65+
66+
queryInput := DDB.QueryInput (
67+
TableName := "foo",
68+
ExpressionAttributeValues := Some(expressionAttributeValues),
69+
KeyConditionExpression := Some("std2 = :other")
70+
);
71+
var result2 := QueryInputForBeacons(Some(search), FullTableConfig.attributeActionsOnEncrypt, queryInput);
72+
expect result2 == Failure(AwsCryptographyDbEncryptionSdkDynamoDbTypes.Error.DynamoDbEncryptionException(
73+
message := "Need KeyId because of beacon std2 but no KeyId found in query"));
74+
75+
var expressionAttributeNames := map[
76+
"#beacon" := "std2",
77+
"#keyfield" := "TheKeyField"
78+
];
79+
queryInput := DDB.QueryInput (
80+
TableName := "foo",
81+
ExpressionAttributeNames := Some(expressionAttributeNames),
82+
ExpressionAttributeValues := Some(expressionAttributeValues),
83+
KeyConditionExpression := Some("#keyfield = :value AND #beacon = :other")
84+
);
85+
result :- expect QueryInputForBeacons(Some(search), FullTableConfig.attributeActionsOnEncrypt, queryInput);
86+
}
3587
}
88+
// Map<String, String> expressionAttributesNames = new HashMap<>();
89+
// expressionAttributesNames.put("#compound", "firstNameCompound");
90+
91+
// Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
92+
// expressionAttributeValues.put(":value", AttributeValue.builder().s("f1-l.f2-li.f3-lil.f4-lily.s-Placeholder - 3afba703-6345-4a25-b28a-ec22b1b79a35").build());
93+
94+
// QueryRequest queryRequest = QueryRequest.builder()
95+
// .tableName(tableName)
96+
// .indexName("aws_dbe_b_firstNameCompound-index")
97+
// .keyConditionExpression("#compound = :value")
98+
// .expressionAttributeNames(expressionAttributesNames)
99+
// .expressionAttributeValues(expressionAttributeValues)
100+
// .build();

0 commit comments

Comments
 (0)