Wondering where to find docs on serverless dynamoDB Schema - amazon-web-services

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

Related

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

Add Index arn in DynamoDB to sam yml file

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}"

Serverless deploy fails

Iam trying to deploy my lambda function to AWS using serverless. When executing
serverless deploy --verbose
Iam getting the following error every time:
Serverless Error ---------------------------------------
An error occurred: mainTable - Invalid KeySchema: The first > KeySchemaElement is not a HASH key type (Service: AmazonDynamoDBv2;Status Code: 400; Error Code: ValidationException; Request ID: EACEH0RDMBR36TR0DDBGODTRT3VV4KQNSO5AEMVJF66Q9ASUAAJG).
My serverless.yml looks as following:
service: backend-1 # NOTE: update this with your service name
provider:
name: aws
runtime: nodejs10.x
stage: dev
region: eu-central-1
functions:
graphql:
handler: src/handler.graphql
events:
- http:
path: graphql
method: post
cors: true
plugins:
- serverless-webpack
- serverless-offline
custom:
webpack:
webpackCOnfig: 'webpack.config.js'
includeModules: true
packager: 'npm'
stage: ${opt:stage, self:provider.stage}
resources:
Resources:
mainTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: main_${self:custom.stage}
AttributeDefinitions:
- AttributeName: id
AttributeType: S
- AttributeName: sort
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
- AttributeName: sort
KeyType: RANGE
BillingMode: PAY_PER_REQUEST
GlobalSecondaryIndexes:
- IndexName: spinned-primary
KeySchema:
- AttributeName: id
KeyType: RANGE
- AttributeName: sort
KeyType: HASH
Projection:
ProjectionType: ALL
labelTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: labels_${self:custom.stage}
AttributeDefinitions:
- AttributeName: sort
AttributeType: S
- AttributeName: label
AttributeType: S
KeySchema:
- AttributeName: sort
KeyType: HASH
- AttributeName: label
KeyType: RANGE
BillingMode: PAY_PER_REQUEST
GlobalSecondaryIndexes:
- IndexName: spinned-primary
KeySchema:
- AttributeName: sort
KeyType: RANGE
- AttributeName: label
KeyType: HASH
Projection:
ProjectionType: ALL
logTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: logs_${self:custom.stage}
AttributeDefinitions:
- AttributeName: id
AttributeType: S
- AttributeName: sort
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
- AttributeName: sort
KeyType: RANGE
BillingMode: PAY_PER_REQUEST
Can someone of you help?
Cheers!
When using KeySchemaElements, the HASH keytype must come before the RANGE keytype.
In your YAML, on you GSI for spinned-primary, you have to put the HASH keytype before the RANGE keytype; switch them around so that the HASH is the first keytype in that element.

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

How to set DynamoDB Read/write capacity mode to On-demand on CloudFormation

I've seen this site about DynamoDB On-demand and I updated my tables, created by CloudFormation, to On-demand. Now, when I try to update my Stack, I get this error:
One or more parameter values were invalid: Neither ReadCapacityUnits nor WriteCapacityUnits can be specified when BillingMode is PAY_PER_REQUEST
Is there a way to set DynamoDB Read/write capacity mode to On-demand on CloudFormation?
EDIT:
I've updated to On-demand on AWS Console.
EDIT 2:
My template:
DynamoDBUsersTable:
Type: AWS::DynamoDB::Table
Description: Users table
Properties:
TableName: !Sub ${StackName}-users-table
AttributeDefinitions:
- AttributeName: userId
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 10
WriteCapacityUnits: 10
Thank you.
You need to add BillingMode: PAY_PER_REQUEST to properties and remove ProvisionedThroughput both from table properties and from all GlobalSecondaryIndexes if they specified. So finally your template have to look like:
DynamoDBUsersTable:
Type: AWS::DynamoDB::Table
Description: Users table
Properties:
TableName: !Sub ${StackName}-users-table
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: userId
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH