constructor()

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);
  }