Skip to content

feat: improve error message for missing key #398

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ module AwsCryptographyDbEncryptionSdkDynamoDbItemEncryptorOperations refines Abs
//# If this item does not have a sort key attribute,
//# the DynamoDB Item Context MUST NOT contain the key `aws-crypto-sort-name`.
ensures ret.Success? && config.sortKeyName.None? ==>
SORT_NAME !in ret.value
SORT_NAME !in ret.value
{
UTF8.EncodeAsciiUnique();
:- Need(config.partitionKeyName in item, DDBError("Partition key " + config.partitionKeyName + " not found in Item to be encrypted or decrypted"));
Expand Down Expand Up @@ -514,15 +514,47 @@ module AwsCryptographyDbEncryptionSdkDynamoDbItemEncryptorOperations refines Abs
{
// We can formally verify these properties, but it is too resource intensive
:- Need(forall k <- schema.content.SchemaMap :: InSignatureScope(config, k),
DynamoDbItemEncryptorException( message := "Recieved unexpected Crypto Schema: mismatch with signature scope"));
DynamoDbItemEncryptorException( message := "Received unexpected Crypto Schema: mismatch with signature scope"));
:- Need(forall k <- schema.content.SchemaMap :: ComAmazonawsDynamodbTypes.IsValid_AttributeName(k),
DynamoDbItemEncryptorException( message := "Recieved unexpected Crypto Schema: Invalid attribute names"));
DynamoDbItemEncryptorException( message := "Received unexpected Crypto Schema: Invalid attribute names"));
Success(map k <- schema.content.SchemaMap :: k := schema.content.SchemaMap[k].content.Action)
}

predicate EncryptItemEnsuresPublicly(input: EncryptItemInput, output: Result<EncryptItemOutput, Error>)
{true}

function method GetItemNames(item : ComAmazonawsDynamodbTypes.AttributeMap) : string
{
var keys := SortedSets.ComputeSetToOrderedSequence2(item.Keys, CharLess);
if |keys| == 0 then
"item is empty"
else
Join(keys, " ")
}

function method KeyMissingMsg(
config: InternalConfig,
item : ComAmazonawsDynamodbTypes.AttributeMap,
tag : string)
: string
{
"On " + tag + " : "
+
(if config.partitionKeyName !in item then
"Partition key '" + config.partitionKeyName + "' does not exist in item. "
else
"")

+
(if config.sortKeyName.Some? && config.sortKeyName.value !in item then
"Sort key '" + config.sortKeyName.value + "' does not exist in item. "
else
"")

+ "Item contains these attributes : "
+ GetItemNames(item) + "."
}

// public Encrypt method
method {:vcs_split_on_every_assert} EncryptItem(config: InternalConfig, input: EncryptItemInput)
returns (output: Result<EncryptItemOutput, Error>)
Expand Down Expand Up @@ -621,7 +653,7 @@ module AwsCryptographyDbEncryptionSdkDynamoDbItemEncryptorOperations refines Abs
:- Need(
&& config.partitionKeyName in input.plaintextItem
&& (config.sortKeyName.None? || config.sortKeyName.value in input.plaintextItem)
, DynamoDbItemEncryptorException( message := "Configuration mismatch partition or sort key does not exist in item."));
, E(KeyMissingMsg(config, input.plaintextItem, "Encrypt")));

if |input.plaintextItem| > MAX_ATTRIBUTE_COUNT {
var actCount := String.Base10Int2String(|input.plaintextItem|);
Expand Down Expand Up @@ -839,7 +871,7 @@ module AwsCryptographyDbEncryptionSdkDynamoDbItemEncryptorOperations refines Abs
:- Need(
&& config.partitionKeyName in input.encryptedItem
&& (config.sortKeyName.None? || config.sortKeyName.value in input.encryptedItem)
, DynamoDbItemEncryptorException( message := "Configuration mismatch partition or sort key does not exist in item."));
, DynamoDbItemEncryptorException( message := KeyMissingMsg(config, input.encryptedItem, "Decrypt")));

//= specification/dynamodb-encryption-client/decrypt-item.md#behavior
//# If a [Legacy Policy](./ddb-table-encryption-config.md#legacy-policy) of
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ module DynamoDbItemEncryptorTest {
);
expect encryptRes.Failure?;
expect encryptRes.error == Types.AwsCryptographyDbEncryptionSdkDynamoDb(
DDBE.DynamoDbEncryptionException(message := "No Crypto Action configured for attribute unknown"));
DDBE.DynamoDbEncryptionException(message := "No Crypto Action configured for attribute unknown"));
}

method {:test} TestMissingSortKey() {
var config := TestFixtures.GetEncryptorConfig();
var inputItem := map["bar" := DDBS("key"), "encrypt" := DDBS("foo"), "sign" := DDBS("bar"), "nothing" := DDBS("baz")];
var config2 := config.(
sortKeyName := Some("sort"),
attributeActionsOnEncrypt := config.attributeActionsOnEncrypt["sort" := CSE.SIGN_ONLY]
sortKeyName := Some("sort"),
attributeActionsOnEncrypt := config.attributeActionsOnEncrypt["sort" := CSE.SIGN_ONLY]
);
var encryptor := TestFixtures.GetDynamoDbItemEncryptorFrom(config2);
var encryptRes := encryptor.EncryptItem(
Expand All @@ -56,7 +56,9 @@ module DynamoDbItemEncryptorTest {
)
);
expect encryptRes.Failure?;
expect encryptRes.error == Types.DynamoDbItemEncryptorException(message := "Configuration mismatch partition or sort key does not exist in item.");
expect encryptRes.error == Types.DynamoDbItemEncryptorException(
message := "On Encrypt : Sort key 'sort' does not exist in item. Item contains these attributes : bar encrypt nothing sign."
);
}

method {:test} TestRoundTrip() {
Expand Down Expand Up @@ -148,7 +150,7 @@ module DynamoDbItemEncryptorTest {
expect |parsedHeader.value.encryptedDataKeys| == 1;
}

method {:test} TestTooManyAttributes() {
method {:test} TestTooManyAttributes() {
var inputItem : DDB.AttributeMap := map["bar" := DDBS("key")];
var actions : DDBE.AttributeActions := map["bar" := CSE.SIGN_ONLY];
for i := 0 to MAX_ATTRIBUTE_COUNT {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ public void TestPutWithInvalidCryptoAction() {

@Test(
expectedExceptions = DynamoDbItemEncryptorException.class,
expectedExceptionsMessageRegExp = "Configuration mismatch partition or sort key does not exist in item."
expectedExceptionsMessageRegExp = "On Encrypt : Partition key 'partition_key' does not exist in item. Item contains these attributes : attr1 attr2 sort_key."
)
public void TestPutMissingPartition() {
Map<String, AttributeValue> item = createTestItem("foo", "10", "bar", "awol");
Expand All @@ -530,7 +530,7 @@ public void TestPutMissingPartition() {

@Test(
expectedExceptions = DynamoDbItemEncryptorException.class,
expectedExceptionsMessageRegExp = "Configuration mismatch partition or sort key does not exist in item."
expectedExceptionsMessageRegExp = "On Encrypt : Sort key 'sort_key' does not exist in item. Item contains these attributes : attr1 attr2 partition_key."
)
public void TestPutMissingSort() {
Map<String, AttributeValue> item = createTestItem("foo", "10", "bar", "awol");
Expand Down