What is the correct way of setting up authorization for API gateway using AWS SAM

0

I am trying to set up a very basic API using AWS SAM and API Gateway. My API is being setup to retrieve engine hours from some machinery. This information is retrieved using a Lambda function (getHoursFromInflux)

This is a broken down version of my template.yaml in my SAM-Project

# This is the SAM template that represents the architecture of your serverless application
# https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-template-basics.html

# The AWSTemplateFormatVersion identifies the capabilities of the template
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/format-version-structure.html
AWSTemplateFormatVersion: 2010-09-09
Description: >-
  hours-api

# Transform section specifies one or more macros that AWS CloudFormation uses to process your template
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/transform-section-structure.html
Transform:
- AWS::Serverless-2016-10-31

# Resources declares the AWS resources that you want to include in the stack
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html
Resources:
  # Each Lambda function is defined by properties:
  # https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction

  #Create API authentication
  HOURSAPI:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      Auth:
        DefaultAuthorizer: AWS_IAM
  


  getHoursFromInflux:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/telemetry/assetHours/
      Handler: index.handler
      Layers:
        - !Ref apiLayer
      Runtime: nodejs16.x
      Architectures:
        - x86_64
      MemorySize: 128
      Timeout: 100
      Description: Retreives latest engine hours from all vessels that published engine hours in last 24hours
      Policies:
        # Give Create/Read/Update/Delete Permissions to the VesselIDTable
        - DynamoDBCrudPolicy:
            TableName: !Ref VesselIDTable
      Environment:
        Variables:
          # Make table name accessible as environment variable from function code during execution
          SAMPLE_TABLE: !Ref VesselIDTable
      Events:
        GetRoot:
          Type: Api
          Properties:
            RestApiId: !Ref HOURSAPI
            Path: /assets/hours
            Method: POST
  # Simple syntax to create a DynamoDB table with a single attribute primary key, more in
  # https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlesssimpletable

  
  #Lambda Layers
  apiLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: apiLayer
      Description: Dependencies for API
      ContentUri: dependencies/apiDependencies
      CompatibleRuntimes:
        - nodejs16.x
      LicenseInfo: 'MIT'
      RetentionPolicy: Retain
  
  # DynamoDB table to store item: {id: <ID>, name: <NAME>}
  VesselIDTable:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
        Name: id
        Type: Number
      ProvisionedThroughput:
        ReadCapacityUnits: 2
        WriteCapacityUnits: 2

Outputs:
  WebEndpoint:
    Description: "API Gateway endpoint URL for Prod stage"
    Value: !Sub "MYURL???????"

When I deploy this API I create a user in IAM and give it the following permissions: which allows this user to invoke the API and invoke the Lambda

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction",
                "execute-api:Invoke"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

What I would like to understand is a two part question.

1: Why do I need to specifically allow the invoking of the Lambda function when that is the whole intention of setting up the API. If the API has permission to be invoked then it would make sense to me that the Lambda can be invoked too. 2: Is there another way to set permissions on this api without having to set up the user permissions to allow the invoking of the lambda function?

I tried this in the template:

  HOURSAPI:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      Auth:
        DefaultAuthorizer: AWS_IAM
        InvokeRole: Transdev_API_InvokeRole

That invoke role (Transdev_API_InvokeRole) has the permissions to invoke the lambda however it does not work.


The second question I had around authorisation is the ability to use one generic lambda function for multiple different users.

example:

my API POST requests takes an argument of "fleetOperator"

in the 'getHoursFromInflux' lambda function this 'fleetOperator' value is used to reference a specific AWS-Secret-Manager Secret.

I currently have to provide policies for the lambda to access this secret value. Ideally I would like to use the user policies that made the POST request when the lambda is invoked. This was I can set that userA has the permission to access AWS-Secret "fleetOperatorA" and userB has the permission to access AWS-Secret "fleetOperatorB". They cannot then access each others information.

Is this possible to set up using the SAM Template?

1 Answer
0

The reason for users to have permissions to invoke both API Gateway and Lambda are for troubleshooting purposes. In my cases you need to invoke Lambda to a clearer view of the logs than API Gateway, since API Gateway summarizes the results.

AWS
vtjean
answered a year ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions