Tool Is Not Transforming SAM (`AWS::Serverless-2016-10-31`) Correctly
Given the following reduced test template:
---
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: A reduced test template.
Globals:
Api:
OpenApiVersion: '3.0.1'
AccessLogSetting:
Format: $context.requestId
Auth:
UsagePlan:
CreateUsagePlan: PER_API
Resources:
Http:
Type: AWS::Serverless::Function
Properties:
Runtime: nodejs14.x
Handler: index.default
InlineCode: |-
exports.default = () => { }
Events:
ProxyApi:
Type: Api
Properties:
Method: ANY
Path: /{proxy+}
…cfn_nag reports the following:
------------------------------------------------------------
./template.yml
------------------------------------------------------------------------------------------------------------------------
| WARN W68
|
| Resources: ["ServerlessRestApiDeployment"]
| Line Numbers: [-1]
|
| AWS::ApiGateway::Deployment resources should be associated with an AWS::ApiGateway::UsagePlan.
------------------------------------------------------------
| WARN W69
|
| Resources: ["ServerlessRestApiProdStage"]
| Line Numbers: [-1]
|
| AWS::ApiGateway::Stage should have the AccessLogSetting property defined.
------------------------------------------------------------
| WARN W64
|
| Resources: ["ServerlessRestApiProdStage"]
| Line Numbers: [-1]
|
| AWS::ApiGateway::Stage resources should be associated with an AWS::ApiGateway::UsagePlan.
Failures count: 0
Warnings count: 3
These associations and property do exist, however. When transformed by SAM, the template produced is this:
The transformed template is kinda verbose.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "A reduced test template.",
"Resources": {
"Http": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"ZipFile": "exports.default = () => { }"
},
"Handler": "index.default",
"Role": {
"Fn::GetAtt": [
"HttpRole",
"Arn"
]
},
"Runtime": "nodejs14.x",
"Tags": [
{
"Key": "lambda:createdBy",
"Value": "SAM"
}
]
}
},
"HttpRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"sts:AssumeRole"
],
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com"
]
}
}
]
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
],
"Tags": [
{
"Key": "lambda:createdBy",
"Value": "SAM"
}
]
}
},
"HttpProxyApiPermissionProd": {
"Type": "AWS::Lambda::Permission",
"Properties": {
"Action": "lambda:InvokeFunction",
"FunctionName": {
"Ref": "Http"
},
"Principal": "apigateway.amazonaws.com",
"SourceArn": {
"Fn::Sub": [
"arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*/*",
{
"__ApiId__": {
"Ref": "ServerlessRestApi"
},
"__Stage__": "*"
}
]
}
}
},
"ServerlessRestApi": {
"Type": "AWS::ApiGateway::RestApi",
"Properties": {
"Body": {
"info": {
"version": "1.0",
"title": {
"Ref": "AWS::StackName"
}
},
"paths": {
"/{proxy+}": {
"x-amazon-apigateway-any-method": {
"x-amazon-apigateway-integration": {
"type": "aws_proxy",
"httpMethod": "POST",
"uri": {
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Http.Arn}/invocations"
}
},
"responses": {}
}
}
},
"openapi": "3.0.1"
}
}
},
"ServerlessRestApiDeployment7a650ad703": {
"Type": "AWS::ApiGateway::Deployment",
"Properties": {
"Description": "RestApi deployment id: 7a650ad703b8db9ec385abf58d5a42934aa71554",
"RestApiId": {
"Ref": "ServerlessRestApi"
}
}
},
"ServerlessRestApiProdStage": {
"Type": "AWS::ApiGateway::Stage",
"Properties": {
"AccessLogSetting": {
"Format": "$context.requestId"
},
"DeploymentId": {
"Ref": "ServerlessRestApiDeployment7a650ad703"
},
"RestApiId": {
"Ref": "ServerlessRestApi"
},
"StageName": "Prod"
}
},
"ServerlessRestApiUsagePlan": {
"Type": "AWS::ApiGateway::UsagePlan",
"DependsOn": [
"ServerlessRestApi"
],
"Properties": {
"ApiStages": [
{
"ApiId": {
"Ref": "ServerlessRestApi"
},
"Stage": {
"Ref": "ServerlessRestApiProdStage"
}
}
]
}
},
"ServerlessRestApiApiKey": {
"Type": "AWS::ApiGateway::ApiKey",
"DependsOn": [
"ServerlessRestApiUsagePlan"
],
"Properties": {
"Enabled": true,
"StageKeys": [
{
"RestApiId": {
"Ref": "ServerlessRestApi"
},
"StageName": {
"Ref": "ServerlessRestApiProdStage"
}
}
]
}
},
"ServerlessRestApiUsagePlanKey": {
"Type": "AWS::ApiGateway::UsagePlanKey",
"DependsOn": [
"ServerlessRestApiApiKey"
],
"Properties": {
"KeyId": {
"Ref": "ServerlessRestApiApiKey"
},
"KeyType": "API_KEY",
"UsagePlanId": {
"Ref": "ServerlessRestApiUsagePlan"
}
}
}
}
}
When scanned, this produces no warnings or failures:
------------------------------------------------------------
./template.processed.json
------------------------------------------------------------
Failures count: 0
Warnings count: 0
This was run via the Docker image stelligent/cfn_nag:latest.
Thanks for the detailed report @chrisoverzero . The way that cfn_nag models the transformation for AWS::Serverless is somewhat static. We'll review and update as appropriate.
Thanks for the detailed report @chrisoverzero . The way that cfn_nag models the transformation for
AWS::Serverlessis somewhat static. We'll review and update as appropriate.
@arothian For the time being is there anyway to use metadata to ignore this?
@mongoDynamo Not currently, metadata on the serverless resource will currently pass through some of the generated resources(https://github.com/stelligent/cfn-model/pull/84), but I don't think it will work for the ones warning in this issue.