Architecture help - How can I architect a web app with a custom subdomain and it's own configuration for each customer?

-1

I would like to deploy a multi tenant web application say webapp.com and I would like each customer to have their own subdomain like app.customer1.webapp.com, api.customer1.webapp.com, app.customer2.webapp.com, api.customer2.webapp.com, etc. This was each customer has their own API and Web App URL. I would like all web app urls to go to the same instance of the application but load a different configuration for each customer - each customer has their own cognito userpool. Similarly for API but I would need to authenticate based on Bearer Token and Domain used. For the backend I think I will have a dynamodb table to hold the details of each customer.

The web app is NextJS app so I think I will use a fargate cluster for both the web app and api (I want to avoid API Gateway and lambda). I will also use CDK for all infrastructure so I might also use it to bootstrap each customer using a stack that consists of Route53 configs and other resources like userpool that is unique to each customer. What is the easiest way to achieve this (preferably with CDK) ?

已提問 2 年前檢視次數 191 次
1 個回答
0

If I were doing this, I would take the easiest approach which would be to have a r53 CNAME pointing to an application load balancer:

// ...
 const tenantName = new cdk.CfnParameter(this, "TenantName", {
      type: "String"
    })
    const webAlb = new elb.ApplicationLoadBalancer(this, 'alb', { 
      ...
    })
    const apiAlb = new elb.ApplicationLoadBalancer(this, 'alb', { 
      ...
    })
    const zone = new r53.HostedZone(this, 'zone', { 
      zoneName: 'example.com' 
    })
    new r53.CnameRecord(this, 'webcname', {
      domainName: webAlb.loadBalancerDnsName, 
      zone: zone, 
      recordName: `${tenantName.valueAsString}.example.com`
    })
    new r53.CnameRecord(this, 'apicname', {
      domainName: apiAlb.loadBalancerDnsName, 
      zone: zone, 
      recordName: `api.${tenantName.valueAsString}.example.com`
    })
// ...

then you can also have a Cognito user pool per tenant per the documentation here.

Alternatively, and slightly more complicated would be to use CloudFront to provide CDN capability with R53 in front, also with CNAME entries. With this, you can also provide tenant-specific behavior rules in CloudFront to provide custom branding per tenant for example.

// ...
 const tenantName = new cdk.CfnParameter(this, "TenantName", {
      type: "String"
    })
    
    const webAlb = new elb.ApplicationLoadBalancer(this, 'alb', { 
      ...
    })
    const apiAlb = new elb.ApplicationLoadBalancer(this, 'alb', { 
      ...
    })

    const distro = new cf.Distribution(this, 'distro', {
      defaultBehavior: {origin: new cfo.LoadBalancerV2Origin(webAlb)},
      ...
    })
    const zone = new r53.HostedZone(this, 'zone', { 
      zoneName: 'example.com' 
    })
    new r53.CnameRecord(this, 'webcname', {
      domainName: distro.distributionDomainName, 
      zone: zone, 
      recordName: `${tenantName.valueAsString}.example.com`
    })
    new r53.CnameRecord(this, 'apicname', {
      domainName: apiAlb.loadBalancerDnsName, 
      zone: zone, 
      recordName: `api.${tenantName.valueAsString}.example.com`
    })
// ...

You can read the details of the CDK apis I used here:

https://docs.aws.amazon.com/cdk/api/v1/docs/aws-cloudfront-origins-readme.html https://docs.aws.amazon.com/cdk/api/v1/docs/aws-cloudfront-origins-readme.html https://docs.aws.amazon.com/cdk/api/v1/docs/aws-route53-readme.html

AWS
已回答 2 年前

您尚未登入。 登入 去張貼答案。

一個好的回答可以清楚地回答問題並提供建設性的意見回饋,同時有助於提問者的專業成長。

回答問題指南