in src/drift-monitor.ts [51:117]
constructor(scope: Construct, id: string, props: DriftMonitorProps = {}) {
super(scope, id);
if ((props.stacks !== undefined && props.stacks.length > 0) && (props.stackNames !== undefined && props.stackNames.length > 0)) {
throw new Error('Must have either stacks or stackNames, not both');
}
const supportedDuration = [1, 3, 6, 12, 24];
if (props.runEvery !== undefined && !supportedDuration.includes(props.runEvery.toHours({ integral: false }))) {
throw new Error('runEvery must be either 1, 3, 6, 12 or 24 hours');
}
const stacks = props.stacks?.map(stack => stack.stackName) ?? props.stackNames;
const metricNamespace = props.metricNamespace ?? 'DriftMonitor';
const detectDriftLambda = new DetectDriftFunction(this, 'DetectDriftLambda', {
environment: {
metricNamespace: metricNamespace,
... stacks ? { stackNames: stacks.join(',') } : {},
},
timeout: Duration.minutes(5),
});
const runEvery = props.runEvery ?? Duration.hours(1);
new events.Rule(this, 'DetectDriftRule', {
targets: [new eventsTargets.LambdaFunction(detectDriftLambda)],
schedule: events.Schedule.rate(runEvery),
enabled: true,
});
const alarmOptions = props.alarmOptions ?? {
alarmName: 'DriftDetected',
threshold: 0,
evaluationPeriods: 1,
treatMissingData: TreatMissingData.IGNORE,
comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,
};
this.alarm = new Alarm(this, 'DriftAlarm', {
metric: new Metric({
metricName: 'DriftedStacks',
namespace: metricNamespace,
period: this.getClosestCloudWatchMetricPeriod(runEvery),
statistic: Statistic.AVERAGE,
unit: Unit.COUNT,
}),
...alarmOptions,
});
const lambdaHandlerPolicy = new Policy(this, 'LambdaHandlerPolicy', {
policyName: 'DetectDriftLambdaPolicy',
statements: [
new PolicyStatement({
effect: Effect.ALLOW,
actions: [
'cloudformation:ListStackResources',
'cloudformation:DescribeStackDriftDetectionStatus',
'cloudformation:DetectStackDrift',
'cloudformation:DetectStackResourceDrift',
'cloudwatch:PutMetricData',
],
resources: ['*'],
}),
],
});
const readOnlyAccessPolicy = ManagedPolicy.fromAwsManagedPolicyName('ReadOnlyAccess');
detectDriftLambda.role!.attachInlinePolicy(lambdaHandlerPolicy);
detectDriftLambda.role!.addManagedPolicy(readOnlyAccessPolicy);
}