in lib/base/base-stack.ts [30:148]
constructor(scope: Construct, id: string, props: AwsSaasFactoryHybridIdentityStackProps) {
super(scope, id, props);
// common components
// tenant creation step function
// example stack to show hybrid saas identity
// we will create a ddb table called oidc-provider, cognito user pool called tenant1,
// cognito app client with ADMIN_SRP_AUTH enabled.
// bootstrap it with default config, features, tenant and client
// we will then pass on these parameters to oidc-provider, oidc-resource,
// oidc-client in that order
// first up dynamodb table
// TODO change this from a static name to a ref
const oidcProviderTable = new dynamodb.Table(this, 'oidc-provider-table', {
partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
tableName: 'oidc-provider',
removalPolicy: RemovalPolicy.DESTROY,
});
// adding a GSI on "type" because OIDC-provider-dynamodb-adapter needs this
oidcProviderTable.addGlobalSecondaryIndex({
indexName: 'type-index',
partitionKey: { name: 'type', type: dynamodb.AttributeType.STRING },
});
// adding a GSI on "domain" because OIDC-provider needs this
oidcProviderTable.addGlobalSecondaryIndex({
indexName: 'domain-index',
partitionKey: { name: 'domain', type: dynamodb.AttributeType.STRING },
});
// adding a GSI on "domain" because OIDC-provider needs this
oidcProviderTable.addGlobalSecondaryIndex({
indexName: 'type-tenant_id-index',
partitionKey: { name: 'type', type: dynamodb.AttributeType.STRING },
sortKey: { name: 'tenant_id', type: dynamodb.AttributeType.STRING },
});
// next up we will create a cognito user pool and client with adminSRP auth,
// sneaking in a tenantid custom attribute.
const federationCognitoUserpool = new cognito.UserPool(this, 'saas-op', {
userPoolName: 'saas-op',
customAttributes: {
tenantid: new cognito.StringAttribute({ minLen: 5, maxLen: 36, mutable: true }),
},
});
federationCognitoUserpool.addDomain('saas-op-domain', { cognitoDomain: { domainPrefix: props.cognitoUserPoolDomainPrefix || 'somefoo' } });
// tenants dynamodb table
// TODO change this from a static name to a ref
const tenantsTable = new dynamodb.Table(this, 'tenants-table', {
partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
tableName: 'tenants',
removalPolicy: RemovalPolicy.DESTROY,
});
// adding a GSI on "domain" because OIDC-provider needs this
tenantsTable.addGlobalSecondaryIndex({
indexName: 'subdomain-index',
partitionKey: { name: 'subdomain', type: dynamodb.AttributeType.STRING },
});
const createDefaultSettingsLambda = new nodejslambda.NodejsFunction(this, 'DefaultSettingsFunc', {
entry: `${path.join(path.resolve(__dirname, '..', '..'), 'resources', 'add_default_features_lambda')}/handler.js`,
handler: 'handler',
timeout: Duration.seconds(900), // +acm validation wait of 530 seconds
memorySize: 3008,
});
oidcProviderTable.grantReadWriteData(createDefaultSettingsLambda);
const createBaseFeatures = new tasks.LambdaInvoke(this, 'Default Features Bootstrap', {
lambdaFunction: createDefaultSettingsLambda,
outputPath: '$.Payload',
});
const createBaseFeaturesStateMachineDefinition = createBaseFeatures;
const createBaseFeaturesStateMachine = new sfn.StateMachine(this, 'createBaseFeaturesStateMachine', {
definition: createBaseFeaturesStateMachineDefinition,
timeout: Duration.minutes(5),
stateMachineName: 'mysaasapp-hsi-createbasefeatures',
});
const oidcResource = new OidcResourceStack(this, 'oidc-resource', {
clientSecret: 'not_needed_for_cognito_introspection',
clientId: 'not_needed_for_cognito_introspection',
introspectionUrl: 'not_needed_for_cognito_introspection',
cognitoPoolId: federationCognitoUserpool.userPoolId,
});
const oidcClient = new OidcClientStack(this, 'oidc-client', {
oidcResourceUrl: oidcResource.resourceUrl,
tenantsTableName: 'tenants',
});
const tenantService = new TenantServiceStack(this, 'tenant-service', {
oidcProviderTableName: 'oidc-provider',
tenantsTableName: 'tenants',
federationCognitoUserpool,
hostedZoneId: props.hostedZoneId,
});
const ssmparamCognitoUserPoolId = new ssm.StringParameter(this, 'cognitoUserPoolId', {
parameterName: '/mysaasapp/cognitoUserPoolId',
stringValue: federationCognitoUserpool.userPoolId,
});
const ssmparamCognitoUserPoolRegion = new ssm.StringParameter(this, 'cognitoUserPoolRegion', {
parameterName: '/mysaasapp/cognitoUserPoolRegion',
stringValue: Stack.of(this).region,
});
const ssmparamBaseFeaturesStepFunctionArn = new ssm.StringParameter(this, 'baseFeaturesStepFunctionArn', {
parameterName: '/mysaasapp/baseFeaturesStepFunctionArn',
stringValue: createBaseFeaturesStateMachine.stateMachineArn,
});
}