How to set a role to AWS::Serverless::Api

52 Views Asked by At

I want to set a role to my API gateway so that I can see the logs for any errors. But while trying to do this, I am getting the below error.

Failed to create change set. Current status: FAILED

I am not sure if there is a Role property in AWS::Serverless::Api My editor says "Unknown resource type property: Role" when I set the Role here.

Here is my CF script.

MyApiGateway:
  Type: AWS::Serverless::Api
  Properties:
    Name:
      !Sub
      - '${TheEnv}-${TheAppNameForResources}-api'
      - TheEnv: !Ref Environment
        TheAppNameForResources: !Ref AppNameForResources
        TheBucketRegion: !Ref AWS::Region
    TracingEnabled: true
    OpenApiVersion: 3.0.2
    Cors:
      AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
    AllowMethods: "'*'"
    AllowOrigin: "'*'"
    StageName: test
    Role: !GetAtt APICloudwatchLogRole.Arn
    DefinitionBody:
      swagger: "2.0"
      paths:
        /batch:
          get:
            x-amazon-apigateway-integration:
              uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03- 
31/functions/${MyLambdaFunction.Arn}/invocations
              httpMethod: GET
              type: "aws_proxy"


APICloudwatchLogRole:
  Type: AWS::IAM::Role
  Properties:
    RoleName:
      !Sub
      - "${TheAppNameForResources}-${TheEnvName}-cw-role-for-api"
      - TheAppNameForResources: !Ref AppNameForResources
        TheEnvName: !Ref Environment
    AssumeRolePolicyDocument:
      Statement:
        - Effect: Allow
          Principal:
            Service: "apigateway.amazonaws.com"
          Action: ['sts:AssumeRole']
    Policies:
      - PolicyName:
          !Sub
          - "${TheAppNameForResources}-${TheEnvName}-cw-role-for-api"
          - TheAppNameForResources: !Ref AppNameForResources
            TheEnvName: !Ref Environment
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
                - 'logs:CreateLogGroup'
                - 'logs:CreateLogStream'
                - 'logs:PutLogEvents'
              Resource: "*"

Could some one know if there is a way to set a role to API gateway when using AWS::Serverless::Api? I also tried deleting the entire stack and re-creating, but still no luck.

Thanks

2

There are 2 best solutions below

2
lpizzinidev On

You should be able to attach a resource-based policy to the AWS::Serverless::Api using the ApiAuth.ResourcePolicyStatement.CustomStatements attribute.

See example.

0
Ram On

I tried setting up AWS::Logs::LogGroup for my API gateway, but looks like I also need to setup "AWS::ApiGateway::Stage" for this so that I can provide "AccessLogSetting" there. So when I tried to create these 2 resources my stack still fails with this error.

Type:AWS::ApiGateway::Stage, StatusReason:Resource handler returned message: "Deployment id does not exist (Service: ApiGateway, Status Code: 400)"

My corresponding cloudformation blocks for these are below.

MyApiGateway:
  Type: AWS::Serverless::Api
  Properties:
    Name:
      !Sub
      - '${TheEnv}-${TheAppNameForResources}-api'
      - TheEnv: !Ref Environment
        TheAppNameForResources: !Ref AppNameForResources
        TheBucketRegion: !Ref AWS::Region
    TracingEnabled: true
    OpenApiVersion: 3.0.2
    Cors:
      AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz- 
Security-Token'"
    AllowMethods: "'*'"
    AllowOrigin: "'*'"
    StageName: test
    Auth:
      ResourcePolicy:
        CustomStatements: [{
                       "Effect": "Allow",
                       "Principal": "*",
                       "Action": "execute-api:Invoke",
                       "Resource": "execute-api:/test/GET/batch",
                     }]

MyLogGroupForApi:
  Type: AWS::Logs::LogGroup
  Properties:
    LogGroupName: '/aws/api/MyApi'
    RetentionInDays: 7

MyApiGatewayStage:
  Type: AWS::ApiGateway::Stage
  Properties:
    RestApiId: !Ref MyApiGateway
    StageName: "test"
    DeploymentId: !Ref MyApiGateway
    AccessLogSetting:
      DestinationArn: !GetAtt MyLogGroupForApi.Arn
      Format: "$context.requestId 
$context.identity.sourceIp-$context.requestTime"

Not sure what's wrong here. According to AWS, when using AWS::Serverless::Api, it automatically generates the necessary AWS cloudformation resources to deploy the API, including an AWS::ApiGateway::Deployment resource. This means that when the cloudformation stack is created or updated,it will automatically create a deployment for the API specification.This deployment ID is then referenced by the AWS::ApiGateway::Stage resource that is also generated.

So its bit unclear what is the correct sequence of steps to create CW logs for an API gateway.