We are trying to create a API gateway which has Integration with SNS Topic. We are using Serverless Framework to create the Infrastructure as we need to have other Lambda functions listening to the SNS Topic. We are able to successfully create an API Gateway with backend pointing to SNS Topic using apiGatewayServiceProxies (see below)
apiGatewayServiceProxies:
- sns:
path: /sns
method: post
topicName: TopicName
cors: true
Once we deploy, we are able to submit the messages via the API Gateway. When we try to add custom Authorization to the API Gateway, the serverless deploy command is failing as the authorizerId is not accepting the values passed. This is what we have tried:
custom:
apiGatewayServiceProxies:
- sns:
path: /sns
method: post
topicName: TopicName
cors: true
authorizationType: "CUSTOM"
authorizerId: !Ref TokenAuthorizerFunction
functions:
TokenAuthorizerFunction:
handler: authorizer.handler
We followed as mentioned in the documentation here
Can someone tell me what is going wrong here?
Cloudformation snippet for the role
I am creating a serverless architecture model (SAM) using AWS lambda cloudformation. I have two lambdas - frontend lambda and a backend lambda. The front lambda is in account A and backend lambda is in account B. The front end lambda renders static files from S3 for UI. When it has to do backend data processing it should invoke the backend lambda in another aws account. I do have a role in both the accounts and have trusted both the accounts as well. It is not able to invoke the backend lambda still.
How do I invoke the backend lambda using cloudformation template.
Back End:
Your backend lambda needs to give the front end lambda permission to invoke it:
BackEndLambdaPermission:
Type: AWS::Lambda::Permission
Properties:
Action: 'lambda:InvokeFunction'
FunctionName:
Fn::GetAtt:
- BackEndLambda
- Arn
Principal: <enter principal>
SourceArn: <front end lambda arn is optional but recommended>
Front End:
Front end, you need to give permission to invoke the other function (this goes in the Policies section of either a Serverless::Function or the Iam::Role, depending on how your lambda is set up):
- Effect: Allow
Action:
- 'lambda:InvokeFunction'
Resource: "arn:aws:lambda:us-east-1:123456789012:function:function-name"
Pass the function arn into your front end lambda in the Environment property:
Environment:
Variables:
BackEndFunctionArn:"arn:aws:lambda:us-east-1:123456789012:function:function-name"
Invoke the the back end lambda from the code of your front end lambda (python example):
def invoke_back_end(event):
event = {"data": "Hello back end"}
function_arn = os.environ.get("BackEndFunctionArn")
client = boto3.client('lambda')
# "RequestResponse" is a synchronous invocation. Use "Event" for async
response = client.invoke(FunctionName=function_arn, Payload=json.dumps(event), InvocationType='RequestResponse')
return response
I'm following this tutorial to use Cognito to authorize the access to my lambda function through API Gateway.
I already create my user pool with a validated user, an API Gateway authorizer and a lambda function to login and get the token ID.
When I get the token ID with my lambda function and test it in AWS console, the authorizer returns 200, so I think it is working, but when I try to send the token to my lambda function it returns "401 Unauthorized"
My YML configuration:
teste:
handler: handler.teste
memorySize: 128
events:
- http:
path: teste
method: get
authorizer:
name: api-authorizer
arn: arn:aws:cognito-idp:XXXXXXXXX:XXXXXXXXXX:userpool/XXXXXXX_XXXXXXX
type: token
EDIT
I looked at AWS Console how was my lambda function and API Gateway trigger had this details:
Autorização: COGNITO_USER_POOLS
Caminho do recurso: /teste
Endpoint de API: https://XXXXXXXXX.execute-api.XXXXXXXXX.amazonaws.com/dev/teste
Estágio: dev
Método: GET
EDIT 2
I also discovery that my serverless version is 1.47 and it looks like it is the most updated although I've read some questions on Stack where they said that serverless is in 1.5
I read this page a few times and I realize that I wasn't using the correct way, so I change my YML code to this:
functions:
teste:
handler: handler.teste
memorySize: 128
events:
- http:
path: teste
method: get
type: COGNITO_USER_POOLS
authorizer:
arn: arn:aws:cognito-idp:XXXXXXXX:XXXXXXXXX:userpool/XXXXXXXX_XXXXXXXXX
authorizerId:
Ref: api-authorizer
And I also change my authorizer source to Authorization.
I have created two Lambda functions using C#. One is to authorize and another is to perform some business logic.
I have configured first Lambda function as API gateway Authorizer and second one as Resource.
How I can pass the response of first lambda function to a API gateway request so that second one can read and continue with remaining processing?
Thanks
Satya
If your first lambda function has been authorized by API Gateway then you can just call the second lambda function directly from the first one provided the first lambda has the correct permissions to call the second lambda.
iamRoleStatements:
- Effect: Allow
Action:
- lambda:InvokeFunction
- lambda:InvokeAsync
Resource: "*"
I am trying to build a discord bot and was wonderig if i can use AWS lambda for it. So far i haven't seen someone did it already so was confuse if its possible or not. Specially when lambda's aren't active all the time.
ancient question, but this is now possible, since discord starting providing outgoing webhooks a few weeks ago
(shameless self plug) i wrote a bit of a guide here
This is now possible but following an integration approach rather than the traditional bot approach. This differs as detailed below.
The slash commands official documentation gives us this info:
Slash Commands and Interactions bring something entirely new to the table: the ability to interact with an application without needing a bot user in the guild.
You are now able to receive interaction events via your preferred URL endpoint such as an AWS Lamba function, Firebase Cloud function, Azure Cloud function, etc.
This official receiving an interaction section tells us:
In your application in the Developer Portal, there is a field on the main page called "Interactions Endpoint URL". If you want to receive Interactions via outgoing webhook, you can set your URL in this field.
It is important to remember, though, that the data sent to the endpoint URL for interactions is not the same as running a bot client, in fact they make comment on that here:
In many cases, you may still need a bot user. If you need to receive gateway events, or need to interact with other parts of our API...
In my opinion, although We can post messages by AWS Lambda using Webhook, But we can not receive and process messages using AWS Lambda.
This is because discord does not provide message posting events.
here's a minimal implementation in nodejs that will give you an acceptable Interactions Endpoint URL:
serverless.yml
service: discord
variablesResolutionMode: 20210326
frameworkVersion: '2'
provider:
name: aws
runtime: nodejs14.x
stage: whatever
region: us-east-1
lambdaHashingVersion: 20201221
iam:
role:
name: discord
# https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-paramstore-access.html
statements:
-
Effect: Allow
Action:
- 'ssm:DescribeParameters'
Resource: '*'
-
Effect: Allow
Action:
- 'ssm:GetParameter'
Resource:
- 'arn:aws:ssm:us-east-1::parameter/discord_token'
- 'arn:aws:ssm:us-east-1::parameter/discord_application_id'
- 'arn:aws:ssm:us-east-1::parameter/discord_public_key'
functions:
interactions:
handler: handler.interactions
environment:
DISCORD_TOKEN: ${ssm:/discord_token}
DISCORD_APPLICATION_ID: ${ssm:/discord_application_id}
DISCORD_PUBLIC_KEY: ${ssm:/discord_public_key}
events:
-
http:
path: interactions
method: post
cors: true
handler.js
'use strict';
const nacl = require('tweetnacl');
module.exports.interactions = async (event) => {
const verified = nacl.sign.detached.verify(
Buffer.from(event.headers['x-signature-timestamp'] + event.body),
Buffer.from(event.headers['x-signature-ed25519'], 'hex'),
Buffer.from(process.env.DISCORD_PUBLIC_KEY, 'hex')
);
const body = JSON.parse(event.body);
const response = {
body: JSON.stringify(
verified
? { type: body.type }
: { error: 'invalid request signature' },
null,
2
),
statusCode: verified
? 200
: 401
};
console.log(JSON.stringify({ event, response }, null, 2));
return response;
};