aws-cloudformation / cfn-lint

CloudFormation Linter
MIT No Attribution
2.43k stars 586 forks source link

AWS::Serverless::Api DefinitionBody not linted #3631

Open paul-uz opened 2 weeks ago

paul-uz commented 2 weeks ago

CloudFormation Lint Version

1.10.3

What operating system are you using?

Mac OS

Describe the bug

When I run cfn-lint, it does not check the validity of the paths in DefinitionBody under the AWS::Serverless::Api resource.

Cloudformation errors when there are issues, but running cfn-lint, these issues are not caught.

EG

1 validation error detected: Value 'Errors found during import: Unable to create resource at path '/clients/membership/{$clientId}': Resource's path part only allow a-zA-Z0-9._-: or a valid greedy path variable and curly braces at the beginning and the end. 

This was caused by having a $ symbol in the path parameter, {$clientId} but cfn-lint did not pick this up.

Expected behavior

cfn-lint should check the DefinitionBody in AWS::Serverless::Api resources.

Reproduction template

  MiddlewareRestAPI:
    Type: 'AWS::Serverless::Api'
    Properties:
      Auth:
        ApiKeyRequired: true
      StageName: api-middleware
      DefinitionBody:
        openapi: 3.0.1
        info:
          title: 'API Middleware'
          version: 1.0.0
        paths:
          /clients/membership/{$clientId}:
            get:
              parameters:
                - name: clientId
                  in: path
                  required: true
                  description: CRM Client ID
                  schema:
                    type: string
                - name: membershipDefinitionId
                  in: query
                  required: true
                  description: Membership Definition ID
                  schema:
                    type: string
                - name: contextId
                  in: query
                  required: true
                  description: SRO Context ID
                  schema:
                    type: string
              responses:
                "200":
                  description: "200 response"
                  headers:
                    Access-Control-Allow-Origin:
                      schema:
                        type: "string"
                  content:
                    application/json:
                      schema:
                        $ref: "#/components/schemas/Client"
              security:
              - api_key: []
              x-amazon-apigateway-integration:
                credentials:
                  'Fn::GetAtt':
                    - MiddlewareAPIRole
                    - Arn
                httpMethod: POST
                uri:
                  'Fn::Sub': 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ClientsGetMembership.Arn}/invocations'
                responses:
                  default:
                    statusCode: '200'
                    responseParameters:
                      method.response.header.Access-Control-Allow-Origin: '''*'''
                passthroughBehavior: when_no_templates
                contentHandling: CONVERT_TO_TEXT
                type: aws_proxy
            options:
              parameters:
                - name: clientId
                  in: path
                  required: true
                  description: CRM Client ID
                  schema:
                    type: string
                - name: membershipDefinitionId
                  in: query
                  required: true
                  description: Membership Definition ID
                  schema:
                    type: string
                - name: contextId
                  in: query
                  required: true
                  description: SRO Context ID
                  schema:
                    type: string
              responses:
                "200":
                  description: "200 response"
                  headers:
                    Access-Control-Allow-Origin:
                      schema:
                        type: string
                    Access-Control-Allow-Methods:
                      schema:
                        type: string
                    Access-Control-Allow-Headers:
                      schema:
                        type: string
                  content:
                    application/json:
                      schema:
                        $ref: "#/components/schemas/Empty"
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: '200'
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: '''GET,OPTIONS'''
                      method.response.header.Access-Control-Allow-Headers: '''Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'''
                      method.response.header.Access-Control-Allow-Origin: '''*'''
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                passthroughBehavior: when_no_match
                type: mock
kddejong commented 2 weeks ago

Since this dumps into a generic json object we will need to figure out how to define a JSON schema for this. We do this for IAM policies, step functions, etc.

paul-uz commented 2 weeks ago

So in this case, I'm using OpenAPI for my path definitions. Hopefully that is of some help to you.