We are in the process of setting up api gateway with Lamba function behind it. The setup uses aws cognito authorizer. We have the VPC endpoint for api gateway so that is reachable through private IP.
But cognito does not support private links so we can't have the VPC endpoint for it. So this means the token issued by Cognito has to travel from https://ourdomain.auth.ap-southeast-2.amazoncognito.com to client over the internet.
Cognito documentation says following for data in transit:-
" Encryption in transit
All requests to Amazon Cognito must be made over the Transport Layer Security protocol (TLS). Clients must support Transport Layer Security (TLS) 1.0 or later. We recommend TLS 1.2 or later. Clients must also support cipher suites with perfect forward secrecy (PFS) such as Ephemeral Diffie-Hellman (DHE) or Elliptic Curve Ephemeral Diffie-Hellman (ECDHE). Most modern systems such as Java 7 and later support these modes."
According to above the token should be encrypted.
But I have following questions:
Is TLS (1.2) enforced for Cognito?
with encryption in transit being available would security best practices still dictate having Cognito available through VPC endpoint so that the token does not need to travel on internet.
if a client application is coming from on-prem environment and accessing the api then if we make it go through a proxy in AWS then will the traffic remain in AWS backbone network or still flow through internet?
Is TLS (1.2) enforced for Cognito:
Unfortunately, no. For most API calls you could use API gateway as a layer in between and enforce TLS1.2 there. However, for the AUTHORIZATION and TOKEN endpoints this does not work.
Alternatively, you can enforce it for all endpoints by deploying cognito to the US regions and using the FIPS endpoints of cognito there. See https://docs.aws.amazon.com/general/latest/gr/cognito_identity.html for the available fips endpoints.
with encryption in transit being available would security best practices still dictate having Cognito available through VPC endpoint so that the token does not need to travel on internet:
That all depends on your risk apetite. For most organizations, encryption will be sufficient. However if your risk apetite is lower, you'll want extra mitigations, following the "defense in depth" best practice. Private connectivity is just one option if many you could add. Monitoring on suapicious user activity and adaptable MFA are other methods for example.
if a client application is coming from on-prem environment and accessing the api then if we make it go through a proxy in AWS then will the traffic remain in AWS backbone network or still flow through internet?
As the api endpoints are public, they will go over the internet (public ip address, so it's routed to a NAT gateway or internet gateway).
EDIT:
In this press release, AWS states all endpoints have TLS1.2 minimum:
https://aws.amazon.com/blogs/security/tls-1-2-required-for-aws-endpoints/. However, I haven't tested if this also applies to non-control-plane API's like the ones mentioned above.
Related
There are two versions of the AWS API Gateway:
REST version
HTTP version (v2)
I am using the newer HTTP version with a lambda authorizer and would like to protect my staging/test environments from outside requests. One idea is to put a WAF in front of the API gateway, but unfortunately only the REST version of the gateway supports a WAF.
Any suggestions for how to protect these resources so they can only be accessed from a specific IP range? (Company VPN)
When using API Gateway, the HTTP API type misses some of the Security options that we have available when comparing it with a REST API, as we can see in the following table:
Security
HTTP API
REST API
Mutual TLS authentication
✓
✓
Certificates for backend authentication
✓
AWS WAF
✓
Resource policies
✓
A full comparison can be found here.
To protect your HTTP API from certain threats, like malicious users or spikes in traffic the API Gateway provides by default the options of setting throttling targets or/and enabling mutual TLS.
To understand more about these default options, take a look on this page Protecting your HTTP API.
If you want to use WAF, you can create a private integration with ALBs, that supports WAF, which means you can get the benefits of WAF while still enjoying the lower cost and higher performance of HTTP APIs.
Your architecture can be similar with the following one:
To understand more about these integrations, take a look on this page: Best Practices for Designing Amazon API Gateway Private APIs and Private Integration.
You can create private Api Gateways using the tags aws:SourceVpc and aws:SourceVpce in the Api resource policy.
link to aws official documentation
I have built an AWS API Gateway API endpoint which will be hit by one of the machines of my company's network to POST data every regular interval. But, the office firewall blocks it when I try it from office network through Postman (but when I use mobile hotspot/other wifi, it works seamlessly due to no firewall challenge), so I have to give the range of IP addresses to be white-listed by the office network team to be able to hit the API endpoint.
Where to get the IPs? Will they be constant or changing? Since it is a long process of raising tickets for IPs to be white-listed by the network security team, is there a smooth process on the same?
Also, is there a risk associated to this way of data push from on-prem to cloud? I've already implemented AWS IAM Authorization and also API-Key for security and access control. If there still is a risk, how to make this process totally secured?
Please help!
Unluckly you can not give a static IP to an API Gateway as it can change without notice, that is by AWS Design. What you can do in such case is to have a reverse poxy with and elastic IP associated that will transparently route your http traffic to the API Gateway (Then you need a domain name and a certificate because you will not use the APIGateway name anymore)
Also, is there a risk associated to this way of data push from on-prem
to cloud? I've already implemented AWS IAM Authorization and also
API-Key for security and access control. If there still is a risk, how
to make this process totally secured?
There's nothing totally secured in any organization, but in order to secure in transit data, you should use an encrypted channel like https (which is natively supported by API Gateway). That is why you need a domain name and a certificate for the proxy
how about:
https://www.reddit.com/r/aws/comments/8f1pve/whitelisting_aws_api_gateway/
API Gateway is proxied through Cloudfront so you could whitelist the IPs here that are for the CLOUDFRONT service. The ips are rotated so you’ll need to update your whitelist every
There is an SNS topic that you can subscribe to that sends out the IP ranges of AWS services whenever they are updated.
https://aws.amazon.com/blogs/security/how-to-automatically-update-your-security-groups-for-amazon-cloudfront-and-aws-waf-by-using-aws-lambda/
https://aws.amazon.com/blogs/aws/subscribe-to-aws-public-ip-address-changes-via-amazon-sns/
Unless it's a regional APIGW endpoint.
This explains the IPs of AWS https://docs.aws.amazon.com/general/latest/gr/aws-ip-ranges.html
You need the ranges for the "EC2" service for the region where your API Gateway is deployed.
To me it was not clear enough to know which of the IP ranges in the JSON are those of API Gateway endpoints. I made a few experiments with nslookup and found out that you need the ranges for the "EC2" service using a script like this one:
const IPCIDR = require("ip-cidr");
const ipRanges = require('./ips.json');
const relevantRanges = ipRanges.prefixes.filter(el => {
const cidr = new IPCIDR(el.ip_prefix);
// Those IPs I get from `nslookup` to my endpoint. They belong to EC2 of the region
return cidr.contains('3.5.136.1') || cidr.contains('18.192.0.1');
});
console.log(JSON.stringify(relevantRanges, undefined, 2));
You could use it for experiments to find out what service and ranges are responsible for an endpoint.
I want to secure a REST API with mutual authentication on AWS. This means, only clients with a specific client certificate should be able to access the API. What is the best way to secure a REST API on AWS with mutual authentication?
I know, there is client certificate support for API Gateway, but this is not what I am looking for. As far as I understand, this only authenticates Api Gateway against backend and is not able to authenticate clients to Api gateway.
Is Api Gateway, Load balancer or any other AWS product able to do mutual authentication to secure a rest API or do I need to implement this by my own?
You'll have to do this on your servers.
None of the services that terminate TLS and forward requests or connections to your app tier -- Elastic Load Balancers (Classic, Application, and Network), CloudFront, or API Gateway -- support TLS mutual auth.
Of course, a Network Load Balancer without TLS termination or a Classic Load Balancer in TCP mode will pass-through your payload, whatever it is, so either of these can be used in front of your servers, but the servers will need to handle all the TLS.
Also, your conclusion is correct that API Gateway's client certificates are not what you are looking for. They work as you described them.
As of 17th September, 2020, support for Mutual Authentication using TLS is available on AWS API Gateway: https://aws.amazon.com/about-aws/whats-new/2020/09/amazon-api-gateway-supports-mutual-tls-authentication/ . It can be used to authenticate clients calling an API on API Gateway.
tldr: See bold generic questions below.
I have built the infrastructure outlined below(in attachment) in AWS. OAuth specifies an auth server which issues tokens(Authorizes) and then authenticates tokens on each request and allows a proxy to the internal ALB.
It's based on a micro-services architecture and uses oauth to issue tokens and authenticate them from the client apps. The client apps could be apps inside the VPC or apps external to the VPC. As you can see I want all requests to go through OAuth server before they get to the internal ALB. Now the different types of apps should use different types of grants to get an access tokens. Those access tokens will contain a scope which relates to the routes(API endpoints) of the internal ALB.
Now I have a few questions which I hope are as succinct as possible:
AWS VPC ALB Questions
What is the most secure way of insuring that only the oauth apps communicate with the internal ALB and not other apps in the public subnet? So we can be sure that all requests to the internal ALB are authenticated? Do I have to somehow attach a new oauth only subnet to the input of internal ALB but how do I restrict the internal ALBs input?
To the same end, how do I ensure apps in the same subnet do not communicate with each other? Basically, how do I ensure that no internal apps communicate with each other and must be passed all the way to the external load balancer and therefore to oauth from the private subnet.
Route 53 SLL termination ALB
Does SSL termination on certain port stop traffic directed from different domains. If I make a call to ALB port 433 from internal ALB with SSL termination do I have to call from the host(route53 something.com) specified by the certificate or can I use the DNS hostname of the ALB(something.elb.amozonaws.com) resolved by AWS ok?
Scopes and OAuth
How to compare each request's url and it's token with oauth scopes? I want to relate oauth scopes to api endpoints. So each request goes to a route endpoint with an access_token which contains scopes. This scope will have to be compared with the request url on each request to make sure it’s allowed. Does oauth come with this functionality? I would guess not. However whats the point of scopes if this is not the case? Seems like scope is just an array I need to do some processing on after authentication rather than it being special in oauth. I’m probably missing something :-).
This post is too long already so I can’t for obvious reasons get into all the details but if you would like more detail I would of course give them. Even a help in the right direction would be useful at this point.
Thanks in advance.
This does not make sense to me at all. When you create a new API Gateway you can specify whether it should be regional or edge-optimized. But then again, when you are creating a custom domain name for API Gateway, you can choose between the two.
Worst of all, you can mix and match them!!! You can have a regional custom domain name for an edge-optimized API gateway and it's absolutely meaningless to me!
Why these two can be regional/edge-optimized separately? And when do I want each of them to be regional/edge-optimized?
Why these two can be regional/edge-optimized separately?
Regional and Edge-Optimized are deployment options. Neither option changes anything fundamental about how the API is processed by the AWS infrastructure once the request arrives at the core of the API Gateway service or how the services behind API Gateway ultimately are accessed -- what changes is how the requests initially arrive at AWS and are delivered to the API Gateway core for execution. More about this, below.
When you use a custom domain name, your selected API stage is deployed a second time, on a second endpoint, which is why you have a second selection of a deployment type that must be made.
Each endpoint has the characteristics of its deployment type, whether regional or edge-optimized. The original deployment type of the API itself does not impact the behavior of the API if deployed with a custom domain name, and subsequently accessed using that custom domain name -- they're independent.
Typically, if you deploy your API with a custom domain name, you wouldn't continue to use the deployment endpoint created for the main API (e.g. xxxx.execute-api.{region}.amazonaws.com), so the initial selection should not matter.
And when do I want each of them to be regional/edge-optimized?
If you're using a custom domain name, then, as noted above, your original deployment selection for the API as a whole has no further impact when you use the custom domain.
Edge-optimized endpoints were originally the only option available. If you don't have anything on which to base your selection, this choice is usually a reasonable one.
This option routes incoming requests through the AWS "Edge Network," which is the CloudFront network, with its 100+ global edge locations. This does not change where the API Gateway core ultimately handles your requests -- they are still ultimately handled within the same region -- but the requests are routed from all over the world into the nearest AWS edge, and they travel from there on networks operated by AWS to arrive at the region where you deployed your API.
If the clients of your API Gateway stage are globally dispersed, and you are only deploying your API in a single region, you probably want an edge-optimized deployment.
The edge-optimized configuration tends to give you better global responsiveness, since it tends to reduce the impact of network round trips, and the quality of the transport is not subject to as many of the vagaries of the public Internet because the request covers the least amount of distance possible before jumping off the Internet and onto the AWS network. The TCP handshake and TLS are negotiated with the connecting browser/client across a short distance (from the client to the edge) and the edge network maintains keep-alive connections that can be reused, all of which usually works in your favor... but this optimization becomes a relative impairment when your clients are always (or usually) calling the API from within the AWS infrastructure, within the same region, since the requests need to hop over to the edge network and then back into the core regional network.
If the clients of your API Gateway stage are inside AWS and within the same region where you deployed the API (such as when the API is being called by other systems in EC2 within the region), then you will most likely want a regional endpoint. Regional endpoints route requests through less of the AWS infrastructure, ensuring minimal latency and reduced jitter when requests are coming from EC2 within the same region.
As a side-effect of routing through the edge network, edge-optimized endpoints also provide some additional request headers that you may find useful, such as CloudFront-Viewer-Country: XX which attempts to identify the two-digit country code of the geographic location of the client making the API request. Regional endpoints don't have these headers.
As a general rule, go with edge-optimized unless you find a reason not to.
What would be some reasons not to? As mentioned above, if you or others are calling the API from within the same AWS region, you probably want a regional endpoint. Edge-optimized endpoints can introduce some edge-case side-effects in more advanced or complicated configurations, because of the way they integrate into the rest of the infrastructure. There are some things you can't do with an edge-optimized deployment, or that are not optimal if you do:
if you are using CloudFront for other sites, unrelated to API Gateway, and CloudFront is configured for a wildcard alternate domain name, like *.example.com, then you can't use a subdomain from that wildcard domain, such as api.example.com, on an edge-optimized endpoint with a custom domain name, because API Gateway submits a request to the edge network on your behalf to claim all requests for that subdomain when they arrive via CloudFront, and CloudFront rejects this request since it represents an unsupported configuration when used with API Gateway, even though CloudFront supports it in some other circumstances.
if you want to provide redundant APIs that respond to the same custom domain name in multiple regions, and use Route 53 Latency-Based Routing to deliver requests to the region nearest to the requester, you can't do this with an edge-optimized custom domain, because the second API Gateway region will not be able to claim the traffic for that subdomain on the edge network, since the edge network requires exactly 1 target for any given domain name (subdomain). This configuration can be achieved using regional endpoints and Route 53 LBR, or can be achieved while leveraging the edge network by using your own CloudFront distribution, Lambda#Edge to select the target endpoint based on the caller's location, and API Gateway regional deployments. Note that this can't be achieved by any means if you need to support IAM authentication of the caller, because the caller needs to know the target region before signing and submitting the request.
if you want to use your API as part of a larger site that integrates multiple resources, is deployed behind CloudFront, and uses the path to route to different services -- for example, /images/* might route to an S3 bucket, /api/* might route to your API Gateway stage, and * (everything else) might route to an elastic load balancer in EC2 -- then you don't want to use an edge-optimized API, because this causes your requests to loop through the edge network twice (increasing latency) and causes some header values to be lost. This configuration doesn't break, but it isn't optimal. For this, a regional endpoint is desirable.