Skip to content

feat: implement beacon styles #441

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 6 commits into from
Sep 22, 2023
Merged

feat: implement beacon styles #441

merged 6 commits into from
Sep 22, 2023

Conversation

ajewellamz
Copy link
Contributor

Issue #, if available:

Description of changes:

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@ajewellamz ajewellamz requested a review from a team as a code owner September 21, 2023 13:56
Copy link
Contributor

@lavaleri lavaleri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't have to be a part of this PR, but we need to add examples for each of these beacon styles. It's not immediately clear when/for what use cases a customers would want to utilize these options.

var str := UTF8.Encode(val);
if str.Failure? then
Failure(E(str.error))
else
hash(str.value, keys[base.name])
hash(str.value, keys[keyName()])
}

//= specification/searchable-encryption/beacons.md#value-for-a-standard-beacon
//= type=implication
//# * This operation MUST take an [hmac key](./search-config.md#hmac-key-generation), a record as input, and produce an optional string.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to update the spec with the new output type

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

function method {:opaque} getHash(item : DDB.AttributeMap, vf : VirtualFieldMap, key : Bytes) : (ret : Result<Option<string>, Error>)
ensures ret.Success? ==>
function method {:opaque} getHash(item : DDB.AttributeMap, vf : VirtualFieldMap, key : Bytes) : (ret : Result<Option<DDB.AttributeValue>, Error>)
ensures ret.Success? && !asSet ==>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add specification for if it is asSet?

Comment on lines 260 to 263
if h in converted then
BeaconizeStringSet(value[1..], key, converted)
else
BeaconizeStringSet(value[1..], key, converted + [h])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can DDB Sets contain duplicates? If so, isn't this collapsing them when calculating beacons? Would a customer want to be able to distinguish between [A, A, B] and [A, B]? Or are we accepting that this may be one of the "false positives" we filter out?

Is this behavior surprising to the customer, if they are trying to reason about the distribution of their data, and don't realize that the same beacon value will be created for the above example?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, sets are not supposed to contain duplicates. You made me add code to DynamoToStruct to fail if a set contains duplicates.

BeaconizeStringSet(value[1..], key, converted + [h])
}

function method {:tailrecursion} BeaconizeNumberSet(value : DDB.StringSetAttributeValue, key : Bytes, converted : seq<string> := [])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be?

Suggested change
function method {:tailrecursion} BeaconizeNumberSet(value : DDB.StringSetAttributeValue, key : Bytes, converted : seq<string> := [])
function method {:tailrecursion} BeaconizeNumberSet(value : DDB.NumberSetAttributeValue, key : Bytes, converted : seq<string> := [])

Or does that not exist, and the number set just reuses the StringSetAttributeValue in DDB?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They're the same type, but yes, that should be changed.

@@ -374,18 +391,23 @@ module CompoundBeacon {
//= specification/searchable-encryption/beacons.md#value-for-a-compound-beacon
//= type=implication
//# * This operation MUST take a record as input, and produce an optional string.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we make this change, the spec needs to update it's output type. But do we need to change the type here? Why not have this contain to work with strings, and callers to this method deal with unpacking attribute values?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Reverted.

// Are all beacons internally consistent?
function method CheckBeacons(data : I.BeaconMap) : Result<bool, Error>
{
var beaconNames := SortedSets.ComputeSetToOrderedSequence2(data.Keys, CharLess);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we sort the beacons?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to sort them, we just need to iterate over all the items in a map, and this is the only way I know to do that in a function.

case SS(n) => BeaconizeStringSet(n, key)
case NS(n) => BeaconizeNumberSet(n, key)
case BS(n) => BeaconizeBinarySet(n, key)
case _ => Failure(E("Beacon " + base.name + " has style AsSet, but attribute has type " + AttrTypeToStr(value)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: We have this same error on L227, which to me implies that we could factor out similar logic in these two places. I recognize that there might be ergonomic/verification reasons that make this difficult though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. Refactored.

var BadItem := MyItem["partOnly" := DDB.AttributeValue.S("abc")];
var badAttrs := bv.GenerateEncryptedBeacons(BadItem, DontUseKeyId);
expect badAttrs.Failure?;
expect badAttrs.error == E("Beacon partOnly has style AsSet, but attribute has type S.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we return this error in two places, it is not clear to me which code path this test case is exercising. Is it possible to test both code paths?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. This tested on the Write path, added test on the Query path.

expect bv.error == E("Beacon twinBeacon is twinned to DoesNotExist but DoesNotExist has not yet been defined.");
}

method {:test} TwinnedBadLength()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about testing that we throw the right error is configured with a compound beacon?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

else
Failure(E("Encrypted part needs standard beacon " + parts[0].name + " which is not configured."))
Failure(E("Compound beacon " + name + " refers to standard beacon " + parts[0].name + " which is not configured."))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we are missing a test for this case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

expect bv.error == E("Beacon twinBeacon is twinned to NameTitle but NameTitle is a compound beacon.");
}

method {:test} TwinnedToCompound()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: name of this test appears to be swapped with L305

@ajewellamz ajewellamz merged commit 470eff9 into main Sep 22, 2023
@ajewellamz ajewellamz deleted the beacon-styles branch September 22, 2023 18:09
ajewellamz added a commit that referenced this pull request Nov 14, 2023
* feat: implement beacon styles
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants