Add Index arn in DynamoDB to sam yml file - amazon-web-services

I am trying access my DynamoDB via a user that has all access to the table.
However I am failing to query the LSI for the same table. It says user doesn't have permissions to query index.
I checked the documentation and it shows that index needs to be define separately like arn:aws:dynamodb:region:account-id:table/table-name/index/index-name
However I am not sure how to define this in cloudformation yml file.
BooksTable:
Type: AWS::DynamoDB::Table
DeletionPolicy: Retain
Properties:
TableName:
Fn::Sub: ${SamStackPrefix}${Stage}-BooksTable
BillingMode: PAY_PER_REQUEST
KeySchema:
- AttributeName: hashKey
KeyType: HASH
- AttributeName: rangeKey
KeyType: RANGE
LocalSecondaryIndexes:
- IndexName: LSI1
KeySchema:
- AttributeName: hashKey
KeyType: HASH
- AttributeName: clientToken
KeyType: RANGE
Projection:
ProjectionType: ALL
AttributeDefinitions:
- AttributeName: hashKey
AttributeType: S
- AttributeName: rangeKey
AttributeType: S
- AttributeName: clientToken
AttributeType: S
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES
TimeToLiveSpecification:
AttributeName: expirationTime
Enabled: true
Outputs:
BooksTableName:
Description: books table.
Value:
!Ref BooksTable
Export:
Name:
Fn::Sub: ${SamStackPrefix}${Stage}-BooksTableName
BooksTableArn:
Description: Arn for books DynamoDB Table
Value:
Fn::GetAtt: [ BooksTable, Arn ]
Export:
Name:
Fn::Sub: ${SamStackPrefix}${Stage}-BooksTableArn
BooksTableStreamArn:
Description: The DDB stream for the books table.
Value:
Fn::GetAtt: [BooksTable, StreamArn]
Export:
Name:
Fn::Sub: ${SamStackPrefix}${Stage}-BooksStreamArn
IAM policy right now
Policies:
- PolicyDocument:
Statement:
- Action: ['dynamodb:PutItem', 'dynamodb:ConditionCheckItem', 'dynamodb:Query', 'dynamodb:GetItem', 'dynamodb:UpdateItem']
Effect: Allow
Resource:
- Fn::GetAtt: [BooksTable, Arn]
How to add LSI to the list of resources so that I can use that ARN to add permissions in the policy document.

Update IAM policy
this should work
Policies:
- PolicyDocument:
Statement:
- Action: ['dynamodb:PutItem', 'dynamodb:ConditionCheckItem', 'dynamodb:Query', 'dynamodb:GetItem', 'dynamodb:UpdateItem']
Effect: Allow
Resource:
- Fn::GetAtt: [BooksTable, Arn]
- "arn:aws:dynamodb:{region}:{account}:table/{tableName}/index/{indexName}"

Related

AWS Lambda get access denied when accessing DynamoDB

I configured my AWS stack using AWS CloudFormation as follow
Resources:
DynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
-
AttributeName: "PK"
AttributeType: "S"
-
AttributeName: "SK"
AttributeType: "S"
-
AttributeName: "GSI1_PK"
AttributeType: "S"
-
AttributeName: "GSI2_PK"
AttributeType: "S"
-
AttributeName: "GSI1_SK"
AttributeType: "S"
-
AttributeName: "GSI2_SK"
AttributeType: "S"
KeySchema:
-
AttributeName: "PK"
KeyType: "HASH"
-
AttributeName: "SK"
KeyType: "RANGE"
GlobalSecondaryIndexes:
-
IndexName: "line_tickets"
KeySchema:
-
AttributeName: "GSI1_PK"
KeyType: "HASH"
-
AttributeName: "GSI1_SK"
KeyType: "RANGE"
Projection:
ProjectionType: "ALL"
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
-
IndexName: "users_tickets"
KeySchema:
-
AttributeName: "GSI2_PK"
KeyType: "HASH"
-
AttributeName: "GSI2_SK"
KeyType: "RANGE"
Projection:
ProjectionType: "ALL"
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
TableName: !Ref TableName
Tags:
- Key: ENV
Value: !Ref ENVName
DependsOn:
- "LambdaExecutionRole"
GetAccountLambdaFun:
Type: AWS::Lambda::Function
Properties:
FunctionName: GetAccountLambdaFun
Description: Retrive account From DB.
Role: !GetAtt LambdaExecutionRole.Arn
Handler: index.handler
MemorySize: 128
Runtime: !Ref LambdaRuntime
Environment:
Variables:
DB_END_POINT: !Ref LambdaDBEndPoint
TABLE_NAME: !Ref TableName
DB_API_VERSION: !Ref LambdaDBApiVersion
DB_AWS_REGION: !Ref "AWS::Region"
Code:
S3Bucket: !Ref LambdaHostS3BucketName
S3Key: !Sub
- "${Folder}/account-get-lambda-fun.zip"
- Folder: !Ref ENVName
Tags:
- Key: ENV
Value: !Ref ENVName
DependsOn:
- "DynamoDBTable"
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
RoleName: **LambdaExecutionRole**
Path: /
ManagedPolicyArns:
- !Ref LambdaLogGroupPolicy
- !Ref DynamoFullAccessPolicy
LambdaLogGroupPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
Description: Lambda log groupt policy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- 'logs:CreateLogGroup'
Resource: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*
- Effect: Allow
Action:
- 'logs:CreateLogStream'
- 'logs:PutLogEvents'
Resource: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*:*
DynamoFullAccessPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
Description:dynamo full access policy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Sid: "DynamoDBIndexAndStreamAccess"
Action:
- 'dynamodb:GetShardIterator'
- 'dynamodb:Scan'
- 'dynamodb:Query'
- 'dynamodb:DescribeStream'
- 'dynamodb:GetRecords'
- 'dynamodb:ListStream'
Resource:
- !Sub
- arn:aws:dynamodb:*:*:table/*/index/*
- tableName: !Ref TableName
- !Sub
- arn:aws:dynamodb:*:*:table/*/stream/*
- tableName: !Ref TableName
- Effect: Allow
Sid: "DynamoDBTableAccess"
Action:
- dynamodb:BatchGetItem'
- dynamodb:BatchWriteItem'
- dynamodb:ConditionCheckItem'
- dynamodb:PutItem'
- dynamodb:DescribeTable'
- dynamodb:DeleteItem'
- dynamodb:GetItem'
- dynamodb:Scan'
- dynamodb:Query'
- dynamodb:UpdateIte'
Resource:
- !Sub
- arn:aws:dynamodb:*:*:table/*
- tableName: !Ref TableName
- Effect: Allow
Sid: "DynamoDBDescribeLimitsAccess"
Action: 'dynamodb:DescribeLimits'
Resource:
- !Sub
- arn:aws:dynamodb:*:*:table/*
- tableName: !Ref TableName
- !Sub
- arn:aws:dynamodb:*:*:table/*/index/*
- tableName: !Ref TableName
when i try to test the lambda function via AWS console i get an error:
ERROR DynamoDB GET REQUEST failed AccessDeniedException: User:
arn:aws:sts::XXXX:assumed-role/LambdaExecutionRole/GetAccountLambdaFun
is not authorized to perform: dynamodb:Query on resource:
arn:aws:dynamodb:eu-central-1:XXXX:table/TableName
I am not sure why is that as i configure a DynamoFullAccessPolicy that should grant the lambda access to this DB.

CloudFormation for DynamoDB: "Encountered unsupported property AttributeType"

Deployment of DynamoDB stack rollbacks with error:
CREATE_FAILED Encountered unsupported property AttributeType
I tried various modifications of attributes configuration, used quotes, also checked similar question.
My template:
Resources:
checkpointsTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: sf_instance_table_key
AttributeType: S
BillingMode: PAY_PER_REQUEST
KeySchema:
- AttributeName: sf_instance_table_key
AttributeType: HASH
TableName: !Ref tableName
Tags:
- Key: "Division"
Value: !Ref division
Not many lines here, but cannot figure it out. Thanks for help!
It should be like this:
Resources:
checkpointsTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: sf_instance_table_key
AttributeType: S
BillingMode: PAY_PER_REQUEST
KeySchema:
- AttributeName: sf_instance_table_key
KeyType: HASH
TableName: !Ref tableName
Tags:
- Key: "Division"
Value: !Ref division

How do I reference AWS GlobalSecondaryIndex name in AWS CloudFormationTemplate for a Lambda

I am trying to write a cloud formation template, where the Global Secondary Index (GSI) name of a DynamoDBTable is available as environment variable in a AWS Lambda. I have the template below and am having trouble getting the reference to the GSI name in the AWS Lambda (last line in the template).
Thanks in advance for your help.
# The AWSTemplateFormatVersion identifies the capabilities of the template
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/format-version-structure.html
AWSTemplateFormatVersion: 2010-09-09
Description: >-
temp
Parameters:
Environment:
Type: String
Description: The name of the stage, e.g. "dev", "preprod", "prod"
Default: ravi
Transform:
- AWS::Serverless-2016-10-31
Resources:
customerLambdaDLQ:
Type: AWS::SQS::Queue
Properties:
QueueName: !Sub "${Environment}-customer-lambda-dead-letter-queue"
projectionsLambdaRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- "sts:AssumeRole"
Path: /
Policies:
- PolicyName: !Sub "${Environment}-customer-lambda-role"
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- "sqs:SendMessage*"
- "dynamodb:GetItem"
- "dynamodb:DeleteItem"
- "dynamodb:PutItem"
- "dynamodb:Scan"
- "dynamodb:Query"
- "dynamodb:UpdateItem"
- "dynamodb:BatchWriteItem"
- "dynamodb:BatchGetItem"
- "dynamodb:DescribeTable"
- "dynamodb:ConditionCheckItem"
- "dynamodb:DescribeStream"
- "dynamodb:GetRecords"
- "dynamodb:GetShardIterator"
- "dynamodb:ListStreams"
Resource:
- !GetAtt customerLambdaDLQ.Arn
customerTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: !Sub "${Environment}-customer-table"
AttributeDefinitions:
- AttributeName: PK
AttributeType: S
- AttributeName: SK
AttributeType: S
- AttributeName: indexKey_1
AttributeType: S
- AttributeName: indexKey_2
AttributeType: S
- AttributeName: customerId
AttributeType: S
KeySchema:
- AttributeName: PK
KeyType: HASH
- AttributeName: SK
KeyType: RANGE
GlobalSecondaryIndexes:
- IndexName: customer-index-1
KeySchema:
- AttributeName: indexKey_1
KeyType: HASH
- AttributeName: indexKey_2
KeyType: RANGE
Projection:
ProjectionType: ALL
- IndexName: customer-index-2
KeySchema:
- AttributeName: customerId
KeyType: HASH
- AttributeName: indexKey_2
KeyType: RANGE
Projection:
NonKeyAttributes:
- first_name
- last_name
- city
- state
- country
ProjectionType: INCLUDE
BillingMode: PAY_PER_REQUEST
SSESpecification:
SSEEnabled: true
primer:
Type: AWS::Lambda::Function
Properties:
Runtime: nodejs12.x
Role: !GetAtt projectionsLambdaRole.Arn
Handler: index.handler
Code:
ZipFile: |
var aws = require('aws-sdk')
var response = require('cfn-response')
exports.handler = function(event, context) {
console.log("REQUEST RECEIVED:\n" + JSON.stringify(event))
// For Delete requests, immediately send a SUCCESS response.
if (event.RequestType == "Delete") {
response.send(event, context, "SUCCESS")
return
}
var responseStatus = "FAILED"
var responseData = {}
var functionName = event.ResourceProperties.FunctionName
var lambda = new aws.Lambda()
lambda.invoke({ FunctionName: functionName }, function(err, invokeResult) {
if (err) {
responseData = {Error: "Invoke call failed"}
console.log(responseData.Error + ":\n", err)
}
else responseStatus = "SUCCESS"
response.send(event, context, responseStatus, responseData)
})
}
Description: Invoke a function during stack creation.
Environment:
Variables:
TABLE_NAME: !Ref customerTable
GSI_1_NAME: !GetAtt customerTable.GlobalSecondaryIndexes.customer-index-1
The GSI is exactly what you named it, so you can just pass in customer-index-1

Prevent AWS CloudFormation from deleting DynamoDB using IAM

I'm trying to create an AWS Role which prevents CloudFormation delete a table. For instance, I created my table as follows:
UsersDynamoDBTable:
Type: AWS::DynamoDB::Table
Description: Users DynamoDB Table
Properties:
AttributeDefinitions:
- AttributeName: hashKey
AttributeType: S
- AttributeName: rangeKey
AttributeType: S
KeySchema:
- AttributeName: hashKey
KeyType: HASH
- AttributeName: rangeKey
KeyType: RANGE
BillingMode: PAY_PER_REQUEST
GlobalSecondaryIndexes:
- IndexName: index-rangeKey
KeySchema:
- AttributeName: rangeKey
KeyType: HASH
- AttributeName: hashKey
KeyType: RANGE
Projection:
ProjectionType: ALL
Now suppose that a develop accidentally delete this lines and update stack. This way the table with all its data would be removed. So I'd like to create a role which prevents CloudFormation delete DynamoDB tables. My first attempt was creating the Role below, but it didn't work.
PreventCloudFormationDeleteTableIAMRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- cloudformation.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: PreventTableDeletePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Deny
Action:
- dynamodb:DeleteTable
Resource:
- !Join
- '/'
- - !Join [':', ['arn:aws:dynamodb', !Sub '${AWS::Region}', '*', 'table']]
- !Join ['', [!Sub '${StackName}', '*']]
Am I missing some Role configuration?
Thank you.
You can use a DeletionPolicy of RETAIN to prevent the table from being deleted when the stack is removed or table is removed from the template. Also the new UpdateReplacePolicy will prevent CloudFormation from deleting the table when it needs to do so due to primary key changes.
Considering that the role is properly attached to the invoking user/principal, is it possible that the policy Arn from that join does not match the table Arn?
Also consider retaining the resource instead of denying the operation:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html

Wondering where to find docs on serverless dynamoDB Schema

I am writing the following for a db schema:
resources:
Resources:
DynamoDbTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: EmployeeType
AttributeDefinitions:
- AttributeName: timeoffgroupid
AttributeType: S
- AttributeName: timeOffGroup
AttributeType: S
- AttributeName: timeOffGroupColor
AttributeType: S
KeySchema:
- AttributeName: timeoffgroupid
KeyType: HASH
- AttributeName: timeOffGroup
KeyType: HASH
- AttributeName: timeOffGroupColor
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
DynamoDBIamPolicy:
Type: AWS::IAM::Policy
DependsOn: DynamoDbTable
Properties:
PolicyName: lambda-dynamodb
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Resource: arn:aws:dynamodb:*:*:table/moviesTwo
Roles:
- Ref: IamRoleLambdaExecution
But I copied that from a few tutorials and figured out how to post to a db, but I am not sure what all the options are. For example, KeyType: HASH - what are the other options, what do they do? I saw one tutorial tell me this creates a table and sets up the properties with required keys, but I am not sure how to call one primary or how to reference these Attributes and keyTypes. I understand the S is for String, but I am not sure what the other Properties do? I have looked in the documentation but came up empty.
Thanks in advance.
The resources schema used by serverless.yml is the CloudFormation schema. For DynamoDB take a look here.
To understand DynamoDB concepts and terms I'd suggest to start here:
Intro
Core components
Sample