I am trying to create multiple APIs in APIGateway using a Swagger file.
Right now, when I use the AWS console, I manually import the swagger file and then add the endpoints/authentication in every API created.
I want to complete the same task using AWS Lambda (Node JS), so that i may:
Create APIs using Swagger
Add endpoints (custom server)
Add authorizer (cognito)
I looked into AWS documentation but was not able to understand it in a proper way.
How to complete this task?
If you really have to use swagger, I would say
Write your APIs in swagger json format
Parse it to add your API gateway extensions (endpoints/authorizer/role)
Publish it
Or
Create your API with the given swagger document
Pass the restapi id to a lambda function
Use apigateway SDK (e.g. NodeJS SDK for APIGateway) to get resources and methods for the restapi and add integrations to it.
But have you considered AWS Cloudformation scripts? In my current project, I have considered what you want to do but being no expert in swagger I chose Cloudformation over it. (also considered AWS SAM and serverless). It is a little repetitive but found much easier to write and understand. Here's an example of an endpoint in CFN yaml format -
ResourceUserActions:
Type: AWS::ApiGateway::Resource
DeletionPolicy: Delete
Properties:
RestApiId: !Ref RestAPI
ParentId: !Ref ResourceUser
PathPart: "{action+}"
UserActionsMethod:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref RestAPI
ResourceId: !Ref ResourceUserActions
HttpMethod: ANY
AuthorizationType: COGNITO_USER_POOLS
AuthorizerId: !Ref ApiAuthorizer
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: POST
Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HandlerFunction.Arn}/invocations
Credentials: !GetAtt ApiGatewayRole.Arn
Type AWS::ApiGateway::Resource defines a resource, and AWS::ApiGateway::Method adds method, authorizer, integration type details to the resource. For more details, see AWS CFN for APIGateway
Related
I'm learning aws lambda (creating some rest apis, apply rate limiting). I have read some examples from aws and they said that we need to create/use aws API gateway to route to lambda function (UI based)
But I also found in the internet this serverless.yml. No need to use UI anymore
functions:
simple:
handler: handler.simple
events:
- httpApi: 'PATCH /elo'
extended:
handler: handler.extended
events:
- httpApi:
method: POST
path: /post/just
You guys can see there is no where that mention about api gateway. So my questions are:
If I use configuration like that, how can I know whether it is using API gateway or not? If not, how can I specify it to use API gateway?
Is Lambda-Proxy or Lambda Integration used in this case (read more here)? How can I specify it to use Lambda Integration?
Is aws API gateway suitable for rate limiting? Like allow only 1000 request per user (bearer token) per 120 minutes.
Since I'm still waiting for aws account, I have no environment to test. Any help would be appreciated
First, let's establish that there are two different types of endpoints in API Gateway: REST APIs and HTTPS APIs. These offer different features and customization. For example, REST APIs offer client-level throttling, whereas HTTPS APIs do not. You can see more information about both versions here.
This configuration would create a new HTTPS API gateway endpoint. When you specify that the event triggering the lambda is a post to that specific path, your deployment will create a new endpoint with API gateway to enable that automatically.
The serverless framework allows you to specify whether or not you want to use a REST API or an HTTPS API. The syntax above is for the HTTPS API -- also referred to in serverless' documentation as v2, which by default only supports lambda-proxy. You can opt to use a REST API which can be configured to use either, as you can see reading through the documentation here
You can enable throttling on REST APIs as shown in the (documentation)3:
service: my-service
provider:
name: aws
apiGateway:
apiKeys:
- myFirstKey
- ${opt:stage}-myFirstKey
# you can hide it in a serverless variable
- ${env:MY_API_KEY}
- name: myThirdKey
value: myThirdKeyValue
# let cloudformation name the key (recommended when setting api key value)
- value: myFourthKeyValue
description: Api key description # Optional
customerId: A string that will be set as the customerID for the key # Optional
usagePlan:
quota:
limit: 5000
offset: 2
period: MONTH
throttle:
burstLimit: 200
rateLimit: 100
Then in your function definition:
functions:
hello:
events:
- http:
path: user/create
method: get
private: true
Please help .i am new to cloud endpoint and not able to authenticate my nodejs api using cloud endpoint and api key .
My nodejs api:https://iosapi-dot-ingka-rrm-ugc-dev.appspot.com is working perfectly .However it's not working after authenticate with cloud endpoint and Api key.
For fetching data(get), i am using routing in my api like :
https://iosapi-dot-ingka-rrm-ugc-dev.appspot.com/ugc/iosreviewratings/20200611 : 20200611 : is any date range i have to pass .
https://iosapi-dot-ingka-rrm-ugc-dev.appspot.com/ugc/iosreviewratings/20200611?Limit=2&Offset=1
after endpoint deployment ., whenever i am acessing my api with api key , i am getting error " "message": "Method doesn't allow unregistered callers (callers without established identity). Please use API Key or other form of API consumer identity to call this API.",
"
My Cloud endpoint has been deployed successfully .The below are my openapi.yaml .(ingka-rrm-ugc-dev : is my project id)
openapi.yaml
swagger: "2.0"
info:
description: "A simple Google Cloud Endpoints API example."
title: "Endpoints Example"
version: "1.0.0"
host: "ingka-rrm-ugc-dev.appspot.com"
consumes:
- "application/json"
produces:
- "application/json"
schemes:
- "https"
paths:
"/ugc/iosreviewratings/*":
get:
produces:
- application/json
operationId: "auth_info_google_jwt"
parameters:
- name: Limit
in: query
required: false
type: string
x-example: '200'
- name: Offset
in: query
required: false
type: string
x-example: '2'
responses:
'200':
description: Definition generated from Swagger Inspector
# This section requires all requests to any path to require an API key.
security:
- api_key: []
securityDefinitions:
# This section configures basic authentication with an API key.
api_key:
type: "apiKey"
name: "key"
in: "query"
app.yaml
========--
runtime: nodejs
env: flex
service: iosapi
# This sample incurs costs to run on the App Engine flexible environment.
# The settings below are to reduce costs during testing and are not appropriate
# for production use. For more information, see:
# https://cloud.google.com/appengine/docs/flexible/nodejs/configuring-your-app-with-app-yaml
manual_scaling:
instances: 1
resources:
cpu: 1
memory_gb: 0.5
disk_size_gb: 10
# [START configuration]
endpoints_api_service:
# The following values are to be replaced by information from the output of
# 'gcloud endpoints services deploy openapi-appengine.yaml' command.
name: ingka-rrm-ugc-dev.appspot.com
rollout_strategy: managed
# [END configuration]
Please help me finding where is issue exactly and why api is not working with end point and api key
already enabled all service for for endpoint
gcloud services enable servicemanagement.googleapis.com
gcloud services enable servicecontrol.googleapis.com
gcloud services enable endpoints.googleapis.com
gcloud services enable ingka-rrm-ugc-dev.appspot.com
.
TL;DR: Is there a way to set app client custom scopes via cli or sdk?
I'm trying to automate my Cognito deployment with CloudFormation. I've already made some custom resources since not everything is supported. For this I'm using the AWS JS SDK. I want to set 'Allowed Custom Scopes' for the app clients in a specific user pool. However, I am unable to find how to do this in any documentation AWS provides. The CLI docs say only this on there docs here Cognito-user-identity docs:
AllowedOAuthScopes
A list of allowed OAuth scopes. Currently supported values are "phone", "email", "openid", and "Cognito".
The scopes mentioned there are default scopes that are always available in user pool. But I also use custom scopes that are provided by a Custom Resource Server I've defined. Those look like: resourceServer.com/scope. I can't find any docs about setting those scopes.
So, is there a way to set custom scopes via cli or sdk?
Custom Scope is supported on AllowedOAuthScopes field.
Documentation: https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html#CognitoUserPools-CreateUserPoolClient-request-AllowedOAuthScopes
To update userpool client via CLI: https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/update-user-pool-client.html
(check out the --allowed-o-auth-scopes option)
See example cloudformation below
UserPoolResourceServer:
Type: AWS::Cognito::UserPoolResourceServer
Properties:
Identifier: users
Name: User API
UserPoolId: !Ref UserPool
Scopes:
- ScopeName: "write"
ScopeDescription: "Write access"
- ScopeName: "read"
ScopeDescription: "Read access"
UserPoolClientAdmin:
Type: "AWS::Cognito::UserPoolClient"
Properties:
AllowedOAuthFlows:
- client_credentials
AllowedOAuthFlowsUserPoolClient: true
AllowedOAuthScopes:
- users/read
- users/write
For anyone coming here looking for a solution, please follow #JohnPauloRodriguez's sample template. But you might need to add DependsOn attribute key in the UserPoolClient template for it work.
The reason being, first the Resource Server with these custom scopes should exist, then only we can refer to them in the client. As per the Cloud Formation Docs:
With the DependsOn attribute you can specify that the creation of a
specific resource follows another. When you add a DependsOn attribute
to a resource, that resource is created only after the creation of the
resource specified in the DependsOn attribute.
So the template for UserPoolClient will become:
CognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
DependsOn: UserPoolResourceServer
Properties:
UserPoolId: !Ref UserPool
AllowedOAuthFlowsUserPoolClient: true
AllowedOAuthFlows:
- code
AllowedOAuthScopes:
- users/read
- users/write
I have a custom domain URL (my-custom-domain.com), and the REST API supports query and path parameters.
https://my-custom-domain.com/hello
https://my-custom-domain.com?firstparam=abc&secondparam=def
The invoked lambda has to return the response with some path/query parameters appended to the custom domain URL in json body. Basically the other resources which can be accessed.
Example:
https://my-custom-domain.com/hellofromlambda1123
https://my-custom-domain.com?firstparam=abc&secondparam=yourblogpage&pagenumber=30
An Ideal usecase is pagination, where I have to give the previous and next links. How do I pass the custom domain URL to my lambda.
I am working on node js 8
In conventional JAVA programming we can achieve this by HttpServletRequest.getRequestURL().
What is the way to get the custom Domain URL. I have enabled Headers for DefaultCacheBehavior. The host in the lambda event gives the API gateway URL. Is there a way to get the mapping of the Custom Domain inside lambda?
My Cloud Formation Template for custom domain looks like this
AWSTemplateFormatVersion: '2010-09-09'
Description: Custom domain template
Parameters:
ServiceName:
Description: Name of the Service
Type: String
DeploymentEnv:
Default: dev
Description: The environment this stack is being deployed to.
Type: String
CertificateId:
Description: SSL Certificate Id
Type: String
DomainName:
Description: Name of the custom domain
Type: String
HostedZoneId:
Description: Id of the hosted zone
Type: String
Resources:
APIDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Origins:
- DomainName:
Fn::ImportValue:
!Sub "InvokeURL-${DeploymentEnv}"
Id: !Sub 'Custom-Domain-${DeploymentEnv}'
CustomOriginConfig:
OriginProtocolPolicy: https-only
OriginSSLProtocols: [TLSv1.2]
Enabled: 'true'
DefaultCacheBehavior:
AllowedMethods:
- DELETE
- GET
- HEAD
- OPTIONS
- PATCH
- POST
- PUT
DefaultTTL: 0
TargetOriginId: !Sub 'Custom-Domain-${DeploymentEnv}'
ForwardedValues:
QueryString: 'true'
Cookies:
Forward: none
Headers:
- 'Accept'
- 'api-version'
- 'Authorization'
ViewerProtocolPolicy: https-only
Aliases:
- !Sub '${DomainName}'
ViewerCertificate:
AcmCertificateArn: !Sub '${CertificateId}'
SslSupportMethod: sni-only
MinimumProtocolVersion: TLSv1.2_2018
APIDNSRecord:
Type: AWS::Route53::RecordSet
DependsOn: "APIDistribution"
Properties:
HostedZoneId: !Sub '${HostedZoneId}'
Comment: DNS name for the custom distribution.
Name: !Sub '${DomainName}'
Type: A
AliasTarget:
DNSName: !GetAtt APIDistribution.DomainName
HostedZoneId: Z2FDTNDATAQYW2
EvaluateTargetHealth: false
Outputs:
DomainName:
Value: !GetAtt APIDistribution.DomainName
Thanks to #thomasmichaelwallace for pointing to my post on the AWS Forum that explains a way to inject the original request Host header into an alternate request header, using a Lambda#Edge Origin Request trigger. That is one solution, but requires the Lambda trigger, so there is additional overhead and cost. That solution was really about a CloudFront distribution that handles multiple domain names, but needs to send a single Host header to the back-end application while alerting the application of another request header, which I arbitrarily called X-Forwarded-Host.
There are alternatives.
If the CloudFront distribution is only handling one incoming hostname, you could simply configure a static custom origin header. These are injected unconditionally into requests by CloudFront (and if the original requester sets such a header, it is dropped before the configured header is injected). Set X-Forwarded-Host: api.example.com and it will be injected into all requests and visible at API Gateway.
That is the simplest solution and based on what's in the question, it should work.
But the intuitive solution does not work -- you can't simply whitelist the Host header for forwarding to the origin, because that isn't what API Gateway is expecting.
But there should be a way to make it expect that header.
The following is based on a number of observations that are accurate, independently, but I have not tested them all together. Here's the idea:
use a Regional API Gateway deployment, not Edge-Optimized. You don't want an edge-optimized deployment anyway when you are using your own CloudFront distribution because this increases latency by sending the request through the CloudFront network redundantly. It also won't work in this setup.
configure your API as a custom domain (for your exposed domain)
attaching the appropriate certificate to API Gateway, but
do, not point DNS to the assigned regional domain name API Gateway gives you; instead,
use the assigned regional endpoint hostname as the Origin Domain Name in CloudFront
whitelist the Host header for forwarding
This should work because it will cause API Gateway to expect the original Host header, coupled with the way CloudFront handles TLS on the back-end when the Host header is whitelisted for forwarding.
When using API Gateway + Lambda with the Lambda Proxy integration the event the lambda receives includes the headers.Host and headers.X-Forwarded-Proto keys which can be concatenated to build the full request url.
For example for https://my-custom-domain.com/hellofromlambda1123
{
"headers": {
"Host": "my-custom-domain.com"
"X-Forwarded-Proto": "https"
}
}
Hi i created post api using nodejs express js for my web application and using aws serverless development process but i am getting issue that when i adding more then one post, Options and Get api than last registered api removed from lambda api gateway and therefore i unable to access that previous api, i tried a lot with different solution but no luck yet.
Here my template.yml code and i attached my lambda api gateway screenshot
AWSTemplateFormatVersion: 2010-09-09
Transform:
- AWS::Serverless-2016-10-31
- AWS::CodeStar
Parameters:
ProjectId:
Type: String
Description: AWS CodeStar projectID used to associate new resources to team members
# Enable blue/green deployments using this Globals section. For instructions, see the AWS CodeStar User Guide:
# https://docs.aws.amazon.com/codestar/latest/userguide/how-to-modify-serverless-project.html?icmpid=docs_acs_rm_tr
#
# Globals:
# Function:
# AutoPublishAlias: live
# DeploymentPreference:
# Enabled: true
# Type: Canary10Percent5Minutes
Resources:
HelloWorld:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs6.10
Environment:
Variables:
NODE_ENV: production
Role:
Fn::ImportValue:
!Join ['-', [!Ref 'ProjectId', !Ref 'AWS::Region', 'LambdaTrustRole']]
Events:
GetEvent:
Type: Api
Properties:
Path: /
Method: get
PostEvent:
Type: Api
Properties:
Path: /
Method: post
OptionsEvent:
Type: Api
Properties:
Path: /savefundrisk
Method: options
PostEvent:
Type: Api
Properties:
Path: /savefundrisk
Method: post
OptionsEvent:
Type: Api
Properties:
Path: /saveUpdateLog
Method: options
PostEvent:
Type: Api
Properties:
Path: /saveUpdateLog
Method: post
lambda api gateway screen shot