Skip to content

Commit

Permalink
Custom Domain for Microservice (#365)
Browse files Browse the repository at this point in the history
  • Loading branch information
williamputraintan authored Jun 24, 2024
1 parent cfef058 commit 46244d7
Show file tree
Hide file tree
Showing 12 changed files with 179 additions and 100 deletions.
116 changes: 32 additions & 84 deletions config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,110 +44,58 @@ interface EnvironmentConfig {
* @returns the configuration for the given app stage
*/
export const getEnvironmentConfig = (stage: AppStage): EnvironmentConfig | null => {
const stackProps = {
statefulConfig: {
sharedStackProps: getSharedStackProps(stage),
tokenServiceStackProps: getTokenServiceStackProps(),
icaEventPipeStackProps: getIcaEventPipeStackProps(),
bclconvertInteropQcIcav2PipelineTableStackProps:
getBclconvertInteropQcIcav2PipelineTableStackProps(),
cttsov2Icav2PipelineTableStackProps: getCttsov2Icav2PipelineTableStackProps(),
BclConvertTableStackProps: getBclConvertManagerTableStackProps(stage),
stackyStatefulTablesStackProps: getStatefulGlueStackProps(),
},
statelessConfig: {
postgresManagerStackProps: getPostgresManagerStackProps(),
metadataManagerStackProps: getMetadataManagerStackProps(stage),
sequenceRunManagerStackProps: getSequenceRunManagerStackProps(stage),
fileManagerStackProps: getFileManagerStackProps(stage),
bsRunsUploadManagerStackProps: getBsRunsUploadManagerStackProps(stage),
bsshIcav2FastqCopyManagerStackProps: getBsshIcav2FastqCopyManagerStackProps(stage),
bclconvertInteropQcIcav2PipelineManagerStackProps:
getBclconvertInteropQcIcav2PipelineManagerStackProps(stage),
cttsov2Icav2PipelineManagerStackProps: getCttsov2Icav2PipelineManagerStackProps(stage),
eventSchemaStackProps: getEventSchemaStackProps(),
dataSchemaStackProps: getDataSchemaStackProps(),
bclConvertManagerStackProps: getBclConvertManagerStackProps(stage),
workflowManagerStackProps: getWorkflowManagerStackProps(stage),
stackyMcStackFaceProps: getGlueStackProps(),
},
};

switch (stage) {
case AppStage.BETA:
return {
name: 'beta',
region,
accountId: accountIdAlias[stage], // umccr_development
stackProps: {
statefulConfig: {
sharedStackProps: getSharedStackProps(stage),
tokenServiceStackProps: getTokenServiceStackProps(),
icaEventPipeStackProps: getIcaEventPipeStackProps(),
bclconvertInteropQcIcav2PipelineTableStackProps:
getBclconvertInteropQcIcav2PipelineTableStackProps(),
cttsov2Icav2PipelineTableStackProps: getCttsov2Icav2PipelineTableStackProps(),
BclConvertTableStackProps: getBclConvertManagerTableStackProps(stage),
stackyStatefulTablesStackProps: getStatefulGlueStackProps(),
},
statelessConfig: {
postgresManagerStackProps: getPostgresManagerStackProps(),
metadataManagerStackProps: getMetadataManagerStackProps(stage),
sequenceRunManagerStackProps: getSequenceRunManagerStackProps(),
fileManagerStackProps: getFileManagerStackProps(stage),
bsRunsUploadManagerStackProps: getBsRunsUploadManagerStackProps(stage),
bsshIcav2FastqCopyManagerStackProps: getBsshIcav2FastqCopyManagerStackProps(stage),
bclconvertInteropQcIcav2PipelineManagerStackProps:
getBclconvertInteropQcIcav2PipelineManagerStackProps(stage),
cttsov2Icav2PipelineManagerStackProps: getCttsov2Icav2PipelineManagerStackProps(stage),
eventSchemaStackProps: getEventSchemaStackProps(),
dataSchemaStackProps: getDataSchemaStackProps(),
bclConvertManagerStackProps: getBclConvertManagerStackProps(stage),
workflowManagerStackProps: getWorkflowManagerStackProps(),
stackyMcStackFaceProps: getGlueStackProps(),
},
},
stackProps: stackProps,
};

case AppStage.GAMMA:
return {
name: 'gamma',
region,
accountId: accountIdAlias[stage], // umccr_staging
stackProps: {
statefulConfig: {
sharedStackProps: getSharedStackProps(stage),
tokenServiceStackProps: getTokenServiceStackProps(),
icaEventPipeStackProps: getIcaEventPipeStackProps(),
bclconvertInteropQcIcav2PipelineTableStackProps:
getBclconvertInteropQcIcav2PipelineTableStackProps(),
cttsov2Icav2PipelineTableStackProps: getCttsov2Icav2PipelineTableStackProps(),
BclConvertTableStackProps: getBclConvertManagerTableStackProps(stage),
stackyStatefulTablesStackProps: getStatefulGlueStackProps(),
},
statelessConfig: {
postgresManagerStackProps: getPostgresManagerStackProps(),
metadataManagerStackProps: getMetadataManagerStackProps(stage),
sequenceRunManagerStackProps: getSequenceRunManagerStackProps(),
fileManagerStackProps: getFileManagerStackProps(stage),
bsRunsUploadManagerStackProps: getBsRunsUploadManagerStackProps(stage),
bsshIcav2FastqCopyManagerStackProps: getBsshIcav2FastqCopyManagerStackProps(stage),
bclconvertInteropQcIcav2PipelineManagerStackProps:
getBclconvertInteropQcIcav2PipelineManagerStackProps(stage),
cttsov2Icav2PipelineManagerStackProps: getCttsov2Icav2PipelineManagerStackProps(stage),
eventSchemaStackProps: getEventSchemaStackProps(),
dataSchemaStackProps: getDataSchemaStackProps(),
bclConvertManagerStackProps: getBclConvertManagerStackProps(stage),
workflowManagerStackProps: getWorkflowManagerStackProps(),
stackyMcStackFaceProps: getGlueStackProps(),
},
},
stackProps: stackProps,
};

case AppStage.PROD:
return {
name: 'prod',
region,
accountId: accountIdAlias[stage], // umccr_production
stackProps: {
statefulConfig: {
sharedStackProps: getSharedStackProps(stage),
tokenServiceStackProps: getTokenServiceStackProps(),
icaEventPipeStackProps: getIcaEventPipeStackProps(),
bclconvertInteropQcIcav2PipelineTableStackProps:
getBclconvertInteropQcIcav2PipelineTableStackProps(),
cttsov2Icav2PipelineTableStackProps: getCttsov2Icav2PipelineTableStackProps(),
BclConvertTableStackProps: getBclConvertManagerTableStackProps(stage),
stackyStatefulTablesStackProps: getStatefulGlueStackProps(),
},
statelessConfig: {
postgresManagerStackProps: getPostgresManagerStackProps(),
metadataManagerStackProps: getMetadataManagerStackProps(stage),
sequenceRunManagerStackProps: getSequenceRunManagerStackProps(),
fileManagerStackProps: getFileManagerStackProps(stage),
bsRunsUploadManagerStackProps: getBsRunsUploadManagerStackProps(stage),
bsshIcav2FastqCopyManagerStackProps: getBsshIcav2FastqCopyManagerStackProps(stage),
bclconvertInteropQcIcav2PipelineManagerStackProps:
getBclconvertInteropQcIcav2PipelineManagerStackProps(stage),
cttsov2Icav2PipelineManagerStackProps: getCttsov2Icav2PipelineManagerStackProps(stage),
eventSchemaStackProps: getEventSchemaStackProps(),
dataSchemaStackProps: getDataSchemaStackProps(),
bclConvertManagerStackProps: getBclConvertManagerStackProps(stage),
workflowManagerStackProps: getWorkflowManagerStackProps(),
stackyMcStackFaceProps: getGlueStackProps(),
},
},
stackProps: stackProps,
};
}
};
8 changes: 8 additions & 0 deletions config/stacks/fileManager.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { RetentionDays } from 'aws-cdk-lib/aws-logs';
import { FilemanagerConfig } from '../../lib/workload/stateless/stacks/filemanager/deploy/stack';
import {
AppStage,
Expand All @@ -13,8 +14,14 @@ import {
icav2PipelineCacheBucket,
fileManagerIngestRoleName,
} from '../constants';
import { RemovalPolicy } from 'aws-cdk-lib';

export const getFileManagerStackProps = (stage: AppStage): FilemanagerConfig => {
const logsConfig = {
retention: stage === AppStage.PROD ? RetentionDays.TWO_YEARS : RetentionDays.TWO_WEEKS,
removalPolicy: stage === AppStage.PROD ? RemovalPolicy.RETAIN : RemovalPolicy.DESTROY,
};

return {
securityGroupName: computeSecurityGroupName,
vpcProps,
Expand All @@ -25,6 +32,7 @@ export const getFileManagerStackProps = (stage: AppStage): FilemanagerConfig =>
cognitoPortalAppClientIdParameterName: cognitoPortalAppClientIdParameterName,
cognitoStatusPageAppClientIdParameterName: cognitoStatusPageAppClientIdParameterName,
cognitoUserPoolIdParameterName: cognitoUserPoolIdParameterName,
apiGwLogsConfig: logsConfig,
inventorySourceBuckets: ['filemanager-inventory-test'],
eventSourceBuckets: [oncoanalyserBucket[stage], icav2PipelineCacheBucket[stage]],
fileManagerIngestRoleName: fileManagerIngestRoleName,
Expand Down
9 changes: 8 additions & 1 deletion config/stacks/metadataManager.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { AppStage, cognitoApiGatewayProps, computeSecurityGroupName, vpcProps } from '../constants';
import { MetadataManagerStackProps } from '../../lib/workload/stateless/stacks/metadata-manager/deploy/stack';
import { RemovalPolicy } from 'aws-cdk-lib';
import { RetentionDays } from 'aws-cdk-lib/aws-logs';

export const getMetadataManagerStackProps = (stage: AppStage): MetadataManagerStackProps => {
const logsConfig = {
retention: stage === AppStage.PROD ? RetentionDays.TWO_YEARS : RetentionDays.TWO_WEEKS,
removalPolicy: stage === AppStage.PROD ? RemovalPolicy.RETAIN : RemovalPolicy.DESTROY,
};

const isDailySync = stage == AppStage.PROD ? true : false;

return {
vpcProps,
isDailySync: isDailySync,
lambdaSecurityGroupName: computeSecurityGroupName,
apiGatewayCognitoProps: cognitoApiGatewayProps,
apiGatewayCognitoProps: { ...cognitoApiGatewayProps, apiGwLogsConfig: logsConfig },
};
};
11 changes: 10 additions & 1 deletion config/stacks/sequenceRunManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
AppStage,
cognitoPortalAppClientIdParameterName,
cognitoStatusPageAppClientIdParameterName,
cognitoUserPoolIdParameterName,
Expand All @@ -7,14 +8,22 @@ import {
vpcProps,
} from '../constants';
import { SequenceRunManagerStackProps } from '../../lib/workload/stateless/stacks/sequence-run-manager/deploy/stack';
import { RetentionDays } from 'aws-cdk-lib/aws-logs';
import { RemovalPolicy } from 'aws-cdk-lib';

export const getSequenceRunManagerStackProps = (stage: AppStage): SequenceRunManagerStackProps => {
const logsConfig = {
retention: stage === AppStage.PROD ? RetentionDays.TWO_YEARS : RetentionDays.TWO_WEEKS,
removalPolicy: stage === AppStage.PROD ? RemovalPolicy.RETAIN : RemovalPolicy.DESTROY,
};

export const getSequenceRunManagerStackProps = (): SequenceRunManagerStackProps => {
return {
vpcProps,
lambdaSecurityGroupName: computeSecurityGroupName,
mainBusName: eventBusName,
cognitoUserPoolIdParameterName: cognitoUserPoolIdParameterName,
cognitoPortalAppClientIdParameterName: cognitoPortalAppClientIdParameterName,
cognitoStatusPageAppClientIdParameterName: cognitoStatusPageAppClientIdParameterName,
apiGwLogsConfig: logsConfig,
};
};
11 changes: 10 additions & 1 deletion config/stacks/workflowRunManager.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { RetentionDays } from 'aws-cdk-lib/aws-logs';
import { WorkflowManagerStackProps } from '../../lib/workload/stateless/stacks/workflow-manager/deploy/stack';
import {
vpcProps,
Expand All @@ -6,15 +7,23 @@ import {
cognitoUserPoolIdParameterName,
cognitoPortalAppClientIdParameterName,
cognitoStatusPageAppClientIdParameterName,
AppStage,
} from '../constants';
import { RemovalPolicy } from 'aws-cdk-lib';

export const getWorkflowManagerStackProps = (stage: AppStage): WorkflowManagerStackProps => {
const logsConfig = {
retention: stage === AppStage.PROD ? RetentionDays.TWO_YEARS : RetentionDays.TWO_WEEKS,
removalPolicy: stage === AppStage.PROD ? RemovalPolicy.RETAIN : RemovalPolicy.DESTROY,
};

export const getWorkflowManagerStackProps = (): WorkflowManagerStackProps => {
return {
vpcProps,
lambdaSecurityGroupName: computeSecurityGroupName,
mainBusName: eventBusName,
cognitoUserPoolIdParameterName: cognitoUserPoolIdParameterName,
cognitoPortalAppClientIdParameterName: cognitoPortalAppClientIdParameterName,
cognitoStatusPageAppClientIdParameterName: cognitoStatusPageAppClientIdParameterName,
apiGwLogsConfig: logsConfig,
};
};
68 changes: 60 additions & 8 deletions lib/workload/components/api-gateway/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,39 @@
import { Construct } from 'constructs';
import { aws_ssm, Duration } from 'aws-cdk-lib';
import { aws_ssm, Duration, RemovalPolicy } from 'aws-cdk-lib';
import { HttpJwtAuthorizer } from 'aws-cdk-lib/aws-apigatewayv2-authorizers';
import { CorsHttpMethod, HttpApi, CfnStage } from 'aws-cdk-lib/aws-apigatewayv2';
import { IStringParameter } from 'aws-cdk-lib/aws-ssm';
import { LogGroup } from 'aws-cdk-lib/aws-logs';
import { CorsHttpMethod, HttpApi, CfnStage, DomainName } from 'aws-cdk-lib/aws-apigatewayv2';
import { Certificate } from 'aws-cdk-lib/aws-certificatemanager';
import { IStringParameter, StringParameter } from 'aws-cdk-lib/aws-ssm';
import { LogGroup, RetentionDays } from 'aws-cdk-lib/aws-logs';
import { ARecord, HostedZone, RecordTarget } from 'aws-cdk-lib/aws-route53';
import { Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam';
import { ApiGatewayv2DomainProperties } from 'aws-cdk-lib/aws-route53-targets';

export interface ApiGwLogsConfig {
/**
* The number of days log events are kept in CloudWatch Logs.
*/
retention: RetentionDays;
/**
* The removal policy to apply to the log group.
*/
removalPolicy: RemovalPolicy;
}

export interface ApiGatewayConstructProps {
region: string;
apiName: string | undefined;
cognitoUserPoolIdParameterName: string;
cognitoPortalAppClientIdParameterName: string;
cognitoStatusPageAppClientIdParameterName: string;
/**
* The prefix for the custom domain name
*/
customDomainNamePrefix: string;
/**
* The configuration for aws cloudwatch logs
*/
apiGwLogsConfig: ApiGwLogsConfig;
}

export class ApiGatewayConstruct extends Construct {
Expand All @@ -20,6 +42,17 @@ export class ApiGatewayConstruct extends Construct {
constructor(scope: Construct, id: string, props: ApiGatewayConstructProps) {
super(scope, id);

// umccr acm arn
const umccrAcmArn = StringParameter.valueFromLookup(this, '/umccr/certificate_arn');
const hostedDomainName = StringParameter.valueFromLookup(this, '/hosted_zone/umccr/name');
const hostedZoneId = StringParameter.valueFromLookup(this, '/hosted_zone/umccr/id');

const domainName = `${props.customDomainNamePrefix}.${hostedDomainName}`;
const apiGWDomainName = new DomainName(this, 'UmccrDomainName', {
domainName: `${props.customDomainNamePrefix}.${hostedDomainName}`,
certificate: Certificate.fromCertificateArn(this, 'cert', umccrAcmArn),
});

this._httpApi = new HttpApi(this, 'HttpApi', {
apiName: 'OrcaBusAPI-' + props.apiName,
corsPreflight: {
Expand All @@ -34,11 +67,27 @@ export class ApiGatewayConstruct extends Construct {
maxAge: Duration.days(10),
},
defaultAuthorizer: this.getAuthorizer(props),
// defaultDomainMapping: ... TODO
defaultDomainMapping: {
domainName: apiGWDomainName,
},
});

new ARecord(this, 'CustomDomainARecord', {
zone: HostedZone.fromHostedZoneAttributes(this, 'UmccrHostedZone', {
hostedZoneId,
zoneName: hostedDomainName,
}),
recordName: domainName,
target: RecordTarget.fromAlias(
new ApiGatewayv2DomainProperties(
apiGWDomainName.regionalDomainName,
apiGWDomainName.regionalHostedZoneId
)
),
});

// LogGroups
this.setupAccessLogs();
this.setupAccessLogs(props.apiGwLogsConfig);

// CloudMap
// this.setupCloudServiceDiscovery()
Expand All @@ -50,8 +99,11 @@ export class ApiGatewayConstruct extends Construct {

// TODO: Taken from https://github.com/aws/aws-cdk/issues/11100#issuecomment-904627081
// Monitor for higher level CDK construct instead of leveraging CfnStage
private setupAccessLogs() {
const accessLogs = new LogGroup(this, 'OrcaBus-ApiGw-AccessLogs');
private setupAccessLogs(props: ApiGwLogsConfig) {
const accessLogs = new LogGroup(this, 'ApiGwAccessLogs', {
retention: props.retention,
removalPolicy: props.removalPolicy,
});
const stage = this.httpApi.defaultStage?.node.defaultChild as CfnStage;
stage.accessLogSettings = {
destinationArn: accessLogs.logGroupArn,
Expand Down
4 changes: 3 additions & 1 deletion lib/workload/stateless/stacks/filemanager/deploy/stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Vpc, SecurityGroup, VpcLookupOptions, IVpc, ISecurityGroup } from 'aws-
import { Arn, Stack, StackProps } from 'aws-cdk-lib';
import { StringParameter } from 'aws-cdk-lib/aws-ssm';
import { ProviderFunction } from '../../../../components/provider-function';
import { ApiGatewayConstruct } from '../../../../components/api-gateway';
import { ApiGatewayConstruct, ApiGwLogsConfig } from '../../../../components/api-gateway';
import { IQueue, Queue } from 'aws-cdk-lib/aws-sqs';
import { HttpMethod, HttpRoute, HttpRouteKey } from 'aws-cdk-lib/aws-apigatewayv2';
import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
Expand All @@ -30,6 +30,7 @@ export type FilemanagerConfig = Omit<DatabaseProps, 'host' | 'securityGroup'> &
cognitoUserPoolIdParameterName: string;
cognitoPortalAppClientIdParameterName: string;
cognitoStatusPageAppClientIdParameterName: string;
apiGwLogsConfig: ApiGwLogsConfig;
fileManagerIngestRoleName: string;
};

Expand Down Expand Up @@ -141,6 +142,7 @@ export class Filemanager extends Stack {
const ApiGateway = new ApiGatewayConstruct(this, 'ApiGateway', {
region: this.region,
apiName: 'FileManager',
customDomainNamePrefix: 'file',
...props,
});
const httpApi = ApiGateway.httpApi;
Expand Down
Loading

0 comments on commit 46244d7

Please sign in to comment.