![](/img/trans.png)
[英]How to output a custom domain endpoint configuration url in Terraform for Apigatewayv2?
[英]ApiGatewayV2 how to set the "Execution Role" via CloudFormation
我正在尝试通过 API 网关设置 websockets。 当我尝试建立连接时,我在 CloudWatch 日志中收到错误“ Execution failed due to configuration error: Invalid permissions on Lambda function
”。
我在我的 CloudFormation 中创建了AWS::IAM::Role
资源,并将其作为Role
附加到我的AWS::Lambda::Function
资源中。 但我想我需要将它附加到AWS::ApiGatewayV2::Integration
,但我不知道该怎么做。
当我查看 AWS 控制台时,我发现没有选择执行角色:
但我看不到如何在 CloudFormation 中添加角色。 我错过了什么?
完整的 CloudFormation:
---
AWSTemplateFormatVersion: '2010-09-09'
Description: Website S3 Hosted, API Gateway Backend
Parameters:
DomainName:
Type: String
Description: The DNS name of an Amazon Route 53 hosted zone e.g. server.com
AllowedPattern: '(?!-)[a-zA-Z0-9-.]{1,63}(?<!-)'
ConstraintDescription: must be a valid DNS zone name.
DiscordToken:
Type: String
DiscordChannelID:
Type: String
HostedZoneId:
Type: String
SSLARN:
Description: Cloudfront SSL ARN (us-east-1)
Type: String
Mappings:
APIRegionMap:
us-east-1:
APIHostedZoneId: Z1UJRXOUMOOFQ8
us-east-2:
APIHostedZoneId: ZOJJZC49E0EPZ
us-west-1:
APIHostedZoneId: Z2MUQ32089INYE
us-west-2:
APIHostedZoneId: Z2OJLYMUO9EFXC
Resources:
# SSL
SSL:
Type: AWS::CertificateManager::Certificate
Properties:
DomainName: !Ref DomainName
DomainValidationOptions:
- DomainName: !Join ['.', ['api', !Ref DomainName]]
HostedZoneId: !Ref HostedZoneId
SubjectAlternativeNames:
- !Join ['.', ['*', !Ref DomainName]]
ValidationMethod: DNS
# DynamoDB Tables
SocketTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
-
AttributeName: connectionId
AttributeType: S
KeySchema:
-
AttributeName: connectionId
KeyType: HASH
BillingMode: PAY_PER_REQUEST
TableName: clients
# Lambda Items
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: '/'
Policies:
- PolicyName: execution
PolicyDocument:
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: '*'
- Effect: Allow
Action:
- s3:GetObject
- s3:PutObject
- s3:ListBucket
Resource: '*'
Resource: '*'
- Effect: Allow
Action:
- lambda:InvokeFunction
Resource: '*'
- Effect: Allow
Action:
- execute-api:Invoke
- execute-api:ManageConnections
Resource: '*'
LambdaFunctionSocketServer:
Type: AWS::Lambda::Function
Properties:
Code:
ZipFile: exports.handler = function (event, context, callback) { callback(null, event); };
Handler: index.handler
MemorySize: 1024
Role: !GetAtt LambdaExecutionRole.Arn
Runtime: nodejs12.x
Timeout: 900
Environment:
Variables:
DBTable: !Ref SocketTable
DiscordToken: !Ref DiscordToken
DiscordChannelID: !Ref DiscordChannelID
# API Gateway Items
WebSocketLoggingRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: apigateway.amazonaws.com
Action:
- sts:AssumeRole
Path: '/'
Policies:
- PolicyName: execution
PolicyDocument:
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:DescribeLogGroups
- logs:DescribeLogStreams
- logs:PutLogEvents
- logs:GetLogEvents
- logs:FilterLogEvents
Resource: '*'
WebSocketAPI:
Type: AWS::ApiGatewayV2::Api
Properties:
Name: !Join ['-', !Split ['.', !Join ['.', ['ws', !Ref DomainName]]]]
ProtocolType: WEBSOCKET
RouteSelectionExpression: "$request.body.action"
WebSocketInteg:
Type: AWS::ApiGatewayV2::Integration
DependsOn:
- LambdaFunctionSocketServer
Properties:
ApiId: !Ref WebSocketAPI
Description: WebSocket Integration
IntegrationType: AWS_PROXY
IntegrationUri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunctionSocketServer.Arn}/invocations'
WebSocketConnectRoute:
Type: AWS::ApiGatewayV2::Route
Properties:
ApiId: !Ref WebSocketAPI
RouteKey: $connect
AuthorizationType: NONE
OperationName: ConnectRoute
Target: !Join ['/', ['integrations', !Ref WebSocketInteg]]
WebSocketDisconnectRoute:
Type: AWS::ApiGatewayV2::Route
Properties:
ApiId: !Ref WebSocketAPI
RouteKey: $disconnect
AuthorizationType: NONE
OperationName: DisconnectRoute
Target: !Join ['/', ['integrations', !Ref WebSocketInteg]]
WebSocketSendRoute:
Type: AWS::ApiGatewayV2::Route
Properties:
ApiId: !Ref WebSocketAPI
RouteKey: sendmessage
AuthorizationType: NONE
OperationName: SendRoute
Target: !Join ['/', ['integrations', !Ref WebSocketInteg]]
WebSocketDeployment:
Type: AWS::ApiGatewayV2::Deployment
DependsOn:
- WebSocketConnectRoute
- WebSocketSendRoute
- WebSocketDisconnectRoute
Properties:
ApiId: !Ref WebSocketAPI
WebSocketLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Join ['.', ['ws', !Ref DomainName]]
RetentionInDays: 3
WebSocketStage:
Type: AWS::ApiGatewayV2::Stage
Properties:
StageName: Prod
Description: Prod Stage
DeploymentId: !Ref WebSocketDeployment
ApiId: !Ref WebSocketAPI
WebSocketDomain:
Type: 'AWS::ApiGatewayV2::DomainName'
Properties:
DomainName: !Join ['.', ['ws', !Ref DomainName]]
DomainNameConfigurations:
- EndpointType: REGIONAL
CertificateArn: !Ref SSL
WebSocketMapping:
Type: 'AWS::ApiGatewayV2::ApiMapping'
DependsOn:
- WebSocketDeployment
Properties:
DomainName: !Ref WebSocketDomain
ApiId: !Ref WebSocketAPI
Stage: !Ref WebSocketStage
# Website items
WebsiteBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Delete
DependsOn:
- WebSocketDeployment
Properties:
BucketName:
Ref: DomainName
AccessControl: PublicRead
WebsiteConfiguration:
IndexDocument: index.html
ErrorDocument: 404.html
Tags:
- Key: Name
Value: !Join ['_', ['WebsiteBucket', !Ref 'AWS::StackName']]
- Key: Domain
Value: !Ref DomainName
DeletionPolicy: Retain
WWWBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Delete
DependsOn:
- WebSocketDeployment
Properties:
BucketName: !Join ['.', ['www', !Ref DomainName]]
AccessControl: PublicRead
WebsiteConfiguration:
RedirectAllRequestsTo:
HostName: !Ref WebsiteBucket
Tags:
- Key: Name
Value: !Join ['_', ['WWWBucket', !Ref 'AWS::StackName']]
- Key: Domain
Value: !Ref DomainName
ImageBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Delete
DependsOn:
- WebSocketDeployment
Properties:
BucketName: !Join ['.', ['images', !Ref DomainName]]
AccessControl: Private
Tags:
- Key: Name
Value: !Join ['_', ['ImageBucket', !Ref 'AWS::StackName']]
- Key: Domain
Value: !Ref DomainName
DeletionPolicy: Retain
WebsiteBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref WebsiteBucket
PolicyDocument:
Statement:
- Action:
- s3:GetObject
Effect: Allow
Resource: !Join ['', ['arn:aws:s3:::', !Ref WebsiteBucket, '/*']]
Principal: '*'
WWWBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref WWWBucket
PolicyDocument:
Statement:
- Action:
- s3:GetObject
Effect: Allow
Resource: !Join ['', ['arn:aws:s3:::', !Ref WWWBucket, '/*']]
Principal: '*'
WebsiteCloudfront:
Type: AWS::CloudFront::Distribution
DependsOn:
- WebsiteBucket
Properties:
DistributionConfig:
Comment: !Ref DomainName
Origins:
- DomainName: !Select [2, !Split ["/", !GetAtt WebsiteBucket.WebsiteURL]]
Id: S3Origin
CustomOriginConfig:
HTTPPort: '80'
HTTPSPort: '443'
OriginProtocolPolicy: http-only
Enabled: true
HttpVersion: 'http2'
DefaultRootObject: index.html
Aliases:
- !Ref DomainName
- !Join ['.', ['www', !Ref DomainName]]
DefaultCacheBehavior:
DefaultTTL: 60
MaxTTL: 60
MinTTL: 60
AllowedMethods:
- GET
- HEAD
Compress: true
TargetOriginId: S3Origin
ForwardedValues:
QueryString: true
Cookies:
Forward: none
ViewerProtocolPolicy: redirect-to-https
PriceClass: PriceClass_All
ViewerCertificate:
AcmCertificateArn: !Ref SSLARN
SslSupportMethod: sni-only
CustomErrorResponses:
- ErrorCode: 404
ResponseCode: 200
ResponsePagePath: /index.html
CloudfrontDNSRecord:
Type: AWS::Route53::RecordSetGroup
Properties:
HostedZoneName:
Fn::Join: ['', [!Ref DomainName, '.']]
Comment: Cloudfront zone records.
RecordSets:
- Name: !Ref DomainName
Type: A
AliasTarget:
HostedZoneId: Z2FDTNDATAQYW2
DNSName: !GetAtt [WebsiteCloudfront, DomainName]
- Name: !Join ['.', ['www', !Ref DomainName]]
Type: A
AliasTarget:
HostedZoneId: Z2FDTNDATAQYW2
DNSName: !GetAtt [WebsiteCloudfront, DomainName]
WebsocketDNSRecord:
Type: AWS::Route53::RecordSetGroup
Properties:
HostedZoneName:
Fn::Join: ['', [!Ref DomainName, '.']]
Comment: Websocket zone records.
RecordSets:
- Name: !Join ['.', ['ws', !Ref DomainName]]
Type: A
AliasTarget:
HostedZoneId:
Fn::FindInMap:
- APIRegionMap
- Ref: AWS::Region
- APIHostedZoneId
DNSName: !GetAtt [WebSocketDomain, RegionalDomainName]
Outputs:
S3WebsiteURL:
Value: !GetAtt WebsiteBucket.WebsiteURL
Description: URL for website hosted on S3
我认为您只需要添加一个AWS::Lambda::Permission
以允许网关调用 function。
OnConnectPermission:
Type: AWS::Lambda::Permission
DependsOn:
- WebSocketAPI
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref LambdaFunctionSocketServer
Principal: apigateway.amazonaws.com
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.