Skip to content

Commit

Permalink
Merge pull request #2309 from metriport/develop
Browse files Browse the repository at this point in the history
RELEASE 2/3 Point infra to ALB
  • Loading branch information
leite08 committed Jun 20, 2024
2 parents 33cf8f4 + 1963b3b commit cadf537
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 79 deletions.
4 changes: 2 additions & 2 deletions packages/api/src/external/carequality/patient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,12 @@ async function prepareAndTriggerPD({
);

if (numGatewaysV1 > 0) {
log(`Kicking off patient discovery Gateway V1`);
log(`Kicking off patient discovery Gateway V1 - ${numGatewaysV1} gateways`);
await enabledIHEGW.startPatientDiscovery(pdRequestGatewayV1);
}

if (numGatewaysV2 > 0) {
log(`Kicking off patient discovery Gateway V2`);
log(`Kicking off patient discovery Gateway V2 - ${numGatewaysV2} gateways`);
const iheGatewayV2 = makeIHEGatewayV2();
await iheGatewayV2.startPatientDiscovery({
pdRequestGatewayV2,
Expand Down
66 changes: 30 additions & 36 deletions packages/infra/lib/api-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,8 @@ export class APIStack extends Stack {
const {
cluster,
service: apiService,
loadBalancerAddress: apiLoadBalancerAddress,
loadBalancer: apiLoadBalancer,
loadBalancerAddress: apiDirectUrl,
serverAddress: apiServerUrl,
apiServiceAdditional,
} = createAPIService({
Expand Down Expand Up @@ -429,6 +430,7 @@ export class APIStack extends Stack {
},
cookieStore,
});
const apiLoadBalancerAddress = apiLoadBalancer.loadBalancerDnsName;

if (props.config.iheGateway) {
const mtlsBucketName = s3.Bucket.fromBucketName(
Expand All @@ -439,7 +441,7 @@ export class APIStack extends Stack {
new IHEGatewayV2LambdasNestedStack(this, "IHEGatewayV2LambdasNestedStack", {
lambdaLayers,
vpc: this.vpc,
apiService: apiService,
apiTaskRole: apiService.taskDefinition.taskRole,
secrets,
cqOrgCertificate: props.config.carequality?.secretNames.CQ_ORG_CERTIFICATE,
cqOrgPrivateKey: props.config.carequality?.secretNames.CQ_ORG_PRIVATE_KEY,
Expand All @@ -448,7 +450,7 @@ export class APIStack extends Stack {
cqOrgPrivateKeyPassword: props.config.carequality?.secretNames.CQ_ORG_PRIVATE_KEY_PASSWORD,
cqTrustBundleBucket: mtlsBucketName,
medicalDocumentsBucket: medicalDocumentsBucket,
apiURL: apiService.loadBalancer.loadBalancerDnsName,
apiURL: apiDirectUrl,
envType: props.config.environmentType,
sentryDsn: props.config.lambdasSentryDSN,
iheResponsesBucketName: props.config.iheResponsesBucketName,
Expand All @@ -460,9 +462,9 @@ export class APIStack extends Stack {
// TODO remove this on 3/3
dbCluster.connections.allowDefaultPortFrom(apiServiceAdditional);

// setup a private link so the API can talk to the NLB
// setup a private link so the API GW can talk to the API's LB
const link = new apig.VpcLink(this, "link", {
targets: [apiService.loadBalancer],
targets: [apiLoadBalancer],
});

const integration = new apig.Integration({
Expand Down Expand Up @@ -503,26 +505,15 @@ export class APIStack extends Stack {
dlq: fhirConverterDLQ,
fhirConverterBucket,
conversionResultQueueUrl: fhirServerQueue.queueUrl,
apiServiceDnsAddress: apiLoadBalancerAddress,
apiServiceDnsAddress: apiDirectUrl,
alarmSnsAction: slackNotification?.alarmAction,
})
: undefined;

// Add ENV after apiserivce is created
outboundPatientDiscoveryLambda.addEnvironment(
"API_URL",
`http:https://${apiService.loadBalancer.loadBalancerDnsName}`
);

outboundDocumentQueryLambda.addEnvironment(
"API_URL",
`http:https://${apiService.loadBalancer.loadBalancerDnsName}`
);

outboundDocumentRetrievalLambda.addEnvironment(
"API_URL",
`http:https://${apiService.loadBalancer.loadBalancerDnsName}`
);
// Add ENV after the API service is created
outboundPatientDiscoveryLambda.addEnvironment("API_URL", `http:https://${apiDirectUrl}`);
outboundDocumentQueryLambda.addEnvironment("API_URL", `http:https://${apiDirectUrl}`);
outboundDocumentRetrievalLambda.addEnvironment("API_URL", `http:https://${apiDirectUrl}`);

// Access grant for medical documents bucket
sandboxSeedDataBucket &&
Expand All @@ -535,15 +526,15 @@ export class APIStack extends Stack {
lambdaLayers,
stack: this,
vpc: this.vpc,
apiAddress: apiLoadBalancerAddress,
apiAddress: apiDirectUrl,
alarmSnsAction: slackNotification?.alarmAction,
});

createCqDirectoryRebuilder({
lambdaLayers,
stack: this,
vpc: this.vpc,
apiAddress: apiLoadBalancerAddress,
apiAddress: apiDirectUrl,
alarmSnsAction: slackNotification?.alarmAction,
});

Expand All @@ -554,7 +545,7 @@ export class APIStack extends Stack {
lambdaLayers,
envType: props.config.environmentType,
secrets,
apiAddress: apiLoadBalancerAddress,
apiAddress: apiDirectUrl,
bucket: generalBucket,
alarmSnsAction: slackNotification?.alarmAction,
cookieStore,
Expand Down Expand Up @@ -699,7 +690,7 @@ export class APIStack extends Stack {
lambdaLayers,
stack: this,
vpc: this.vpc,
apiService,
apiAddress: apiDirectUrl,
envType: props.config.environmentType,
medicalDocumentsBucket,
medicalDocumentsUploadBucket,
Expand All @@ -719,7 +710,8 @@ export class APIStack extends Stack {
searchIndex: ccdaSearchIndexName,
searchUserName: ccdaSearchUserName,
searchPassword: ccdaSearchSecret.secretValue.unsafeUnwrap(),
apiService: apiService,
apiTaskRole: apiService.service.taskDefinition.taskRole,
apiAddress: apiDirectUrl,
});

this.setupGarminWebhookAuth({
Expand Down Expand Up @@ -810,13 +802,13 @@ export class APIStack extends Stack {
stack: this,
lambdaLayers,
vpc: this.vpc,
apiAddress: apiLoadBalancerAddress,
apiAddress: apiDirectUrl,
});
createScheduledDBMaintenance({
stack: this,
lambdaLayers,
vpc: this.vpc,
apiAddress: apiLoadBalancerAddress,
apiAddress: apiDirectUrl,
});

//-------------------------------------------
Expand Down Expand Up @@ -916,7 +908,7 @@ export class APIStack extends Stack {
lambdaLayers: LambdaLayers;
baseResource: apig.Resource;
vpc: ec2.IVpc;
fargateService: ecs_patterns.NetworkLoadBalancedFargateService;
fargateService: ecs_patterns.ApplicationLoadBalancedFargateService;
dynamoDBTokenTable: dynamodb.Table;
envType: EnvType;
sentryDsn: string | undefined;
Expand Down Expand Up @@ -961,7 +953,7 @@ export class APIStack extends Stack {
lambdaLayers: LambdaLayers;
baseResource: apig.Resource;
vpc: ec2.IVpc;
fargateService: ecs_patterns.NetworkLoadBalancedFargateService;
fargateService: ecs_patterns.ApplicationLoadBalancedFargateService;
envType: EnvType;
sentryDsn: string | undefined;
}) {
Expand Down Expand Up @@ -1000,7 +992,7 @@ export class APIStack extends Stack {
baseResource: apig.Resource;
secrets: Secrets;
vpc: ec2.IVpc;
fargateService: ecs_patterns.NetworkLoadBalancedFargateService;
fargateService: ecs_patterns.ApplicationLoadBalancedFargateService;
fitbitClientSecret: string;
fitbitSubscriberVerificationCode: string;
envType: EnvType;
Expand Down Expand Up @@ -1071,7 +1063,7 @@ export class APIStack extends Stack {
baseResource: apig.Resource;
secrets: Secrets;
vpc: ec2.IVpc;
fargateService: ecs_patterns.NetworkLoadBalancedFargateService;
fargateService: ecs_patterns.ApplicationLoadBalancedFargateService;
tenoviAuthHeader: string;
envType: EnvType;
sentryDsn: string | undefined;
Expand Down Expand Up @@ -1126,7 +1118,8 @@ export class APIStack extends Stack {
searchIndex: string;
searchUserName: string;
searchPassword: string;
apiService: ecs_patterns.NetworkLoadBalancedFargateService;
apiTaskRole: iam.IRole;
apiAddress: string;
}): Lambda {
const {
lambdaLayers,
Expand All @@ -1141,7 +1134,8 @@ export class APIStack extends Stack {
searchIndex,
searchUserName,
searchPassword,
apiService,
apiTaskRole,
apiAddress,
} = ownProps;

const isSandboxSeed = envType === "sandbox" && medicalSeedDocumentsBucket;
Expand All @@ -1161,7 +1155,7 @@ export class APIStack extends Stack {
SEARCH_INDEX: searchIndex,
SEARCH_USERNAME: searchUserName,
SEARCH_PASSWORD: searchPassword,
API_URL: `http:https://${apiService.loadBalancer.loadBalancerDnsName}`,
API_URL: `http:https://${apiAddress}`,
...(sentryDsn ? { SENTRY_DSN: sentryDsn } : {}),
},
layers: [lambdaLayers.shared],
Expand All @@ -1173,7 +1167,7 @@ export class APIStack extends Stack {

isSandboxSeed && medicalSeedDocumentsBucket.grantRead(bulkUrlSigningLambda);
medicalDocumentsBucket.grantRead(bulkUrlSigningLambda);
bulkUrlSigningLambda.grantInvoke(apiService.taskDefinition.taskRole);
bulkUrlSigningLambda.grantInvoke(apiTaskRole);

return bulkUrlSigningLambda;
}
Expand Down
54 changes: 28 additions & 26 deletions packages/infra/lib/api-stack/api-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ export function createAPIService({
cookieStore: secret.ISecret | undefined;
}): {
cluster: ecs.Cluster;
service: ecs_patterns.NetworkLoadBalancedFargateService;
service: ecs_patterns.ApplicationLoadBalancedFargateService;
loadBalancer: NetworkLoadBalancer;
serverAddress: string;
loadBalancerAddress: string;
apiServiceAdditional: FargateService;
Expand Down Expand Up @@ -131,7 +132,7 @@ export function createAPIService({
const containerPort = 8080;
const logGroup = LogGroup.fromLogGroupArn(stack, "ApiLogGroup", props.config.logArn);
// TODO RENAME to remove "Alb"
const fargateServiceAlb = new ecs_patterns.ApplicationLoadBalancedFargateService(
const fargateService = new ecs_patterns.ApplicationLoadBalancedFargateService(
stack,
"APIFargateServiceAlb",
{
Expand Down Expand Up @@ -247,7 +248,7 @@ export function createAPIService({
}
);
// TODO DEPRECATED start
const fargateService = new ecs_patterns.NetworkLoadBalancedFargateService(
const fargateServiceNlb = new ecs_patterns.NetworkLoadBalancedFargateService(
stack,
"APIFargateService",
{
Expand All @@ -258,7 +259,7 @@ export function createAPIService({
desiredCount: isProd(props.config) ? 2 : 1,
taskImageOptions: {
image: ecs.ContainerImage.fromEcrRepository(ecrRepo, "latest"),
containerPort: 8080,
containerPort,
containerName: "API-Server",
secrets: {
DB_CREDS: ecs.Secret.fromSecretsManager(dbCredsSecret),
Expand Down Expand Up @@ -367,7 +368,7 @@ export function createAPIService({
),
});

const alb = fargateServiceAlb.loadBalancer;
const alb = fargateService.loadBalancer;
const nlb = new NetworkLoadBalancer(stack, `ApiNetworkLoadBalancer`, {
vpc,
internetFacing: false,
Expand All @@ -390,15 +391,15 @@ export function createAPIService({
unhealthyThresholdCount: 2,
interval: Duration.seconds(10),
};
fargateServiceAlb.targetGroup.configureHealthCheck(healthcheck);
fargateService.targetGroup.configureHealthCheck(healthcheck);
nlbTargetGroup.configureHealthCheck({
...healthcheck,
interval: healthcheck.interval.plus(Duration.seconds(3)),
});

// Access grant for Aurora DB's secret
dbCredsSecret.grantRead(fargateService.taskDefinition.taskRole);
dbCredsSecret.grantRead(fargateServiceAlb.taskDefinition.taskRole);
dbCredsSecret.grantRead(fargateServiceNlb.taskDefinition.taskRole);
// RW grant for Dynamo DB
dynamoDBTokenTable.grantReadWriteData(fargateService.taskDefinition.taskRole);
cdaToVisualizationLambda.grantInvoke(fargateService.taskDefinition.taskRole);
Expand All @@ -407,29 +408,29 @@ export function createAPIService({
outboundDocumentQueryLambda.grantInvoke(fargateService.taskDefinition.taskRole);
outboundDocumentRetrievalLambda.grantInvoke(fargateService.taskDefinition.taskRole);
fhirToCdaConverterLambda?.grantInvoke(fargateService.taskDefinition.taskRole);
dynamoDBTokenTable.grantReadWriteData(fargateServiceAlb.taskDefinition.taskRole);
cdaToVisualizationLambda.grantInvoke(fargateServiceAlb.taskDefinition.taskRole);
documentDownloaderLambda.grantInvoke(fargateServiceAlb.taskDefinition.taskRole);
outboundPatientDiscoveryLambda.grantInvoke(fargateServiceAlb.taskDefinition.taskRole);
outboundDocumentQueryLambda.grantInvoke(fargateServiceAlb.taskDefinition.taskRole);
outboundDocumentRetrievalLambda.grantInvoke(fargateServiceAlb.taskDefinition.taskRole);
fhirToCdaConverterLambda?.grantInvoke(fargateServiceAlb.taskDefinition.taskRole);
dynamoDBTokenTable.grantReadWriteData(fargateServiceNlb.taskDefinition.taskRole);
cdaToVisualizationLambda.grantInvoke(fargateServiceNlb.taskDefinition.taskRole);
documentDownloaderLambda.grantInvoke(fargateServiceNlb.taskDefinition.taskRole);
outboundPatientDiscoveryLambda.grantInvoke(fargateServiceNlb.taskDefinition.taskRole);
outboundDocumentQueryLambda.grantInvoke(fargateServiceNlb.taskDefinition.taskRole);
outboundDocumentRetrievalLambda.grantInvoke(fargateServiceNlb.taskDefinition.taskRole);
fhirToCdaConverterLambda?.grantInvoke(fargateServiceNlb.taskDefinition.taskRole);

// Access grant for medical document buckets
medicalDocumentsUploadBucket.grantReadWrite(fargateService.taskDefinition.taskRole);
medicalDocumentsUploadBucket.grantReadWrite(fargateServiceAlb.taskDefinition.taskRole);
medicalDocumentsUploadBucket.grantReadWrite(fargateServiceNlb.taskDefinition.taskRole);

if (fhirToMedicalRecordLambda) {
fhirToMedicalRecordLambda.grantInvoke(fargateService.taskDefinition.taskRole);
fhirToMedicalRecordLambda.grantInvoke(fargateServiceAlb.taskDefinition.taskRole);
fhirToMedicalRecordLambda.grantInvoke(fargateServiceNlb.taskDefinition.taskRole);
cdaToVisualizationLambda.grantInvoke(fhirToMedicalRecordLambda);
}

if (cookieStore) {
cookieStore.grantRead(fargateService.service.taskDefinition.taskRole);
cookieStore.grantWrite(fargateService.service.taskDefinition.taskRole);
cookieStore.grantRead(fargateServiceAlb.service.taskDefinition.taskRole);
cookieStore.grantWrite(fargateServiceAlb.service.taskDefinition.taskRole);
cookieStore.grantRead(fargateServiceNlb.service.taskDefinition.taskRole);
cookieStore.grantWrite(fargateServiceNlb.service.taskDefinition.taskRole);
}

// Allow access to search services/infra
Expand All @@ -442,9 +443,9 @@ export function createAPIService({
provideAccessToQueue({
accessType: "send",
queue: searchIngestionQueue,
resource: fargateServiceAlb.taskDefinition.taskRole,
resource: fargateServiceNlb.taskDefinition.taskRole,
});
searchAuth.secret.grantRead(fargateServiceAlb.taskDefinition.taskRole);
searchAuth.secret.grantRead(fargateServiceNlb.taskDefinition.taskRole);

// Setting permissions for AppConfig
fargateService.taskDefinition.taskRole.attachInlinePolicy(
Expand All @@ -467,7 +468,7 @@ export function createAPIService({
],
})
);
fargateServiceAlb.taskDefinition.taskRole.attachInlinePolicy(
fargateServiceNlb.taskDefinition.taskRole.attachInlinePolicy(
new iam.Policy(stack, "ApiPermissionsForAppConfig", {
statements: [
new iam.PolicyStatement({
Expand Down Expand Up @@ -521,24 +522,24 @@ export function createAPIService({
ec2.Port.allTraffic(),
"Allow traffic from within the VPC to the service secure port"
);
fargateServiceAlb.service.connections.allowFrom(
fargateServiceNlb.service.connections.allowFrom(
ec2.Peer.ipv4(vpc.vpcCidrBlock),
ec2.Port.allTraffic(),
"Allow traffic from within the VPC to the service secure port"
);
// TODO: #489 ain't the most secure, but the above code doesn't work as CDK complains we can't use the connections
// from the cluster created above, should be fine for now as it will only accept connections in the VPC
fargateService.service.connections.allowFromAnyIpv4(ec2.Port.allTcp());
fargateServiceAlb.service.connections.allowFromAnyIpv4(ec2.Port.allTcp());
fargateServiceNlb.service.connections.allowFromAnyIpv4(ec2.Port.allTcp());

// TODO DEPRECATED start
// This speeds up deployments so the tasks are swapped quicker.
// See for details: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-target-groups.html#deregistration-delay
fargateService.targetGroup.setAttribute("deregistration_delay.timeout_seconds", "17");
fargateServiceNlb.targetGroup.setAttribute("deregistration_delay.timeout_seconds", "17");

// This also speeds up deployments so the health checks have a faster turnaround.
// See for details: https://docs.aws.amazon.com/elasticloadbalancing/latest/network/target-group-health-checks.html
fargateService.targetGroup.configureHealthCheck({
fargateServiceNlb.targetGroup.configureHealthCheck({
healthyThresholdCount: 2,
interval: Duration.seconds(10),
});
Expand All @@ -564,7 +565,8 @@ export function createAPIService({
cluster,
service: fargateService,
serverAddress: apiUrl,
loadBalancer: nlb,
loadBalancerAddress: serverAddress,
apiServiceAdditional: fargateServiceAlb.service,
apiServiceAdditional: fargateServiceNlb.service,
};
}
Loading

0 comments on commit cadf537

Please sign in to comment.