Set up AWS API GW with a Typescript authorizer and logging
2022-04-19
Previous article
Introduction
A CloudFormation template to set up AWS API GW with a Typescript authorizer and logging
- The trick to use SAM deploy for Typescript:
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: true
Target: "es2020"
Sourcemap: true
EntryPoints:
- TargetServiceSUTAuthorizer.ts
And to invoke SAM with sam build --beta-features && sam deploy
- The trick to enable Cloudwatch logs on the API GW:
ApiGwAccountConfig:
Type: "AWS::ApiGateway::Account"
Properties:
CloudWatchRoleArn: !GetAtt "ApiGatewayLoggingRole.Arn"
ApiGatewayLoggingRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- "apigateway.amazonaws.com"
Action: "sts:AssumeRole"
Path: "/"
ManagedPolicyArns:
- !Sub "arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"
Here’s the full CloudFormation file:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
This stack creates the target-service-sut resources.
They are: An API GW with authorizer, and a microservice lambda that is called by the API GW
Parameters:
myVPC:
Type: String
Subnet1:
Type: String
Subnet2:
Type: String
Environment:
Type: String
BuildNumber:
Type: String
Branch:
Type: String
AudienceList:
Type: String
Globals:
Function:
Runtime: nodejs14.x
Tracing: Active
MemorySize: 1024
ReservedConcurrentExecutions: 1
Timeout: 2
VpcConfig:
SecurityGroupIds:
- !Ref TargetServiceSUTSecurityGroup
SubnetIds:
- !Ref Subnet1
- !Ref Subnet2
Environment:
Variables:
ENVIRONMENT: !Ref Environment
BUILD_NUMBER: !Ref BuildNumber
BRANCH: !Ref Branch
AUDIENCE_LIST: !Ref AudienceList
REGION: ${AWS::Region}
Resources:
ApiGwAccountConfig:
Type: "AWS::ApiGateway::Account"
Properties:
CloudWatchRoleArn: !GetAtt "ApiGatewayLoggingRole.Arn"
ApiGatewayLoggingRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- "apigateway.amazonaws.com"
Action: "sts:AssumeRole"
Path: "/"
ManagedPolicyArns:
- !Sub "arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"
TargetServiceSUTFunctionApi:
Type: AWS::Serverless::Api
Description: API GW fronting the TargetServiceSUT function
Properties:
StageName: Prod
Name: target-service-sut
Description: API GW fronting the TargetServiceSUT function
TracingEnabled: true
EndpointConfiguration:
Type: PRIVATE
Auth:
DefaultAuthorizer: LambdaRequestAuthorizer
ApiKeyRequired: false
Authorizers:
LambdaRequestAuthorizer:
FunctionArn: !GetAtt TargetServiceSUTAuthorizerFunction.Arn
FunctionPayloadType: REQUEST
Identity:
Headers:
- Authorization
ValidationExpression: Bearer.*
ReauthorizeEvery: 3600
ResourcePolicy:
CustomStatements:
[
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "execute-api:/Prod/GET/*"
}
]
UsagePlan:
CreateUsagePlan: PER_API
MethodSettings:
- LoggingLevel: INFO
ResourcePath: '/*'
HttpMethod: '*'
MetricsEnabled: 'true'
DataTraceEnabled: 'true'
TargetServiceSUTFunction:
Type: AWS::Serverless::Function
Description: Target Service SUT
Properties:
FunctionName: target-service-sut
Tracing: Active
CodeUri: target-service/src
Handler: app.lambdaHandler
Role: !GetAtt TargetServiceSUTFunctionExecutionRole.Arn
Events:
Healthcheck:
Type: Api
Properties:
RestApiId: !Ref TargetServiceSUTFunctionApi
Path: /sut
Method: get
TargetServiceSUTAuthorizerFunction:
Type: AWS::Serverless::Function
Description: API GW Authorizer function
Properties:
FunctionName: target-service-sut-authorizer
Tracing: Active
CodeUri: authorizer/src
Handler: TargetServiceSUTAuthorizer.authorize
Role: !GetAtt TargetServiceSUTAuthorizerFunctionExecutionRole.Arn
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: true
Target: "es2020"
Sourcemap: true
EntryPoints:
- TargetServiceSUTAuthorizer.ts
TargetServiceSUTFunctionExecutionRole:
Type: AWS::IAM::Role
Description: The execution role of the function
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action:
- "sts:AssumeRole"
RoleName: TargetServiceSUTFunctionExecutionRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
- arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess
- arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- arn:aws:iam::aws:policy/service-role/AWSLambdaRole
- !Ref TargetServiceSUTFunctionEC2NetworkPolicy
- !Ref TargetServiceSUTFunctionSSMPolicy
TargetServiceSUTFunctionSSMPolicy:
Type: AWS::IAM::ManagedPolicy
Description: Policy allowing the lambda to access SSM
Properties:
ManagedPolicyName: !Sub "TargetServiceSUTFunctionAllowSSMOperations"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: TargetServiceSUTFunctionSSMPolicy
Effect: Allow
Action:
- ssm:GetParameter
Resource: "*"
TargetServiceSUTFunctionEC2NetworkPolicy:
Type: AWS::IAM::ManagedPolicy
Description: Policy allowing the lambda to be attached to our VPC
Properties:
ManagedPolicyName: !Sub "TargetServiceSUTFunctionAllowEC2NetworkOperations"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: TargetServiceSUTFunctionAllowEC2NetworkPolicy
Effect: Allow
Action:
- ec2:CreateNetworkInterface
- ec2:DeleteNetworkInterfacePermission
- ec2:DescribeNetworkInterfaces
- ec2:CreateNetworkInterfacePermission
- ec2:ResetNetworkInterfaceAttribute
- ec2:ModifyNetworkInterfaceAttribute
- ec2:DeleteNetworkInterface
- ec2:AttachNetworkInterface
Resource: "*"
TargetServiceSUTSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "TargetServiceSUT SG"
GroupName: TargetServiceSUTSecurityGroup
VpcId: !Ref myVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: -1
FromPort: -1
CidrIp: 0.0.0.0/0
TargetServiceSUTAuthorizerFunctionExecutionRole:
Type: AWS::IAM::Role
Description: The execution role of the function
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
- "apigateway.amazonaws.com"
Action:
- "sts:AssumeRole"
RoleName: TargetServiceSUTAuthorizerFunctionExecutionRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
- arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess
- arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- arn:aws:iam::aws:policy/service-role/AWSLambdaRole
- !Ref TargetServiceSUTFunctionEC2NetworkPolicy
Outputs:
TargetServiceSUTFunctionApi:
Description: "API Gateway endpoint URL for Prod stage for a function"
Value: !Sub "https://${TargetServiceSUTFunctionApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/target-service-sut"
Happy coding!
Previous article
Filed under
API GW
AWS
- Programming ESP32 using MQTT with AWS and FreeRTOS
- Quick AWS IoT Setup and test
- Use AWS CodePipline to execute CloudFormation templates
- Use GitHub Actions to deploy your SPA hosted on Amazon S3
- Use an AWS CloudFormation script to create and host an SPA on S3 with SSL and apex/subdomain redirection using CloudFront
- Writing an Alexa skill using Ruby and AWS Lambda (Part 0)
CloudFormation
CloudWatch
Lambda
Other Tags
API GW
AWS
- Programming ESP32 using MQTT with AWS and FreeRTOS
- Quick AWS IoT Setup and test
- Set up AWS API GW with a Typescript authorizer and logging
- Use AWS CodePipline to execute CloudFormation templates
- Use GitHub Actions to deploy your SPA hosted on Amazon S3
- Use an AWS CloudFormation script to create and host an SPA on S3 with SSL and apex/subdomain redirection using CloudFront
- Writing an Alexa skill using Ruby and AWS Lambda (Part 0)
ActiveRecord
Agile
- A review of software development metrics
- Agile programme management brief
- An alternative to current product development metrics
- An alternative to the current product development governance model
- Command & Control Management - The Party Killer
- Document Driven Development
- Inceptions revisited
- Managing multiple stakeholders
- Returns Driven Development
- The tip of the (good) iceberg
Alexa
Analysis
Ansible
BDD
BLE
C
CAB
CloudFormation
- Set up AWS API GW with a Typescript authorizer and logging
- Use AWS CodePipline to execute CloudFormation templates
- Use GitHub Actions to deploy your SPA hosted on Amazon S3
- Use an AWS CloudFormation script to create and host an SPA on S3 with SSL and apex/subdomain redirection using CloudFront
- Writing an Alexa skill using Ruby and AWS Lambda (Part 0)
CloudFront
CloudWatch
Cross-compile
Cucumber
DevOps
Devops
DotNet
Embedded
Fitbit
GNU
GitHub Actions
Governance
How-to
Inception
IoT
Javascript
Jest
Lambda
Mac OS X
- Bluetooth Low Energy (BLE) Implementing a peripheral on Mac OS X
- Cross-compiling for Raspberry Pi on a Mac and debugging using NetBeans
- Drobo will not mount in Finder
- Quickie - ssh dynamic port forwarding to avoid unsecured public networks
- Remote compilation, execution and debugging Raspberry Pi from a Mac using NetBeans
- Weekend warrior - MacRuby and rSpec, Mac OS X Lion, Xcode V4.3.2
MacRuby
Metrics
MySQL
NetBeans
Objective-C
PMO
Product Management
- A path to accelerating value realization
- A review of software development metrics
- Agile programme management brief
- An alternative to current product development metrics
- An alternative to the current product development governance model
- Express initiative kickoff formula
- Inceptions revisited
- Managing multiple stakeholders
- Plan for value delivery
- Pre-prod activity - Futurespective
- Value Stream Mapping
- When planning, it's not only about relative complexity
Programme management
Project Management
- A path to accelerating value realization
- A review of software development metrics
- Agile programme management brief
- An alternative to current product development metrics
- An alternative to the current product development governance model
- Command & Control Management - The Party Killer
- Express initiative kickoff formula
- Inceptions revisited
- Managing multiple stakeholders
- Plan for value delivery
- Pre-prod activity - Futurespective
- Value Stream Mapping
- When planning, it's not only about relative complexity
Quality Assurance
Rails
Raspberry Pi
Remote compilation
Remote debugging
Remote execution
Risk Assessment
Route 53
Ruby
- Alexa on Rails - how to develop and test Alexa skills using Rails
- Arduino programming using Ruby, Cucumber & rSpec
- How to reconnect to a database when its connection was lost
- Oh, the places you'll go...
- Quick AWS IoT Setup and test
- Weekend warrior - MacRuby and rSpec, Mac OS X Lion, Xcode V4.3.2
- Writing an Alexa skill using Ruby and AWS Lambda (Part 0)