Stacks and outputs
There are two CDK apps: server/cdk (everything AWS-side) and client/cdk (the web hosting). They are separate on purpose, because the provisioning job synthesizes the server app in CodeBuild, where the web apps’ build output doesn’t exist.
| Stack | CDK app | Created by | Contents |
|---|---|---|---|
ControlPlaneStack |
server | deploy.sh |
SBT CognitoAuth (system admin pool) and ControlPlane (HTTP API, tenant tables, EventBridge bus), and the bus watcher log |
serverless-saas-bootstrap |
server | deploy.sh |
Tenant mapping table, one API key per tier in SSM, versioned source bucket, provisioning and deprovisioning jobs |
serverless-saas-tenant-template-pooled |
server | deploy.sh |
Pooled tenant user pool, REST API, authorizer, usage plans, product, order and user services |
serverless-saas-tenant-template-<tenantId> |
server | provisioning job | The same template for one Platinum tenant |
serverless-saas-tenant-pipeline |
server | deploy.sh |
CodePipeline, Step Functions state machine, CodeBuild project, list-stacks Lambda |
serverless-saas-client |
client | deploy-client.sh |
S3 and CloudFront for the admin console, the SaaS app and these docs; with DOMAIN_NAME, also the certificate and DNS records |
Outputs
Section titled “Outputs”| Stack | Output | Example | Used by |
|---|---|---|---|
ControlPlaneStack |
controlPlaneAPIEndpoint |
https://w2g4jn8evg.execute-api.us-east-1.amazonaws.com/ |
Admin console, SaaS app, scripts |
ControlPlaneIdpUserPoolId |
us-east-1_NJ8yJK7e9 |
Admin console, admin-token.sh |
|
ControlPlaneIdpClientId |
2b4l421t5f3rnkq16tk9m3f8ai |
Admin console, admin-token.sh |
|
eventBridgeArn |
arn:aws:events:…:event-bus/… |
Bootstrap stack | |
serverless-saas-bootstrap |
SourceBucketName |
serverless-saas-source-<account>-<region> |
upload-source.sh, provisioning, pipeline |
serverless-saas-tenant-template-* |
ApiGatewayUrl |
https://0xlsgzuyxh.execute-api.us-east-1.amazonaws.com/prod/ |
Provisioning (tenantConfig), scripts |
TenantUserpoolId |
us-east-1_a1M1hAn8y |
Provisioning, dev scripts | |
UserPoolClientId |
q33critjq1ba1puje9nnrea78 |
Provisioning, tenant-token.sh |
|
ProductTableName, OrderTableName |
dev-isolation-check.sh |
||
serverless-saas-client |
AdminSiteUrl |
https://saas-admin.haibui.click |
You |
AppSiteUrl |
https://saas.haibui.click |
You | |
DocsSiteUrl |
https://saas-docs.haibui.click |
You |
Print a stack’s outputs:
aws cloudformation describe-stacks --stack-name serverless-saas-client \ --query 'Stacks[0].Outputs[].[OutputKey,OutputValue]' --output tableCDK parameters
Section titled “CDK parameters”The server app reads these environment variables:
| Variable | Default | Meaning |
|---|---|---|
CDK_PARAM_SYSTEM_ADMIN_EMAIL |
(required) | Email of the first system admin. deploy.sh sets it from its argument. |
CDK_PARAM_TENANT_ID |
pooled |
Which tenant template stack to synthesize |
CDK_PARAM_COMMIT_ID |
local |
Code version recorded in the mapping table and returned by /whoami |
CDK_PARAM_WAVE_NUMBER |
1 |
Pipeline wave for a new tenant stack |
CDK_PARAM_LAMBDA_RESERVE_CONCURRENCY |
5 for silo |
Reserved concurrency per function in a silo stack |
CDK_PARAM_API_KEY_<TIER>_TIER |
built-in values | Override the API key value of a tier |
The client app reads CONTROL_PLANE_API_URL, ADMIN_USER_POOL_ID and ADMIN_APP_CLIENT_ID (set by deploy-client.sh), and optionally DOMAIN_NAME.
Tenant mapping table
Section titled “Tenant mapping table”One row per tenant template stack, in serverless-saas-bootstrap:
{ "tenantId": "pooled", "stackName": "serverless-saas-tenant-template-pooled", "codeCommitId": "YTZTkJso…", "waveNumber": "1" }Each stack writes its own row with a custom resource on create and update, and deletes it on delete.