λ
DynamoDB encryption-at-rest is now available, but you can’t enable it on existing tables—only new ones. Here’s my migration approach:
Four-stage deployment prevents data loss:
Original template:
DynamoDbUsers:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: user
AttributeType: S
KeySchema:
- AttributeName: user
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
Migration template:
dynamoDbUsers:
Type: AWS::DynamoDB::Table
Properties:
StreamSpecification:
StreamViewType: NEW_IMAGE
AttributeDefinitions:
- AttributeName: user
AttributeType: S
KeySchema:
- AttributeName: user
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
dynamoDbUsersEncrypted:
Type: AWS::DynamoDB::Table
Properties:
SSESpecification:
SSEEnabled: true
AttributeDefinitions:
- AttributeName: user
AttributeType: S
KeySchema:
- AttributeName: user
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
tableStream:
Type: AWS::Lambda::EventSourceMapping
Properties:
BatchSize: 1
Enabled: true
EventSourceArn: !GetAtt dynamoDbUsers.StreamArn
FunctionName: !GetAtt replicationFunction.Arn
StartingPosition: LATEST
replicationLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: "/"
Policies:
- PolicyName: LambdaRolePolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: 'arn:aws:logs:*:*:*'
- Effect: Allow
Action:
- dynamodb:UpdateItem
- dynamodb:DeleteItem
- dynamodb:PutItem
- dynamodb:GetRecords
- dynamodb:GetShardIterator
- dynamodb:DescribeStream
- dynamodb:ListStreams
Resource: "*"
replicationFunction:
Type: AWS::Lambda::Function
Properties:
Code:
ZipFile: !Sub |
import boto3
import copy
table = "${dynamoDbUsersEncrypted}"
def handler(event, context):
ddb = boto3.client('dynamodb')
for record in event['Records']:
try:
data = record['dynamodb']
newdata = copy.deepcopy(data)
args = {
'TableName': table,
'Key': data['Keys']
}
if record['eventName'] in ['INSERT', 'MODIFY']:
for k, v in data['NewImage'].items():
newdata['NewImage'][k] = {}
newdata['NewImage'][k]['Action'] = 'PUT'
newdata['NewImage'][k]['Value'] = v
if k in data['Keys']:
del newdata['NewImage'][k]
args['AttributeUpdates'] = newdata['NewImage']
ddb.update_item(**args)
elif record['eventName'] == 'REMOVE':
ddb.delete_item(**args)
except Exception as e:
print(event)
print(f'Exception: {e}')
Handler: index.handler
Role: !GetAtt replicationLambdaRole.Arn
Runtime: python3.6
Timeout: 300
Comments