AWSTemplateFormatVersion: '2010-09-09' Description: >- Serverless API for IoT Dashboard: Lambda (Go) + API Gateway HTTP API + Cognito JWT Authorizer. Parameters: TableName: Type: String Description: DynamoDB table name that contains IoT readings (existing table) LambdaS3Bucket: Type: String Description: S3 bucket that contains the Lambda deployment zip LambdaS3Key: Type: String Description: S3 key (object name) for the Lambda deployment zip CognitoUserPoolId: Type: String Description: Cognito User Pool ID (provide via ImportValue from iot-cognito or parameter) CognitoUserPoolClientId: Type: String Description: Cognito App Client ID (provide via ImportValue from iot-cognito or parameter) Resources: IotLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "iot-lambda-dashboardApi-ExecRole-${AWS::StackName}" AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: IotLambdaDynamoDBRead PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - dynamodb:Scan - dynamodb:Query - dynamodb:GetItem Resource: !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${TableName}" IotLambdaFunction: Type: AWS::Lambda::Function Properties: FunctionName: iot-lambda-dashboardApi Runtime: go1.x Handler: main Role: !GetAtt IotLambdaExecutionRole.Arn Code: S3Bucket: !Ref LambdaS3Bucket S3Key: !Ref LambdaS3Key Environment: Variables: TABLE_NAME: !Ref TableName Timeout: 30 MemorySize: 128 IotHttpApi: Type: AWS::ApiGatewayV2::Api Properties: Name: iot-lambda-dashboardApi-http ProtocolType: HTTP IotHttpApiAuthorizer: Type: AWS::ApiGatewayV2::Authorizer Properties: ApiId: !Ref IotHttpApi Name: CognitoJwtAuthorizer AuthorizerType: JWT IdentitySource: - "$request.header.Authorization" JwtConfiguration: Issuer: !Sub "https://cognito-idp.${AWS::Region}.amazonaws.com/${CognitoUserPoolId}" Audience: - !Ref CognitoUserPoolClientId LambdaIntegration: Type: AWS::ApiGatewayV2::Integration Properties: ApiId: !Ref IotHttpApi IntegrationType: AWS_PROXY IntegrationUri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${IotLambdaFunction.Arn}/invocations" PayloadFormatVersion: "2.0" ReadingsRoute: Type: AWS::ApiGatewayV2::Route Properties: ApiId: !Ref IotHttpApi RouteKey: "GET /readings" AuthorizationType: JWT AuthorizerId: !Ref IotHttpApiAuthorizer Target: !Sub "integrations/${LambdaIntegration}" ApiStage: Type: AWS::ApiGatewayV2::Stage Properties: ApiId: !Ref IotHttpApi StageName: $default AutoDeploy: true LambdaInvokePermission: Type: AWS::Lambda::Permission Properties: FunctionName: !Ref IotLambdaFunction Action: lambda:InvokeFunction Principal: apigateway.amazonaws.com SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${IotHttpApi}/*/GET/readings" Outputs: ApiEndpoint: Description: HTTP API endpoint URL Value: !Sub "https://${IotHttpApi}.execute-api.${AWS::Region}.amazonaws.com/" Export: Name: !Sub "${AWS::StackName}-ApiEndpoint" LambdaFunctionArn: Description: Lambda function ARN Value: !GetAtt IotLambdaFunction.Arn Export: Name: !Sub "${AWS::StackName}-LambdaFunctionArn" TableNameOutput: Description: DynamoDB table name used by the Lambda Value: !Ref TableName Export: Name: !Sub "${AWS::StackName}-TableName"