I created a lambda function to upload files to s3. When testing via the AWS interface, everything works. Next I created the API Gateway and tried to make a request through ReactJs. But I get an error. I want to see what error occurs but I cannot add logs to the API Gateway. What I do.
Create API Gateway -> go to Stages-> Logs/Tracing
Try to activate checkbox Enable CloudWatch Logs but got CloudWatch Logs role ARN must be set in account settings to enable logging
Create role in IAM with next policy: AmazonS3FullAccess, AmazonAPIGatewayPushToCloudWatchLogs, AWSLambdaBasicExecutionRole
Copy the Role ARN
go to the setting of my api and try to paste to CloudWatch log role ARN. But got The role ARN does not have required permissions set to API Gateway.
Can you tell me what other settings I need?
According to this documentation (https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-cloudwatch-logs/) after creating the Role, you need to add it to the Global AWS Api Gateway Settings (when you open the Console, there is a settings menu in the left pane) as the CloudWatch log role ARN.
Then it will use that role for all the gateways you create, so this is a one-time step.
Using a SAM template
You can automate all your deployment process using Serverless Application Model (SAM) or Serverless Framework. The following SAM template defines the Api Gateway and required configuration to enable CloudWatch Logs:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
ApiGatewayApi:
Type: AWS::Serverless::Api
DependsOn: ApiCWLRoleArn
Properties:
StageName: prod
MethodSettings:
- LoggingLevel: INFO
MetricsEnabled: True
ResourcePath: '/*' # allows for logging on any resource
HttpMethod: '*' # allows for logging on any method
Auth:
ApiKeyRequired: true # sets for all methods
ApiCWLRoleArn:
Type: AWS::ApiGateway::Account
Properties:
CloudWatchRoleArn: !GetAtt CloudWatchRole.Arn
# IAM Role for API Gateway + CloudWatch Logging
CloudWatchRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
Action: 'sts:AssumeRole'
Effect: Allow
Principal:
Service: apigateway.amazonaws.com
Path: /
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs'
Related
I am using AWS apigateway to trigger a lambda function. I deployed them from serverless framework, the configuration looks like:
handler:
handler: src/index.handler
name: handler
tracing: true
role: updateRole
events:
- http:
path: /contact/{id}
method: patch
integration: lambda
request:
parameters:
paths:
id: true
after deploy, it works perfect. But what I don't understand is how I can find out where the iam role/policy defined for this API integration?
When open AWS console, it shows me the right configuration in the "Integration Request" tab:
But I can't find anywhere it specifies the IAM role to this integration. How can I find it or update it?
Permissions to execute a function from API, are set using resource-based policies for lambda, not IAM role. In lambda console they are listed as:
Is there some place with samples on how to make a bunch of actions through ApiGateway integration? Looking how to upload object to S3, push item to SQS & SNS queues, make DynamoDB call and many other things, trying to find documentation on how to construct those paths.
I'm using CloudFormation template, which uses integration URI to setup this AWS ApiGateway integration with AWS services.
Can't find documentation talking how to make these URI paths for all kind of services.
When setting up the integration request with another AWS service action, the integration request URI is also an ARN.
For example, for the integration with the GetBucket action of Amazon S3, the integration request URI is an ARN of the following format:
arn:aws:apigateway:api-region:s3:path
See more: https://docs.aws.amazon.com/apigateway/latest/developerguide/integration-request-basic-setup.html
Dynamodb:
A bit more complicated then S3:
https://aws.amazon.com/blogs/compute/using-amazon-api-gateway-as-a-proxy-for-dynamodb/
SNS:
https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-proxy-integrate-service/
For SQS I have found cloudformation setup:
PostMethod:
Type: "AWS::ApiGateway::Method"
Properties:
AuthorizationType: "NONE"
ApiKeyRequired: "true"
HttpMethod: "POST"
ResourceId: !Ref "SomeResource"
RestApiId: !Ref "RestApi"
MethodResponses:
- StatusCode: 200
Integration:
Credentials: !GetAtt "RestApiRole.Arn"
IntegrationHttpMethod: "POST"
IntegrationResponses:
- StatusCode: 200
Type: "AWS"
Uri: !Sub "arn:aws:apigateway:${AWS::Region}:sqs:action/SendMessage"
RequestParameters:
integration.request.querystring.QueueUrl: !Sub "'${SomeQueue}'"
integration.request.querystring.MessageBody: "method.request.body"
and here the code for RestApiRole:
RestApiRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Action:
- "sts:AssumeRole"
Principal:
Service:
- "apigateway.amazonaws.com"
Effect: "Allow"
Policies:
- PolicyName: "InvokeLambda"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Action:
- "lambda:InvokeFunction"
Resource: !GetAtt "LambdaFunction.Arn"
Effect: "Allow"
From Uri property documentation:
If you specify AWS for the Type property, specify an AWS service that follows this form: arn:aws:apigateway:region:subdomain.service|service:path|action/service_api. For example, a Lambda function URI follows this form: arn:aws:apigateway:region:lambda:path/path. The path is usually in the form /2015-03-31/functions/LambdaFunctionARN/invocations. For more information, see the uri property of the Integration resource in the Amazon API Gateway REST API Reference.
More descriptions and samples from another AWS documentation:
From these documentation samples & descriptions it seems there are 2 type of APIs - action based and path based.
Using Action based API 😍
I think most, if not all support this. While those actions are available in IAM settings and all API documentations, while all AWS services are web services, aka they have API interfaces and those interfaces use Actions. Correct me if that's wrong for some service, but I think by following this structure should be possible to make any call to any service which has integration with API Gateway service.
Sometimes need to use path API 😭
Was trying to upload file to S3 with PutObject and it was giving error:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>MethodNotAllowed</Code>
<Message>The specified method is not allowed against this resource.</Message>
<Method>PUT</Method>
<ResourceType>SERVICE</ResourceType>
<RequestId>....</RequestId>
<HostId>....=</HostId>
</Error>
Replaced with path API format and it worked out. So the learning here is I will continue to try using action APIs first and if can't for that specific action - switch to path API while I feel Action API is more declarative.
Sample structure Action API:
arn:aws:apigateway:us-east-1:SERVICE_NAME:action/ACTION_NAME&Var1=Value1&Var2=Value2
Sample call to S3 service. Action name - GetObject. Documentation for this API Actions says there are 2 required properties - Bucket (bucket name) and Key. So full sample URI:
arn:aws:apigateway:us-east-1:s3:action/GetObject&Bucket=myDemoBucket1&Key=some/path/to/file
Same thing with path API:
arn:aws:apigateway:us-east-1:s3:path/myDemoBucket1/some/path/to/file
I found one way to get samples. Use console UI, make the endpoint, deploy to some stage and go to stage, select Export tab, and export as Swagger + API Gateway Extensions in Yaml format. While i use Yaml with cloudformation. Inside that Yaml there are all you need. If there are no "Stages", go to "Resources" and from dropdown select deploy and create Stage inside dialog.
Here are some different samples I was able to find for main services:
Invoke Lambda docs:
arn:aws:apigateway:api-region:lambda:path//2015-03-31/functions/arn:aws:lambda:lambda-region:account-id:function:lambda-function-name/invocations
The path part seems to map to API action from API docs:
DynamoDB blog post
You need to use HTTP method by API Action documentation + Api Action name + IntegrationRequest template to call DynamoDB.
Sample URI for Query action:
arn:aws:apigateway:us-east-1:dynamodb:action/Query
SNS blog post
Sample URI: arn:aws:apigateway:region:sns:action/Publish
With region: arn:aws:apigateway:us-east-1:sns:action/Publish
You need to pass in TopicArn and Message and other parameters through URL Query String Parameters. There is good thread on the topic: https://stackoverflow.com/a/64268791/1737158
https://docs.aws.amazon.com/sns/latest/api/API_Publish.html#API_Publish_Examples
I am using serverless.yml to deploy lambdas to AWS and I'd like to know how to configure the resource-based policy for my lambda.
I deploy a customised alias to my lambda and need to grant invoke:lambda in the policy of the resouce-based policy. So when you open lambda -> configuration -> permission, the policy should appear as below
when I use the role configure in serverless.yml, it only changes the permission for my lambda execution role. How can I modify the Resource-based policy for my lambda?
I have used before the API Gateway Resource Policy:
https://www.serverless.com/framework/docs/providers/aws/events/apigateway/#resource-policy
For the lambda function association directly you can take a look at that thread:
https://github.com/serverless/serverless/issues/4926
An example serverless.yaml would look like this:
provider:
name: aws
runtime: nodejs8.10
memorySize: 128
stage: dev
apiGateway:
resourcePolicy:
- Effect: Allow
Principal: '*'
Action: execute-api:Invoke
Resource:
- execute-api:/*/*/*
Condition:
IpAddress:
aws:SourceIp:
- 'your ip here'
How to restrict access to a lambda
Please note that the resource policy currently only works for the REST API Gateways. https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-vs-rest.html
HTTP APIs do not support resource policies.
When trying to deploy to AWS using AWS SAM CLI my Lambda functions using the following script:
aws cloudformation deploy --template-file /Users/ndelvalle/Projects/foo/functions/packaged-template.yaml --stack-name foo --region sa-east-1 --capabilities CAPABILITY_IAM --no-fail-on-empty-changeset
I got the following error in the stack events:
API: iam:CreateRole User: arn:aws:iam::user/nico is not authorized to perform: iam:CreateRole on resource
This is because I don't have role creation permissions on my account. That is why I wonder if there is a way to define pre-created roles to my lambdas, so the script does not need to create the role.
There is more information needed to answer this for you. Many different permissions come into play when deploying with SAM. I implemented SAM template for my company to manage our lambda stacks. We needed to give our Java Developers working on the stacks the same permissions that the SAM template implicitly and explicitly creates, beyond just creating roles. For this we created several special groups in IAM that we attached our Serverless Devs too. It is possible to assign specific predefined roles to Lambdas, https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction. If you define a role in the template, it does not automatically create a role. However, if you are declaring other resources like Api Gateway and DynamoDB, you will still run into problems.
So long story short, if you are working with SAM its better you have your Sys admin give you permissions to Create role, and you will need other permissions as well, or have the deployment of the SAM template done by a Job runner like Jenkins (that has the permissions). It it is too permissive for your team/company, maybe SAM is not a good solution... Best to switch to something like pure CloudFormation and abandon a developer oriented workflow. Somethings to think about, hope its helpful.
You can use the Role property as mentioned in the docs for AWS::Serverless::Function
A sample template which creates a new lambda without creating a new role,
Transform: AWS::Serverless-2016-10-31
Description: >
sam-app
Sample SAM Template for sam-app
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 3
Tracing: Active
Api:
TracingEnabled: True
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: nodejs18.x
Role: <ARN of ROLE>
Architectures:
- x86_64
Events:
HelloWorld:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /hello
Method: get
Metadata: # Manage esbuild properties
BuildMethod: esbuild
BuildProperties:
Minify: true
Target: "es2020"
Sourcemap: true
EntryPoints:
- app.ts
Outputs:
# ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
# Find out more about other implicit resources you can reference within SAM
# https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
HelloWorldApi:
Description: "API Gateway endpoint URL for Prod stage for Hello World function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
HelloWorldFunction:
Description: "Hello World Lambda Function ARN"
Value: !GetAtt HelloWorldFunction.Arn
HelloWorldFunctionIamRole:
Description: "Implicit IAM Role created for Hello World function"
Value: !GetAtt HelloWorldFunctionRole.Arn
I want to attach an existing role to my serverless.yml file, I have created a role in aws console, my code works fine when I test it in aws console, but when I try to test it with the http endpoint it gives me the following:
{"message": "Internal server error"}
I think is because I did not specify any role in the serverless.yml file for the simple reason that I don't know how to do it.
Here is my serverless.yml file :
Resources:
ec2-dev-instance-status:
Properties:
Path: "arn:aws:iam::119906431229:role/lambda-ec2-describe-status"
RoleName: lambda-ec2-describe-status
Type: "AWS::IAM::Role"
functions:
instance-status:
description: "Status ec2 instances"
events:
-
http:
method: get
path: users/create
handler: handler.instance_status
role: "arn:aws:iam::119906431229:role/lambda-ec2-describe-status"
provider:
name: aws
region: us-east-1
runtime: python2.7
stage: dev
resources: ~
service: ec2
Please help.
Thank you.
According to the documentation, there's a few ways to attach existing roles to a function (or entire stack)
Role defined as a Serverless resource
resources:
Resources:
myCustRole0:
Type: AWS::IAM::Role
# etc etc
functions:
func0:
role: myCustRole0
Role defined outside of the Serverless stack
functions:
func0:
role: arn:aws:iam::0123456789:role//my/default/path/roleInMyAccount
Note that the role you use must have additional permissions to log to cloudwatch etc, otherwise you won't get logging.