The DynamoDB Support Layer provides everything necessary to the middleware interceptors, with the exception of encryption and decryption.
This document specifies the interface and high level semantics of these entry points.
DynamoDB SDK Integration should be specified in terms of these operations.
There are two categories of support functions.
The first category is for general support, used across multiple DynamoDB API transformations.
- Writable - are the attributes in this item ok to write
- TestConditionExpression - Is this condition expression suitable for use
- TestUpdateExpression - Is this update expression suitable for use
- AddSignedBeacons - Add non encrypted attributes to an item to enable searchable encryption
- GetEncryptedBeacons - Get new attributes for an item to enable searchable encryption
- RemoveBeacons - Remove all private attributes from an item, e.g. the ones added in AddSignedBeacons and GetEncryptedBeacons
- HandleBeaconKeyFieldName - Handle the beacon key field name for Multi Key Store configurations
The second category is support for specific interceptors, where the whole input or output structure is modified.
Writeable MUST reject any item containing an attribute which begins with aws_dbe_
.
One needn't worry about attributes with the same names as beacons or virtual fields, because elsewhere we make sure that the beacons do not overlap with configured fields, and so trying to write those fields will result in "writing unconfigured field" errors already.
TestConditionExpression MUST fail if any operand in the condition expression is an encrypted attribute name.
TestUpdateExpression MUST fail if any operand in the update expression is a signed attribute name.
AddSignedBeacons examines an AttributeMap and modifies it to be appropriate for Searchable Encryption, returning a replacement AttributeMap.
AddSignedBeacons MUST only operate on compound beacons that do not have any encrypted parts.
For every configured compound beacons which only contains non encrypted parts that can be successfully built from the attributes in the input AttributeMap, AddSignedBeacons MUST add an attribute named NAME, where NAME is the name of the beacon. The value of this attribute MUST be a string, and must have the value defined in beacons.
If the attribute NAME already exists, if the constructed compound beacon does not match the existing attribute value AddSignedBeacons MUST fail.
AddSignedBeacons MUST also add an attribute with name aws_dbe_v_1
and whose value is a string containing a single space.
The result of AddSignedBeacons MUST be a super set of everything in the input AttributeMap.
GetEncryptedBeacons examines the Encrypt Item Input and Encrypt Item Output.
To obtain [Beacon Key Materials] GetEncryptedBeacons MUST call Get beacon key after encrypt.
GetEncryptedBeacons MUST NOT operate on compound beacons that only have signed parts.
For all other configured beacons that can be successfully built from the attributes in the input AttributeMap, GetEncryptedBeacons MUST add an attribute named aws_dbe_b_NAME, where NAME is the name of the beacon. The value of this attribute MUST be a string, and must have the value defined in beacons
The result of GetEncryptedBeacons MUST NOT contain any keys in the Encrypt Item Output AttributeMap.
RemoveBeacons examines an AttributeMap and modifies it to be appropriate for customer use, returning a replacement AttributeMap.
RemoveBeacons MUST remove any attributes whose name begins with aws_dbe_
,
and leave all other attributes unchanged.
HandleBeaconKeyFieldName examines an AttributeMap, the Beacon Key Source and the Attribute Actions to determine how the Beacon Key Field Name should be handled.
The Beacon Key Source MUST be Multi Key Store or HandleBeaconKeyFieldName MUST fail.
If the AttributeMap does not have a key
equal to Beacon Key Field Name
HandleBeaconKeyFieldName MUST return a beacon key id
of None
and the unaltered AttributeMap.
This case is because a specific item
may not have any beacons that need to be constructed.
If the AttributeMap does have a key
equal to Beacon Key Field Name
then the beacon key id
MUST be the value of this Attribute.
If there is not an Attribute Action
configured for the Beacon Key Field Name
HandleBeaconKeyFieldName MUST remove the Beacon Key Field Name
from the AttributeMap and return the beacon key id
and the altered AttributeMap.
If there is an Attribute Action
configured for the Beacon Key Field Name
and that action is DO_NOTHING
HandleBeaconKeyFieldName MUST remove the Beacon Key Field Name
from the AttributeMap and return the beacon key id
and the altered AttributeMap.
If there is an Attribute Action
configured for the Beacon Key Field Name
and that action is SIGN_ONLY
HandleBeaconKeyFieldName MUST return the beacon key id
and the unaltered AttributeMap.
Having an attribute action of ENCRYPT_AND_SIGN for the Beacon Key Field Name is not a valid configuration.
Transform an unencrypted QueryInput object for searchable encryption.
The KeyConditions property MUST NOT be defined on QueryInput.
If the QueryObject has encrypted values then QueryInputForBeacons MUST obtain Beacon Key Materials from Get beacon key for query. If the QueryObject does not have encrypted values then QueryInputForBeacons MUST NOT attempt to obtain Beacon Key Materials.
For any operand in the KeyConditionExpression or FilterExpression which is a beacon name, the name MUST be replaced by the internal beacon name (i.e. NAME replaced by aws_dbe_b_NAME).
If the name is used directly in the expression, the name MUST be changed in the expression. For example the expression "MyBeacon = :value" must be changed to "aws_dbe_b_MyBeacon = :value".
If the name is used indirectly through the ExpressionAttributeNames mapping, the name MUST be changed in the ExpressionAttributeNames. For example if the query is "#Beacon = :value" and ExpressionAttributeNames holds (#Beacon = MyBeacon), the query must remain unchanged and ExpressionAttributeNames changed to (#Beacon = aws_dbe_b_MyBeacon).
In this regard, each use of each operand is handled separately.
Similarly, any values in ExpressionAttributeValues that are referred to by a beacon name MUST be changed to the beacon value, as calculated defined in beacons. The hmac key used MUST be obtained from the Beacon Key Materials HMAC Keys map using the beacon name as the key.
For example if the query is "MyBeacon = :value" and ExpressionAttributeValues holds (:value = banana), then the ExpressionAttributeValues must be changed to (:value = 13fd), where "13fd" is the calculated beacon value.
If a single value in ExpressionAttributeValues is used in more than one context,
for example an expression of this = :foo OR that = :foo
where this
and that
are both beacons, this operation MUST fail.
This includes the case where the KeyConditionExpression contains this = :foo
and the FilterExpression includes that = :foo
.
This is because :foo
can only hold one value, but the beaconization of :foo
would be different for different beacons.
Hypothetically, this operation could split :foo
into :foo1
and :foo2
in this situation, but that risks leaking the connection between the two beacons and spoiling k-anonymity.
Similarly, if one of the two was not a beacon, then we would be leaking the fact that
this beacon came from that text.
Determines if a Query Object has encrypted values (ENCRYPT_AND_SIGN fields)
If there are any ExpressionAttributeValues that are referred to by a beacon name that contain encrypted values (ENCRYPT_AND_SIGN field) then QueryObject has encrypted values MUST return true. Otherwise it MUST return false.
This is the original Query request that was made by the customer.
Transform an unencrypted QueryOutput object for searchable encryption.
We expect that the list of items returned will contain some extra records that matched the beacon values, but do not match the plaintext values if the customer has made a query over any encrypted fields.
If the QueryObject does not have encrypted values then QueryOutputForBeacons MUST not filter the results and MUST return. This is because the query may not have a beacon key id filed.
If the Beacon Key Source for the configured table
is a Multi Key Store
you MUST construct an expected beacon key id
equal to the Beacon Key Id
on materials obtained from Get beacon key for query
These Beacon Key Materials
SHOULD then be discarded.
Using the constructed expected beacon key id
,
for each item the result
the Get beacon key id from Parsed Header
MUST match the expected beacon key id
.
If Get beacon key id from Parsed Header
fails or an item does not match it MUST be discarded.
For each item, we MUST evaluate the query expressions supplied in the QueryInput against the decrypted field values returned by the query. That is, we must filter the decrypted records exactly the way that the DynamoDB server would have, if the server had access to the plaintext values of the item. Any items that do not match MUST be discarded.
For example, imagine that the query input used the expression "Fruit = :fruit" with the value map containing (:fruit = banana).
The actual query resolved by the server will be "aws_dbe_b_Fruit = :fruit" with the value map containing (:fruit = 12345).
Further imagine that two records were returned, one with fruit = banana, and one with fruit = orange (but both with aws_dbe_b_Fruit = 12345).
This operation must look at the field "fruit" and keep only the record where fruit = banana.
The Count
field, MUST be updated to reflect the new item count.
In this context, the DynamoDB server has already verified that the query is well formed, and so any errors encountered during this filtering step must reflect some more fundamental system error. For this reason, any error encountered during filtering MUST result in a failure of the query operation.
Transform an unencrypted ScanInput object for searchable encryption.
The ScanInput is transformed in the same way as QueryInputForBeacons.
Transform an unencrypted ScanOutput object for searchable encryption.
The ScanOutput is transformed in the same way as QueryOutputForBeacons.