-
Notifications
You must be signed in to change notification settings - Fork 71
Update documentation and warnings related to SaveBehavior. #44
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
Changes from all commits
b988c8e
b5f7fe9
8a00b2a
c1f74d0
cd1ebb4
7530a1e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ | |
import java.util.Set; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
|
||
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig.SaveBehavior; | ||
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingsRegistry.Mapping; | ||
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingsRegistry.Mappings; | ||
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.DoNotEncrypt; | ||
|
@@ -32,13 +33,18 @@ | |
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.TableAadOverride; | ||
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.EncryptionMaterialsProvider; | ||
import com.amazonaws.services.dynamodbv2.model.AttributeValue; | ||
import org.apache.commons.logging.Log; | ||
import org.apache.commons.logging.LogFactory; | ||
|
||
/** | ||
* Encrypts all non-key fields prior to storing them in DynamoDB. | ||
* <em>This must be used with @{link SaveBehavior#CLOBBER}. Use of | ||
* any other @{code SaveBehavior} can result in data-corruption.</em> | ||
* | ||
* @author Greg Rubin | ||
*/ | ||
public class AttributeEncryptor implements AttributeTransformer { | ||
private static final Log LOG = LogFactory.getLog(AttributeEncryptor.class); | ||
private final DynamoDBEncryptor encryptor; | ||
private final Map<Class<?>, ModelClassMetadata> metadataCache = new ConcurrentHashMap<>(); | ||
|
||
|
@@ -58,9 +64,26 @@ public DynamoDBEncryptor getEncryptor() { | |
public Map<String, AttributeValue> transform(final Parameters<?> parameters) { | ||
// one map of attributeFlags per model class | ||
final ModelClassMetadata metadata = getModelClassMetadata(parameters); | ||
|
||
final Map<String, AttributeValue> attributeValues = parameters.getAttributeValues(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please add a short comment explaining the case being handled here / why this is set to behave this way, for clarity/maintainers? |
||
// If this class is marked as "DoNotTouch" then we know our encryptor will not change it at all | ||
// so we may as well fast-return and do nothing. This also avoids emitting errors when they would not apply. | ||
if (metadata.doNotTouch) { | ||
return attributeValues; | ||
} | ||
|
||
// When AttributeEncryptor is used without SaveBehavior.CLOBBER, it is trying to transform only a subset | ||
// of the actual fields stored in DynamoDB. This means that the generated signature will not cover any | ||
// unmodified fields. Thus, upon untransform, the signature verification will fail as it won't cover all | ||
// expected fields. | ||
if (parameters.isPartialUpdate()) { | ||
LOG.error("Use of AttributeEncryptor without SaveBehavior.CLOBBER is an error and can result in data-corruption. " + | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For anyone who is not using CLOBBER today, there will be tons of errors in the log and the operation is not actually failing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is correct because they are in a dangerous error case and are at risk for data-corruption. Minor software changes outside of their (or our) control could result in this going from a "working due to luck" state to a "broken" state. We consider it sufficiently important to notify people of this dangerous configuration that an ERROR level log is appropriate. The next minor (non-patch) version will throw an exception in this case. Please see #32 |
||
"This occured while trying to save " + parameters.getModelClass()); | ||
} | ||
|
||
try { | ||
return encryptor.encryptRecord( | ||
parameters.getAttributeValues(), | ||
attributeValues, | ||
metadata.getEncryptionFlags(), | ||
paramsToContext(parameters)); | ||
} catch (Exception ex) { | ||
|
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.
Explain why this is the 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.
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.
+1 - I want to learn more about why this is the desired behavior
Using CLOBBER basically disables the Optimistic Locking which is a super useful feature provided by DynamoDB. This says we shouldn't use AttributeEncryptor and Optimistic Locking together.
We support partial encryption and signing today, can those fields be updated safely without CLOBBER save?
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 will re-visit how optimistic logging works with encrypted data. It definitely will not work without a version field. This change is still important due to the need to warn people about the risk of data-corruption.