AWS SAM AWS::ApiGatewayV2::Stage AccessLogSetting Property validation failure - aws-cloudformation

Unfortunately I cannot get AWS WebSocket logging to work. Property validation failure: [Encountered unsupported properties in {/}: [AccessLogSetting]]. Any help highly appreciated.
Stage:
Type: AWS::ApiGatewayV2::Stage
Properties:
StageName: Prod
Description: Prod Stage
DeploymentId: !Ref Deployment
ApiId: !Ref TriviaWebSocket
AccessLogSetting:
DestinationArn: !GetAtt GwLogGroup.Arn
Format: '{"requestTime":"$context.requestTime","requestId":"$context.requestId"}'
GwLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: /aws/apigateway/gw-ws-loggroup
RetentionInDays: 7

Related

how to pass bucket/key name to fargate job via a cloudwatch event trigger on s3 object creation event?

I have create a fargate task and trying to trigger it via s3 object creation event ( see sample below) via cloudformation.as it cannot trigger it directly, i have created a cloudwatchevent. I am trying to pass the bucket and obj name to my fargate task code . doing some research, i came across -> InputTransformer, but i'm not sure how to pass the value of my bucket and key name and how to read it in my python code. any help will be appreciated.
AWSTemplateFormatVersion: 2010-09-09
Description: An example CloudFormation template for Fargate.
Parameters:
VPC:
Type: AWS::EC2::VPC::Id
SubnetA:
Type: AWS::EC2::Subnet::Id
SubnetB:
Type: AWS::EC2::Subnet::Id
Image:
Type: String
Default: 123456789012.dkr.ecr.region.amazonaws.com/image:tag
Resources:
mybucket:
Properties:
BucketName: 'mytestbucket-us'
cloudwatchEvent:
Type: AWS::Events::Rule
Properties:
EventPattern:
source:
- aws.s3
detail:
eventSource:
- s3.amazonaws.com
eventName:
- PutObject
- CompleteMultipartUpload
requestParameters:
bucketName:
- !Ref mybucket
Targets:
- Id: my-fargate-task
Arn: myclusterArn
RoleArn: myinvocationrolearn
Input:
'Fn::Sub':
- >-
{"containerOverrides": [{"name":"somecontainer"]}
EcsParameters:
TaskDefinition:
LaunchType: 'FARGATE'
...
NetworkConfiguration:
...
Cluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Join ['', [!Ref ServiceName, Cluster]]
TaskDefinition:
Type: AWS::ECS::TaskDefinition
DependsOn: LogGroup
Properties:
Family: !Join ['', [!Ref ServiceName, TaskDefinition]]
NetworkMode: awsvpc
RequiresCompatibilities:
- FARGATE
Cpu: 256
Memory: 2GB
ExecutionRoleArn: !Ref ExecutionRole
TaskRoleArn: !Ref TaskRole
ContainerDefinitions:
- Name: !Ref ServiceName
Image: !Ref Image
# A role needed by ECS
ExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Join ['', [!Ref ServiceName, ExecutionRole]]
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: 'sts:AssumeRole'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy'
# A role for the containers
TaskRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Join ['', [!Ref ServiceName, TaskRole]]
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: 'sts:AssumeRole'
You would use a CloudWatch Event Input Transformer to extract the data you need from the event, and pass that data to the ECS task as environment variable(s) in the target's ContainerOverrides. I don't use CloudFormation, but here's an example using Terraform.
You can't. CloudWatch events do not pass data to ECS jobs. You need to develop your own mechanism for that. For example, trigger lambda first, store event in S3 Parameter Store or DynamoDB, and then invoke your ECS job which will get stored data.

Getting Fn::GetAtt error in the AWS SAM template

I have declared the SNS topic and Subscription like below in my AWS Serverless Application Model template :-
MyTopic:
Type: AWS::SNS::Topic
Properties:
DisplayName: !Sub 'test-${Environment}-${AWS::AccountId}-${AWS::Region}'
Tags:
- Key: Environment
Value: !FindInMap [Environment, FullForm, !Ref Environment]
TopicName: !Sub 'test-${Environment}-${AWS::AccountId}-${AWS::Region}'
MySubscription:
Type: AWS::SNS::Subscription
Properties:
Endpoint: !Ref SubscriptionEndPoint
Protocol: !Ref SubscriptionProtocol
Region: !Ref 'AWS::Region'
TopicArn: !Ref MyTopic
And then using the SNS Topic ARN in my Lambda function's environment as following in the same template file :-
MyLambda:
Type: AWS::Serverless::Function
Properties:
Environment:
Variables:
RUNTIME_SNS_TOPIC_ARN: !GetAtt MyTopic.Arn
Outputs (in SAM template):-
MyTopic:
Description: SNS Topic for the Ingest to send notification to
Export:
Name: !Sub
- ${ExportPrefix_}:${AWS::Region}:MyTopic
- ExportPrefix_: !If
- HasExportPrefix
- !Join ['-', [!Ref ExportPrefix, !Ref Environment]]
- !Join ['-', [!Select [0, !Split ["-", !Ref "AWS::StackName"]], !Ref Environment]]
Value: !Sub "${MyTopic.Arn}:${MyTopic.Version.Version}"
MySubscription:
Description: Subscription to get messages from a topic
Export:
Name: !Sub
- ${ExportPrefix_}:${AWS::Region}:MySubscription
- ExportPrefix_: !If
- HasExportPrefix
- !Join ['-', [!Ref ExportPrefix, !Ref Environment]]
- !Join ['-', [!Select [0, !Split ["-", !Ref "AWS::StackName"]], !Ref Environment]]
Value: !Sub "${MySubscription.Arn}:${MySubscription.Version.Version}"
However, I'm getting following error :-
13:30:30 Error: Failed to create changeset for the stack: my-stack, ex: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state Status: FAILED. Reason: Template error: resource MyTopic does not support attribute type Arn in Fn::GetAtt
An AWS::SNS:Topic returns the ARN when you use Ref
Check out the Docs on the return values.
Try with
MyLambda:
Type: AWS::Serverless::Function
Properties:
Environment:
Variables:
RUNTIME_SNS_TOPIC_ARN: !Ref MyTopic # Using !Ref
Recommend trying the CloudFormation Linter in VSCode to see some of these errors inline while authoring templates:
[cfn-lint] E1010: Invalid GetAtt MyTopic.Arn for resource MyLambda
[cfn-lint] E1019: Parameter MyTopic.Arn for Fn::Sub not found at Outputs/MyTopic/Value/Fn::Sub
[cfn-lint] E1019: Parameter MyTopic.Version.Version for Fn::Sub not found at Outputs/MyTopic/Value/Fn::Sub
[cfn-lint] E1019: Parameter MySubscription.Arn for Fn::Sub not found at Outputs/MySubscription/Value/Fn::Sub
[cfn-lint] E1019: Parameter MySubscription.Version.Version for Fn::Sub not found at Outputs/MySubscription/Value/Fn::Sub
It'll also point out that Value needs to be indented less in the Outputs
AWS::SNS::Topic return values
AWS::SNS::Subscription

SAM API Gateway with Cloudformation WAFRegional

To secure our API, I'm trying to deploy a WAFRegional with a RateBasedRule. The API Gateway is located in a SAM template wherein I have also a nested stack for the child template holding the WAFRegional configurations. The child template for the WAFRegional configuration is provided below. What happens during the ExecuteChangeSet phase is the following:
CamerasIpSet is created
CamerasRateRule is created
WAFCamerasWebACL CREATE_FAILED: The referenced item does not exist. (Service: AWSWAFRegional; Status Code: 400; Error Code: WAFNonexistentItemException
I found the following post from about 2 months ago where someone has the same issue when using Serverless: https://forum.serverless.com/t/dependon-api-gateway-deployment/7792
What am I missing out on here?
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Template for WAF Configuration'
Parameters:
CamerasApi:
Description: "Arn of the Cameras Api"
Type: String
Default: cameras-api-dev
StageName:
Description: "Stage name of the Cameras Api"
Type: String
Default: v
Blocking:
Description: "Number of calls per 5 minutes for WAF IP blocking."
Type: Number
Default: 2000
EnvironmentType:
Type: String
Default: "dev"
Description: "Type of environment: dev, staging or prod."
Resources:
WAFCamerasWebACL:
Type: AWS::WAFRegional::WebACL
DependsOn: CamerasRateRule
Properties:
DefaultAction:
Type: ALLOW
MetricName: !Join ['', ['IPBlockingMetric', !Ref EnvironmentType]]
Name: !Join ['', ['IPBlockingACL', !Ref EnvironmentType]]
Rules:
-
Action:
Type: "BLOCK"
Priority: 1
RuleId: !Ref CamerasRateRule
CamerasRateRule:
Type: AWS::WAFRegional::RateBasedRule
Properties:
MetricName: UnallowedAccessCount
Name: FiveMinuteRule
RateKey: IP
RateLimit: !Ref Blocking
MatchPredicates:
-
DataId: !Ref CamerasIpSet
Negated: false
Type: "IPMatch"
CamerasIpSet:
Type: AWS::WAFRegional::IPSet
Properties:
Name: !Join ['-', ['IpBlacklist', !Ref EnvironmentType]]
MyWebACLAssociation:
Type: AWS::WAFRegional::WebACLAssociation
Properties:
ResourceArn: !Sub arn:aws:apigateway:${AWS::Region}::/restapis/${CamerasApi}/stages/${StageName}
WebACLId: !Ref WAFCamerasWebACL
Outputs:
WebACL:
Description: Name of the web ACL
Value: !Ref WAFCamerasWebACL
I finally resolved the issue with the help of the AWS customer service. This is a limitation they have with CloudFormation when dealing with AWS::WAFRegional::RateBasedRule.
Despite the fact that CloudFormation supports creating WAF regional rate-based rules, the association of them with a Web ACL is not currently supported. If you observe link [1] below, you will realize that:
"To add the rate-based rules created through CloudFormation to a web ACL, use the AWS WAF console, API, or command line interface (CLI)."
[1] AWS::WAFRegional::RateBasedRule:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-wafregional-ratebasedrule.html
I used the Cloudformation template to generate the WebACL, the RateBasedRule, and the association of the WebACL with my APIGW. Using CodeBuild in our CI/CD pipeline, I'm now adding the RateBasedRule to the WebACL by using the CLI command aws waf-regional update-web-acl.
I ran in the same issue and I solve the problem with WAFv2
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Template for WAF Configuration'
Parameters:
CamerasApi:
Description: "Arn of the Cameras Api"
Type: String
Default: YOUR-API-ID
StageName:
Description: "Stage name of the Cameras Api"
Type: String
Default: YOUR-Stage
Blocking:
Description: "Number of calls per 5 minutes for WAF IP blocking."
Type: Number
Default: 2000
EnvironmentType:
Type: String
Default: Prod
Description: "Type of environment: dev, staging or prod."
Resources:
WAFCamerasWebACL:
Type: AWS::WAFv2::WebACL
Properties:
Name: ExampleWebACL
Description: This is an example WebACL
Scope: REGIONAL
DefaultAction:
Allow: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: ExampleWebACLMetric
Rules:
- Name: RulesTest
Priority: 0
Action:
Block: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: test
Statement:
RateBasedStatement:
Limit: 100
AggregateKeyType: IP
MyWebACLAssociation:
Type: AWS::WAFv2::WebACLAssociation
Properties:
ResourceArn: !Sub arn:aws:apigateway:${AWS::Region}::/restapis/${CamerasApi}/stages/${StageName}
WebACLArn: !GetAtt WAFCamerasWebACL.Arn
Outputs:
WebACL:
Description: Name of the web ACL
Value: !Ref WAFCamerasWebACL
Assuming a AWS::WAFRegional::WebACL and AWS::WAFRegional::RateBasedRule are defined in a Cloudformation stack, they can be attached using the following bash script:
CHANGE_TOKEN=$(aws waf-regional get-change-token --output text)
WEBACL_ID=$(aws waf-regional list-web-acls --query WebACLs[0].WebACLId --output text)
RULE_ID=$(aws waf-regional list-rate-based-rules --query Rules[0].RuleId --output text)
aws waf-regional update-web-acl --web-acl-id $WEBACL_ID --change-token $CHANGE_TOKEN \
--updates Action="INSERT",ActivatedRule='{Priority=1,RuleId="'$RULE_ID'",Action={Type="BLOCK"},Type="RATE_BASED"}'
However unfortunately this leads to issues when deleting the Cloudformation stack
The following resource(s) failed to delete: [RateBasedRuleName].
Any ideas how to enable the stack to remove the rule when issueing aws cloudformation delete-stack?
Resources:
BlueWafAlbAssociation:
Type: "AWS::WAFv2::WebACLAssociation"
Properties:
WebACLArn: arn:aws:wafv2:us-east-1:1234567890:regional/webacl/name-of-webacl/id-of-webacl
ResourceArn: arn:aws:elasticloadbalancing:us-east-1:1234567890:loadbalancer/app/load-balancer-name/xxxxxxxxxxx

Nested Fn::ImportValue in Fn::Sub not working for SAM template

Description:
I am trying to define Serverless API resource. But having trouble in defining location of swagger specification file using function ImportValue.
Steps to reproduce the issue:
I am not able to define AWS::Serverless::Api resource having nested function ImportValue in Location. I have tried following three ways, none of them work.
Note: Stack parameters are defined properly and export value from other stack exists. Not showing them here for brevity reason.
ApiGatewayApi:
Type: AWS::Serverless::Api
Properties:
Name: !Sub ${AWS::StackName}-API
StageName: !Ref ApiGatewayStageName
DefinitionBody:
'Fn::Transform':
Name: 'AWS::Include'
Parameters:
Location:
Fn::Sub:
- s3://${BucketName}/${SwaggerSpecificationS3Key}
- BucketName:
Fn::ImportValue:
!Sub "${EnvironmentName}-dist-bucket-${AWS::Region}"
ApiGatewayApi:
Type: AWS::Serverless::Api
Properties:
Name: !Sub ${AWS::StackName}-API
StageName: !Ref ApiGatewayStageName
DefinitionBody:
'Fn::Transform':
Name: 'AWS::Include'
Parameters:
Location:
Fn::Sub:
- s3://${BucketName}/${SwaggerSpecificationS3Key}
- BucketName:
!ImportValue 'dev-dist-bucket-us-east-1'
ApiGatewayApi:
Type: AWS::Serverless::Api
Properties:
Name: !Sub ${AWS::StackName}-API
StageName: !Ref ApiGatewayStageName
DefinitionBody:
'Fn::Transform':
Name: 'AWS::Include'
Parameters:
Location:
Fn::Sub:
- s3://${BucketName}/${SwaggerSpecificationS3Key}
- BucketName:
Fn::ImportValue: 'dev-dist-bucket-us-east-1'
Cloudformation shows following error.
FAILED - The value of parameter Location under transform Include must
resolve to a string, number, boolean or a list of any of these.
However, if I do not use ImportValue it works with a nested Fn::Sub
ApiGatewayApi:
Type: AWS::Serverless::Api
Properties:
Name: !Sub ${AWS::StackName}-API
StageName: !Ref ApiGatewayStageName
DefinitionBody:
'Fn::Transform':
Name: 'AWS::Include'
Parameters:
Location:
Fn::Sub:
- s3://${BucketName}/${SwaggerSpecificationS3Key}
- BucketName:
Fn::Sub: dist-bucket-${EnvironmentName}-${AWS::Region}
Is it because of Fn::Transform or AWS::Include?

Not able to map VPC_LINK with Method Integration on Api Gateway using cloud formation

I am using Cloudformation to configure API Gateway Method to use VPC Link.
Its not working.
Sample code is as below:
ProxyResourceANY:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref RestApi
ResourceId: !Ref RestApiResource
HttpMethod: ANY
AuthorizationType: NONE
Integration:
Type: HTTP_PROXY
IntegrationHttpMethod: ANY
#ConnectionType: VPC_LINK
#ConnectionId: !Ref VpcLink
Uri: !Sub http://${LoadBalancerUrl}:8098
CloudFormation error:
Encountered unsupported property ConnectionId
You can't use !Ref there but you have 2 solution for this :
Simply use !Sub instead of !Ref like this :
#ConnectionId: !Sub ${VpcLink}
Or more complex you can use stage variable :
Use a stage variable "${stageVariables.variable}" in your method instead of the reference to your VpcLink
ProxyResourceANY:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref RestApi
ResourceId: !Ref RestApiResource
HttpMethod: ANY
AuthorizationType: NONE
Integration:
Type: HTTP_PROXY
IntegrationHttpMethod: ANY
ConnectionType: VPC_LINK
ConnectionId: '${stageVariables.vpcLink}'
Uri: !Sub http://${LoadBalancerUrl}:8098
And then set your stage variable referencing your VpcLink when you create your stage :
Stage:
Type: AWS::ApiGateway::Stage
Properties:
StageName: 'Stage'
Variables:
VpcLink: !Ref VpcLink