Securing APIGW with IAM role in Cloudformation

331 Views Asked by At

Recently I've been working on stand alone cloud formation template, which will create REST API, via API gateway and lambda hooked behind doing all the business logic.

Right now it is public, anyone can make the call to APIGW url and get the response. I want to make it secure so that only certain people with a IAM role will be able to call the APIGW.

If there is any other better way securing the same, any suggestion are appreciated.

Current cloudformation

AWSTemplateFormatVersion: 2010-09-09
Description: My API Gateway and Lambda function

Parameters:
  apiGatewayName:
    Type: String
    Default: final-apigw-2
  apiGatewayStageName:
    Type: String
    Default: v1
  apiGatewayHTTPMethod:
    Type: String
    Default: ANY
  lambdaFunctionName:
    Type: String
    AllowedPattern: "[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+"
    Default: final-lambda-2

Resources:
  apiGateway:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Description: Example API Gateway
      EndpointConfiguration:
        Types:
          - REGIONAL
      Name: !Ref apiGatewayName

  apiGatewayLambdaResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref apiGateway
      PathPart: '{proxy+}'
      ParentId: !GetAtt apiGateway.RootResourceId

  apiGatewayLambdaResourceMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      AuthorizationType: NONE
      RestApiId: !Ref apiGateway
      ResourceId: !Ref apiGatewayLambdaResource
      HttpMethod: ANY
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: POST
        Uri: !Sub 
          - >-
            arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
          - lambdaArn: !GetAtt lambdaFunction.Arn
        IntegrationResponses:
          - ResponseTemplates:
              application/json: ""
            StatusCode: 200
        PassthroughBehavior: WHEN_NO_TEMPLATES

  apiGatewayDeployment:
    Type: AWS::ApiGateway::Deployment
    DependsOn:
      - apiGatewayLambdaResourceMethod
    Properties:
      RestApiId: !Ref apiGateway
      StageName: !Ref apiGatewayStageName

  lambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: |
          exports.handler = async (event) => {
              // TODO implement
              const response = {
                  statusCode: 200,
                  body: JSON.stringify(event),
              };
              return response;
          };
      Description: Example Lambda function
      FunctionName: !Ref lambdaFunctionName
      Handler: index.handler
      Role: !GetAtt lambdaIAMRole.Arn
      Runtime: nodejs12.x

  lambdaApiGatewayInvoke:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !GetAtt lambdaFunction.Arn
      Principal: apigateway.amazonaws.com
      # note: if route *not* at API Gateway root, `SourceArn` would take the form of:
      #               arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGateway}/${apiGatewayStageName}/${apiGatewayHTTPMethod}/PATH_PART
      SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGateway}/${apiGatewayStageName}/${apiGatewayHTTPMethod}/*

  lambdaIAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Action:
              - sts:AssumeRole
            Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
      Policies:
        - PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Effect: Allow
                Resource:
                  - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${lambdaFunctionName}:*
          PolicyName: lambda

  lambdaLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub /aws/lambda/${lambdaFunctionName}
      RetentionInDays: 90

Outputs:
  apiGatewayInvokeURL:
    Value: !Sub https://${apiGateway}.execute-api.${AWS::Region}.amazonaws.com/${apiGatewayStageName}

  lambdaArn:
    Value: !GetAtt lambdaFunction.Arn

UPDATE

Found this doc : https://docs.aws.amazon.com/apigateway/api-reference/resource/method/

authorizationType

The method's authorization type. Valid values are NONE for open access, AWS_IAM for using AWS IAM permissions, CUSTOM for using a custom authoriser, or COGNITO_USER_POOLS for using a Cognito user pool.

I added the authorisation type as AWS_IAM, but still I'm able to call the APIGW endpoint, I am missing anything

enter image description here

1

There are 1 best solutions below

0
On

Adding authorizationType : AWS_IAM only made it work, apparently the cloudformation template was not updating. Had to manually delete the stack and reuploading worked for me