Solution components
Waiting room public and private APIs
The Virtual Waiting Room on AWS solution’s primary purpose is to control the generation of JSON Web Tokens (JWT) for clients in a controlled way to avoid bursts of new users that might overwhelm the destination website. The JWTs can be used for site protection, preventing access to web pages until the waiting room token is obtained, and also for API access authorization.
The core template installs a public API and private (IAM-authorized) API used for most Virtual Waiting Room on AWS operations. The public API is configured with a CloudFront distribution with multiple caching policies based on the API path. A DynamoDB table and EventBridge event bus are created. The template adds a new VPC with two Availability Zones (AZs), an Elasticache (Redis OSS) cluster in both AZs, and several Lambda functions. Lambda functions that interact with Elasticache (Redis OSS) have network interfaces within the VPC and all other Lambda functions have default network connectivity. The core APIs are the lowest layer of interaction with the solution. Other Lambda functions, Amazon Elastic Compute Cloud (Amazon EC2) instance, and containers can act as extensions and call the core APIs to build waiting rooms, control inlet traffic, and react to events generated from the solution.
In addition, the core stack creates an alarm for all of its Lambda function errors and throttle conditions, as well as alarms for each API Gateway deployment for 4XX and 5XX status codes.
-
CloudFront distribution delivers public API calls for the client and caches result where appropriate.
-
Amazon API Gateway public API process queue requests from the virtual waiting room, track the queue position, and support validation of tokens that allow access to the target website.
-
SQS queue regulates traffic to the AWS Lambda function that processes the queue messages.
-
The
AssignQueueNum
Lambda function validates each message in its batch received, increments the queue counter in Elasticache (Redis OSS), and stores each request in Elasticache (Redis OSS) with its associated queue position. -
The
GetPublicKey
Lambda function retrieves the public key value from Secrets Manager. -
The
GenerateToken
Lambda function generates a JWT for a valid request that has been allowed to complete its transaction at the target site. It writes an event to the waiting room’s custom event bus that a token has been generated. If a token has been previously generated for this request, no new token is generated. -
The
GetQueueNumber
Lambda function retrieves and returns the client’s numeric position in the queue from Elasticache (Redis OSS). -
The
GetServingNumber
Lambda function retrieves and returns the number currently being served by the waiting room from Elasticache (Redis OSS). -
The
GetWaitingNum
Lambda function returns the number currently queued in the waiting room and have yet to be issued a token. -
VPC endpoints allow Lambda functions in the VPC to communicate with services within the solution.
-
Elasticache (Redis OSS) cluster stores all requests to enter the waiting room with a valid Event ID. It also stores several counters like number of requests enqueued, number currently being served, number of tokens generated, number of sessions completed, and number of sessions abandoned.
-
API Gateway private API resources to support administrative functions. The private APIs are AWS IAM authenticated.
-
The
GetExpiredTokens
Lambda function returns a list of request IDs with expired tokens. -
The
AuthGenerateToken
Lambda function generates a token for a valid request that has been allowed to complete its transaction at the target site. The issuer and the validity period of a token initially set during the core stack deployment can be overridden. It writes an event to the waiting room’s custom event bus that a token has been generated. If token has been previously generated for this request, no new token is generated. -
The
IncrementServingCounter
Lambda function increments the waiting room’s serving counter stored in Elasticache (Redis OSS) given an increment by value. -
The
GetNumActiveTokens
Lambda function queries DynamoDB for the number of tokens that have yet to expire, have not been used to complete its transaction, and have not been marked abandoned. -
The
ResetState
Lambda function resets all counters stored in Elasticache (Redis OSS). It also deletes and recreates theTokenTable
,QueuePositionEntryTime
, andServingCounterIssuedAt
DynamoDB tables. Additionally, it performs CloudFront cache invalidation. -
The
UpdateSession
Lambda function updates the status of a session (token) stored in theTokenTable
DynamoDB table. Session status is denoted by an integer. Sessions set to a status of1
indicates completed, and-1
indicates abandoned. It writes an event to the waiting room’s custom event bus that a session has been updated. -
The
TokenTable
DynamoDB table stores token data. -
The
QueuePositionEntryTime
DynamoDB table stores queue position and entry time data. -
The
ServingCounterIssuedAt
DynamoDB table stores updates to the serving counter. -
The
GetQueuePositionExpireTime
Lambda function is invoked when the client requests the remaining queue position expiry time. -
The
SetMaxQueuePositionExpired
Lambda function sets the maximum queue position that has expired corresponding to theServingCounterIssuedAt
table values. It runs every minute if theIncrSvcOnQueuePositionExpiry
parameter is set totrue
during core stack deployment. -
The
GenerateEvents
Lambda function writes various waiting room metrics to the waiting room's custom event bus. It gets run every minute if the Enable Events Generation parameter is set totrue
during core stack deployment. -
AWS Secrets Manager stores keys for token operations and other sensitive data.
-
Amazon EventBridge custom event bus receives an event every time a token is generated and a session is updated in the
TokenTable
DynamoDB table. It also receives events when the serving counter is moved in theSetMaxQueuePositionExpired
Lambda. It gets written to with various waiting room metrics, if activated during core stack deployment. -
Amazon CloudWatch event rule is created if the Enable Events Generation parameter is set to true during core stack deployment. This event rule initiates the
GenerateEvents
Lambda function every minute.
Authorizers
The solution includes an API Gateway Lambda authorizers stack. The stack consists of one IAM
role and a Lambda function. The APIGatewayAuthorizer
Lambda function is an
authorizer for API Gateway that can validate the signature and claims of a token issued by the
Virtual Waiting Room on AWS API. The Lambda function supplied with the stack can be used to
protect cloud APIs until a user has progressed through the waiting room and receives an access
token. The authorizer automatically retrieves and caches the public key and configuration from
the core API for token verification. It can be used without modification and can be installed
in any AWS Region that supports AWS Lambda.
OpenID adapter
The
OpenID
adapter
-
CloudFront distribution serves the S3 bucket’s content to the user.
-
S3 bucket hosts sample waiting room pages.
-
Amazon API Gateway API provides a set of OIDC-compatible APIs that can be used with existing web hosting software that support OIDC identity provider’s Lambda authorize function.
-
The
APIHandler
Lambda function handles requests for all API Gateway resource paths. Different Python functions within the same module are mapped to each API path. For example, the/authorize
resource path in API Gateway invokesauthorize()
within the Lambda Function. -
OIDC settings are stored in Secrets Manager.
Sample inlet strategies
Inlet strategies determine when the solution's serving counter should move forward to accommodate more users in the target site. For more conceptual information about waiting room inlet strategies, refer to Design considerations.
There are two sample inlet strategies provided by the solution: MaxSize and Periodic.
Max Size inlet strategy option:
-
A client issues an Amazon SNS notification that invokes the
MaxSizeInlet
Lambda function to increase the serving counter based on the message payload. -
The
MaxSizeInlet
Lambda function expects to receive a message that it uses it determine how much to increment the serving counter.
Periodic inlet strategy option:
-
A CloudWatch rule invokes a Lambda function every minute to increase the serving counter by a fixed quantity.
-
The
PeriodicInlet
Lambda function increments the serving counter by the given size if the time is between the start and end time provided. Optionally, it checks a CloudWatch alarm and, if the alarm is inOK
state, performs the increment, otherwise skips it.
Sample waiting room
The sample waiting room integrates with the public and private APIs in addition to the custom authorizer to demonstrate a minimal end-to-end waiting room solution. The main web page is stored in an S3 bucket and used as an origin to CloudFront. It takes the user through the following steps:
-
Get in line at the waiting room for entry into the site.
-
Obtain the client’s position in line.
-
Obtain the serving position of the waiting room.
-
Obtain a token set once the serving position is equal or greater to the client’s position.
-
Use the token to call an API protected by the Lambda authorizer.
-
S3 bucket hosts the sample content for the waiting room and control panel.
-
CloudFront distribution serves the S3 bucket content to user.
-
Sample API Gateway deployment with shopping-like resource paths like
/search
and/checkout
. This API is installed by the stack and configured with the token authorizer. It is intended as an example of a simple way to protect an API with the waiting room. Requests that present a valid token are forwarded to the Lambda, otherwise an error is returned. There is no functionality to the API other than the response from the Lambda function attached.