fix(cis): require 3-of-3 periods for UnauthorizedAPICalls alarm (INFRA-104) (#25)
Some checks are pending
Deploy / deploy (push) Waiting to run

The cis-UnauthorizedAPICalls alarm fired on a single breaching 5-min period
(1/1), so any CloudFormation/CDK deploy burst of benign describe-API denials or
a one-off console fat-finger paged and self-recovered, producing notification
storms (~17 flips on 2026-06-10). Require 3 consecutive breaching periods so
only sustained unauthorized activity alarms; CIS detection of a real persistent
problem is preserved (detection window up to ~15 min). Per-control override so
the other 14 CIS alarms keep their 1/1 sensitivity (templates untouched).

GPT-4.1 cross-review: no blockers (documentation FIX noted re: detection latency).
This commit is contained in:
Adam Moussa 2026-06-10 19:32:03 -04:00 • committed by GitHub
parent cbd98da049
commit 67f4ca81d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -28,6 +28,11 @@ interface CisControl {
readonly metricName: string;
readonly pattern: string;
readonly description: string;
// Optional alarm-sensitivity override. Defaults to 1/1 (page on a single
// breaching 5-min period) which suits low-frequency security signals. Raise
// for noisy high-volume metrics where one-off breaches are expected.
readonly evaluationPeriods?: number;
readonly datapointsToAlarm?: number;
}
const CIS_CONTROLS: CisControl[] = [
@ -37,6 +42,14 @@ const CIS_CONTROLS: CisControl[] = [
pattern:
'{ ($.errorCode = "*UnauthorizedOperation") || ($.errorCode = "AccessDenied*") && ($.sourceIPAddress != "delivery.logs.amazonaws.com") && ($.eventName != "HeadBucket") }',
description: "CIS 4.1 — unauthorized API calls",
// This metric is high-volume: a single CloudFormation/CDK deploy can emit a
// burst of benign describe-API denials, and any one-off console fat-finger
// trips a 1/1 alarm and self-recovers, producing notification storms. Require
// 3 consecutive breaching 5-min periods so only *sustained* unauthorized
// activity (e.g. a misconfigured role failing every call) pages. Detection of
// a real persistent problem is preserved; transient bursts are filtered.
evaluationPeriods: 3,
datapointsToAlarm: 3,
},
{
id: "ConsoleSigninNoMfa",
@ -209,7 +222,10 @@ export class CisMonitoring extends Construct {
threshold: 1,
comparisonOperator:
cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
evaluationPeriods: 1,
evaluationPeriods: c.evaluationPeriods ?? 1,
// Omitted (undefined) for default 1/1 controls so their templates are
// untouched; CloudWatch defaults datapointsToAlarm to evaluationPeriods.
datapointsToAlarm: c.datapointsToAlarm ?? c.evaluationPeriods,
treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
});