Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions cdk/PatchManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Stack, StackProps } from 'aws-cdk-lib';
import * as ssm from 'aws-cdk-lib/aws-ssm';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Construct } from 'constructs';

export class PatchManagerStack extends Stack {
constructor(scope: Construct, id: string, props?: Props) {
super(scope, id, props);

// IAM role used by the maintenance window
const maintenanceRole = new iam.Role(this, 'MaintenanceWindowRole', {
assumedBy: new iam.ServicePrincipal('ssm.amazonaws.com'),
});

maintenanceRole.addToPolicy(
new iam.PolicyStatement({
actions: [
'ssm:SendCommand',
'ssm:ListCommands',
'ssm:ListCommandInvocations',
],
resources: ['*'],
}),
);

// Maintenance Window
const maintenanceWindow = new ssm.CfnMaintenanceWindow(
this,
'PatchMaintenanceWindow',
{
name: 'patch-maintenance-window',
description: 'Weekly patching using AWS default patch baseline',
schedule: 'cron(0 7 ? * WED *)', // Wednesdays 07:00 UTC
duration: 3,
cutoff: 1,
allowUnassociatedTargets: false,
},
);

// Target EC2 instances by Name tag
const target = new ssm.CfnMaintenanceWindowTarget(
this,
'PatchTarget',
{
windowId: maintenanceWindow.ref,
resourceType: 'INSTANCE',
targets: [
{
key: 'tag:Name',
values: [
`MAAP-STAC-${props?.stage}-pgSTAC-pgbouncer`,
`MAAP-STAC-${props?.stage}-userSTAC-pgbouncer`,
Comment on lines +51 to +52
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be best to provide the full instance names via props instead of just the stage. You might need to export the instance names in the other stack but it would be safer in case those instance names change for some reason.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, I didn't add the condition to check that the other stack existed first but I can add that and export the name.

],
},
],
},
);

// Patch task (Install)
new ssm.CfnMaintenanceWindowTask(this, 'PatchInstallTask', {
windowId: maintenanceWindow.ref,
taskArn: 'AWS-RunPatchBaseline',
taskType: 'RUN_COMMAND',
priority: 1,
maxConcurrency: '2',
maxErrors: '1',
serviceRoleArn: maintenanceRole.roleArn,
targets: [
{
key: 'WindowTargetIds',
values: [target.ref],
},
],
taskInvocationParameters: {
maintenanceWindowRunCommandParameters: {
parameters: {
Operation: ['Install'],
},
},
},
});
}
}

export interface Props extends StackProps {
/**
* Stage of this stack. Used for naming resources.
*/
stage: string;
}
5 changes: 5 additions & 0 deletions cdk/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Vpc } from "./Vpc";
import { Config } from "./config";
import { PgStacInfra } from "./PgStacInfra";
import { MaapEoapiCommon } from "./MaapEoapiCommon";
import { PatchManagerStack } from "./PatchManager";

const {
buildStackName,
Expand Down Expand Up @@ -127,3 +128,7 @@ new PgStacInfra(app, buildStackName("userSTAC"), {
}),
terminationProtection: false,
});

new PatchManagerStack(app, buildStackName("patch-manager"), {
stage,
});