This doc if focused on building authorization api that only users with cognito token can access the api and perform CRUD operations.
- Python
- SAM
- Aws account
jksjdlkskd
- Initialize a new SAM application. Use the
sam init
command to initialize a new SAM application. This will create a directory for your application and download a default template.
projectName
├── event
├── events.json
├── hello_world
├── _init_.py
├── app.py
├── requirements.txt
├── test
├── __init__.py
├── samconfig.toml
├── README.md
└── template.yaml
Now Lets go ahead and modify the default application to accomplish our target.
Modify the hello_world folder to src. you can delete any other folder and file except samconfig.toml and template.yaml.
The final folder structure
projectName
├── src
├── app.py
├── requirements.txt
├── samconfig.toml
├── README.md
└── template.yaml
Open you app.py and import the neccessary libraries.
import boto3
import json
from boto3.dynamodb.conditions import Key, Attr
import random
-
Boto3 is the AWS SDK for Python. It provides a high-level, object-oriented API for interacting with AWS services.
-
Create a lambda handler function that is used to create items on dynamodb
def createWeather(event, context): print(event) print(context) Weather = json.loads(event['body'])['Weather'] print(Weather) id = str(random.randrange(100, 999)) dynamodb_client.put_item(TableName='WeatherData', Item={'id': {'S': id}, 'Weather': {'S': Weather}}) return { 'statusCode': 200, 'body': 'Successfully inserted data!' } ```
You can print out the event and the context to see their contents. (To see this when the api is invoke, open your AWS account and search for lambda, open the lambda function with the corresponding createWeather
, Click on monitor
and click on Cloudwatch
)
- Save your file and open
template.yaml
file
Resources
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
LambdaFunction:
Type: AWS::Serverless::Function
Description: 'Lambda function inserts data into DynamoDB table'
Properties:
FunctionName: WeatherFunction
Handler: app.createWeather
Runtime: python3.7
CodeUri: src/
Policies:
DynamoDBCrudPolicy:
TableName: !Ref DynamoDBTable
Events:
ApiEvent:
Type: Api
Properties:
Path: /
Method: POST
- Congifuge dynamodb table name by adding the code snippet bellow.
DynamoDBTable:
Type: AWS::Serverless::SimpleTable
Properties:
TableName: WeatherData
- Repeat
step 2 and 3
above to add other lambda handlers - Lambda handler to get items from dynamodb
def getWeather(event, context):
table = dynamodb.Table('WeatherData')
response = table.scan(TableName='WeatherData')
print(response)
return {
'statusCode': 200,
'body': json.dumps(response['Items'])
}
- Lambda handler to delete an item from dynamodb
def DeleteWeather(event, context):
table = dynamodb.Table('WeatherData')
key = json.loads(event['body'])['id']
table.delete_item(
Key = {
"id": key
}
)
return {
'statusCode' : 200,
'body': "Delete Succeessfull"
}
- Lambda handler to delete an item from dynamodb
def updateWeather(event, context):
Weather = json.loads(event['body'])['weather']
key = json.loads(event['body'])['id']
dynamodb_client.put_item(TableName='WeatherData', Item={'id': {'S': key}, 'Weather': {'S': Weather}})
return {
'statusCode': 200,
'body': 'Data Updated Successfully!'
}
-
Adjusting the the
template.yaml
by adding the corresponding methonds and routes.GetLambdaFunction: Type: AWS::Serverless::Function Description: 'Lambda function inserts data into DynamoDB table' Properties: FunctionName: GetWeatherFunction Handler: app.getWeather Runtime: python3.7 CodeUri: src/ Policies: DynamoDBCrudPolicy: TableName: !Ref DynamoDBTable Events: ApiEvent: Type: Api Properties: Path: / Method: GET DeleteLambdaFunction: Type: AWS::Serverless::Function Description: 'Lambda function inserts data into DynamoDB table' Properties: FunctionName: DeleteWeatherFunction Handler: app.DeleteWeather Runtime: python3.7 CodeUri: src/ Policies: DynamoDBCrudPolicy: TableName: !Ref DynamoDBTable Events: ApiEvent: Type: Api Properties: Path: / Method: DELETE UpdateLambdaFunction: Type: AWS::Serverless::Function Description: 'Lambda function inserts data into DynamoDB table' Properties: FunctionName: UpdateWeatherFunction Handler: app.updateWeather Runtime: python3.7 CodeUri: src/ Policies: DynamoDBCrudPolicy: TableName: !Ref DynamoDBTable Events: ApiEvent: Type: Api Properties: Path: / Method: PUT
The final template.yaml file
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Serverless patterns - Amazon API Gateway to AWS Lambda to Amazon DynamoDB
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
LambdaFunction:
Type: AWS::Serverless::Function
Description: 'Lambda function inserts data into DynamoDB table'
Properties:
FunctionName: WeatherFunction
Handler: index.lambda_handler
Runtime: python3.7
CodeUri: src/
Policies:
DynamoDBCrudPolicy:
TableName: !Ref DynamoDBTable
Events:
ApiEvent:
Type: Api
Properties:
Path: /
Method: POST
GetLambdaFunction:
Type: AWS::Serverless::Function
Description: 'Lambda function inserts data into DynamoDB table'
Properties:
FunctionName: GetWeatherFunction
Handler: index.getWeather
Runtime: python3.7
CodeUri: src/
Policies:
DynamoDBCrudPolicy:
TableName: !Ref DynamoDBTable
Events:
ApiEvent:
Type: Api
Properties:
Path: /
Method: GET
DeleteLambdaFunction:
Type: AWS::Serverless::Function
Description: 'Lambda function inserts data into DynamoDB table'
Properties:
FunctionName: DeleteWeatherFunction
Handler: index.DeleteWeather
Runtime: python3.7
CodeUri: src/
Policies:
DynamoDBCrudPolicy:
TableName: !Ref DynamoDBTable
Events:
ApiEvent:
Type: Api
Properties:
Path: /
Method: DELETE
UpdateLambdaFunction:
Type: AWS::Serverless::Function
Description: 'Lambda function inserts data into DynamoDB table'
Properties:
FunctionName: UpdateWeatherFunction
Handler: index.updateWeather
Runtime: python3.7
CodeUri: src/
Policies:
DynamoDBCrudPolicy:
TableName: !Ref DynamoDBTable
Events:
ApiEvent:
Type: Api
Properties:
Path: /
Method: PUT
DynamoDBTable:
Type: AWS::Serverless::SimpleTable
Properties:
TableName: WeatherData
Outputs:
EndpointUrl:
Description: 'HTTP REST endpoint URL'
Value: !Sub 'https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod'
- Build your application. Use the
sam build
command to build your application. This will create a ZIP file that contains your application code and dependencies. - Deploy your application. Use the
sam deploy --guided
command to deploy your application. This will create the AWS resources defined in your template and deploy your application code.
Open postman and send a post request to your end point.
Open postman and send a post request to your end point.
Currently, The endpoints we have can be accessed by any body and that is not what we want. Lets add Authorization such that without the Cognito token, you cannot access our API's
To Add authorization with cognito follow the following steps.
- Open your aws console and Create cognito user pool
- Configure your
template.yaml
file - Add the below code to
MyApi
in theresources
in youryaml file
Cors: "'*'"
Auth:
DefaultAuthorizer: CognitoAuthorizer
Authorizers:
CognitoAuthorizer:
UserPoolArn: yourUserPoolArn
Resulting code after adding the snippet above
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
Cors: "'*'"
Auth:
DefaultAuthorizer: CognitoAuthorizer
Authorizers:
CognitoAuthorizer:
UserPoolArn: yourUserPoolArn
- Add user cognito properties to the
resources
int theyaml file
MyCognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: test1
Policies:
PasswordPolicy:
MinimumLength: 8
UsernameAttributes:
- email
Schema:
- AttributeDataType: String
Name: email
Required: false
MyCognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
UserPoolId: yourUserPoolId
ClientName: YourClientName
GenerateSecret: false
After Adding the above code, your final yaml file will look like this.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Serverless patterns - Amazon API Gateway to AWS Lambda to Amazon DynamoDB
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
Cors: "'*'"
Auth:
DefaultAuthorizer: CognitoAuthorizer
Authorizers:
CognitoAuthorizer:
UserPoolArn: YourUserPoolArn
LambdaFunction:
Type: AWS::Serverless::Function
Description: 'Lambda function inserts data into DynamoDB table'
Properties:
FunctionName: WeatherFunction
Handler: index.lambda_handler
Runtime: python3.7
CodeUri: src/
Policies:
DynamoDBCrudPolicy:
TableName: !Ref DynamoDBTable
Events:
ApiEvent:
Type: Api
Properties:
Path: /
Method: POST
RestApiId: !Ref MyApi
GetLambdaFunction:
Type: AWS::Serverless::Function
Description: 'Lambda function inserts data into DynamoDB table'
Properties:
FunctionName: GetWeatherFunction
Handler: index.getWeather
Runtime: python3.7
CodeUri: src/
Policies:
DynamoDBCrudPolicy:
TableName: !Ref DynamoDBTable
Events:
ApiEvent:
Type: Api
Properties:
Path: /
Method: GET
RestApiId: !Ref MyApi
DeleteLambdaFunction:
Type: AWS::Serverless::Function
Description: 'Lambda function inserts data into DynamoDB table'
Properties:
FunctionName: DeleteWeatherFunction
Handler: index.DeleteWeather
Runtime: python3.7
CodeUri: src/
Policies:
DynamoDBCrudPolicy:
TableName: !Ref DynamoDBTable
Events:
ApiEvent:
Type: Api
Properties:
Path: /
Method: DELETE
RestApiId: !Ref MyApi
UpdateLambdaFunction:
Type: AWS::Serverless::Function
Description: 'Lambda function inserts data into DynamoDB table'
Properties:
FunctionName: UpdateWeatherFunction
Handler: index.updateWeather
Runtime: python3.7
CodeUri: src/
Policies:
DynamoDBCrudPolicy:
TableName: !Ref DynamoDBTable
Events:
ApiEvent:
Type: Api
Properties:
RestApiId: !Ref MyApi
Path: /
Method: PUT
MyCognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: YourUserPoolName
Policies:
PasswordPolicy:
MinimumLength: 8
UsernameAttributes:
- email
Schema:
- AttributeDataType: String
Name: email
Required: false
MyCognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
UserPoolId: YourUserPoolId
ClientName: YourClientName
GenerateSecret: false
DynamoDBTable:
Type: AWS::Serverless::SimpleTable
Properties:
TableName: WeatherData
Run sam deploy
to deploy your recent changes.
if you try to access your api again
To be able to access the api, do the following in postman
click on authorization
Now Click on the Generate
Login Screen pops up. Sign up with your email
Another screen with pop that contains the IdToken and AccessToken
Copy the IdToken and change the type
to Bearee token
Paste the copied token on the space for Token
Once you are done you can click on send.
Open postman and send a post request to your end point.
To Know more about cognito, click here
Reference
👍👏👍