Best Practices for Serverless Endpoints on AWS

Modernizing Security: AWS Series - Security Best Practices for Serverless Applications on AWS

Modernizing Security: AWS Series - Security Best Practices for Serverless Applications on AWS

How to Use AWS Services to Secure your Endpoints Without Provisioning Infrastructure

This is the second in a series of posts about best security practices for serverless applications running in AWS. Serverless applications free you from much of the pain and complication that comes with traditional infrastructure management, which can get your product to market much faster. They also come with some unique security considerations. In the previous installment, we discussed how to secure the Lambda execution environment itself, and now we move on to endpoint security.

Your application almost certainly exposes HTTP endpoints, and serverless endpoints have many of the same security concerns as legacy endpoints. Thankfully, AWS boasts a variety of services to help you secure your transport layer and offload authentication logic, as well as providing multiple options for exposing your Lambdas to HTTP events in the first place.

In this post we’ll discuss how to choose a technology for exposing your Lambdas, how to get free and secure TLS/SSL certificates from AWS, and how to separate authentication and authorization logic from your business logic with custom authorizers.

In the next post we’ll explore how to tie that all together with Web Application Firewall and CloudFront to provide layered Defense in Depth for your serverless web app.

Transport Layer Security: AWS Certificate Manager

The internet is rapidly moving away from insecure HTTP connections in favor of encrypted connections over HTTPS. Public HTTPS connections require certificates signed by a recognized Certificate Authority, and these were once expensive and difficult to provision and manage, which was a significant barrier to the widespread adoption of secure HTTP connections.

There are now several providers of free SSL/TLS certificates, including the very popular Let’s Encrypt, but the AWS Certificate Manager (ACM) is your best choice for generating and managing certificates in AWS.

Certificate Manager will issue free public certificates for any domain you control, and even supports wildcards. You can validate that you own a domain by creating a DNS record, or with an email to the domain’s publicly registered owner. If your DNS is hosted with Route 53, Certificate Manager will even create the DNS records for you automatically.

Most importantly - Certificate Manager will automatically renew and rotate your certificates for you, and deploy them when they’re renewed. When you configure an Application Load Balancer or an API Gateway custom domain, you can simply specify an ACM certificate and AWS takes care of the rest. Once it’s set up, you never have to worry about your certificates expiring again.

Application Load Balancer (ALB) vs. API Gateway

There are two options for triggering your Lambda functions with HTTP requests. Until recently, API Gateway was the only option, but AWS recently added support for Lambda functions as targets for Application Load Balancers as well. Both options support TLS/SSL with ACM certificates (in fact, API Gateway requires it).

ALB integration with Lambda is straightforward and relatively bare-bones in terms of features when compared with API Gateway. API Gateway is a feature-rich service with many options, and it provides two different endpoint types with different feature sets and price points, depending on your requirements and budget.

ALBs are cheaper per-request than either API Gateway option, even with tiered pricing and the newer, cheaper HTTP API type. API Gateway still has a significant security advantage, however, in the form of custom authorizers.

If you need features like rate limiting, automatic SDK generation, request validation and transformation, or the authorizer features we’re about to discuss, API Gateway is a great choice, if it fits in your budget.

If you implement those features yourself or don’t need them, or if you just want to add some Lambdas to an existing web app that already sits behind an ALB, direct ALB integration might be a better choice.

API Gateway: Authorizers

One of the biggest security advantages to using API Gateway is Authorizers. Authorizers let you separate your authentication and authorization logic from your business logic, by essentially delegating those decisions to API Gateway before your business logic is invoked. Unauthorized requests are gated before they reach your API, so your business logic can simply retrieve the authorized principal from the request context and execute, knowing it can not be invoked in an unauthorized context. This makes for cleaner code and very neat separation of concerns.

API Gateway can be configured to use AWS-provided authorizers for Cognito User Pools, IAM Roles, and JWTs from OpenID Connect / OAuth 2 identity providers, or you can even write your own authorizer by specifying an arbitrary Lambda function.

Support for different authorizer types varies depending on what kind of endpoint type you have configured in API Gateway.

Authorizer Type HTTP API REST API
Cognito User Pools x x
IAM (Federated Identities) x
Custom Lambda x
OpenID Connect / OAuth 2 x

Cognito User Pools

If you’re already using Cognito User Pools for your application, AWS provides an integration with API Gateway that just works out of the box. This is the only authorizer option that is available for both HTTP and REST API types.

API Gateway will inspect an HTTP header for the token issued by Cognito, verify its signature, and check that it’s still valid before invoking your Lambda function. If it’s not, it will automatically redirect the user to your Cognito auth flow.

AWS provides detailed instructions for configuring the authorizer here, but the process is essentially as simple as specifying a User Pool, and which HTTP header to check for the bearer token.

Cognito User Pools

Cognito User Pools

In this setup, the authorizer is just checking to see if the user is a valid user in your pool, and the Lambda is invoked with its normal execution role. It does not give you a way to differentiate between different types of users and assign finer-grained permissions. For that kind of fine-grained authorization, you’ll need to use one of the following other options.

IAM-based Authorization (Cognito Federated Identities)

API Gateway also supports IAM-based authorization, by integrating with Cognito Federated Identities (also confusingly referred to as Cognito Identity Pools). This type of authorizer is only supported if you’re using a REST endpoint type with API Gateway.

Like the User Pools authorizer, the client first authenticates with Cognito and receives a JWT. Instead of passing that token directly to API Gateway and making a request, however, the token is sent to Cognito Federated Identities and exchanged for a set of temporary IAM credentials, which can be attached to any IAM policy you care to specify. Cognito Federated Identities allows you to configure which IAM roles are assigned to which users in your pool.

Those IAM credentials are then used to make requests to API Gateway by signing the requests with Signature V4, which is the same request signature used for all other AWS APIs. When API Gateway receives a request with this signature, it knows what IAM role is making the request, and it can check what policies are associated with that role.

IAM-based Authorization (Cognito Federated Identities)

IAM-based Authorization (Cognito Federated Identities)

Since each request now has a specific IAM role, you can use this method to implement fine-grained access control by allowing or denying permission to invoke specific Lambda functions in the IAM roles assigned to your users.

A custom IAM policy used in this method that provides finer-grained access control might look like:

{
   "Version": "2012-10-17",
   "Statement": [
       {
           "Action": "execute-api:Invoke",
           "Effect": "Allow",
           "Resource": "arn:aws:execute-api:*:*:ff5h7fdsed/*"
       },       
       {
           "Action": "execute-api:Invoke",
           "Effect": "Deny",
           "Resource": "arn:aws:execute-api:*:*:ff5h7fdsed/*/POST/inventory"
       }
   ]
}

In this example, the user is allowed to access any operation in the API except POSTs to /inventory.

Lambda Authorizers

If you’re not using Cognito, or if you need to implement custom logic, API Gateway also provides the option of specifying your own Lambda Authorizer. Like the IAM-based authorizer above, this option is only available for REST endpoint types in API Gateway.

(Note: AWS previously referred to these as “Custom Authorizers”, and you may still see documentation using the terms interchangeably.)

Lambda Authorizers are Lambda functions that API Gateway will invoke before your business logic to perform authentication and authorization. They have the advantage of allowing you to authenticate against any identity provider (IdP), or implement any custom authentication scheme of your choice, as long as your identity provider issues a bearer token you can send to API Gateway when making requests.

Lambda Authorizers

Lambda Authorizers

Before invoking your custom authorizer, API Gateway will inspect an HTTP header of your choice for the bearer token, and check its own local cache for a known valid policy associated with that token. If it finds no policy cached, it will invoke your custom authorizer.

Your custom authorizer function examines the HTTP request and can either reject it outright as unauthorized, or accept the request and return an IAM policy document that will be used to invoke the underlying Lambda. Much like the Federated Identities example, this IAM policy document can be used for finer-grained access control.

OpenID Connect / OAuth 2 (JWT Authorizers)

HTTP endpoint types in API Gateway are an attempt by AWS to simplify the vast array of (often unneeded) features provided by the older REST endpoint type. If you’re not going to use the Cognito User Pool authorizer with an API of this type, your other option is to use native support for OpenID Connect (OIDC) or OAuth 2.0 to secure your API.

AWS refers to this as “JWT Authorizers”, and the flow is similar to the Cognito User Pool flow above, except that instead of using Cognito as the IdP, API Gateway validates the JWT using the public key fetched from the issuer’s jwks_uri, and then checks that the various claims in the token are valid. If any of the checks fail, API Gateway denies the request.

OpenID Connect / OAuth 2 (JWT Authorizers)

OpenID Connect / OAuth 2 (JWT Authorizers)

After the token is validated, API Gateway will take all the claims in the token and pass them to the Lambda backend. For example, if the validated token includes an emailIDclaim, that will be available in the Lambda context as $context.authorizer.claims.emailID.

What’s Next

Once you’ve picked a strategy for exposing your endpoints, secured them with TLS/SSL, and wired up an authentication system, the next step is to secure your application against common attacks.

AWS provides tools like the Web Application Firewall (WAF) and CloudFront that can help you fend off cross-site scripting (XSS), SQL injection, distributed denial of service (DDoS), and other common attack types. We’ll dive into those in the next installment of this series on serverless best practices.


Connect with ScaleSec for AWS business

ScaleSec is an Advanced Consulting Partner guiding AWS customers through security and compliance challenges. ScaleSec’s compliance advisory and implementation services help teams leverage cloud-native services on AWS. We are hiring!

Connect with ScaleSec for AWS business.

Cloudknocking

Using Cloud Native Services to Obfuscate Command and Control.

Previous article

Here for you

Have questions? Leverage our expertise to help you meet your business goals with a strong security posture.

Join us

ScaleSec is a well-connected, fully remote team. We thrive in the great undocumented beyond. We’re hiring in most US metros.

Get in touch

Considering cloud? Want to optimize and transform your existing digital portfolio?
Reach out to us.

Gap Assessment

Get perspective. Address security comprehensively.

Prepare for compliance.

ScaleSec
San Diego, CA 92120, United States

619-SCALE15

© 2020 ScaleSec. All rights reserved. | Privacy Policy