-
Notifications
You must be signed in to change notification settings - Fork 15
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
Conversation
There was a problem hiding this 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. |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 ==> |
There was a problem hiding this comment.
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
?
if h in converted then | ||
BeaconizeStringSet(value[1..], key, converted) | ||
else | ||
BeaconizeStringSet(value[1..], key, converted + [h]) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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> := []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be?
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?
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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))) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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."); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.")) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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
* feat: implement beacon styles
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.