Skip to content

Commit f541ce4

Browse files
authored
Merge pull request #14 from aws-samples/feat/one-az
feat: AZ count setting and Shorten ECS Service name
2 parents c13ee3d + cf54dc8 commit f541ce4

File tree

13 files changed

+260
-385
lines changed

13 files changed

+260
-385
lines changed

client/AdminWeb/src/app/auth-config.module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { environment } from 'src/environments/environment';
1313
postLogoutRedirectUri: window.location.origin,
1414
redirectUrl: window.location.origin,
1515
responseType: 'code',
16-
scope: 'openid profile email',
16+
scope: 'openid profile email tenant/tenant_read tenant/tenant_write user/user_read user/user_write',
1717
},
1818
}),
1919
],

client/AdminWeb/src/app/auth.interceptor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export class AuthInterceptor implements HttpInterceptor {
2929
return next.handle(req);
3030
}
3131

32-
return this.service.getIdToken().pipe(
32+
return this.service.getAccessToken().pipe(
3333
switchMap((tok) => {
3434
req = req.clone({
3535
headers: req.headers.set('Authorization', 'Bearer ' + tok),

server/bin/ecs-saas-ref-template.ts

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import * as cdk from 'aws-cdk-lib';
33
import { TenantTemplateStack } from '../lib/tenant-template/tenant-template-stack';
44
import { DestroyPolicySetter } from '../lib/utilities/destroy-policy-setter';
55
import { CoreAppPlaneStack } from '../lib/bootstrap-template/core-appplane-stack';
6-
import { TenantUpdatePipeline } from '../lib/tenant-template/tenant-update-stack';
76
import { getEnv } from '../lib/utilities/helper-functions';
87
import { ControlPlaneStack } from '../lib/bootstrap-template/control-plane-stack';
98
import { SharedInfraStack } from '../lib/shared-infra/shared-infra-stack';
@@ -20,11 +19,14 @@ if (!process.env.CDK_PARAM_TENANT_ID) {
2019
console.log('Tenant ID is empty, a default tenant id "basic" will be assigned');
2120
}
2221
const basicId = 'basic';
22+
const AzCount = 3;
2323

24+
if(AzCount < 2 || AzCount > 3) {
25+
throw new Error('Please Availability Zones count must be 2 or 3');
26+
}
2427
// required input parameters
2528
const systemAdminEmail = process.env.CDK_PARAM_SYSTEM_ADMIN_EMAIL;
2629
const tenantId = process.env.CDK_PARAM_TENANT_ID || basicId;
27-
const codeCommitRepositoryName = getEnv('CDK_PARAM_CODE_COMMIT_REPOSITORY_NAME');
2830

2931
const commitId = getEnv('CDK_PARAM_COMMIT_ID');
3032
const tier = getEnv('CDK_PARAM_TIER');
@@ -87,41 +89,40 @@ const apiKeySSMParameterNames = {
8789
}
8890
};
8991

90-
const controlPlaneStack = new ControlPlaneStack(app, 'controlplane-stack', {
91-
systemAdminEmail: systemAdminEmail,
92-
systemAdminRoleName: systemAdminRoleName,
92+
const sharedInfraStack = new SharedInfraStack(app, 'shared-infra-stack', {
93+
isPooledDeploy: isPooledDeploy,
94+
ApiKeySSMParameterNames: apiKeySSMParameterNames,
95+
apiKeyPlatinumTierParameter: apiKeyPlatinumTierParameter,
96+
apiKeyPremiumTierParameter: apiKeyPremiumTierParameter,
97+
apiKeyAdvancedTierParameter: apiKeyAdvancedTierParameter,
98+
apiKeyBasicTierParameter: apiKeyBasicTierParameter,
99+
stageName: stageName,
100+
azCount: AzCount,
93101
env: {
94102
account: process.env.CDK_DEFAULT_ACCOUNT,
95103
region: process.env.CDK_DEFAULT_REGION
96104
}
97105
});
98106

99-
const coreAppPlaneStack = new CoreAppPlaneStack(app, 'core-appplane-stack', {
107+
const controlPlaneStack = new ControlPlaneStack(app, 'controlplane-stack', {
100108
systemAdminEmail: systemAdminEmail,
101-
regApiGatewayUrl: controlPlaneStack.regApiGatewayUrl,
102-
eventBusArn: controlPlaneStack.eventBusArn,
103-
apiKeyPlatinumTierParameter: apiKeyPlatinumTierParameter,
104-
apiKeyPremiumTierParameter: apiKeyPremiumTierParameter,
105-
apiKeyAdvancedTierParameter: apiKeyAdvancedTierParameter,
106-
apiKeyBasicTierParameter: apiKeyBasicTierParameter,
107-
ApiKeySSMParameterNames: apiKeySSMParameterNames,
109+
systemAdminRoleName: systemAdminRoleName,
108110
env: {
109111
account: process.env.CDK_DEFAULT_ACCOUNT,
110112
region: process.env.CDK_DEFAULT_REGION
111113
}
112114
});
113-
cdk.Aspects.of(coreAppPlaneStack).add(new DestroyPolicySetter());
114115

115-
const sharedInfraStack = new SharedInfraStack(app, 'shared-infra-stack', {
116-
isPooledDeploy: isPooledDeploy,
117-
ApiKeySSMParameterNames: apiKeySSMParameterNames,
118-
stageName: stageName,
116+
const coreAppPlaneStack = new CoreAppPlaneStack(app, 'core-appplane-stack', {
117+
systemAdminEmail: systemAdminEmail,
118+
regApiGatewayUrl: controlPlaneStack.regApiGatewayUrl,
119+
eventManager: controlPlaneStack.eventManager,
119120
env: {
120121
account: process.env.CDK_DEFAULT_ACCOUNT,
121122
region: process.env.CDK_DEFAULT_REGION
122123
}
123124
});
124-
sharedInfraStack.addDependency(coreAppPlaneStack);
125+
cdk.Aspects.of(coreAppPlaneStack).add(new DestroyPolicySetter());
125126

126127
const tenantTemplateStack = new TenantTemplateStack(app, `tenant-template-stack-${tenantId}`, {
127128
tenantId: tenantId,

server/lib/bootstrap-template/control-plane-stack.ts

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
1-
import { Stack, type StackProps, CfnOutput } from 'aws-cdk-lib';
2-
import { type Construct } from 'constructs';
31
import * as cdk from 'aws-cdk-lib';
4-
import * as control_plane from '@cdklabs/sbt-aws';
5-
import { CognitoAuth } from '@cdklabs/sbt-aws';
2+
import { type Construct } from 'constructs';
63
import { StaticSiteDistro } from './static-site-distro';
74
import path = require('path');
85
import { StaticSite } from './static-site';
96
import { ControlPlaneNag } from '../cdknag/control-plane-nag';
7+
import * as sbt from '@cdklabs/sbt-aws';
108

11-
interface ControlPlaneStackProps extends StackProps {
9+
interface ControlPlaneStackProps extends cdk.StackProps {
1210
systemAdminRoleName: string
1311
systemAdminEmail: string
1412
}
1513

16-
export class ControlPlaneStack extends Stack {
14+
export class ControlPlaneStack extends cdk.Stack {
1715
public readonly regApiGatewayUrl: string;
18-
public readonly eventBusArn: string;
19-
public readonly auth: CognitoAuth;
16+
public readonly eventManager: sbt.IEventManager;
17+
public readonly auth: sbt.CognitoAuth;
2018
public readonly adminSiteUrl: string;
2119
public readonly StaticSite: StaticSite;
2220

@@ -37,34 +35,42 @@ export class ControlPlaneStack extends Stack {
3735

3836
this.adminSiteUrl = `https://${distro.cloudfrontDistribution.domainName}`;
3937

40-
const cognitoAuth = new CognitoAuth(this, 'CognitoAuth', {
41-
systemAdminRoleName: props.systemAdminRoleName,
42-
systemAdminEmail: props.systemAdminEmail,
38+
const cognitoAuth = new sbt.CognitoAuth(this, 'CognitoAuth', {
39+
// Avoid checking scopes for API endpoints. Done only for testing purposes.
40+
// setAPIGWScopes: false,
4341
controlPlaneCallbackURL: this.adminSiteUrl
4442
});
4543

46-
const controlPlane = new control_plane.ControlPlane(this, 'controlplane-sbt', {
47-
auth: cognitoAuth
44+
const controlPlane = new sbt.ControlPlane(this, 'controlplane-sbt', {
45+
systemAdminEmail: props.systemAdminEmail,
46+
auth: cognitoAuth,
47+
apiCorsConfig: {
48+
allowOrigins: ['https://*'],
49+
allowCredentials: true,
50+
allowHeaders: ['*'],
51+
allowMethods: [cdk.aws_apigatewayv2.CorsHttpMethod.ANY],
52+
maxAge: cdk.Duration.seconds(300),
53+
},
4854
});
4955

56+
this.eventManager = controlPlane.eventManager;
5057
this.regApiGatewayUrl = controlPlane.controlPlaneAPIGatewayUrl;
51-
this.eventBusArn = controlPlane.eventManager.busArn;
5258
this.auth = cognitoAuth;
5359

5460
this.StaticSite = new StaticSite(this, 'AdminWebUi', {
5561
name: 'AdminSite',
5662
assetDirectory: path.join(__dirname, '../../../client/AdminWeb/'),
5763
production: true,
58-
clientId: this.auth.clientId,
59-
issuer: this.auth.authorizationServer,
64+
clientId: this.auth.userClientId, //.clientId,
65+
issuer: this.auth.tokenEndpoint,
6066
apiUrl: this.regApiGatewayUrl,
6167
wellKnownEndpointUrl: this.auth.wellKnownEndpointUrl,
6268
distribution: distro.cloudfrontDistribution,
6369
appBucket: distro.siteBucket,
6470
accessLogsBucket
6571
});
66-
67-
new CfnOutput(this, 'adminSiteUrl', {
72+
73+
new cdk.CfnOutput(this, 'adminSiteUrl', {
6874
value: this.adminSiteUrl
6975
});
7076

server/lib/bootstrap-template/core-appplane-stack.ts

Lines changed: 40 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,20 @@
1-
import { Stack, type StackProps, CfnOutput } from 'aws-cdk-lib';
1+
import * as cdk from 'aws-cdk-lib';
22
import { type Construct } from 'constructs';
3-
import { type ApiKeySSMParameterNames } from '../interfaces/api-key-ssm-parameter-names';
4-
import { TenantApiKey } from './tenant-api-key';
53
import { Table, AttributeType } from 'aws-cdk-lib/aws-dynamodb';
64
import { PolicyDocument } from 'aws-cdk-lib/aws-iam';
75
import { EventBus } from 'aws-cdk-lib/aws-events';
6+
import * as fs from 'fs';
87
import { UserInterface } from './user-interface';
98
import { CoreAppPlaneNag } from '../cdknag/core-app-plane-nag';
10-
import * as fs from 'fs';
11-
import * as core_app_plane from '@cdklabs/sbt-aws';
12-
import { type CoreApplicationPlaneJobRunnerProps, DetailType, EventManager } from '@cdklabs/sbt-aws';
9+
import * as sbt from '@cdklabs/sbt-aws';
1310

14-
interface CoreAppPlaneStackProps extends StackProps {
15-
ApiKeySSMParameterNames: ApiKeySSMParameterNames
16-
apiKeyPlatinumTierParameter: string
17-
apiKeyPremiumTierParameter: string
18-
apiKeyAdvancedTierParameter: string
19-
apiKeyBasicTierParameter: string
20-
eventBusArn: string
11+
interface CoreAppPlaneStackProps extends cdk.StackProps {
12+
eventManager: sbt.IEventManager
2113
systemAdminEmail: string
2214
regApiGatewayUrl: string
2315
}
2416

25-
export class CoreAppPlaneStack extends Stack {
17+
export class CoreAppPlaneStack extends cdk.Stack {
2618
public readonly userInterface: UserInterface;
2719
public readonly tenantMappingTable: Table;
2820
constructor (scope: Construct, id: string, props: CoreAppPlaneStackProps) {
@@ -34,8 +26,7 @@ export class CoreAppPlaneStack extends Stack {
3426
partitionKey: { name: 'tenantId', type: AttributeType.STRING }
3527
});
3628

37-
const provisioningJobRunnerProps: CoreApplicationPlaneJobRunnerProps = {
38-
name: 'provisioning',
29+
const provisioningJobRunnerProps = {
3930
permissions: PolicyDocument.fromJson(
4031
JSON.parse(`
4132
{
@@ -53,28 +44,26 @@ export class CoreAppPlaneStack extends Stack {
5344
`)
5445
),
5546
script: fs.readFileSync('../scripts/provision-tenant.sh', 'utf8'),
56-
outgoingEvent: DetailType.PROVISION_SUCCESS,
57-
incomingEvent: DetailType.ONBOARDING_REQUEST,
58-
59-
postScript: '',
60-
environmentStringVariablesFromIncomingEvent: [
61-
'tenantId',
62-
'tier',
63-
'tenantName',
64-
'email',
65-
'tenantStatus'
47+
environmentStringVariablesFromIncomingEvent: ['tenantId', 'tier', 'tenantName', 'email'],
48+
environmentVariablesToOutgoingEvent: [
49+
'tenantConfig',
50+
'tenantStatus',
51+
'prices', // added so we don't lose it for targets beyond provisioning (ex. billing)
52+
'tenantName', // added so we don't lose it for targets beyond provisioning (ex. billing)
53+
'email', // added so we don't lose it for targets beyond provisioning (ex. billing)
6654
],
67-
environmentVariablesToOutgoingEvent: ['tenantConfig', 'tenantStatus'],
6855
scriptEnvironmentVariables: {
69-
// CDK_PARAM_SYSTEM_ADMIN_EMAIL is required - as part of deploying the bootstrap-template
56+
// CDK_PARAM_SYSTEM_ADMIN_EMAIL is required because as part of deploying the bootstrap-template
7057
// the control plane is also deployed. To ensure the operation does not error out, this value
7158
// is provided as an env parameter.
72-
CDK_PARAM_SYSTEM_ADMIN_EMAIL: systemAdminEmail
73-
}
59+
CDK_PARAM_SYSTEM_ADMIN_EMAIL: systemAdminEmail,
60+
},
61+
outgoingEvent: sbt.DetailType.PROVISION_SUCCESS,
62+
incomingEvent: sbt.DetailType.ONBOARDING_REQUEST,
63+
eventManager: props.eventManager
7464
};
7565

76-
const deprovisioningJobRunnerProps: CoreApplicationPlaneJobRunnerProps = {
77-
name: 'deprovisioning',
66+
const deprovisioningJobRunnerProps = {
7867
permissions: PolicyDocument.fromJson(
7968
JSON.parse(`
8069
{
@@ -92,56 +81,38 @@ export class CoreAppPlaneStack extends Stack {
9281
`)
9382
),
9483
script: fs.readFileSync('../scripts/deprovision-tenant.sh', 'utf8'),
95-
environmentStringVariablesFromIncomingEvent: ['tenantId', 'tier'],
84+
environmentStringVariablesFromIncomingEvent: ['tenantId'],
9685
environmentVariablesToOutgoingEvent: ['tenantStatus'],
97-
outgoingEvent: DetailType.DEPROVISION_SUCCESS,
98-
incomingEvent: DetailType.OFFBOARDING_REQUEST,
99-
86+
outgoingEvent: sbt.DetailType.DEPROVISION_SUCCESS,
87+
incomingEvent: sbt.DetailType.OFFBOARDING_REQUEST,
10088
scriptEnvironmentVariables: {
10189
TENANT_STACK_MAPPING_TABLE: this.tenantMappingTable.tableName,
102-
CDK_PARAM_SYSTEM_ADMIN_EMAIL: systemAdminEmail
103-
}
90+
// CDK_PARAM_SYSTEM_ADMIN_EMAIL is required because as part of deploying the bootstrap-template
91+
// the control plane is also deployed. To ensure the operation does not error out, this value
92+
// is provided as an env parameter.
93+
CDK_PARAM_SYSTEM_ADMIN_EMAIL: systemAdminEmail,
94+
},
95+
eventManager: props.eventManager
10496
};
10597

106-
const eventBus = EventBus.fromEventBusArn(this, 'EventBus', props.eventBusArn);
107-
const eventManager = new EventManager(this, 'EventManager', {
108-
eventBus: eventBus,
109-
});
110-
111-
new core_app_plane.CoreApplicationPlane(this, 'coreappplane-sbt', {
112-
eventManager: eventManager,
113-
jobRunnerPropsList: [provisioningJobRunnerProps, deprovisioningJobRunnerProps]
114-
});
115-
116-
new TenantApiKey(this, 'BasicTierApiKey', {
117-
apiKeyValue: props.apiKeyBasicTierParameter,
118-
ssmParameterApiKeyIdName: props.ApiKeySSMParameterNames.basic.keyId,
119-
ssmParameterApiValueName: props.ApiKeySSMParameterNames.basic.value
120-
});
121-
122-
new TenantApiKey(this, 'AdvancedTierApiKey', {
123-
apiKeyValue: props.apiKeyAdvancedTierParameter,
124-
ssmParameterApiKeyIdName: props.ApiKeySSMParameterNames.advanced.keyId,
125-
ssmParameterApiValueName: props.ApiKeySSMParameterNames.advanced.value
126-
});
98+
const provisioningJobRunner: sbt.BashJobRunner = new sbt.BashJobRunner(this,
99+
'provisioningJobRunner', provisioningJobRunnerProps
100+
);
127101

128-
new TenantApiKey(this, 'PremiumTierApiKey', {
129-
apiKeyValue: props.apiKeyPremiumTierParameter,
130-
ssmParameterApiKeyIdName: props.ApiKeySSMParameterNames.premium.keyId,
131-
ssmParameterApiValueName: props.ApiKeySSMParameterNames.premium.value
132-
});
102+
const deprovisioningJobRunner: sbt.BashJobRunner = new sbt.BashJobRunner(this,
103+
'deprovisioningJobRunner', deprovisioningJobRunnerProps
104+
);
133105

134-
new TenantApiKey(this, 'PlatinumTierApiKey', {
135-
apiKeyValue: props.apiKeyPlatinumTierParameter,
136-
ssmParameterApiKeyIdName: props.ApiKeySSMParameterNames.platinum.keyId,
137-
ssmParameterApiValueName: props.ApiKeySSMParameterNames.platinum.value
106+
new sbt.CoreApplicationPlane(this, 'coreappplane-sbt', {
107+
eventManager: props.eventManager,
108+
jobRunnersList: [provisioningJobRunner, deprovisioningJobRunner]
138109
});
139110

140111
this.userInterface = new UserInterface(this, 'saas-application-ui', {
141112
regApiGatewayUrl: props.regApiGatewayUrl
142113
});
143114

144-
new CfnOutput(this, 'appSiteUrl', {
115+
new cdk.CfnOutput(this, 'appSiteUrl', {
145116
value: this.userInterface.appSiteUrl
146117
});
147118

server/lib/cdknag/control-plane-nag.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,8 @@ export class ControlPlaneNag extends Construct {
3333
NagSuppressions.addResourceSuppressionsByPath(
3434
cdk.Stack.of(this),
3535
[
36-
`${sbtPath}/controlplane-api-stack/controlPlaneAPI/EventsRole/DefaultPolicy/Resource`,
37-
`${sbtPath}/services-stack/tenantManagementExecRole/DefaultPolicy/Resource`,
38-
`${sbtPath}/auth-info-service-stack/TenantConfigServiceLambda/ServiceRole/DefaultPolicy/Resource`
36+
`${sbtPath}/tenantManagementServicves/tenantManagementLambda/tenantManagementExecRole/DefaultPolicy/Resource`,
37+
`${sbtPath}/tenantConfigService/tenantConfigLambda/TenantConfigServiceLambda/ServiceRole/DefaultPolicy/Resource`,
3938
],
4039
[
4140
policy,
@@ -47,7 +46,7 @@ export class ControlPlaneNag extends Construct {
4746
regex: '/^Resource::arn:aws:execute-api:(.*):(.*)\\*$/g'
4847
},
4948
{
50-
regex: '/^Resource::<controlplanesbttablesstackTenant(.*).Arn(.*)\\*$/g'
49+
regex: '/^Resource::<controlplanesbttenantManagementServicves(.*).Arn(.*)\\*$/g'
5150
}
5251
]
5352
}

server/lib/cdknag/core-app-plane-nag.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,14 @@ export class CoreAppPlaneNag extends Construct {
2121
]
2222
};
2323

24-
const sbtNagPath = '/core-appplane-stack/coreappplane-sbt';
2524
const nagWebPath = '/core-appplane-stack/saas-application-ui/TenantWebUI';
2625
const nagStaticPath = '/core-appplane-stack/saas-application-ui/StaticSiteDistro';
2726

2827
NagSuppressions.addResourceSuppressionsByPath(
2928
cdk.Stack.of(this),
3029
[
31-
`${sbtNagPath}/provisioning-codeBuildProvisionProjectRole/Resource`,
32-
`${sbtNagPath}/deprovisioning-codeBuildProvisionProjectRole/Resource`
30+
'core-appplane-stack/provisioningJobRunner/codeBuildProvisionProjectRole/Resource',
31+
'core-appplane-stack/deprovisioningJobRunner/codeBuildProvisionProjectRole/Resource'
3332
],
3433
[
3534
{

0 commit comments

Comments
 (0)