I have a sample template, which is creating an AWS Lambda function and an API Gateway,
The issue that I'm facing is the template is able to enable CORS, but it seems to be wrong as on calls from a frontend application still receive the CORS error.
Following is the template -
AWSTemplateFormatVersion: '2010-09-09'
Description: AWS API Gateway with a Lambda Integration
Parameters:
  CorsOrigin:
    Type: String
    Default: "'*'"
  CorsHeaders:
    Type: String
    Default: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
  CorsMethods:
    Type: String
    Default: "'OPTIONS,POST'"
Resources:
  BusinessLambda:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: |
          def handler(event, context):
            response = {
              'isBase64Encoded': False,
              'statusCode': 200,
              'headers': {},
              'multiValueHeaders': {},
              'body': 'Hello, World!'
            }
            return response
      Description: AWS Lambda function
      FunctionName: 'businessLambda'
      Handler: index.handler
      MemorySize: 128
      Role: 'arn:aws:iam::awsAccountId:role/service-role/TestRole'
      Runtime: python3.7
      Timeout: 15
  ApiGatewayRestApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      ApiKeySourceType: HEADER
      Description: An API Gateway with a Lambda Integration
      EndpointConfiguration:
        Types:
          - EDGE
      Name: api-gw
  ApiGatewayResource:
    Type: AWS::ApiGateway::Resource
    Properties:
      ParentId: !GetAtt ApiGatewayRestApi.RootResourceId
      PathPart: 'lambda'
      RestApiId: !Ref ApiGatewayRestApi
  ApiGatewayMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      ApiKeyRequired: false
      AuthorizationType: NONE
      HttpMethod: POST
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: "POST"
        Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${!stageVariables.lambdaAlias}/invocations'
        IntegrationResponses:
          - StatusCode: 200
            ResponseTemplates:
              application/json: $input.json('$')
            ResponseParameters:
              method.response.header.Access-Control-Allow-Headers: !Ref CorsHeaders
              method.response.header.Access-Control-Allow-Methods: !Ref CorsMethods
              method.response.header.Access-Control-Allow-Origin: !Ref CorsOrigin
        RequestTemplates:
          application/json: $input.json('$')
      MethodResponses:
        - ResponseParameters:
            method.response.header.Access-Control-Allow-Headers: true
            method.response.header.Access-Control-Allow-Methods: true
            method.response.header.Access-Control-Allow-Origin: true
          StatusCode: '200'
      OperationName: 'lambda'
      ResourceId: !Ref ApiGatewayResource
      RestApiId: !Ref ApiGatewayRestApi
  APIGatewayOptionsMethod:
    Type: "AWS::ApiGateway::Method"
    Properties:
      ResourceId: !Ref ApiGatewayResource
      RestApiId: !Ref ApiGatewayRestApi
      AuthorizationType: NONE
      HttpMethod: OPTIONS
      Integration:
        Type: MOCK
        IntegrationResponses:
          - ResponseParameters:
              method.response.header.Access-Control-Allow-Headers: !Ref CorsHeaders
              method.response.header.Access-Control-Allow-Methods: !Ref CorsMethods
              method.response.header.Access-Control-Allow-Origin: !Ref CorsOrigin
            ResponseTemplates:
              application/json: ''
            StatusCode: '200'
        PassthroughBehavior: WHEN_NO_MATCH
        RequestTemplates:
          application/json: '{"statusCode": 200}'
      MethodResponses:
        - ResponseModels:
            application/json: 'Empty'
          ResponseParameters:
            method.response.header.Access-Control-Allow-Headers: false
            method.response.header.Access-Control-Allow-Methods: false
            method.response.header.Access-Control-Allow-Origin: false
          StatusCode: '200'
  ApiGatewayStage:
    Type: AWS::ApiGateway::Stage
    Properties:
      DeploymentId: !Ref ApiGatewayDeployment
      Description: API GW Stage dev
      RestApiId: !Ref ApiGatewayRestApi
      StageName: 'dev'
      Variables: 
        'lambdaAlias' : 'businessLambda'
  GWLambdaPermission:
    Type: "AWS::Lambda::Permission"
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !Ref BusinessLambda
      Principal: "apigateway.amazonaws.com"
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestApi}/*/POST/lambda"
  ApiGatewayDeployment:
    Type: AWS::ApiGateway::Deployment
    DependsOn: APIGatewayOptionsMethod
    Properties:
      Description: Lambda API Deployment
      RestApiId: !Ref ApiGatewayRestApi
Outputs:
  test:
    Value: !Ref ApiGatewayRestApi
Script to test the endpoint from browser console -
let url = "enterUrlHere";
fetch(url, {
    method : "POST"
})
.then(function(response) {
    console.log('success =>\n', response);
})
.catch(function(error) {
    console.log('error =>\n', error);
});
Error -
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Reference -
Enable CORS for API Gateway in Cloudformation template