fix(iam): skip sanctioned org-admin assumes in the alarm (SEC-37)

Count failed assumes for every principal. Do not page on a successful
assume by the Platform permission set or the two repo script sessions.

Co-authored-by: Adam Moussa <amoussa1229@users.noreply.github.com>
This commit is contained in:
Cursor Agent 2026-09-28 16:07:57 +00:00
parent f38ed7357b
commit 00626f1fc7
No known key found for this signature in database

View file

@ -264,16 +264,29 @@ export class CisMonitoring extends Construct {
alarm.addAlarmAction(new cwactions.SnsAction(topic));
}
// SEC-37. Not a CIS control. Counts every AssumeRole of
// OrganizationAccountAccessRole, including failures. Same topic as the
// CIS alarms. SCP exemptions for that role stay in place.
// SEC-37. Not a CIS control. Same topic as the CIS alarms.
// SCP exemptions for OrganizationAccountAccessRole stay in place.
//
// A 1/1 alarm on every assume would page for each Platform operator
// session and each run of the bootstrap and substrate scripts. CIS 4.1
// treats that single-event paging on a routine path as alert fatigue.
// Successful assumes are excluded only for those callers:
// * the Platform permission set (AWSReservedSSO_Platform_*)
// * session plat-145-hcptf-bootstrap (create-hcptf-bootstrap-roles.sh)
// * session plat-147-tf-substrate (delete-terraform-substrate-prod-dev.sh)
// Any errorCode still counts, including a failed call from those callers.
//
// Residual: roleSessionName is chosen by the caller, so a successful
// assume that copies one of those two session names is not counted.
// The scripts stay on OrganizationAccountAccessRole until the permission
// set is deployed and a real sign-in has assumed the member role.
const orgAdminAssume = new logs.MetricFilter(
this,
"OrganizationAccountAccessRoleAssumeFilter",
{
logGroup,
filterPattern: logs.FilterPattern.literal(
'{ ($.eventName = "AssumeRole") && ($.requestParameters.roleArn = "*OrganizationAccountAccessRole") }',
'{ ($.eventName = "AssumeRole") && ($.requestParameters.roleArn = "*OrganizationAccountAccessRole") && (($.errorCode = "*") || (($.userIdentity.arn != "*AWSReservedSSO_Platform_*") && ($.requestParameters.roleSessionName != "plat-145-hcptf-bootstrap") && ($.requestParameters.roleSessionName != "plat-147-tf-substrate"))) }',
),
metricNamespace: "SeahavenSecurity",
metricName: "OrganizationAccountAccessRoleAssume",
@ -289,7 +302,7 @@ export class CisMonitoring extends Construct {
.createAlarm(this, "OrganizationAccountAccessRoleAssumeAlarm", {
alarmName: "organization-account-access-role-assume",
alarmDescription:
"AssumeRole of OrganizationAccountAccessRole, including failed attempts",
"AssumeRole of OrganizationAccountAccessRole outside the Platform permission set and the two repo script sessions. Failed attempts count for every principal.",
threshold: 1,
comparisonOperator:
cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,