Skip to content

Commit

Permalink
Feat: Update API Gateway Configuration (#531)
Browse files Browse the repository at this point in the history
  • Loading branch information
williamputraintan authored Sep 4, 2024
1 parent 24f56f9 commit 36bb67b
Show file tree
Hide file tree
Showing 13 changed files with 146 additions and 166 deletions.
39 changes: 29 additions & 10 deletions config/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { RemovalPolicy } from 'aws-cdk-lib';
import { VpcLookupOptions } from 'aws-cdk-lib/aws-ec2';
import { RetentionDays } from 'aws-cdk-lib/aws-logs';
import path from 'path';

export enum AppStage {
Expand Down Expand Up @@ -35,15 +37,35 @@ export const vpcProps: VpcLookupOptions = {
};

// upstream infra: cognito
export const cognitoUserPoolIdParameterName = '/data_portal/client/cog_user_pool_id';
export const cognitoPortalAppClientIdParameterName =
'/data_portal/client/data2/cog_app_client_id_stage';
export const cognitoStatusPageAppClientIdParameterName =
'/data_portal/status_page/cog_app_client_id_stage';
export const cognitoApiGatewayProps = {
cognitoUserPoolIdParameterName: cognitoUserPoolIdParameterName,
cognitoPortalAppClientIdParameterName: cognitoPortalAppClientIdParameterName,
cognitoStatusPageAppClientIdParameterName: cognitoStatusPageAppClientIdParameterName,
export const cognitoUserPoolIdParameterName = '/data_portal/client/cog_user_pool_id';
export const logsApiGatewayConfig = {
[AppStage.BETA]: {
retention: RetentionDays.TWO_WEEKS,
removalPolicy: RemovalPolicy.DESTROY,
},
[AppStage.GAMMA]: {
retention: RetentionDays.TWO_WEEKS,
removalPolicy: RemovalPolicy.DESTROY,
},
[AppStage.PROD]: {
retention: RetentionDays.TWO_YEARS,
removalPolicy: RemovalPolicy.RETAIN,
},
};
export const corsAllowOrigins = {
[AppStage.BETA]: ['https://orcaui.dev.umccr.org'],
[AppStage.GAMMA]: ['https://orcaui.stg.umccr.org'],
[AppStage.PROD]: ['https://orcaui.prod.umccr.org', 'https://orcaui.umccr.org'],
};
export const cognitoApiGatewayConfig = {
region,
cognitoUserPoolIdParameterName,
cognitoClientIdParameterNameArray: [
cognitoPortalAppClientIdParameterName, // portal - TokenServiceStack
'/orcaui/cog_app_client_id_stage', // orcaui - https://github.com/umccr/orca-ui
],
};

export const oncoanalyserBucket: Record<AppStage, string> = {
Expand Down Expand Up @@ -153,9 +175,6 @@ export const bclconvertInteropQcDynamoDbTableSSMArn = path.join(
);

// Stateless

export const corsAllowOrigins = ['*'];

export const bclconvertInteropQcIcav2PipelineWorkflowName = 'bclconvert-interop-qc';
export const bclconvertInteropQcIcav2PipelineWorkflowTypeVersion = '1.3.1--1.21';
export const bclconvertInteropQcIcav2ServiceVersion = '2024.07.01';
Expand Down
24 changes: 9 additions & 15 deletions config/stacks/fileManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { RetentionDays } from 'aws-cdk-lib/aws-logs';
import { FilemanagerConfig } from '../../lib/workload/stateless/stacks/filemanager/deploy/stack';
import {
AppStage,
Expand All @@ -7,36 +6,31 @@ import {
dbClusterEndpointHostParameterName,
eventSourceQueueName,
vpcProps,
cognitoPortalAppClientIdParameterName,
cognitoStatusPageAppClientIdParameterName,
cognitoUserPoolIdParameterName,
oncoanalyserBucket,
icav2PipelineCacheBucket,
fileManagerIngestRoleName,
logsApiGatewayConfig,
cognitoApiGatewayConfig,
corsAllowOrigins,
} 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,
eventSourceQueueName: eventSourceQueueName,
databaseClusterEndpointHostParameter: dbClusterEndpointHostParameterName,
port: databasePort,
migrateDatabase: true,
cognitoPortalAppClientIdParameterName: cognitoPortalAppClientIdParameterName,
cognitoStatusPageAppClientIdParameterName: cognitoStatusPageAppClientIdParameterName,
cognitoUserPoolIdParameterName: cognitoUserPoolIdParameterName,
apiGwLogsConfig: logsConfig,
inventorySourceBuckets: ['filemanager-inventory-test'],
eventSourceBuckets: [oncoanalyserBucket[stage], icav2PipelineCacheBucket[stage]],
fileManagerIngestRoleName: fileManagerIngestRoleName,
corsAllowOrigins,
apiGatewayCognitoProps: {
...cognitoApiGatewayConfig,
corsAllowOrigins: corsAllowOrigins[stage],
apiGwLogsConfig: logsApiGatewayConfig[stage],
apiName: 'FileManager',
customDomainNamePrefix: 'file',
},
};
};
19 changes: 9 additions & 10 deletions config/stacks/metadataManager.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
import {
AppStage,
cognitoApiGatewayProps,
cognitoApiGatewayConfig,
computeSecurityGroupName,
corsAllowOrigins,
logsApiGatewayConfig,
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, apiGwLogsConfig: logsConfig },
corsAllowOrigins,
apiGatewayCognitoProps: {
...cognitoApiGatewayConfig,
corsAllowOrigins: corsAllowOrigins[stage],
apiGwLogsConfig: logsApiGatewayConfig[stage],
apiName: 'MetadataManager',
customDomainNamePrefix: 'metadata',
},
};
};
24 changes: 9 additions & 15 deletions config/stacks/sequenceRunManager.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,25 @@
import {
AppStage,
cognitoPortalAppClientIdParameterName,
cognitoStatusPageAppClientIdParameterName,
cognitoUserPoolIdParameterName,
cognitoApiGatewayConfig,
computeSecurityGroupName,
corsAllowOrigins,
eventBusName,
logsApiGatewayConfig,
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,
};

return {
vpcProps,
lambdaSecurityGroupName: computeSecurityGroupName,
mainBusName: eventBusName,
cognitoUserPoolIdParameterName: cognitoUserPoolIdParameterName,
cognitoPortalAppClientIdParameterName: cognitoPortalAppClientIdParameterName,
cognitoStatusPageAppClientIdParameterName: cognitoStatusPageAppClientIdParameterName,
apiGwLogsConfig: logsConfig,
corsAllowOrigins,
apiGatewayCognitoProps: {
...cognitoApiGatewayConfig,
corsAllowOrigins: corsAllowOrigins[stage],
apiGwLogsConfig: logsApiGatewayConfig[stage],
apiName: 'SequenceRunManager',
customDomainNamePrefix: 'sequence',
},
};
};
24 changes: 9 additions & 15 deletions config/stacks/workflowRunManager.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,25 @@
import { RetentionDays } from 'aws-cdk-lib/aws-logs';
import { WorkflowManagerStackProps } from '../../lib/workload/stateless/stacks/workflow-manager/deploy/stack';
import {
vpcProps,
computeSecurityGroupName,
eventBusName,
cognitoUserPoolIdParameterName,
cognitoPortalAppClientIdParameterName,
cognitoStatusPageAppClientIdParameterName,
AppStage,
cognitoApiGatewayConfig,
logsApiGatewayConfig,
corsAllowOrigins,
} 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,
};

return {
vpcProps,
lambdaSecurityGroupName: computeSecurityGroupName,
mainBusName: eventBusName,
cognitoUserPoolIdParameterName: cognitoUserPoolIdParameterName,
cognitoPortalAppClientIdParameterName: cognitoPortalAppClientIdParameterName,
cognitoStatusPageAppClientIdParameterName: cognitoStatusPageAppClientIdParameterName,
apiGwLogsConfig: logsConfig,
corsAllowOrigins,
apiGatewayCognitoProps: {
...cognitoApiGatewayConfig,
corsAllowOrigins: corsAllowOrigins[stage],
apiGwLogsConfig: logsApiGatewayConfig[stage],
apiName: 'WorkflowManager',
customDomainNamePrefix: 'workflow',
},
};
};
10 changes: 10 additions & 0 deletions docs/developer/MICROSERVICE.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ Either tasks _(developing an app and/or cdk deployment constructs)_; we promote
_Mac user: Option + M for the µ symbol_


### Using API as backend

When integrating the microservice with a client, you might create a new Cognito app client ID. If this is the case, you
will need to add the new client ID to the AWS API Gateway setup to ensure the token generated by that Cognito app is
valid for use with the microservice API Gateway. Store this Cognito app ID in an SSM Parameter and pass the SSM
Parameter name in the `cognitoApiGatewayConfig` constant file (`./config/constants.ts`). Additionally, you may need to set
the appropriate CORS origin in the `corsAllowOrigins` constant file to prevent any CORS errors in your client.

Reference on creating new Cognito App: <https://github.com/umccr/infrastructure/tree/master/terraform/stacks/cognito_aai>

### Native Bootstrap

You may also just simply use "native toolchain bootstrap" method. This could be the typical "getting started" of respective tool or framework. Some examples as follows.
Expand Down
57 changes: 36 additions & 21 deletions lib/workload/components/api-gateway/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,36 @@ export interface ApiGwLogsConfig {
}

export interface ApiGatewayConstructProps {
/**
* The AWS region.
*/
region: string;
apiName: string | undefined;
cognitoUserPoolIdParameterName: string;
cognitoPortalAppClientIdParameterName: string;
cognitoStatusPageAppClientIdParameterName: string;
/**
* The name of the API.
*/
apiName: string;
/**
* The prefix for the custom domain name
*/
customDomainNamePrefix: string;
/**
*The cognito user pool id parameter name.
*/
cognitoUserPoolIdParameterName: string;
/**
* The parameter name for the cognito client id in array.
* In order API Gateway to validate the JWT token, it needs to know the client id which usually
* stored in SSM Parameter. This will accept multiple parameter name in an array.
*/
cognitoClientIdParameterNameArray: string[];
/**
* The configuration for aws cloudwatch logs
*/
apiGwLogsConfig: ApiGwLogsConfig;
/**
* Allowed CORS origins.
*/
corsAllowOrigins?: string[];
corsAllowOrigins: string[];
}

export class ApiGatewayConstruct extends Construct {
Expand All @@ -64,7 +77,15 @@ export class ApiGatewayConstruct extends Construct {
this._httpApi = new HttpApi(this, 'HttpApi', {
apiName: 'OrcaBusAPI-' + props.apiName,
corsPreflight: {
allowHeaders: ['Authorization'],
allowHeaders: [
'content-type',
'content-disposition',
'authorization',
'x-amz-date',
'x-api-key',
'x-amz-security-token',
'x-amz-user-agent',
],
allowMethods: [
CorsHttpMethod.GET,
CorsHttpMethod.HEAD,
Expand Down Expand Up @@ -144,34 +165,28 @@ export class ApiGatewayConstruct extends Construct {
* FIXME One fine day in future when we have proper Cognito AAI setup.
* For the moment, we leverage Portal and established Cognito infrastructure.
* See https://github.com/umccr/orcabus/issues/102
*
* UI clients:
* https://portal.[dev|stg|prod].umccr.org
* https://status.[dev|stg|prod].umccr.org
*/

const userPoolIdParam: IStringParameter = aws_ssm.StringParameter.fromStringParameterName(
this,
'CognitoUserPoolIdParameter',
props.cognitoUserPoolIdParameterName
);
const portalClientIdParam: IStringParameter = aws_ssm.StringParameter.fromStringParameterName(
this,
'CognitoPortalClientIdParameter',
props.cognitoPortalAppClientIdParameterName

const clientIdParamsArray: IStringParameter[] = props.cognitoClientIdParameterNameArray.map(
(name) =>
aws_ssm.StringParameter.fromStringParameterName(
this,
`CognitoClientId${name}Parameter`,
name
)
);
const statusPageClientIdParam: IStringParameter =
aws_ssm.StringParameter.fromStringParameterName(
this,
'CognitoStatusPageClientIdParameter',
props.cognitoStatusPageAppClientIdParameterName
);

const issuer =
'https://cognito-idp.' + props.region + '.amazonaws.com/' + userPoolIdParam.stringValue;

return new HttpJwtAuthorizer('PortalAuthorizer', issuer, {
jwtAudience: [portalClientIdParam.stringValue, statusPageClientIdParam.stringValue],
jwtAudience: clientIdParamsArray.map((param) => param.stringValue),
});
}

Expand Down
Loading

0 comments on commit 36bb67b

Please sign in to comment.