Add custom domain to API gateway without serverless-domain-manager - amazon-web-services

I want to add a custom domain to the API Gateway using serverless framework but without "serverless-domain-manager" or any other plugin. I am looking for a more native way, maybe extending a resource in "serverless.yml"
All articles suggest that plugin, but it isn't the best for multi environment pipelines
https://www.serverless.com/blog/serverless-api-gateway-domain/

Doing it manually is not that complicated, here is the full explanation
Add a custom domain to all envs
Issue a certificate for the domain in the same region of serverless project, in my case us-east-2
Go to API Gateway > Custom domain names > Create, use Regional endpoint type if using HTTP APIs
In the created domain there is API Gateway domain name, you'll need to point a CNAME record to it
Finally go to API mappings and create the mappings, in my case main and prod with stage $default

API Gateway with a custom domain is configured to use TLS 1.2, and it supports some weak cipher. These weak ciphers are removed in TLS 1.3 which is only supported in CloudFront distributions at the moment.
Some security tools like AppScan raised these issues for me during the security testing of these APIs.
You can check the details here.
https://security.stackexchange.com/questions/254667/are-weak-cipher-suites-for-tls1-2-a-valid-concern
If security is concerned, I would suggest using a cloud front distribution in front of the API gateway.
https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-cloudfront-distribution/

Related

How to route requests to right tenant api gateway?

I am creating a multi tenant silo mode architecture to support a SAAS application. Following this link.
I am able to register new tenants and create their respective stack like this:
So far so good, the next step is to create each tenant its own domain, for example: tenant1.admin.foo.com, to access the same CloudFront distribution (the web front end must be the same for all). I can make this by creating a record in Route53 *.admin.foo.com that has access to CloudFront
THE PROBLEM:
I need to route every request to their respective tenant stack, for example: tenant1.api.foo.com/whatever should route to the api gateway created for tenant1.
At first I thought of creating an origin in CloudFront that routes to the api gateway, the problem with this is that CloudFront origins are limited to 25.
I was thinking in creating a record in Route53 to point to their respective api gateway, but the problem is that I will have to use custom domain in the api gateway, because they are limited to 120, and I expect to have more tenants than 120.
How can I make this routing?
Here is an illustration of a use case:
PS: Any advice is welcome.
You can setup a distribution with a wildcard (*.api.foo.com) set for the Alternate Domain Name (CNAMEs). If you attach a Lambda#Edge to the Origin Request (Under Cache Behavior settings), you can dynamically modify the host header to point to the appropriate API Gateway host (xxxxxx.execute-api.us-east-1.amazonaws.com).
AWS Blog where they did this, with S3 buckets for the origin.
It should translate fairly closely to APIGateway hostnames instead:
https://aws.amazon.com/blogs/networking-and-content-delivery/dynamically-route-viewer-requests-to-any-origin-using-lambdaedge/

Does AWS API Gateway RestAPI allow the creation of path based versioning at the API RestAPI level natively?

For example, Azure API Management service allows the creation of an API "proxy" front end and the ability to create an api version such as
https://baseapi.com/apiName1/v1
Here is screenshot of that in Azure platform.
https://learn.microsoft.com/en-us/azure/api-management/api-management-get-started-publish-versions
Does AWS API Gateway RestAPIs allow this type of versioning natively?
If it does, how can I setup for example "v1" of a restAPI?
And if the AWS RestAPI "Stage" is the way to accomplish this, how would I still support the idea of creating stages per environment, while still doing versioning? To me stage seems more associated with environments, whereas versioning is a completely separate concept.
Note: The rest APIs are private
First limitation of private APIs from the documentation is the following:
Custom domain names are not supported for private APIs.
This limits what you can do with API Gateway to support multiple versions.
Run an API Gateway per version - This option grants you complete separation between API versions, however, unfortunately you will need to call a separate endpoint per API.
Deploy a single private API Gateway containing all API versions - This option scopes everything to a single endpoint but as a limitation could become quite complex and hard to manage depending on the number of verbs.
Hopefully in the future this feature from custom domains detailed below will be added.
Previous Answer - Before known using Private API
This can be done in API Gateway through the combination of stages and custom domain configuration.
If you deploy each version of API Gateway to either its own stage i.e. v1, v2 stage you have seperated the schema and actions between the versions.
Alternatively you can have a separate API and stage for each version of your specific API.
Then create a custom domain name for your API endpoint, under base path mappings you can map a specific subfolder v1 to the API and select the v1 stage in your API Gateway endpoint.

Auth between AWS API Gateway and Elastic Cloud hosted Elasticsearch

We're configuring an AWS API Gateway proxy in front of Elasticsearch deployed on Elastic Cloud (for throttling, usage plans, and various other reasons). In order to authenticate between the Gateway and ES, one idea is to configure an integration request on the API Gateway resource to add an Authorization header with creds created in ES. Is this the best strategy? It seems inferior to IAM roles, but that option isn't available as they're not accessible for the ES instance (Elastic Cloud hosts our deployment on AWS, but it's not a resource under our control). The API Gateway itself will require an API key.
I am not an expert at Elasticsearch, but it sounds like you want to securely forward a request from API gateway to another REST web service. Because Elasticsearch is an external REST web service to AWS, you will not have access to IAM roles. I had a similar integration to another cloud rest service (not elasticsearch) will do my best to review the tools in AWS that are available to complete the request.
One idea is to configure an integration request on the API Gateway resource to add an Authorization header with creds created in ES. Is this the best strategy?
This is the most straightforward strategy. In API Gateway, you can map custom headers in the Integration Request. This is where you will map your Authorization header for Elastic Search.
Similarly you can map your Authorization Header as a "Stage Variable" which will make it easier to maintain if the Authorization Header will change across different Elasticsearch environments.
In both strategies, you are storing your Authorization Header in API Gateway. Since the request to Elasticsearch should be HTTPS, the data will be secure in transit. This thread has more information about storing credentials in API Gateway.
From MikeD#AWS: There are currently no known issues with using stage variables to manage credentials; however, stage variables were not explicitly designed to be a secure mechanism for credentials management. Like all API Gateway configuration information, stage variables are protected using standard AWS permissions and policies and they are encrypted when transmitted over the wire. Internally, stage variables are treated as confidential customer information.
I think this applies to your question. You can store the Authorization Header in the API Gateway Proxy, however you have to acknowledge that API Gateway Configuration information was not explicitly designed for sensitive information. That being said, there are no known issues with doing so. This approach is the most straightforward to configure if you are willing to assume that risk.
What is a more "AWS" Approach?
An "AWS" approach would be to use the services designed for the function. For example, using the Key Management Service to store your Elasticsearch Authorization Header.
Similarly to the tutorial referenced in the comments, you will want to forward your request from API Gateway to Lambda. You will be responsible for creating the HTTPS request to Elasticsearch in the language of your choice. There are several tutorials on this but this is the official AWS documentation. AWS provides blueprints as a template to start a Lambda Function. The Blueprint https-request will work.
Once the request is being forwarded from API Gateway to Lambda, configure the authorization header for the Lambda request as an Environment Variable and implement Environment Variable Encryption. This is a secure recommended way to store sensitive data, such as the Elasticsearch authorization header.
This approach will require more configuration but uses AWS services for intended purposes.
My Opinion: I initially used the first approach (Authorization Headers in API Gateway) to authenticate with a dev instance because it was quick and easy, but as I learned more I decided the second approach was more aligned with the AWS Well Architected Framework

Use a sub-domain for a API-gateway/Lambda

I am integrating a web-relay into AWS-service which makes call-outs to a predefined path (
/some-fixed-path and it can not be configured) and I want to intercept it using a lambda on dedicated sub-domain, to keep this separated from the rest of our service, so I want the call-out to be http://subdomain.example.com/some-fixed-path.
I have a domain (lets call it example.com) registered and I have a hosted-zone defined. How can i create a record-set in the hosted-zone and use it in the API-gateway definition? (The url must not contain the stage...)
In the API-gateway definition, there is a "Custom domain name" option, but I can't figure out how to point to a record from my hosted-zone.
You should simply be able to follow the instructions for using a custom domain and then adding an alias record in your hosted zone to the CloudFront distribution provided by the API Gateway console.
You'll want to configure your custom domain with the base path pointing to your deployed stage. At that point you can than create your resource at some-fixed-path.
Note: API Gateway currently requires all APIs to be HTTPS, so if your call out can't be changed to support HTTPS, API Gateway will not work for this use case.
AWS has a detailed guide about how to do that exactly.
A few more things to pay attention to are:
Make sure you remember to re-deploy when you make any change to the API.
When you set up Base Path Mapping, make sure double check the API resource path and method. (For example, if you create the API gateway through lambda template, the API resource will be created under /{API name} instead of /).
A lot of people see Missing Authentication Token when they use API gateway for the first time due to those reasons.

How can I change name of my Lambda Functions API endpoint

I've created couple of AWS Lambda functions which are invoked via API Gateway Proxy request. Note that I am using Serverless framework for deployment. Also, I am using AWS SAM for testing lambda functions locally.
Once I've deployed my lambda function, its API endpoint looks something like this: https://38sp8vme5j.execute-api.us-east-1.amazonaws.com/{STAGE}/{PATH}
I would like to know if there is a way to change 38sp8vme5j.execute-api this part of my API endpoint.
Thanks in advance
In the API Gateway area, you have a option in the left menu called Custom Domain Names where you can set a specific domain you already have and set an alias to the specific Lambda function you want to run.
The Route 53 service is not necessary, you only need to register the domain in the certificates area ACM to have it available in this custom domain names option in API Gateway
You may not be able to change the portion 38sp8vme5j.execute-api of your full domain name but you can surely add a new Alias DNS records in Route53 to use a different domain that you own.
There is an alternative and easier way to give custom domain names in the API gateway itself using the "Custom Domain Names" option as shown here.
Just fill in the details and provide an ACM certificate for HTTPs.