@guardian/cdk 64.4.0 → 64.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @guardian/cdk
|
|
2
2
|
|
|
3
|
+
## 64.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 4bef089: Bump brace-expansion to resolve high severity alert.
|
|
8
|
+
|
|
9
|
+
## 64.5.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 7ebce5d: Sets containerInsights to enhanced and adds monitoring settings as default for ECS
|
|
14
|
+
|
|
3
15
|
## 64.4.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gu-load-balanced-app.d.ts","sourceRoot":"","sources":["../../../src/experimental/patterns/gu-load-balanced-app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,QAAQ,EAAqB,MAAM,aAAa,CAAC;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAuB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAQlG,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"gu-load-balanced-app.d.ts","sourceRoot":"","sources":["../../../src/experimental/patterns/gu-load-balanced-app.ts"],"names":[],"mappings":"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"}
|
|
@@ -139,7 +139,10 @@ class GuLoadBalancedAppExperimental extends constructs_1.Construct {
|
|
|
139
139
|
if (!ecrRepoName) {
|
|
140
140
|
throw new Error("Could not determine an ECR repository name; please set this manually via ecsProps");
|
|
141
141
|
}
|
|
142
|
-
const cluster = new aws_ecs_4.Cluster(this, "EcsCluster", {
|
|
142
|
+
const cluster = new aws_ecs_4.Cluster(this, "EcsCluster", {
|
|
143
|
+
vpc,
|
|
144
|
+
containerInsightsV2: aws_ecs_1.ContainerInsights.ENHANCED,
|
|
145
|
+
});
|
|
143
146
|
const image = aws_ecs_4.ContainerImage.fromEcrRepository(
|
|
144
147
|
// Images are published to the ECR registry in the DeployTools account, so reference that here
|
|
145
148
|
aws_ecr_1.Repository.fromRepositoryAttributes(this, "Repo", {
|
|
@@ -239,6 +242,15 @@ class GuLoadBalancedAppExperimental extends constructs_1.Construct {
|
|
|
239
242
|
}),
|
|
240
243
|
],
|
|
241
244
|
});
|
|
245
|
+
const cfnService = ecsService.node.defaultChild;
|
|
246
|
+
cfnService.addPropertyOverride("Monitoring", {
|
|
247
|
+
MetricConfigurations: [
|
|
248
|
+
{
|
|
249
|
+
MetricNames: ["CPUUtilization", "MemoryUtilization"],
|
|
250
|
+
ResolutionSeconds: 20,
|
|
251
|
+
},
|
|
252
|
+
],
|
|
253
|
+
});
|
|
242
254
|
ecsService.autoScaleTaskCount({
|
|
243
255
|
minCapacity: scaling.minimumTasks,
|
|
244
256
|
maxCapacity: scaling.maximumTasks,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gu-load-balanced-app.js","sourceRoot":"","sources":["../../../src/experimental/patterns/gu-load-balanced-app.ts"],"names":[],"mappings":"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","sourcesContent":["import { ArnFormat, Aspects, Duration, SecretValue, Tags } from \"aws-cdk-lib\";\nimport type { BlockDevice, CfnAutoScalingGroup, UpdatePolicy } from \"aws-cdk-lib/aws-autoscaling\";\nimport { AdditionalHealthCheckType, HealthChecks } from \"aws-cdk-lib/aws-autoscaling\";\nimport {\n ProviderAttribute,\n UserPool,\n UserPoolClientIdentityProvider,\n UserPoolIdentityProviderGoogle,\n} from \"aws-cdk-lib/aws-cognito\";\nimport type { InstanceType, ISubnet, IVpc } from \"aws-cdk-lib/aws-ec2\";\nimport { UserData } from \"aws-cdk-lib/aws-ec2\";\nimport { Repository } from \"aws-cdk-lib/aws-ecr\";\nimport type { Volume } from \"aws-cdk-lib/aws-ecs\";\nimport { OperatingSystemFamily } from \"aws-cdk-lib/aws-ecs\";\nimport { CpuArchitecture } from \"aws-cdk-lib/aws-ecs\";\nimport { PropagatedTagSource } from \"aws-cdk-lib/aws-ecs\";\nimport {\n Cluster,\n ContainerImage,\n FargateService,\n FargateTaskDefinition,\n FireLensLogDriver,\n FirelensLogRouterType,\n LogDriver,\n VersionConsistency,\n} from \"aws-cdk-lib/aws-ecs\";\nimport type { HealthCheck as ALBHealthCheck } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport { ApplicationProtocol, ListenerAction, ListenerCondition } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport { AuthenticateCognitoAction } from \"aws-cdk-lib/aws-elasticloadbalancingv2-actions\";\nimport { Effect, PolicyStatement } from \"aws-cdk-lib/aws-iam\";\nimport { Architecture, Runtime } from \"aws-cdk-lib/aws-lambda\";\nimport { RetentionDays } from \"aws-cdk-lib/aws-logs\";\nimport { StringParameter } from \"aws-cdk-lib/aws-ssm\";\nimport { Construct } from \"constructs\";\nimport { AccessScope, MetadataKeys, NAMED_SSM_PARAMETER_PATHS } from \"../../constants\";\nimport { GuCertificate } from \"../../constructs/acm\";\nimport type { GuUserDataProps } from \"../../constructs/autoscaling\";\nimport { GuUserData } from \"../../constructs/autoscaling\";\nimport { GuAutoScalingGroup } from \"../../constructs/autoscaling\";\nimport type { NoMonitoring } from \"../../constructs/cloudwatch\";\nimport {\n GuAlb4xxPercentageAlarm,\n GuAlb5xxPercentageAlarm,\n GuUnhealthyInstancesAlarm,\n} from \"../../constructs/cloudwatch\";\nimport type { GuStack } from \"../../constructs/core\";\nimport { AppIdentity } from \"../../constructs/core\";\nimport { GuLoggingStreamNameParameter } from \"../../constructs/core\";\nimport { GuHttpsEgressSecurityGroup, GuSecurityGroup, GuVpc, SubnetType } from \"../../constructs/ec2\";\nimport type { GuInstanceRoleProps, GuPolicy } from \"../../constructs/iam\";\nimport { GuLogShippingPolicy } from \"../../constructs/iam\";\nimport { GuInstanceRole } from \"../../constructs/iam\";\nimport { GuGetPrivateConfigPolicy } from \"../../constructs/iam\";\nimport { GuParameterStoreReadPolicy } from \"../../constructs/iam\";\nimport { GuLambdaFunction } from \"../../constructs/lambda\";\nimport {\n GuApplicationLoadBalancer,\n GuApplicationTargetGroup,\n GuHttpsApplicationListener,\n type WafProps,\n} from \"../../constructs/loadbalancing\";\nimport type { Alarms, ApplicationLoggingProps } from \"../../patterns\";\nimport { restrictedCidrRanges } from \"../../patterns\";\nimport { AppAccess } from \"../../types\";\nimport type { GuAsgCapacity, GuDomainName } from \"../../types\";\nimport type { AmigoProps } from \"../../types/amigo\";\nimport { getUserPoolDomainPrefix } from \"../../utils/cognito/cognito\";\nimport { GuRiffRaffDeploymentIdParameterExperimental } from \"../constructs/riff-raff-deployment-id\";\nimport {\n GuAutoScalingRollingUpdateTimeoutExperimental,\n GuHorizontallyScalingDeploymentPropertiesExperimental,\n GuRoleForRollingUpdateExperimental,\n GuRollingUpdatePolicyExperimental,\n GuUserDataForRollingUpdateExperimental,\n} from \"./ec2-app\";\n\nexport interface GuLoadBalancedAppExperimentalProps extends AppIdentity {\n /**\n * Network access restrictions for your load balancer.\n *\n * Note, this merely provides defence in depth; you should NOT rely on network access restrictions alone for\n * restricting access. Use Google Auth for human access, or a suitable machine auth mechanism.\n */\n access: AppAccess;\n /**\n * The port your application runs on.\n */\n applicationPort: number;\n /**\n * Enable access logging for this load balancer.\n * Access logs are written to an S3 bucket within your AWS account.\n * The bucket is created by {@link https://github.com/guardian/aws-account-setup}.\n * The logs are queryable via the `gucdk_access_logs` Athena database.\n *\n * @defaultValue true\n */\n withAccessLogging?: boolean;\n /**\n * Enable and configure alarms.\n */\n monitoringConfiguration: Alarms | NoMonitoring;\n /**\n * Specify certificate for the load balancer.\n */\n certificateProps?: GuDomainName;\n /**\n * Specify the VPC to use.\n *\n * @see https://github.com/guardian/aws-account-setup\n */\n vpc?: IVpc;\n /**\n * Specify private subnets if using a non-default VPC or (generally\n * discouraged) to limit to a subset of the available subnets.\n */\n privateSubnets?: ISubnet[];\n\n /**\n * Specify public subnets if using a non-default VPC or (generally\n * discouraged) to limit to a subset of the available subnets.\n */\n publicSubnets?: ISubnet[];\n /**\n * Configure Google Auth.\n */\n googleAuth?: {\n /**\n * Enables Google Auth (via Cognito). **Additional MANUAL steps required -\n * see below.**\n *\n * Limits access to members of the allowed Google groups.\n *\n * Note, this does not currently support simultaneous machine access, so\n * only set to true if you only require staff access to your service, or are\n * supporting machine access in some other way.\n *\n * MANUAL STEPS: to get this to work, we need a Google Project and\n * associated credentials. Full instructions can be found here:\n *\n * https://docs.google.com/document/d/1_k1FSE52AZHXufWLTiKTI3xy5cGpziyHazSHTKrYfco/edit?usp=sharing\n *\n * DevX hope to automate this process in the near future.\n */\n enabled: true;\n /**\n * The domain users will access your service.\n *\n * Set this to the same as for certificateProps.\n */\n domain: string;\n /**\n * Groups used for membership checks.\n *\n * If specified, cannot be empty. Users must be a member of at least one\n * group to gain access.\n *\n * WARNING: groups must be specified with the `guardian.co.uk` domain, even\n * if that is the non-idiomatic choice for daily use.\n *\n * @defaultValue [`engineering@guardian.co.uk`]\n */\n allowedGroups?: string[];\n /**\n * The number of minutes before the session expires.\n *\n * Set this value to a safe period of time that revoked users\n * sessions will continue to function.\n *\n * NOTE: This value cannot be larger than 60 minutes.\n *\n * @defaultValue 15\n */\n sessionTimeoutInMinutes?: number;\n /**\n * Secrets Manager path containing Google OAuth2 Client credentials.\n *\n * NOTE: you do not need to set this value, but you DO need to generate and\n * store the associated credentials in Secrets Manager.\n *\n * Credentials should be stored in Secrets Manager as JSON:\n *\n * ```json\n * {\n * \"clientId\": \"my-client-id\",\n * \"clientSecret\": \"my-client-secret\"\n * }\n * ```\n *\n * @see `googleAuth.enabled` for how to generate.\n *\n * @defaultValue /:STAGE/:stack/:app/google-auth-credentials\n */\n credentialsSecretsManagerPath?: string;\n\n /**\n * When using Auth in the ALB, which stage of cognito-lambda to use.\n *\n * For most applications this should always be PROD, even in the CODE environments.\n *\n * @defaultValue PROD\n */\n cognitoAuthStage?: string;\n };\n\n /**\n * Specify custom healthcheck settings for your load balancer's target group(s).\n */\n healthcheck?: ALBHealthCheck;\n\n /**\n * Any additional permissions needed to run the application.\n */\n additionalPolicies?: GuPolicy[];\n\n /**\n * You can specify if the arn of this load balancer should be exposed for protection via WAF\n *\n * If this value changes, it is only picked up on WAF configuration redeploy.\n *\n * NB this parameter setting _alone_ is not sufficient to protect the application.\n * You must also ensure that the application and stage combination is present in the WAF\n * configuration.\n *\n * See https://github.com/guardian/waf/tree/main/lib\n *\n * There is a \"gotcha\" when migrating to this functionality. You may not change only the Logical\n * ID of an SSM Parameter (see https://docs.aws.amazon.com/cdk/v2/guide/identifiers.html) and the\n * parameter name must be of the required form, meaning you cannot have an alternate name.\n *\n * You can either:\n *\n * Remove the old param and immediately redeploy with the new param (this does not affect\n * protection unless and until the WAF configuration is redeployed)\n *\n * OR\n *\n * Create an escape hatch by overriding the logical id (see \"ssm param escape hatch\" test for example)\n **/\n waf?: WafProps;\n /**\n * If you want to use an AutoScaling Group with EC2 instances to serve requests, then pass in relevant props here.\n *\n * If you are setting both `ec2Props` and `ecsProps` (i.e. if you are migrating from EC2 to ECS) then you must also\n * specify weights for each compute type using `targetGroupWeights`.\n */\n ec2Props?: {\n /**\n * User data for the autoscaling group.\n */\n userData: GuUserDataProps | UserData;\n /**\n * EC2 instance type. Note, ensure your code is built for the same\n * architecture family (arm64 - 'Graviton' instances - or x64).\n */\n instanceType: InstanceType;\n /**\n * Enable and configures application logs.\n */\n applicationLogging?: ApplicationLoggingProps;\n /**\n * Add block devices (additional storage).\n */\n blockDevices?: BlockDevice[];\n /**\n * Autoscaling group min and max sizes.\n */\n scaling: GuAsgCapacity;\n /**\n * Configure AMIgo image recipe. This is only necessary if you are using GuCDK to generate your riff-raff.yaml file.\n */\n imageRecipe?: string | AmigoProps;\n /**\n * Set http put response hop limit for the launch template.\n * It can be necessary to raise this value from the default of 1\n * for example when sharing the instance profile with a docker container running on the instance.\n */\n instanceMetadataHopLimit?: number;\n\n /**\n * Specify an update policy for the ASG created by this pattern.\n *\n * @see https://docs.aws.amazon.com/cdk/api/latest/docs/aws-autoscaling-readme.html#update-policy\n *\n * @defaultValue UpdatePolicy.none() - Cloudformation does not attempt to rotate instances in the ASG\n * and must rely on riffraff to do so.\n */\n updatePolicy?: UpdatePolicy;\n /**\n * Enable CloudFormation-only deployments for EC2.\n *\n * In order to use this feature you must include the build number in the name of the artifact that you upload to\n * Riff-Raff. Your userData should also refer to this versioned artifact.\n *\n * Users migrating from the `GuEc2AppExperimental` pattern can keep existing deployment behaviour by configuring\n * these props.\n */\n versionedDeployments?: {\n enabled: boolean;\n buildIdentifier: string;\n slowStartDuration?: Duration;\n };\n /**\n * You can specify how long after an instance reaches the InService state it waits before contributing\n * usage data to the aggregated metrics. This specified time is called the default instance warmup.\n * This keeps dynamic scaling from being affected by metrics for individual instances that aren't yet\n * handling application traffic and that might be experiencing temporarily high usage of compute resources.\n *\n * @see https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-default-instance-warmup.html\n */\n defaultInstanceWarmup?: Duration;\n /**\n * How often to send EC2 metrics, such as CPU usage.\n * By default, AWS will produce `5Minute` granular metrics.\n *\n * It is recommended to produce `1Minute` granular metrics in production,\n * especially when using ASG metrics to trigger horizontal scaling as it allows for earlier scaling.\n *\n * @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html\n */\n instanceMetricGranularity: \"1Minute\" | \"5Minute\";\n };\n /**\n * If you want to use an ECS service and ECS tasks to serve requests, then pass in relevant props here.\n *\n * If you are setting both `ecsProps` and `ec2Props` (i.e. if you are migrating from EC2 to ECS) then you must also\n * specify weights for each compute type using `targetGroupWeights`.\n */\n ecsProps?: {\n /**\n * Which image to run.\n * This should be the image digest (e.g. 'sha256:abc123') to ensure immutable deployments.\n *\n * @see https://docs.docker.com/dhi/core-concepts/digests\n */\n imageIdentifier: string;\n cpu: number;\n memoryLimitMiB: number;\n /**\n * ECR repository name which contains your images. This defaults to the name of your GitHub repository as we\n * expect there to be a one-to-one mapping between GitHub repositories and ECR repositories.\n */\n repositoryName?: string;\n /**\n * The number of tasks that you want to run. We recommend running 3 tasks for production services which need a high\n * level of availability so that all 3 Availability Zones are utilised.\n */\n scaling: {\n /**\n * Scaling actions will never scale down below this threshold. This also controls the number of tasks that\n * your ECS service will launch when it is first created.\n */\n minimumTasks: number;\n /**\n * Scaling actions will never scale up above this threshold.\n *\n * Note that this max can be exceeded when a deployment runs (unlike the ASG max size). E.g. if maximumTasks is 6,\n * the service is running 6 tasks and a deployment starts, the ECS service will briefly run with 12 tasks to get\n * the deployment through.\n */\n maximumTasks: number;\n };\n };\n /**\n * If you are specifying `ec2Props` and `ecsProps` use these weights to distribute traffic across the different compute types.\n * Each weight must be between 0 and 999. AWS will work out the relative percentage.\n *\n * @example - Send 10% of traffic to ECS:\n *\n * ```ts\n * targetGroupWeights: {\n * ecs: 1,\n * ec2: 9\n * }\n * ```\n */\n targetGroupWeights?: {\n ecs: number;\n ec2: number;\n };\n}\n\ninterface TargetGroups {\n ec2?: GuApplicationTargetGroup;\n ecs?: GuApplicationTargetGroup;\n}\n\nexport class GuLoadBalancedAppExperimental extends Construct {\n /**\n * The VPC that the pattern's load balancer, EC2 instances and/or ECS tasks are running in.\n */\n public readonly vpc: IVpc;\n /**\n * The certificate associated with your load balancer. This will only be available if `certificateProps` were\n * passed in.\n */\n public readonly certificate?: GuCertificate;\n /**\n * The application load balancer that this pattern creates.\n */\n public readonly loadBalancer: GuApplicationLoadBalancer;\n /**\n * The AutoScaling Group that this pattern creates. This will only be available if `ec2Props` are specified.\n */\n public readonly autoScalingGroup?: GuAutoScalingGroup;\n /**\n * The ECS Service that this pattern creates. This will only be available if `ecsProps` are specified.\n */\n public readonly ecsService?: FargateService;\n /**\n * The load balancer listener that this pattern creates.\n */\n public readonly listener: GuHttpsApplicationListener;\n /**\n * The target groups capable of serving traffic routed to this pattern.\n *\n * If `ec2Props` were passed in but `ecsProps` were not, there will be a single EC2 target group.\n * Similarly, if `ecsProps` were passed in but `ec2Props` were not, there will be a single ECS target group.\n * If both `ec2Props` and `ecsProps` were passed in (e.g. during a migration) then both target groups will be\n * available.\n */\n public readonly targetGroups: TargetGroups;\n\n constructor(scope: GuStack, props: GuLoadBalancedAppExperimentalProps) {\n const {\n access,\n withAccessLogging = true,\n app,\n applicationPort,\n certificateProps,\n monitoringConfiguration,\n vpc = GuVpc.fromIdParameter(scope, AppIdentity.addAppToStringEnd({ app }, \"VPC\")),\n privateSubnets = GuVpc.subnetsFromParameter(scope, { type: SubnetType.PRIVATE, app }),\n publicSubnets = GuVpc.subnetsFromParameter(scope, { type: SubnetType.PUBLIC, app }),\n waf,\n healthcheck,\n ec2Props,\n ecsProps,\n targetGroupWeights,\n additionalPolicies = [],\n } = props;\n\n super(scope, app); // The assumption is `app` is unique\n\n const { stack, stage } = scope;\n\n let targetGroups: TargetGroups = {};\n\n // Setup EC2-specific infrastructure\n if (ec2Props) {\n const {\n applicationLogging = { enabled: false },\n blockDevices,\n instanceType,\n scaling: { minimumInstances, maximumInstances = minimumInstances * 2 },\n userData: userDataLike,\n imageRecipe,\n instanceMetadataHopLimit,\n versionedDeployments,\n updatePolicy,\n defaultInstanceWarmup,\n instanceMetricGranularity,\n } = ec2Props;\n\n const userData =\n userDataLike instanceof UserData ? userDataLike : new GuUserData(scope, { ...userDataLike, app });\n const maybePrivateConfigPolicy =\n userData instanceof GuUserData && userData.configuration\n ? [new GuGetPrivateConfigPolicy(scope, \"GetPrivateConfigFromS3Policy\", userData.configuration)]\n : [];\n const mergedRoleConfiguration: GuInstanceRoleProps = {\n additionalPolicies: maybePrivateConfigPolicy.concat(additionalPolicies),\n };\n\n if (versionedDeployments?.enabled && updatePolicy) {\n throw new Error(\"If versionedDeployments are enabled then updatePolicy should not be set via ec2Props\");\n }\n const asgUpdatePolicy = versionedDeployments\n ? GuRollingUpdatePolicyExperimental.getPolicy(\n maximumInstances,\n minimumInstances,\n versionedDeployments.slowStartDuration,\n )\n : updatePolicy;\n\n const autoScalingGroup = new GuAutoScalingGroup(scope, \"AutoScalingGroup\", {\n app,\n vpc,\n instanceType,\n minimumInstances,\n maximumInstances,\n role: new GuInstanceRole(scope, { app, ...mergedRoleConfiguration }),\n\n healthChecks: HealthChecks.withAdditionalChecks({\n additionalTypes: [AdditionalHealthCheckType.ELB],\n gracePeriod: Duration.minutes(2),\n }),\n\n userData: userData instanceof GuUserData ? userData.userData : userData,\n vpcSubnets: { subnets: privateSubnets },\n ...(blockDevices && { blockDevices }),\n imageRecipe,\n httpPutResponseHopLimit: instanceMetadataHopLimit,\n updatePolicy: asgUpdatePolicy,\n defaultInstanceWarmup,\n instanceMetricGranularity,\n });\n\n // This allows automatic shipping of instance Cloud Init logs when using the\n // `cdk-base` Amigo role on your AMI.\n Tags.of(autoScalingGroup).add(\n MetadataKeys.LOG_KINESIS_STREAM_NAME,\n GuLoggingStreamNameParameter.getInstance(scope).valueAsString,\n );\n\n const ec2TargetGroup = new GuApplicationTargetGroup(scope, \"TargetGroup\", {\n app,\n vpc,\n protocol: ApplicationProtocol.HTTP,\n targets: [autoScalingGroup],\n port: applicationPort,\n healthCheck: healthcheck,\n });\n\n targetGroups = {\n ec2: ec2TargetGroup,\n };\n\n if (versionedDeployments?.enabled) {\n const slowStartDurationInSeconds = versionedDeployments.slowStartDuration?.toSeconds();\n if (slowStartDurationInSeconds && (slowStartDurationInSeconds < 30 || slowStartDurationInSeconds > 900)) {\n throw new Error(\"Slow start duration must be between 30 and 900 seconds\");\n }\n\n const cfnAutoScalingGroup = autoScalingGroup.node.defaultChild as CfnAutoScalingGroup;\n // Note: if the service uses horizontal scaling, this property is unset by an Aspect (to prevent accidental scale downs!)\n cfnAutoScalingGroup.desiredCapacity = minimumInstances.toString();\n\n new GuRoleForRollingUpdateExperimental(scope, { autoScalingGroup });\n new GuUserDataForRollingUpdateExperimental(scope, {\n autoScalingGroup: autoScalingGroup,\n targetGroup: ec2TargetGroup,\n applicationPort: applicationPort,\n buildIdentifier: versionedDeployments.buildIdentifier,\n slowStartDuration: versionedDeployments.slowStartDuration,\n });\n\n // This is used when an ASG is first created; it is not needed to support the new deployment mechanism but we\n // include it here to avoid creating an unnecessary snapshot diff for existing users of this feature\n cfnAutoScalingGroup.cfnOptions.creationPolicy = {\n autoScalingCreationPolicy: {\n minSuccessfulInstancesPercent: 100,\n },\n resourceSignal: {\n count: minimumInstances,\n },\n };\n\n const allAspects = Aspects.of(scope).all;\n const maybeRollingUpdateTimeoutAspect = allAspects.find(\n (_) => _ instanceof GuAutoScalingRollingUpdateTimeoutExperimental,\n );\n if (!maybeRollingUpdateTimeoutAspect) {\n Aspects.of(scope).add(new GuAutoScalingRollingUpdateTimeoutExperimental());\n }\n Aspects.of(scope).add(new GuHorizontallyScalingDeploymentPropertiesExperimental());\n }\n\n if (applicationLogging.enabled) {\n // This allows automatic shipping of application logs when using the\n // `cdk-base` Amigo role on your AMI.\n Tags.of(autoScalingGroup).add(\n MetadataKeys.SYSTEMD_UNIT,\n applicationLogging.systemdUnitName ? `${applicationLogging.systemdUnitName}.service` : `${app}.service`,\n );\n }\n\n this.autoScalingGroup = autoScalingGroup;\n }\n\n // Setup ECS-specific infrastructure\n if (ecsProps) {\n const { cpu, memoryLimitMiB, imageIdentifier, scaling } = ecsProps;\n\n const ecrRepoName = ecsProps.repositoryName ?? scope.repositoryName;\n if (!ecrRepoName) {\n throw new Error(\"Could not determine an ECR repository name; please set this manually via ecsProps\");\n }\n\n const cluster = new Cluster(this, \"EcsCluster\", { vpc });\n\n const image = ContainerImage.fromEcrRepository(\n // Images are published to the ECR registry in the DeployTools account, so reference that here\n Repository.fromRepositoryAttributes(this, \"Repo\", {\n repositoryArn: scope.formatArn({\n account: StringParameter.fromStringParameterName(\n scope,\n \"DeployToolsAccountId\",\n NAMED_SSM_PARAMETER_PATHS.DeployToolsAccountId.path,\n ).stringValue,\n arnFormat: ArnFormat.SLASH_RESOURCE_NAME,\n resource: \"repository\",\n resourceName: ecrRepoName,\n service: \"ecr\",\n }),\n repositoryName: ecrRepoName,\n }),\n imageIdentifier,\n );\n\n const loggingStreamName = GuLoggingStreamNameParameter.getInstance(scope).valueAsString;\n\n const fireLensLogDriver = new FireLensLogDriver({\n options: {\n Name: `kinesis_streams`,\n region: scope.region,\n stream: loggingStreamName,\n retry_limit: \"2\",\n },\n });\n\n const env = {\n STACK: stack,\n STAGE: stage,\n APP: app,\n\n // Required by https://github.com/guardian/devx-logs\n TASK_NAME: app,\n };\n\n // Add the GitHub repo if we can\n const environment = scope.repositoryName ? { ...env, GU_REPO: scope.repositoryName } : env;\n\n const taskDefinition = new FargateTaskDefinition(scope, \"EcsTaskDefinition\", {\n memoryLimitMiB,\n cpu,\n runtimePlatform: { cpuArchitecture: CpuArchitecture.ARM64, operatingSystemFamily: OperatingSystemFamily.LINUX },\n });\n\n taskDefinition.addContainer(app, {\n image,\n dockerLabels: {\n RiffRaffDeploymentId: GuRiffRaffDeploymentIdParameterExperimental.getInstance(scope).valueAsString,\n },\n // This speeds up deployment. We don't need this enabled if users follow the advice to refer to their image\n // using the immutable digest\n versionConsistency: VersionConsistency.DISABLED,\n portMappings: [{ containerPort: applicationPort }],\n logging: fireLensLogDriver,\n readonlyRootFilesystem: true,\n environment,\n });\n\n // Permissions passed to the ECS task...\n const applicationPermissions: GuPolicy[] = [\n // ...to allow writing logs to Kinesis\n GuLogShippingPolicy.getInstance(scope),\n\n // ...to allow reading application config from SSM\n GuParameterStoreReadPolicy.getInstance(scope, { app }),\n\n // ...permissions specific for this application (provided by client)\n ...additionalPolicies,\n ];\n\n applicationPermissions.forEach((policy) => policy.attachToRole(taskDefinition.taskRole));\n\n /*\n GuardDuty is enabled at the organisation level and runs as a sidecar.\n We need to add specific permissions to allow pulling the GuardDuty image.\n See https://docs.aws.amazon.com/guardduty/latest/ug/prereq-runtime-monitoring-ecs-support.html.\n */\n const guardDutyPolicies = [\n new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\"ecr:GetAuthorizationToken\"],\n resources: [\"*\"],\n }),\n new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\"ecr:BatchCheckLayerAvailability\", \"ecr:GetDownloadUrlForLayer\", \"ecr:BatchGetImage\"],\n resources: [\n // See https://docs.aws.amazon.com/guardduty/latest/ug/runtime-monitoring-ecr-repository-gdu-agent.html\n \"arn:aws:ecr:eu-west-1:694911143906:repository/aws-guardduty-agent-fargate\",\n ],\n }),\n ];\n\n guardDutyPolicies.forEach((policy) => taskDefinition.addToExecutionRolePolicy(policy));\n\n const ecsService = new FargateService(scope, \"EcsService\", {\n cluster,\n taskDefinition,\n vpcSubnets: { subnets: privateSubnets },\n // Important for service deployments; with the AWS defaults the service can be scaled down when deploying\n minHealthyPercent: 100,\n // Also important for service deployments; with the AWS defaults we don't get a fast failure when deploying a 'bad' build\n circuitBreaker: { enable: true, rollback: true },\n propagateTags: PropagatedTagSource.SERVICE,\n // By default, AWS will create a new security group which allows all outbound traffic\n // We don't want this so explicitly allow outbound HTTPS only\n // This is what we do for the current GuEc2App pattern:\n // https://github.com/guardian/cdk/blob/3b5688637024642055ed0bf576f668e56e40830d/src/constructs/autoscaling/asg.ts#L143-L145\n securityGroups: [\n GuHttpsEgressSecurityGroup.forVpc(scope, {\n app: `${app}-ecs`,\n vpc,\n }),\n ],\n });\n\n ecsService.autoScaleTaskCount({\n minCapacity: scaling.minimumTasks,\n maxCapacity: scaling.maximumTasks,\n });\n\n this.ecsService = ecsService;\n\n // It's possible to opt-out of log shipping to ELK in the EC2 patterns; should we mirror that here?\n const logRouter = taskDefinition.addFirelensLogRouter(\"LogShipping\", {\n // See https://github.com/guardian/devx-logs\n image: ContainerImage.fromRegistry(\n \"ghcr.io/guardian/devx-logs@sha256:cf91724a5166f1c143e07958820aa2122afb61c164b68555d15cb92abb5acda0\",\n ),\n environment,\n versionConsistency: VersionConsistency.DISABLED,\n // Send this container's logs to CloudWatch logs, retained for 1 day\n logging: LogDriver.awsLogs({\n streamPrefix: [scope.stack, scope.stage, app, \"devx-logs-sidecar\"].join(\"/\"),\n logRetention: RetentionDays.ONE_DAY,\n }),\n\n firelensConfig: {\n type: FirelensLogRouterType.FLUENTBIT,\n },\n\n // To comply with FSBP ECS.5\n readonlyRootFilesystem: true,\n });\n\n const logVolume: Volume = {\n name: \"logging-volume\",\n };\n taskDefinition.addVolume(logVolume);\n\n logRouter.addMountPoints({\n containerPath: \"/init\",\n sourceVolume: logVolume.name,\n readOnly: false,\n });\n\n // We need a new target group even if we share the other load balancer components with the EC2 infrastructure\n const ecsTargetGroup = new GuApplicationTargetGroup(\n scope,\n\n // This ID parameter is used to form the resource's logical ID.\n // If a target group is not explicitly named, CloudFormation will use the logical ID to generate a name of form `<CFN_STACK_NAME>-<LOGICAL_ID>-<12 CHAR GUID>` to a max of 32 chars.\n // Add the App to the start of the logical ID to make the generated names (slightly) glanceable, e.g \"MyAppE-123456123456\" vs. \"EcsTar-123456123456\".\n AppIdentity.addAppToStringStart(props, \"EcsTargetGroup\"),\n\n {\n vpc,\n app,\n port: applicationPort,\n targets: [ecsService],\n healthCheck: healthcheck,\n },\n );\n\n targetGroups = {\n ...targetGroups,\n ecs: ecsTargetGroup,\n };\n\n // Specifically apply App tag to resources.\n // Other resources obtain this tag by extending `GuAppAwareConstruct`.\n [cluster, taskDefinition, ecsService].forEach((_) => AppIdentity.taggedConstruct(props, _));\n }\n\n // Set up the load balancer and listener components\n AppAccess.validate(access);\n\n const certificate =\n typeof certificateProps !== \"undefined\"\n ? new GuCertificate(scope, {\n app,\n domainName: certificateProps.domainName,\n hostedZoneId: certificateProps.hostedZoneId,\n })\n : undefined;\n\n const loadBalancer = new GuApplicationLoadBalancer(scope, \"LoadBalancer\", {\n app,\n vpc,\n // Setting internetFacing to true does not necessarily allow public access to the load balancer itself. That is handled by the listener's `open` prop.\n internetFacing: access.scope !== AccessScope.INTERNAL,\n vpcSubnets: {\n subnets: access.scope === AccessScope.INTERNAL ? privateSubnets : publicSubnets,\n },\n withAccessLogging,\n waf,\n });\n\n const defaultAction: ListenerAction = configureListenerActions(targetGroups, targetGroupWeights);\n\n const listener = new GuHttpsApplicationListener(scope, \"Listener\", {\n app,\n loadBalancer,\n certificate,\n defaultAction,\n // When open=true, AWS will create a security group which allows all inbound traffic over HTTPS\n open: access.scope === AccessScope.PUBLIC && typeof certificate !== \"undefined\",\n });\n if (targetGroups.ec2 && targetGroups.ecs) {\n configureDeterministicRouting(listener, targetGroups.ec2, targetGroups.ecs);\n }\n\n // Since AWS won't create a security group automatically when open=false, we need to add our own\n if (access.scope !== AccessScope.PUBLIC) {\n loadBalancer.addSecurityGroup(\n new GuSecurityGroup(scope, `${access.scope}IngressSecurityGroup`, {\n app,\n vpc,\n description: \"Allow restricted ingress from CIDR ranges\",\n allowAllOutbound: false,\n ingresses: restrictedCidrRanges(access.cidrRanges),\n }),\n );\n }\n\n if (props.googleAuth?.enabled) {\n const prefix = `/${scope.stage}/${scope.stack}/${app}`;\n\n const {\n allowedGroups = [\"engineering@guardian.co.uk\"],\n sessionTimeoutInMinutes = 15,\n credentialsSecretsManagerPath = `${prefix}/google-auth-credentials`,\n } = props.googleAuth;\n\n if (sessionTimeoutInMinutes > 60) {\n throw new Error(\"googleAuth.sessionTimeoutInMinutes must be <= 60!\");\n }\n\n if (allowedGroups.length < 1) {\n throw new Error(\"googleAuth.allowedGroups cannot be empty!\");\n }\n\n if (allowedGroups.find((group) => !group.endsWith(\"@guardian.co.uk\"))) {\n throw new Error(\"googleAuth.allowedGroups must use the @guardian.co.uk domain.\");\n }\n\n const deployToolsAccountId = StringParameter.fromStringParameterName(\n scope,\n \"deploy-tools-account-id-parameter\",\n NAMED_SSM_PARAMETER_PATHS.DeployToolsAccountId.path,\n );\n\n const cognitoAuthStage = props.googleAuth.cognitoAuthStage ?? \"PROD\";\n\n // See https://github.com/guardian/cognito-auth-lambdas for the source\n // code here. ARN format is:\n // arn:aws:lambda:aws-region:acct-id:function:helloworld.\n const gatekeeperFunctionArn = `arn:aws:lambda:eu-west-1:${deployToolsAccountId.stringValue}:function:deploy-${cognitoAuthStage}-gatekeeper-lambda`;\n\n // Note, handler and filename must match here:\n // https://github.com/guardian/cognito-auth-lambdas.\n const authLambda = new GuLambdaFunction(scope, \"auth-lambda\", {\n app: app,\n memorySize: 128,\n handler: \"bootstrap\",\n runtime: Runtime.PROVIDED_AL2023,\n fileName: `deploy/${cognitoAuthStage}/cognito-lambda/devx-cognito-lambda-amd64-v2.zip`,\n withoutFilePrefix: true,\n withoutArtifactUpload: true,\n bucketNamePath: NAMED_SSM_PARAMETER_PATHS.OrganisationDistributionBucket.path,\n architecture: Architecture.X86_64,\n environment: {\n ALLOWED_GROUPS: allowedGroups.join(\",\"),\n GATEKEEPER_FUNCTION_ARN: gatekeeperFunctionArn,\n },\n });\n\n Tags.of(authLambda).add(\"Owner\", \"DevX\");\n\n authLambda.addToRolePolicy(\n new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\"lambda:InvokeFunction\"],\n resources: [gatekeeperFunctionArn],\n }),\n );\n\n // Cognito user pool. We require both lambdas: pre-sign-up runs the first\n // time a user attempts to authenticate (before they exist in the User\n // Pool); pre-auth runs in subsequent authentication flows.\n const userPool = new UserPool(this, \"user-pool\", {\n lambdaTriggers: {\n preAuthentication: authLambda,\n preSignUp: authLambda,\n },\n });\n\n // These help ensure domain is deterministic but also unique. Key\n // assumption is that app/stack/stage combo are unique within Guardian.\n const domainPrefix = `com-gu-${app.toLowerCase()}-${scope.stage.toLowerCase()}`;\n\n const userPoolDomain = userPool.addDomain(\"domain\", {\n cognitoDomain: {\n domainPrefix: getUserPoolDomainPrefix(domainPrefix),\n },\n });\n\n const clientId = SecretValue.secretsManager(credentialsSecretsManagerPath, { jsonField: \"clientId\" });\n const clientSecret = SecretValue.secretsManager(credentialsSecretsManagerPath, { jsonField: \"clientSecret\" });\n\n const userPoolIdp = new UserPoolIdentityProviderGoogle(scope, \"google-idp\", {\n userPool: userPool,\n clientId: clientId.toString(),\n clientSecretValue: clientSecret,\n attributeMapping: {\n email: ProviderAttribute.GOOGLE_EMAIL,\n givenName: ProviderAttribute.GOOGLE_GIVEN_NAME,\n familyName: ProviderAttribute.GOOGLE_FAMILY_NAME,\n profilePicture: ProviderAttribute.GOOGLE_PICTURE,\n custom: {\n name: ProviderAttribute.GOOGLE_NAME,\n },\n },\n scopes: [\"openid\", \"email\", \"profile\"],\n });\n\n const userPoolClient = userPool.addClient(\"alb-client\", {\n supportedIdentityProviders: [UserPoolClientIdentityProvider.GOOGLE],\n generateSecret: true,\n oAuth: {\n callbackUrls: [`https://${props.googleAuth.domain}/oauth2/idpresponse`],\n },\n\n // Note: id and access validity token validity cannot be less than one\n // hour (this is the cognito cookie duration). To quickly invalidate\n // credentials, disable the user in Cognito. It might be that we want to\n // parameterise these going forward, but that would require Infosec\n // discussion.\n idTokenValidity: Duration.hours(1),\n accessTokenValidity: Duration.hours(1),\n refreshTokenValidity: Duration.days(7),\n });\n\n userPoolClient.node.addDependency(userPoolIdp);\n\n if (props.ecsProps) {\n throw new Error(\"Using Google Auth with ECS is currently unsupported\");\n // I think that the code here will probably work fine but it needs some dedicated testing.\n // For Google auth to work we need to 'authenticate-cognito' and then forward to a target group.\n // If we are operating with EC2 and ECS backends then this forwarded request could be sent to either backend.\n // Let's deploy this to a DevX service and check it's valid/works as expected before opening this up to other teams.\n }\n listener.addAction(\"CognitoAuth\", {\n action: new AuthenticateCognitoAction({\n userPool: userPool,\n userPoolClient: userPoolClient,\n userPoolDomain: userPoolDomain,\n next: defaultAction,\n sessionTimeout: Duration.minutes(sessionTimeoutInMinutes),\n }),\n });\n\n // Need to give the ALB outbound access on 443 for the IdP endpoints.\n const idpEgressSecurityGroup = new GuHttpsEgressSecurityGroup(scope, \"ldp-access\", {\n app,\n vpc,\n });\n\n loadBalancer.addSecurityGroup(idpEgressSecurityGroup);\n }\n\n // Setup monitoring\n if (!monitoringConfiguration.noMonitoring) {\n const { http5xxAlarm, http4xxAlarm, snsTopicName } = monitoringConfiguration;\n\n if (http4xxAlarm) {\n new GuAlb4xxPercentageAlarm(scope, {\n app,\n loadBalancer,\n snsTopicName,\n ...http4xxAlarm,\n });\n }\n if (http5xxAlarm) {\n new GuAlb5xxPercentageAlarm(scope, {\n app,\n loadBalancer,\n snsTopicName,\n ...http5xxAlarm,\n });\n }\n if (monitoringConfiguration.unhealthyInstancesAlarm && targetGroups.ec2) {\n const { snsTopicName } = monitoringConfiguration;\n new GuUnhealthyInstancesAlarm(scope, {\n app,\n targetGroup: targetGroups.ec2,\n snsTopicName,\n });\n }\n }\n\n this.vpc = vpc;\n this.certificate = certificate;\n this.loadBalancer = loadBalancer;\n this.listener = listener;\n this.targetGroups = targetGroups;\n }\n}\n\nfunction configureListenerActions(\n targetGroups: TargetGroups,\n targetGroupWeights?: {\n ecs: number;\n ec2: number;\n },\n): ListenerAction {\n // No ECS target, so forward all traffic to EC2\n if (targetGroups.ec2 && !targetGroups.ecs) {\n return ListenerAction.forward([targetGroups.ec2]);\n }\n\n // No EC2 target, so forward all traffic to ECS\n if (targetGroups.ecs && !targetGroups.ec2) {\n return ListenerAction.forward([targetGroups.ecs]);\n }\n\n if (targetGroups.ec2 && targetGroups.ecs) {\n if (!targetGroupWeights) {\n throw new Error(\"EC2 and ECS are both enabled but no target group weights were provided\");\n }\n\n // An individual target can have a weight between 0 and 999. AWS will work out the relative percentage.\n const isBetween = (n: number, min: number, max: number): boolean => n >= min && n <= max;\n if (!isBetween(targetGroupWeights.ecs, 0, 999)) {\n throw new Error(\"targetGroupWeights.ecs must be between 0 and 999\");\n }\n if (!isBetween(targetGroupWeights.ec2, 0, 999)) {\n throw new Error(\"targetGroupWeights.ec2 must be between 0 and 999\");\n }\n\n return ListenerAction.weightedForward([\n { targetGroup: targetGroups.ec2, weight: targetGroupWeights.ec2 },\n { targetGroup: targetGroups.ecs, weight: targetGroupWeights.ecs },\n ]);\n } else {\n throw new Error(\"At least one of 'ec2Props' or 'ecsProps' must be specified\");\n }\n}\n\nfunction configureDeterministicRouting(\n listener: GuHttpsApplicationListener,\n ec2TargetGroup: GuApplicationTargetGroup,\n ecsTargetGroup: GuApplicationTargetGroup,\n): void {\n const headerName = \"X-Gu-Target-Group\";\n const ec2HeaderValue = \"ec2\";\n const ecsHeaderValue = \"ecs\";\n\n listener.addAction(\"DeterministicRouteToEc2\", {\n priority: 10,\n conditions: [ListenerCondition.httpHeader(headerName, [ec2HeaderValue])],\n action: ListenerAction.forward([ec2TargetGroup]),\n });\n\n listener.addAction(\"DeterministicRouteToEcs\", {\n priority: 11,\n conditions: [ListenerCondition.httpHeader(headerName, [ecsHeaderValue])],\n action: ListenerAction.forward([ecsTargetGroup]),\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"gu-load-balanced-app.js","sourceRoot":"","sources":["../../../src/experimental/patterns/gu-load-balanced-app.ts"],"names":[],"mappings":"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","sourcesContent":["import { ArnFormat, Aspects, Duration, SecretValue, Tags } from \"aws-cdk-lib\";\nimport type { BlockDevice, CfnAutoScalingGroup, UpdatePolicy } from \"aws-cdk-lib/aws-autoscaling\";\nimport { AdditionalHealthCheckType, HealthChecks } from \"aws-cdk-lib/aws-autoscaling\";\nimport {\n ProviderAttribute,\n UserPool,\n UserPoolClientIdentityProvider,\n UserPoolIdentityProviderGoogle,\n} from \"aws-cdk-lib/aws-cognito\";\nimport type { InstanceType, ISubnet, IVpc } from \"aws-cdk-lib/aws-ec2\";\nimport { UserData } from \"aws-cdk-lib/aws-ec2\";\nimport { Repository } from \"aws-cdk-lib/aws-ecr\";\nimport { ContainerInsights, OperatingSystemFamily } from \"aws-cdk-lib/aws-ecs\";\nimport { CpuArchitecture } from \"aws-cdk-lib/aws-ecs\";\nimport { PropagatedTagSource } from \"aws-cdk-lib/aws-ecs\";\nimport {\n Cluster,\n ContainerImage,\n FargateService,\n FargateTaskDefinition,\n FireLensLogDriver,\n FirelensLogRouterType,\n LogDriver,\n VersionConsistency,\n} from \"aws-cdk-lib/aws-ecs\";\nimport type { CfnService } from \"aws-cdk-lib/aws-ecs\";\nimport type { Volume } from \"aws-cdk-lib/aws-ecs\";\nimport type { HealthCheck as ALBHealthCheck } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport { ApplicationProtocol, ListenerAction, ListenerCondition } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport { AuthenticateCognitoAction } from \"aws-cdk-lib/aws-elasticloadbalancingv2-actions\";\nimport { Effect, PolicyStatement } from \"aws-cdk-lib/aws-iam\";\nimport { Architecture, Runtime } from \"aws-cdk-lib/aws-lambda\";\nimport { RetentionDays } from \"aws-cdk-lib/aws-logs\";\nimport { StringParameter } from \"aws-cdk-lib/aws-ssm\";\nimport { Construct } from \"constructs\";\nimport { AccessScope, MetadataKeys, NAMED_SSM_PARAMETER_PATHS } from \"../../constants\";\nimport { GuCertificate } from \"../../constructs/acm\";\nimport type { GuUserDataProps } from \"../../constructs/autoscaling\";\nimport { GuUserData } from \"../../constructs/autoscaling\";\nimport { GuAutoScalingGroup } from \"../../constructs/autoscaling\";\nimport type { NoMonitoring } from \"../../constructs/cloudwatch\";\nimport {\n GuAlb4xxPercentageAlarm,\n GuAlb5xxPercentageAlarm,\n GuUnhealthyInstancesAlarm,\n} from \"../../constructs/cloudwatch\";\nimport type { GuStack } from \"../../constructs/core\";\nimport { AppIdentity } from \"../../constructs/core\";\nimport { GuLoggingStreamNameParameter } from \"../../constructs/core\";\nimport { GuHttpsEgressSecurityGroup, GuSecurityGroup, GuVpc, SubnetType } from \"../../constructs/ec2\";\nimport type { GuInstanceRoleProps, GuPolicy } from \"../../constructs/iam\";\nimport { GuLogShippingPolicy } from \"../../constructs/iam\";\nimport { GuInstanceRole } from \"../../constructs/iam\";\nimport { GuGetPrivateConfigPolicy } from \"../../constructs/iam\";\nimport { GuParameterStoreReadPolicy } from \"../../constructs/iam\";\nimport { GuLambdaFunction } from \"../../constructs/lambda\";\nimport {\n GuApplicationLoadBalancer,\n GuApplicationTargetGroup,\n GuHttpsApplicationListener,\n type WafProps,\n} from \"../../constructs/loadbalancing\";\nimport type { Alarms, ApplicationLoggingProps } from \"../../patterns\";\nimport { restrictedCidrRanges } from \"../../patterns\";\nimport { AppAccess } from \"../../types\";\nimport type { GuAsgCapacity, GuDomainName } from \"../../types\";\nimport type { AmigoProps } from \"../../types/amigo\";\nimport { getUserPoolDomainPrefix } from \"../../utils/cognito/cognito\";\nimport { GuRiffRaffDeploymentIdParameterExperimental } from \"../constructs/riff-raff-deployment-id\";\nimport {\n GuAutoScalingRollingUpdateTimeoutExperimental,\n GuHorizontallyScalingDeploymentPropertiesExperimental,\n GuRoleForRollingUpdateExperimental,\n GuRollingUpdatePolicyExperimental,\n GuUserDataForRollingUpdateExperimental,\n} from \"./ec2-app\";\n\nexport interface GuLoadBalancedAppExperimentalProps extends AppIdentity {\n /**\n * Network access restrictions for your load balancer.\n *\n * Note, this merely provides defence in depth; you should NOT rely on network access restrictions alone for\n * restricting access. Use Google Auth for human access, or a suitable machine auth mechanism.\n */\n access: AppAccess;\n /**\n * The port your application runs on.\n */\n applicationPort: number;\n /**\n * Enable access logging for this load balancer.\n * Access logs are written to an S3 bucket within your AWS account.\n * The bucket is created by {@link https://github.com/guardian/aws-account-setup}.\n * The logs are queryable via the `gucdk_access_logs` Athena database.\n *\n * @defaultValue true\n */\n withAccessLogging?: boolean;\n /**\n * Enable and configure alarms.\n */\n monitoringConfiguration: Alarms | NoMonitoring;\n /**\n * Specify certificate for the load balancer.\n */\n certificateProps?: GuDomainName;\n /**\n * Specify the VPC to use.\n *\n * @see https://github.com/guardian/aws-account-setup\n */\n vpc?: IVpc;\n /**\n * Specify private subnets if using a non-default VPC or (generally\n * discouraged) to limit to a subset of the available subnets.\n */\n privateSubnets?: ISubnet[];\n\n /**\n * Specify public subnets if using a non-default VPC or (generally\n * discouraged) to limit to a subset of the available subnets.\n */\n publicSubnets?: ISubnet[];\n /**\n * Configure Google Auth.\n */\n googleAuth?: {\n /**\n * Enables Google Auth (via Cognito). **Additional MANUAL steps required -\n * see below.**\n *\n * Limits access to members of the allowed Google groups.\n *\n * Note, this does not currently support simultaneous machine access, so\n * only set to true if you only require staff access to your service, or are\n * supporting machine access in some other way.\n *\n * MANUAL STEPS: to get this to work, we need a Google Project and\n * associated credentials. Full instructions can be found here:\n *\n * https://docs.google.com/document/d/1_k1FSE52AZHXufWLTiKTI3xy5cGpziyHazSHTKrYfco/edit?usp=sharing\n *\n * DevX hope to automate this process in the near future.\n */\n enabled: true;\n /**\n * The domain users will access your service.\n *\n * Set this to the same as for certificateProps.\n */\n domain: string;\n /**\n * Groups used for membership checks.\n *\n * If specified, cannot be empty. Users must be a member of at least one\n * group to gain access.\n *\n * WARNING: groups must be specified with the `guardian.co.uk` domain, even\n * if that is the non-idiomatic choice for daily use.\n *\n * @defaultValue [`engineering@guardian.co.uk`]\n */\n allowedGroups?: string[];\n /**\n * The number of minutes before the session expires.\n *\n * Set this value to a safe period of time that revoked users\n * sessions will continue to function.\n *\n * NOTE: This value cannot be larger than 60 minutes.\n *\n * @defaultValue 15\n */\n sessionTimeoutInMinutes?: number;\n /**\n * Secrets Manager path containing Google OAuth2 Client credentials.\n *\n * NOTE: you do not need to set this value, but you DO need to generate and\n * store the associated credentials in Secrets Manager.\n *\n * Credentials should be stored in Secrets Manager as JSON:\n *\n * ```json\n * {\n * \"clientId\": \"my-client-id\",\n * \"clientSecret\": \"my-client-secret\"\n * }\n * ```\n *\n * @see `googleAuth.enabled` for how to generate.\n *\n * @defaultValue /:STAGE/:stack/:app/google-auth-credentials\n */\n credentialsSecretsManagerPath?: string;\n\n /**\n * When using Auth in the ALB, which stage of cognito-lambda to use.\n *\n * For most applications this should always be PROD, even in the CODE environments.\n *\n * @defaultValue PROD\n */\n cognitoAuthStage?: string;\n };\n\n /**\n * Specify custom healthcheck settings for your load balancer's target group(s).\n */\n healthcheck?: ALBHealthCheck;\n\n /**\n * Any additional permissions needed to run the application.\n */\n additionalPolicies?: GuPolicy[];\n\n /**\n * You can specify if the arn of this load balancer should be exposed for protection via WAF\n *\n * If this value changes, it is only picked up on WAF configuration redeploy.\n *\n * NB this parameter setting _alone_ is not sufficient to protect the application.\n * You must also ensure that the application and stage combination is present in the WAF\n * configuration.\n *\n * See https://github.com/guardian/waf/tree/main/lib\n *\n * There is a \"gotcha\" when migrating to this functionality. You may not change only the Logical\n * ID of an SSM Parameter (see https://docs.aws.amazon.com/cdk/v2/guide/identifiers.html) and the\n * parameter name must be of the required form, meaning you cannot have an alternate name.\n *\n * You can either:\n *\n * Remove the old param and immediately redeploy with the new param (this does not affect\n * protection unless and until the WAF configuration is redeployed)\n *\n * OR\n *\n * Create an escape hatch by overriding the logical id (see \"ssm param escape hatch\" test for example)\n **/\n waf?: WafProps;\n /**\n * If you want to use an AutoScaling Group with EC2 instances to serve requests, then pass in relevant props here.\n *\n * If you are setting both `ec2Props` and `ecsProps` (i.e. if you are migrating from EC2 to ECS) then you must also\n * specify weights for each compute type using `targetGroupWeights`.\n */\n ec2Props?: {\n /**\n * User data for the autoscaling group.\n */\n userData: GuUserDataProps | UserData;\n /**\n * EC2 instance type. Note, ensure your code is built for the same\n * architecture family (arm64 - 'Graviton' instances - or x64).\n */\n instanceType: InstanceType;\n /**\n * Enable and configures application logs.\n */\n applicationLogging?: ApplicationLoggingProps;\n /**\n * Add block devices (additional storage).\n */\n blockDevices?: BlockDevice[];\n /**\n * Autoscaling group min and max sizes.\n */\n scaling: GuAsgCapacity;\n /**\n * Configure AMIgo image recipe. This is only necessary if you are using GuCDK to generate your riff-raff.yaml file.\n */\n imageRecipe?: string | AmigoProps;\n /**\n * Set http put response hop limit for the launch template.\n * It can be necessary to raise this value from the default of 1\n * for example when sharing the instance profile with a docker container running on the instance.\n */\n instanceMetadataHopLimit?: number;\n\n /**\n * Specify an update policy for the ASG created by this pattern.\n *\n * @see https://docs.aws.amazon.com/cdk/api/latest/docs/aws-autoscaling-readme.html#update-policy\n *\n * @defaultValue UpdatePolicy.none() - Cloudformation does not attempt to rotate instances in the ASG\n * and must rely on riffraff to do so.\n */\n updatePolicy?: UpdatePolicy;\n /**\n * Enable CloudFormation-only deployments for EC2.\n *\n * In order to use this feature you must include the build number in the name of the artifact that you upload to\n * Riff-Raff. Your userData should also refer to this versioned artifact.\n *\n * Users migrating from the `GuEc2AppExperimental` pattern can keep existing deployment behaviour by configuring\n * these props.\n */\n versionedDeployments?: {\n enabled: boolean;\n buildIdentifier: string;\n slowStartDuration?: Duration;\n };\n /**\n * You can specify how long after an instance reaches the InService state it waits before contributing\n * usage data to the aggregated metrics. This specified time is called the default instance warmup.\n * This keeps dynamic scaling from being affected by metrics for individual instances that aren't yet\n * handling application traffic and that might be experiencing temporarily high usage of compute resources.\n *\n * @see https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-default-instance-warmup.html\n */\n defaultInstanceWarmup?: Duration;\n /**\n * How often to send EC2 metrics, such as CPU usage.\n * By default, AWS will produce `5Minute` granular metrics.\n *\n * It is recommended to produce `1Minute` granular metrics in production,\n * especially when using ASG metrics to trigger horizontal scaling as it allows for earlier scaling.\n *\n * @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html\n */\n instanceMetricGranularity: \"1Minute\" | \"5Minute\";\n };\n /**\n * If you want to use an ECS service and ECS tasks to serve requests, then pass in relevant props here.\n *\n * If you are setting both `ecsProps` and `ec2Props` (i.e. if you are migrating from EC2 to ECS) then you must also\n * specify weights for each compute type using `targetGroupWeights`.\n */\n ecsProps?: {\n /**\n * Which image to run.\n * This should be the image digest (e.g. 'sha256:abc123') to ensure immutable deployments.\n *\n * @see https://docs.docker.com/dhi/core-concepts/digests\n */\n imageIdentifier: string;\n cpu: number;\n memoryLimitMiB: number;\n /**\n * ECR repository name which contains your images. This defaults to the name of your GitHub repository as we\n * expect there to be a one-to-one mapping between GitHub repositories and ECR repositories.\n */\n repositoryName?: string;\n /**\n * The number of tasks that you want to run. We recommend running 3 tasks for production services which need a high\n * level of availability so that all 3 Availability Zones are utilised.\n */\n scaling: {\n /**\n * Scaling actions will never scale down below this threshold. This also controls the number of tasks that\n * your ECS service will launch when it is first created.\n */\n minimumTasks: number;\n /**\n * Scaling actions will never scale up above this threshold.\n *\n * Note that this max can be exceeded when a deployment runs (unlike the ASG max size). E.g. if maximumTasks is 6,\n * the service is running 6 tasks and a deployment starts, the ECS service will briefly run with 12 tasks to get\n * the deployment through.\n */\n maximumTasks: number;\n };\n };\n /**\n * If you are specifying `ec2Props` and `ecsProps` use these weights to distribute traffic across the different compute types.\n * Each weight must be between 0 and 999. AWS will work out the relative percentage.\n *\n * @example - Send 10% of traffic to ECS:\n *\n * ```ts\n * targetGroupWeights: {\n * ecs: 1,\n * ec2: 9\n * }\n * ```\n */\n targetGroupWeights?: {\n ecs: number;\n ec2: number;\n };\n}\n\ninterface TargetGroups {\n ec2?: GuApplicationTargetGroup;\n ecs?: GuApplicationTargetGroup;\n}\n\nexport class GuLoadBalancedAppExperimental extends Construct {\n /**\n * The VPC that the pattern's load balancer, EC2 instances and/or ECS tasks are running in.\n */\n public readonly vpc: IVpc;\n /**\n * The certificate associated with your load balancer. This will only be available if `certificateProps` were\n * passed in.\n */\n public readonly certificate?: GuCertificate;\n /**\n * The application load balancer that this pattern creates.\n */\n public readonly loadBalancer: GuApplicationLoadBalancer;\n /**\n * The AutoScaling Group that this pattern creates. This will only be available if `ec2Props` are specified.\n */\n public readonly autoScalingGroup?: GuAutoScalingGroup;\n /**\n * The ECS Service that this pattern creates. This will only be available if `ecsProps` are specified.\n */\n public readonly ecsService?: FargateService;\n /**\n * The load balancer listener that this pattern creates.\n */\n public readonly listener: GuHttpsApplicationListener;\n /**\n * The target groups capable of serving traffic routed to this pattern.\n *\n * If `ec2Props` were passed in but `ecsProps` were not, there will be a single EC2 target group.\n * Similarly, if `ecsProps` were passed in but `ec2Props` were not, there will be a single ECS target group.\n * If both `ec2Props` and `ecsProps` were passed in (e.g. during a migration) then both target groups will be\n * available.\n */\n public readonly targetGroups: TargetGroups;\n\n constructor(scope: GuStack, props: GuLoadBalancedAppExperimentalProps) {\n const {\n access,\n withAccessLogging = true,\n app,\n applicationPort,\n certificateProps,\n monitoringConfiguration,\n vpc = GuVpc.fromIdParameter(scope, AppIdentity.addAppToStringEnd({ app }, \"VPC\")),\n privateSubnets = GuVpc.subnetsFromParameter(scope, { type: SubnetType.PRIVATE, app }),\n publicSubnets = GuVpc.subnetsFromParameter(scope, { type: SubnetType.PUBLIC, app }),\n waf,\n healthcheck,\n ec2Props,\n ecsProps,\n targetGroupWeights,\n additionalPolicies = [],\n } = props;\n\n super(scope, app); // The assumption is `app` is unique\n\n const { stack, stage } = scope;\n\n let targetGroups: TargetGroups = {};\n\n // Setup EC2-specific infrastructure\n if (ec2Props) {\n const {\n applicationLogging = { enabled: false },\n blockDevices,\n instanceType,\n scaling: { minimumInstances, maximumInstances = minimumInstances * 2 },\n userData: userDataLike,\n imageRecipe,\n instanceMetadataHopLimit,\n versionedDeployments,\n updatePolicy,\n defaultInstanceWarmup,\n instanceMetricGranularity,\n } = ec2Props;\n\n const userData =\n userDataLike instanceof UserData ? userDataLike : new GuUserData(scope, { ...userDataLike, app });\n const maybePrivateConfigPolicy =\n userData instanceof GuUserData && userData.configuration\n ? [new GuGetPrivateConfigPolicy(scope, \"GetPrivateConfigFromS3Policy\", userData.configuration)]\n : [];\n const mergedRoleConfiguration: GuInstanceRoleProps = {\n additionalPolicies: maybePrivateConfigPolicy.concat(additionalPolicies),\n };\n\n if (versionedDeployments?.enabled && updatePolicy) {\n throw new Error(\"If versionedDeployments are enabled then updatePolicy should not be set via ec2Props\");\n }\n const asgUpdatePolicy = versionedDeployments\n ? GuRollingUpdatePolicyExperimental.getPolicy(\n maximumInstances,\n minimumInstances,\n versionedDeployments.slowStartDuration,\n )\n : updatePolicy;\n\n const autoScalingGroup = new GuAutoScalingGroup(scope, \"AutoScalingGroup\", {\n app,\n vpc,\n instanceType,\n minimumInstances,\n maximumInstances,\n role: new GuInstanceRole(scope, { app, ...mergedRoleConfiguration }),\n\n healthChecks: HealthChecks.withAdditionalChecks({\n additionalTypes: [AdditionalHealthCheckType.ELB],\n gracePeriod: Duration.minutes(2),\n }),\n\n userData: userData instanceof GuUserData ? userData.userData : userData,\n vpcSubnets: { subnets: privateSubnets },\n ...(blockDevices && { blockDevices }),\n imageRecipe,\n httpPutResponseHopLimit: instanceMetadataHopLimit,\n updatePolicy: asgUpdatePolicy,\n defaultInstanceWarmup,\n instanceMetricGranularity,\n });\n\n // This allows automatic shipping of instance Cloud Init logs when using the\n // `cdk-base` Amigo role on your AMI.\n Tags.of(autoScalingGroup).add(\n MetadataKeys.LOG_KINESIS_STREAM_NAME,\n GuLoggingStreamNameParameter.getInstance(scope).valueAsString,\n );\n\n const ec2TargetGroup = new GuApplicationTargetGroup(scope, \"TargetGroup\", {\n app,\n vpc,\n protocol: ApplicationProtocol.HTTP,\n targets: [autoScalingGroup],\n port: applicationPort,\n healthCheck: healthcheck,\n });\n\n targetGroups = {\n ec2: ec2TargetGroup,\n };\n\n if (versionedDeployments?.enabled) {\n const slowStartDurationInSeconds = versionedDeployments.slowStartDuration?.toSeconds();\n if (slowStartDurationInSeconds && (slowStartDurationInSeconds < 30 || slowStartDurationInSeconds > 900)) {\n throw new Error(\"Slow start duration must be between 30 and 900 seconds\");\n }\n\n const cfnAutoScalingGroup = autoScalingGroup.node.defaultChild as CfnAutoScalingGroup;\n // Note: if the service uses horizontal scaling, this property is unset by an Aspect (to prevent accidental scale downs!)\n cfnAutoScalingGroup.desiredCapacity = minimumInstances.toString();\n\n new GuRoleForRollingUpdateExperimental(scope, { autoScalingGroup });\n new GuUserDataForRollingUpdateExperimental(scope, {\n autoScalingGroup: autoScalingGroup,\n targetGroup: ec2TargetGroup,\n applicationPort: applicationPort,\n buildIdentifier: versionedDeployments.buildIdentifier,\n slowStartDuration: versionedDeployments.slowStartDuration,\n });\n\n // This is used when an ASG is first created; it is not needed to support the new deployment mechanism but we\n // include it here to avoid creating an unnecessary snapshot diff for existing users of this feature\n cfnAutoScalingGroup.cfnOptions.creationPolicy = {\n autoScalingCreationPolicy: {\n minSuccessfulInstancesPercent: 100,\n },\n resourceSignal: {\n count: minimumInstances,\n },\n };\n\n const allAspects = Aspects.of(scope).all;\n const maybeRollingUpdateTimeoutAspect = allAspects.find(\n (_) => _ instanceof GuAutoScalingRollingUpdateTimeoutExperimental,\n );\n if (!maybeRollingUpdateTimeoutAspect) {\n Aspects.of(scope).add(new GuAutoScalingRollingUpdateTimeoutExperimental());\n }\n Aspects.of(scope).add(new GuHorizontallyScalingDeploymentPropertiesExperimental());\n }\n\n if (applicationLogging.enabled) {\n // This allows automatic shipping of application logs when using the\n // `cdk-base` Amigo role on your AMI.\n Tags.of(autoScalingGroup).add(\n MetadataKeys.SYSTEMD_UNIT,\n applicationLogging.systemdUnitName ? `${applicationLogging.systemdUnitName}.service` : `${app}.service`,\n );\n }\n\n this.autoScalingGroup = autoScalingGroup;\n }\n\n // Setup ECS-specific infrastructure\n if (ecsProps) {\n const { cpu, memoryLimitMiB, imageIdentifier, scaling } = ecsProps;\n\n const ecrRepoName = ecsProps.repositoryName ?? scope.repositoryName;\n if (!ecrRepoName) {\n throw new Error(\"Could not determine an ECR repository name; please set this manually via ecsProps\");\n }\n\n const cluster = new Cluster(this, \"EcsCluster\", {\n vpc,\n containerInsightsV2: ContainerInsights.ENHANCED,\n });\n\n const image = ContainerImage.fromEcrRepository(\n // Images are published to the ECR registry in the DeployTools account, so reference that here\n Repository.fromRepositoryAttributes(this, \"Repo\", {\n repositoryArn: scope.formatArn({\n account: StringParameter.fromStringParameterName(\n scope,\n \"DeployToolsAccountId\",\n NAMED_SSM_PARAMETER_PATHS.DeployToolsAccountId.path,\n ).stringValue,\n arnFormat: ArnFormat.SLASH_RESOURCE_NAME,\n resource: \"repository\",\n resourceName: ecrRepoName,\n service: \"ecr\",\n }),\n repositoryName: ecrRepoName,\n }),\n imageIdentifier,\n );\n\n const loggingStreamName = GuLoggingStreamNameParameter.getInstance(scope).valueAsString;\n\n const fireLensLogDriver = new FireLensLogDriver({\n options: {\n Name: `kinesis_streams`,\n region: scope.region,\n stream: loggingStreamName,\n retry_limit: \"2\",\n },\n });\n\n const env = {\n STACK: stack,\n STAGE: stage,\n APP: app,\n\n // Required by https://github.com/guardian/devx-logs\n TASK_NAME: app,\n };\n\n // Add the GitHub repo if we can\n const environment = scope.repositoryName ? { ...env, GU_REPO: scope.repositoryName } : env;\n\n const taskDefinition = new FargateTaskDefinition(scope, \"EcsTaskDefinition\", {\n memoryLimitMiB,\n cpu,\n runtimePlatform: { cpuArchitecture: CpuArchitecture.ARM64, operatingSystemFamily: OperatingSystemFamily.LINUX },\n });\n\n taskDefinition.addContainer(app, {\n image,\n dockerLabels: {\n RiffRaffDeploymentId: GuRiffRaffDeploymentIdParameterExperimental.getInstance(scope).valueAsString,\n },\n // This speeds up deployment. We don't need this enabled if users follow the advice to refer to their image\n // using the immutable digest\n versionConsistency: VersionConsistency.DISABLED,\n portMappings: [{ containerPort: applicationPort }],\n logging: fireLensLogDriver,\n readonlyRootFilesystem: true,\n environment,\n });\n\n // Permissions passed to the ECS task...\n const applicationPermissions: GuPolicy[] = [\n // ...to allow writing logs to Kinesis\n GuLogShippingPolicy.getInstance(scope),\n\n // ...to allow reading application config from SSM\n GuParameterStoreReadPolicy.getInstance(scope, { app }),\n\n // ...permissions specific for this application (provided by client)\n ...additionalPolicies,\n ];\n\n applicationPermissions.forEach((policy) => policy.attachToRole(taskDefinition.taskRole));\n\n /*\n GuardDuty is enabled at the organisation level and runs as a sidecar.\n We need to add specific permissions to allow pulling the GuardDuty image.\n See https://docs.aws.amazon.com/guardduty/latest/ug/prereq-runtime-monitoring-ecs-support.html.\n */\n const guardDutyPolicies = [\n new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\"ecr:GetAuthorizationToken\"],\n resources: [\"*\"],\n }),\n new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\"ecr:BatchCheckLayerAvailability\", \"ecr:GetDownloadUrlForLayer\", \"ecr:BatchGetImage\"],\n resources: [\n // See https://docs.aws.amazon.com/guardduty/latest/ug/runtime-monitoring-ecr-repository-gdu-agent.html\n \"arn:aws:ecr:eu-west-1:694911143906:repository/aws-guardduty-agent-fargate\",\n ],\n }),\n ];\n\n guardDutyPolicies.forEach((policy) => taskDefinition.addToExecutionRolePolicy(policy));\n\n const ecsService = new FargateService(scope, \"EcsService\", {\n cluster,\n taskDefinition,\n vpcSubnets: { subnets: privateSubnets },\n // Important for service deployments; with the AWS defaults the service can be scaled down when deploying\n minHealthyPercent: 100,\n // Also important for service deployments; with the AWS defaults we don't get a fast failure when deploying a 'bad' build\n circuitBreaker: { enable: true, rollback: true },\n propagateTags: PropagatedTagSource.SERVICE,\n // By default, AWS will create a new security group which allows all outbound traffic\n // We don't want this so explicitly allow outbound HTTPS only\n // This is what we do for the current GuEc2App pattern:\n // https://github.com/guardian/cdk/blob/3b5688637024642055ed0bf576f668e56e40830d/src/constructs/autoscaling/asg.ts#L143-L145\n securityGroups: [\n GuHttpsEgressSecurityGroup.forVpc(scope, {\n app: `${app}-ecs`,\n vpc,\n }),\n ],\n });\n\n const cfnService = ecsService.node.defaultChild as CfnService;\n cfnService.addPropertyOverride(\"Monitoring\", {\n MetricConfigurations: [\n {\n MetricNames: [\"CPUUtilization\", \"MemoryUtilization\"],\n ResolutionSeconds: 20,\n },\n ],\n });\n\n ecsService.autoScaleTaskCount({\n minCapacity: scaling.minimumTasks,\n maxCapacity: scaling.maximumTasks,\n });\n\n this.ecsService = ecsService;\n\n // It's possible to opt-out of log shipping to ELK in the EC2 patterns; should we mirror that here?\n const logRouter = taskDefinition.addFirelensLogRouter(\"LogShipping\", {\n // See https://github.com/guardian/devx-logs\n image: ContainerImage.fromRegistry(\n \"ghcr.io/guardian/devx-logs@sha256:cf91724a5166f1c143e07958820aa2122afb61c164b68555d15cb92abb5acda0\",\n ),\n environment,\n versionConsistency: VersionConsistency.DISABLED,\n // Send this container's logs to CloudWatch logs, retained for 1 day\n logging: LogDriver.awsLogs({\n streamPrefix: [scope.stack, scope.stage, app, \"devx-logs-sidecar\"].join(\"/\"),\n logRetention: RetentionDays.ONE_DAY,\n }),\n\n firelensConfig: {\n type: FirelensLogRouterType.FLUENTBIT,\n },\n\n // To comply with FSBP ECS.5\n readonlyRootFilesystem: true,\n });\n\n const logVolume: Volume = {\n name: \"logging-volume\",\n };\n taskDefinition.addVolume(logVolume);\n\n logRouter.addMountPoints({\n containerPath: \"/init\",\n sourceVolume: logVolume.name,\n readOnly: false,\n });\n\n // We need a new target group even if we share the other load balancer components with the EC2 infrastructure\n const ecsTargetGroup = new GuApplicationTargetGroup(\n scope,\n\n // This ID parameter is used to form the resource's logical ID.\n // If a target group is not explicitly named, CloudFormation will use the logical ID to generate a name of form `<CFN_STACK_NAME>-<LOGICAL_ID>-<12 CHAR GUID>` to a max of 32 chars.\n // Add the App to the start of the logical ID to make the generated names (slightly) glanceable, e.g \"MyAppE-123456123456\" vs. \"EcsTar-123456123456\".\n AppIdentity.addAppToStringStart(props, \"EcsTargetGroup\"),\n\n {\n vpc,\n app,\n port: applicationPort,\n targets: [ecsService],\n healthCheck: healthcheck,\n },\n );\n\n targetGroups = {\n ...targetGroups,\n ecs: ecsTargetGroup,\n };\n\n // Specifically apply App tag to resources.\n // Other resources obtain this tag by extending `GuAppAwareConstruct`.\n [cluster, taskDefinition, ecsService].forEach((_) => AppIdentity.taggedConstruct(props, _));\n }\n\n // Set up the load balancer and listener components\n AppAccess.validate(access);\n\n const certificate =\n typeof certificateProps !== \"undefined\"\n ? new GuCertificate(scope, {\n app,\n domainName: certificateProps.domainName,\n hostedZoneId: certificateProps.hostedZoneId,\n })\n : undefined;\n\n const loadBalancer = new GuApplicationLoadBalancer(scope, \"LoadBalancer\", {\n app,\n vpc,\n // Setting internetFacing to true does not necessarily allow public access to the load balancer itself. That is handled by the listener's `open` prop.\n internetFacing: access.scope !== AccessScope.INTERNAL,\n vpcSubnets: {\n subnets: access.scope === AccessScope.INTERNAL ? privateSubnets : publicSubnets,\n },\n withAccessLogging,\n waf,\n });\n\n const defaultAction: ListenerAction = configureListenerActions(targetGroups, targetGroupWeights);\n\n const listener = new GuHttpsApplicationListener(scope, \"Listener\", {\n app,\n loadBalancer,\n certificate,\n defaultAction,\n // When open=true, AWS will create a security group which allows all inbound traffic over HTTPS\n open: access.scope === AccessScope.PUBLIC && typeof certificate !== \"undefined\",\n });\n if (targetGroups.ec2 && targetGroups.ecs) {\n configureDeterministicRouting(listener, targetGroups.ec2, targetGroups.ecs);\n }\n\n // Since AWS won't create a security group automatically when open=false, we need to add our own\n if (access.scope !== AccessScope.PUBLIC) {\n loadBalancer.addSecurityGroup(\n new GuSecurityGroup(scope, `${access.scope}IngressSecurityGroup`, {\n app,\n vpc,\n description: \"Allow restricted ingress from CIDR ranges\",\n allowAllOutbound: false,\n ingresses: restrictedCidrRanges(access.cidrRanges),\n }),\n );\n }\n\n if (props.googleAuth?.enabled) {\n const prefix = `/${scope.stage}/${scope.stack}/${app}`;\n\n const {\n allowedGroups = [\"engineering@guardian.co.uk\"],\n sessionTimeoutInMinutes = 15,\n credentialsSecretsManagerPath = `${prefix}/google-auth-credentials`,\n } = props.googleAuth;\n\n if (sessionTimeoutInMinutes > 60) {\n throw new Error(\"googleAuth.sessionTimeoutInMinutes must be <= 60!\");\n }\n\n if (allowedGroups.length < 1) {\n throw new Error(\"googleAuth.allowedGroups cannot be empty!\");\n }\n\n if (allowedGroups.find((group) => !group.endsWith(\"@guardian.co.uk\"))) {\n throw new Error(\"googleAuth.allowedGroups must use the @guardian.co.uk domain.\");\n }\n\n const deployToolsAccountId = StringParameter.fromStringParameterName(\n scope,\n \"deploy-tools-account-id-parameter\",\n NAMED_SSM_PARAMETER_PATHS.DeployToolsAccountId.path,\n );\n\n const cognitoAuthStage = props.googleAuth.cognitoAuthStage ?? \"PROD\";\n\n // See https://github.com/guardian/cognito-auth-lambdas for the source\n // code here. ARN format is:\n // arn:aws:lambda:aws-region:acct-id:function:helloworld.\n const gatekeeperFunctionArn = `arn:aws:lambda:eu-west-1:${deployToolsAccountId.stringValue}:function:deploy-${cognitoAuthStage}-gatekeeper-lambda`;\n\n // Note, handler and filename must match here:\n // https://github.com/guardian/cognito-auth-lambdas.\n const authLambda = new GuLambdaFunction(scope, \"auth-lambda\", {\n app: app,\n memorySize: 128,\n handler: \"bootstrap\",\n runtime: Runtime.PROVIDED_AL2023,\n fileName: `deploy/${cognitoAuthStage}/cognito-lambda/devx-cognito-lambda-amd64-v2.zip`,\n withoutFilePrefix: true,\n withoutArtifactUpload: true,\n bucketNamePath: NAMED_SSM_PARAMETER_PATHS.OrganisationDistributionBucket.path,\n architecture: Architecture.X86_64,\n environment: {\n ALLOWED_GROUPS: allowedGroups.join(\",\"),\n GATEKEEPER_FUNCTION_ARN: gatekeeperFunctionArn,\n },\n });\n\n Tags.of(authLambda).add(\"Owner\", \"DevX\");\n\n authLambda.addToRolePolicy(\n new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\"lambda:InvokeFunction\"],\n resources: [gatekeeperFunctionArn],\n }),\n );\n\n // Cognito user pool. We require both lambdas: pre-sign-up runs the first\n // time a user attempts to authenticate (before they exist in the User\n // Pool); pre-auth runs in subsequent authentication flows.\n const userPool = new UserPool(this, \"user-pool\", {\n lambdaTriggers: {\n preAuthentication: authLambda,\n preSignUp: authLambda,\n },\n });\n\n // These help ensure domain is deterministic but also unique. Key\n // assumption is that app/stack/stage combo are unique within Guardian.\n const domainPrefix = `com-gu-${app.toLowerCase()}-${scope.stage.toLowerCase()}`;\n\n const userPoolDomain = userPool.addDomain(\"domain\", {\n cognitoDomain: {\n domainPrefix: getUserPoolDomainPrefix(domainPrefix),\n },\n });\n\n const clientId = SecretValue.secretsManager(credentialsSecretsManagerPath, { jsonField: \"clientId\" });\n const clientSecret = SecretValue.secretsManager(credentialsSecretsManagerPath, { jsonField: \"clientSecret\" });\n\n const userPoolIdp = new UserPoolIdentityProviderGoogle(scope, \"google-idp\", {\n userPool: userPool,\n clientId: clientId.toString(),\n clientSecretValue: clientSecret,\n attributeMapping: {\n email: ProviderAttribute.GOOGLE_EMAIL,\n givenName: ProviderAttribute.GOOGLE_GIVEN_NAME,\n familyName: ProviderAttribute.GOOGLE_FAMILY_NAME,\n profilePicture: ProviderAttribute.GOOGLE_PICTURE,\n custom: {\n name: ProviderAttribute.GOOGLE_NAME,\n },\n },\n scopes: [\"openid\", \"email\", \"profile\"],\n });\n\n const userPoolClient = userPool.addClient(\"alb-client\", {\n supportedIdentityProviders: [UserPoolClientIdentityProvider.GOOGLE],\n generateSecret: true,\n oAuth: {\n callbackUrls: [`https://${props.googleAuth.domain}/oauth2/idpresponse`],\n },\n\n // Note: id and access validity token validity cannot be less than one\n // hour (this is the cognito cookie duration). To quickly invalidate\n // credentials, disable the user in Cognito. It might be that we want to\n // parameterise these going forward, but that would require Infosec\n // discussion.\n idTokenValidity: Duration.hours(1),\n accessTokenValidity: Duration.hours(1),\n refreshTokenValidity: Duration.days(7),\n });\n\n userPoolClient.node.addDependency(userPoolIdp);\n\n if (props.ecsProps) {\n throw new Error(\"Using Google Auth with ECS is currently unsupported\");\n // I think that the code here will probably work fine but it needs some dedicated testing.\n // For Google auth to work we need to 'authenticate-cognito' and then forward to a target group.\n // If we are operating with EC2 and ECS backends then this forwarded request could be sent to either backend.\n // Let's deploy this to a DevX service and check it's valid/works as expected before opening this up to other teams.\n }\n listener.addAction(\"CognitoAuth\", {\n action: new AuthenticateCognitoAction({\n userPool: userPool,\n userPoolClient: userPoolClient,\n userPoolDomain: userPoolDomain,\n next: defaultAction,\n sessionTimeout: Duration.minutes(sessionTimeoutInMinutes),\n }),\n });\n\n // Need to give the ALB outbound access on 443 for the IdP endpoints.\n const idpEgressSecurityGroup = new GuHttpsEgressSecurityGroup(scope, \"ldp-access\", {\n app,\n vpc,\n });\n\n loadBalancer.addSecurityGroup(idpEgressSecurityGroup);\n }\n\n // Setup monitoring\n if (!monitoringConfiguration.noMonitoring) {\n const { http5xxAlarm, http4xxAlarm, snsTopicName } = monitoringConfiguration;\n\n if (http4xxAlarm) {\n new GuAlb4xxPercentageAlarm(scope, {\n app,\n loadBalancer,\n snsTopicName,\n ...http4xxAlarm,\n });\n }\n if (http5xxAlarm) {\n new GuAlb5xxPercentageAlarm(scope, {\n app,\n loadBalancer,\n snsTopicName,\n ...http5xxAlarm,\n });\n }\n if (monitoringConfiguration.unhealthyInstancesAlarm && targetGroups.ec2) {\n const { snsTopicName } = monitoringConfiguration;\n new GuUnhealthyInstancesAlarm(scope, {\n app,\n targetGroup: targetGroups.ec2,\n snsTopicName,\n });\n }\n }\n\n this.vpc = vpc;\n this.certificate = certificate;\n this.loadBalancer = loadBalancer;\n this.listener = listener;\n this.targetGroups = targetGroups;\n }\n}\n\nfunction configureListenerActions(\n targetGroups: TargetGroups,\n targetGroupWeights?: {\n ecs: number;\n ec2: number;\n },\n): ListenerAction {\n // No ECS target, so forward all traffic to EC2\n if (targetGroups.ec2 && !targetGroups.ecs) {\n return ListenerAction.forward([targetGroups.ec2]);\n }\n\n // No EC2 target, so forward all traffic to ECS\n if (targetGroups.ecs && !targetGroups.ec2) {\n return ListenerAction.forward([targetGroups.ecs]);\n }\n\n if (targetGroups.ec2 && targetGroups.ecs) {\n if (!targetGroupWeights) {\n throw new Error(\"EC2 and ECS are both enabled but no target group weights were provided\");\n }\n\n // An individual target can have a weight between 0 and 999. AWS will work out the relative percentage.\n const isBetween = (n: number, min: number, max: number): boolean => n >= min && n <= max;\n if (!isBetween(targetGroupWeights.ecs, 0, 999)) {\n throw new Error(\"targetGroupWeights.ecs must be between 0 and 999\");\n }\n if (!isBetween(targetGroupWeights.ec2, 0, 999)) {\n throw new Error(\"targetGroupWeights.ec2 must be between 0 and 999\");\n }\n\n return ListenerAction.weightedForward([\n { targetGroup: targetGroups.ec2, weight: targetGroupWeights.ec2 },\n { targetGroup: targetGroups.ecs, weight: targetGroupWeights.ecs },\n ]);\n } else {\n throw new Error(\"At least one of 'ec2Props' or 'ecsProps' must be specified\");\n }\n}\n\nfunction configureDeterministicRouting(\n listener: GuHttpsApplicationListener,\n ec2TargetGroup: GuApplicationTargetGroup,\n ecsTargetGroup: GuApplicationTargetGroup,\n): void {\n const headerName = \"X-Gu-Target-Group\";\n const ec2HeaderValue = \"ec2\";\n const ecsHeaderValue = \"ecs\";\n\n listener.addAction(\"DeterministicRouteToEc2\", {\n priority: 10,\n conditions: [ListenerCondition.httpHeader(headerName, [ec2HeaderValue])],\n action: ListenerAction.forward([ec2TargetGroup]),\n });\n\n listener.addAction(\"DeterministicRouteToEcs\", {\n priority: 11,\n conditions: [ListenerCondition.httpHeader(headerName, [ecsHeaderValue])],\n action: ListenerAction.forward([ecsTargetGroup]),\n });\n}\n"]}
|