iam-policy-validator 1.5.0__py3-none-any.whl → 1.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. {iam_policy_validator-1.5.0.dist-info → iam_policy_validator-1.6.0.dist-info}/METADATA +89 -60
  2. {iam_policy_validator-1.5.0.dist-info → iam_policy_validator-1.6.0.dist-info}/RECORD +40 -25
  3. iam_validator/__version__.py +1 -1
  4. iam_validator/checks/__init__.py +9 -3
  5. iam_validator/checks/action_condition_enforcement.py +164 -2
  6. iam_validator/checks/action_resource_matching.py +424 -0
  7. iam_validator/checks/condition_key_validation.py +3 -1
  8. iam_validator/checks/condition_type_mismatch.py +259 -0
  9. iam_validator/checks/mfa_condition_check.py +112 -0
  10. iam_validator/checks/sensitive_action.py +78 -6
  11. iam_validator/checks/set_operator_validation.py +157 -0
  12. iam_validator/checks/utils/sensitive_action_matcher.py +35 -1
  13. iam_validator/commands/cache.py +1 -1
  14. iam_validator/commands/validate.py +44 -11
  15. iam_validator/core/aws_fetcher.py +89 -52
  16. iam_validator/core/check_registry.py +165 -21
  17. iam_validator/core/condition_validators.py +626 -0
  18. iam_validator/core/config/__init__.py +13 -15
  19. iam_validator/core/config/aws_global_conditions.py +160 -0
  20. iam_validator/core/config/category_suggestions.py +104 -0
  21. iam_validator/core/config/condition_requirements.py +5 -385
  22. iam_validator/core/{config_loader.py → config/config_loader.py} +3 -0
  23. iam_validator/core/config/defaults.py +187 -54
  24. iam_validator/core/config/sensitive_actions.py +620 -81
  25. iam_validator/core/models.py +14 -1
  26. iam_validator/core/policy_checks.py +4 -4
  27. iam_validator/core/pr_commenter.py +1 -1
  28. iam_validator/sdk/__init__.py +187 -0
  29. iam_validator/sdk/arn_matching.py +274 -0
  30. iam_validator/sdk/context.py +222 -0
  31. iam_validator/sdk/exceptions.py +48 -0
  32. iam_validator/sdk/helpers.py +177 -0
  33. iam_validator/sdk/policy_utils.py +425 -0
  34. iam_validator/sdk/shortcuts.py +283 -0
  35. iam_validator/utils/__init__.py +31 -0
  36. iam_validator/utils/cache.py +105 -0
  37. iam_validator/utils/regex.py +206 -0
  38. iam_validator/checks/action_resource_constraint.py +0 -151
  39. iam_validator/core/aws_global_conditions.py +0 -137
  40. {iam_policy_validator-1.5.0.dist-info → iam_policy_validator-1.6.0.dist-info}/WHEEL +0 -0
  41. {iam_policy_validator-1.5.0.dist-info → iam_policy_validator-1.6.0.dist-info}/entry_points.txt +0 -0
  42. {iam_policy_validator-1.5.0.dist-info → iam_policy_validator-1.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,133 +1,672 @@
1
1
  """
2
2
  Sensitive actions catalog for IAM Policy Validator.
3
3
 
4
- This module defines a curated list of sensitive AWS actions that should
4
+ This module defines categorized lists of sensitive AWS actions that should
5
5
  typically have IAM conditions to limit when they can be used.
6
6
 
7
- Using Python instead of YAML/JSON provides:
8
- - Zero parsing overhead (compiled to .pyc)
9
- - Better PyPI packaging (no data files)
10
- - Type hints and IDE autocomplete
11
- - Easy to extend and maintain
7
+ Actions are organized into four security risk categories:
8
+ - CredentialExposure (46 actions): Actions that expose credentials, secrets, or tokens
9
+ - DataAccess (109 actions): Actions that retrieve sensitive data
10
+ - PrivEsc (27 actions): Actions that enable privilege escalation
11
+ - ResourceExposure (321 actions): Actions that modify resource policies or permissions
12
12
 
13
- The list is a frozenset for O(1) lookup performance.
13
+ Total: 490 sensitive actions across all categories
14
+
15
+ Source: https://github.com/primeharbor/sensitive_iam_actions
14
16
  """
15
17
 
16
18
  from typing import Final
17
19
 
18
20
  # ============================================================================
19
- # Sensitive Actions List
21
+ # Category: CredentialExposure (46 actions)
20
22
  # ============================================================================
21
- # These actions are considered sensitive and should typically have IAM
22
- # conditions to limit when they can be used. Examples include:
23
- # - IAM identity and access management changes
24
- # - Secrets and credential operations
25
- # - Destructive operations (deletions)
26
- # - Security configuration changes
27
- # - Network and firewall modifications
28
- # - Logging and audit trail changes
23
+ # Actions that expose credentials, secrets, API keys, or authentication tokens.
24
+ # These actions should be tightly controlled as they can lead to credential theft.
29
25
  # ============================================================================
30
26
 
31
- DEFAULT_SENSITIVE_ACTIONS: Final[frozenset[str]] = frozenset(
27
+ CREDENTIAL_EXPOSURE_ACTIONS: Final[frozenset[str]] = frozenset(
32
28
  {
33
- # IAM & Identity Management
34
- "iam:AddClientIDToOpenIDConnectProvider",
29
+ "appsync:GetDataSource",
30
+ "appsync:GetFunction",
31
+ "appsync:ListApiKeys",
32
+ "chime:CreateApiKey",
33
+ "chime:DeleteVoiceConnectorTerminationCredentials",
34
+ "chime:PutVoiceConnectorTerminationCredentials",
35
+ "cloud9:CreateEnvironmentSSH",
36
+ "cloud9:CreateEnvironmentToken",
37
+ "codeartifact:GetAuthorizationToken",
38
+ "codebuild:DeleteSourceCredentials",
39
+ "codebuild:ImportSourceCredentials",
40
+ "cognito-identity:GetCredentialsForIdentity",
41
+ "cognito-identity:GetId",
42
+ "cognito-identity:GetOpenIdToken",
43
+ "cognito-identity:GetOpenIdTokenForDeveloperIdentity",
44
+ "connect:GetFederationToken",
45
+ "connect:ListSecurityKeys",
46
+ "ec2-instance-connect:SendSSHPublicKey",
47
+ "ec2:GetPasswordData",
48
+ "ecr-public:GetAuthorizationToken",
49
+ "ecr:GetAuthorizationToken",
50
+ "gamelift:GetComputeAuthToken",
51
+ "gamelift:RequestUploadCredentials",
52
+ "iam:CreateAccessKey",
53
+ "iam:CreateLoginProfile",
54
+ "iam:CreateServiceSpecificCredential",
55
+ "iam:GetServiceLinkedRoleDeletionStatus",
56
+ "iam:ResetServiceSpecificCredential",
57
+ "iam:UpdateAccessKey",
58
+ "lightsail:DownloadDefaultKeyPair",
59
+ "lightsail:GetBucketAccessKeys",
60
+ "lightsail:GetKeyPair",
61
+ "lightsail:GetKeyPairs",
62
+ "lightsail:GetRelationalDatabaseMasterUserPassword",
63
+ "mediapackage:RotateChannelCredentials",
64
+ "mediapackage:RotateIngestEndpointCredentials",
65
+ "rds-db:connect",
66
+ "redshift:CreateClusterUser",
67
+ "redshift:GetClusterCredentials",
68
+ "secretsmanager:GetSecretValue",
69
+ "snowball:GetJobUnlockCode",
70
+ "sts:AssumeRole",
71
+ "sts:AssumeRoleWithSAML",
72
+ "sts:AssumeRoleWithWebIdentity",
73
+ "sts:GetFederationToken",
74
+ "sts:GetSessionToken",
75
+ }
76
+ )
77
+
78
+ # ============================================================================
79
+ # Category: DataAccess (109 actions)
80
+ # ============================================================================
81
+ # Actions that retrieve sensitive data, query databases, or access stored content.
82
+ # These actions can expose confidential business or customer data.
83
+ # ============================================================================
84
+
85
+ DATA_ACCESS_ACTIONS: Final[frozenset[str]] = frozenset(
86
+ {
87
+ "aoss:APIAccessAll",
88
+ "aoss:DashboardsAccessAll",
89
+ "athena:GetQueryExecution",
90
+ "athena:GetQueryResults",
91
+ "athena:GetQueryResultsStream",
92
+ "athena:GetSession",
93
+ "cassandra:Select",
94
+ "chatbot:DescribeSlackChannels",
95
+ "chatbot:DescribeSlackUserIdentities",
96
+ "chatbot:GetMicrosoftTeamsOauthParameters",
97
+ "chatbot:GetSlackOauthParameters",
98
+ "chatbot:ListMicrosoftTeamsConfiguredTeams",
99
+ "chatbot:ListMicrosoftTeamsUserIdentities",
100
+ "chime:GetAttendee",
101
+ "chime:GetChannelMessage",
102
+ "chime:GetMeeting",
103
+ "chime:GetMeetingDetail",
104
+ "chime:GetRoom",
105
+ "chime:GetUser",
106
+ "chime:GetUserActivityReportData",
107
+ "chime:GetUserByEmail",
108
+ "chime:GetUserSettings",
109
+ "chime:ListAttendees",
110
+ "chime:ListMeetingEvents",
111
+ "chime:ListMeetings",
112
+ "chime:ListUsers",
113
+ "cleanrooms:GetProtectedQuery",
114
+ "cloudformation:GetTemplate",
115
+ "cloudfront:GetFunction",
116
+ "codeartifact:GetPackageVersionAsset",
117
+ "codeartifact:GetPackageVersionReadme",
118
+ "codeartifact:ReadFromRepository",
119
+ "cognito-identity:LookupDeveloperIdentity",
120
+ "cognito-idp:AdminGetDevice",
121
+ "cognito-idp:AdminGetUser",
122
+ "cognito-idp:AdminListDevices",
123
+ "cognito-idp:AdminListGroupsForUser",
124
+ "cognito-idp:AdminListUserAuthEvents",
125
+ "cognito-idp:DescribeUserPoolClient",
126
+ "cognito-idp:GetDevice",
127
+ "cognito-idp:GetGroup",
128
+ "cognito-idp:GetUser",
129
+ "cognito-idp:GetUserAttributeVerificationCode",
130
+ "cognito-idp:ListDevices",
131
+ "cognito-idp:ListGroups",
132
+ "cognito-idp:ListUsers",
133
+ "cognito-sync:ListRecords",
134
+ "cognito-sync:QueryRecords",
135
+ "connect:ListUsers",
136
+ "datapipeline:QueryObjects",
137
+ "dax:BatchGetItem",
138
+ "dax:GetItem",
139
+ "dax:Query",
140
+ "dax:Scan",
141
+ "dynamodb:BatchGetItem",
142
+ "dynamodb:GetItem",
143
+ "dynamodb:GetRecords",
144
+ "dynamodb:Query",
145
+ "dynamodb:Scan",
146
+ "ecr:GetDownloadUrlForLayer",
147
+ "gamelift:GetGameSessionLogUrl",
148
+ "gamelift:GetInstanceAccess",
149
+ "healthlake:ReadResource",
150
+ "healthlake:SearchWithGet",
151
+ "healthlake:SearchWithPost",
152
+ "kendra:Query",
153
+ "kinesis:GetRecords",
154
+ "kinesisvideo:GetImages",
155
+ "kinesisvideo:GetMedia",
156
+ "lambda:GetFunction",
157
+ "lambda:GetLayerVersion",
158
+ "lightsail:GetContainerImages",
159
+ "logs:GetLogEvents",
160
+ "logs:GetLogRecord",
161
+ "logs:GetQueryResults",
162
+ "logs:Unmask",
163
+ "macie2:GetFindings",
164
+ "mediastore:GetObject",
165
+ "qldb:GetBlock",
166
+ "rds:DownloadCompleteDBLogFile",
167
+ "rds:DownloadDBLogFilePortion",
168
+ "robomaker:GetWorldTemplateBody",
169
+ "s3-object-lambda:GetObject",
170
+ "s3-object-lambda:GetObjectVersion",
171
+ "s3-object-lambda:ListBucket",
172
+ "s3:GetDataAccess",
173
+ "s3:GetObject",
174
+ "s3:GetObjectVersion",
175
+ "sagemaker:Search",
176
+ "sdb:Select",
177
+ "serverlessrepo:GetApplication",
178
+ "serverlessrepo:GetCloudFormationTemplate",
179
+ "sqs:ReceiveMessage",
180
+ "ssm:GetDocument",
181
+ "ssm:GetParameter",
182
+ "ssm:GetParameterHistory",
183
+ "ssm:GetParameters",
184
+ "ssm:GetParametersByPath",
185
+ "sso-directory:DescribeGroup",
186
+ "sso-directory:DescribeUser",
187
+ "sso-directory:ListBearerTokens",
188
+ "sso-directory:SearchGroups",
189
+ "sso-directory:SearchUsers",
190
+ "sso:SearchGroups",
191
+ "sso:SearchUsers",
192
+ "storagegateway:DescribeChapCredentials",
193
+ "workdocs:GetDocument",
194
+ "workdocs:GetDocumentPath",
195
+ "workdocs:GetDocumentVersion",
196
+ }
197
+ )
198
+
199
+ # ============================================================================
200
+ # Category: PrivEsc (27 actions)
201
+ # ============================================================================
202
+ # Actions that enable privilege escalation by creating or modifying IAM identities,
203
+ # roles, policies, or permission boundaries. These are critical security controls.
204
+ # ============================================================================
205
+
206
+ PRIV_ESC_ACTIONS: Final[frozenset[str]] = frozenset(
207
+ {
208
+ "codestar:AssociateTeamMember",
209
+ "codestar:CreateProject",
210
+ "ec2-instance-connect:SendSSHPublicKey",
211
+ "glue:UpdateDevEndpoint",
212
+ "iam:AddUserToGroup",
213
+ "iam:AttachGroupPolicy",
35
214
  "iam:AttachRolePolicy",
36
215
  "iam:AttachUserPolicy",
37
216
  "iam:CreateAccessKey",
38
- "iam:CreateOpenIDConnectProvider",
217
+ "iam:CreateLoginProfile",
39
218
  "iam:CreatePolicyVersion",
40
- "iam:CreateRole",
219
+ "iam:CreateServiceLinkedRole",
220
+ "iam:CreateVirtualMFADevice",
221
+ "iam:DeleteRolePermissionsBoundary",
222
+ "iam:DeleteUserPermissionsBoundary",
223
+ "iam:EnableMFADevice",
224
+ "iam:PassRole",
225
+ "iam:PutGroupPolicy",
226
+ "iam:PutRolePermissionsBoundary",
227
+ "iam:PutRolePolicy",
228
+ "iam:PutUserPermissionsBoundary",
229
+ "iam:PutUserPolicy",
230
+ "iam:ResyncMFADevice",
231
+ "iam:SetDefaultPolicyVersion",
232
+ "iam:UpdateAssumeRolePolicy",
233
+ "iam:UpdateLoginProfile",
234
+ "kms:CreateGrant",
235
+ }
236
+ )
237
+
238
+ # ============================================================================
239
+ # Category: ResourceExposure (321 actions)
240
+ # ============================================================================
241
+ # Actions that modify resource policies, access policies, sharing settings,
242
+ # or permissions that could expose resources to unauthorized access.
243
+ # ============================================================================
244
+
245
+ RESOURCE_EXPOSURE_ACTIONS: Final[frozenset[str]] = frozenset(
246
+ {
247
+ "account:CloseAccount",
248
+ "account:CreateAccount",
249
+ "account:DeleteAccount",
250
+ "acm-pca:CreatePermission",
251
+ "acm-pca:DeletePermission",
252
+ "acm-pca:DeletePolicy",
253
+ "acm-pca:PutPolicy",
254
+ "apigateway:UpdateRestApiPolicy",
255
+ "backup:DeleteBackupVault",
256
+ "backup:DeleteBackupVaultAccessPolicy",
257
+ "backup:PutBackupVaultAccessPolicy",
258
+ "cloudformation:SetStackPolicy",
259
+ "cloudsearch:UpdateServiceAccessPolicies",
260
+ "cloudtrail:DeleteTrail",
261
+ "cloudtrail:StopLogging",
262
+ "cloudwatch:DeleteLogGroup",
263
+ "codeartifact:DeleteDomainPermissionsPolicy",
264
+ "codeartifact:DeleteRepositoryPermissionsPolicy",
265
+ "codebuild:DeleteResourcePolicy",
266
+ "codebuild:PutResourcePolicy",
267
+ "codeguru-profiler:PutPermission",
268
+ "codeguru-profiler:RemovePermission",
269
+ "codestar:AssociateTeamMember",
270
+ "codestar:CreateProject",
271
+ "codestar:DeleteProject",
272
+ "codestar:DisassociateTeamMember",
273
+ "codestar:UpdateTeamMember",
274
+ "cognito-identity:CreateIdentityPool",
275
+ "cognito-identity:DeleteIdentities",
276
+ "cognito-identity:DeleteIdentityPool",
277
+ "cognito-identity:MergeDeveloperIdentities",
278
+ "cognito-identity:SetIdentityPoolRoles",
279
+ "cognito-identity:UnlinkDeveloperIdentity",
280
+ "cognito-identity:UnlinkIdentity",
281
+ "cognito-identity:UpdateIdentityPool",
282
+ "config:DeleteConfigurationRecorder",
283
+ "deeplens:AssociateServiceRoleToAccount",
284
+ "ds:CreateConditionalForwarder",
285
+ "ds:CreateDirectory",
286
+ "ds:CreateMicrosoftAD",
287
+ "ds:CreateTrust",
288
+ "ds:ShareDirectory",
289
+ "dynamodb:DeleteTable",
290
+ "ec2:ApplySecurityGroupsToClientVpnTargetNetwork",
291
+ "ec2:AssociateClientVpnTargetNetwork",
292
+ "ec2:AssociateSecurityGroupVpc",
293
+ "ec2:AttachVpnGateway",
294
+ "ec2:AuthorizeClientVpnIngress",
295
+ "ec2:AuthorizeSecurityGroupIngress",
296
+ "ec2:CreateClientVpnRoute",
297
+ "ec2:CreateNetworkInterfacePermission",
298
+ "ec2:CreateVpnConnection",
299
+ "ec2:DeleteNetworkInterfacePermission",
300
+ "ec2:DeleteSecurityGroup",
301
+ "ec2:DeleteSnapshot",
302
+ "ec2:DeleteVolume",
303
+ "ec2:DeleteVpc",
304
+ "ec2:DeleteVpnConnection",
305
+ "ec2:DisableImageBlockPublicAccess",
306
+ "ec2:DisassociateRouteTable",
307
+ "ec2:ModifyInstanceAttribute",
308
+ "ec2:ModifySnapshotAttribute",
309
+ "ec2:ModifyVpcEndpointServicePermissions",
310
+ "ec2:ResetSnapshotAttribute",
311
+ "ec2:RevokeSecurityGroupEgress",
312
+ "ec2:TerminateInstances",
313
+ "ecr:DeleteRepository",
314
+ "ecr:DeleteRepositoryPolicy",
315
+ "ecr:SetRepositoryPolicy",
316
+ "ecs:DeleteCluster",
317
+ "ecs:DeleteService",
318
+ "efs:DeleteFileSystem",
319
+ "eks:DeleteCluster",
320
+ "elasticache:DeleteCacheCluster",
321
+ "elasticfilesystem:DeleteFileSystemPolicy",
322
+ "elasticfilesystem:PutFileSystemPolicy",
323
+ "elasticmapreduce:PutBlockPublicAccessConfiguration",
324
+ "es:CreateElasticsearchDomain",
325
+ "es:ESHttpDelete",
326
+ "es:ESHttpPatch",
327
+ "es:ESHttpPost",
328
+ "es:ESHttpPut",
329
+ "es:UpdateElasticsearchDomainConfig",
330
+ "fsx:DeleteFileSystem",
331
+ "glacier:AbortVaultLock",
332
+ "glacier:CompleteVaultLock",
333
+ "glacier:DeleteArchive",
334
+ "glacier:DeleteVaultAccessPolicy",
335
+ "glacier:InitiateVaultLock",
336
+ "glacier:SetDataRetrievalPolicy",
337
+ "glacier:SetVaultAccessPolicy",
338
+ "glue:DeleteResourcePolicy",
339
+ "glue:PutResourcePolicy",
340
+ "glue:UpdateDevEndpoint",
341
+ "greengrass:AssociateServiceRoleToAccount",
342
+ "guardduty:DeleteDetector",
343
+ "health:DisableHealthServiceAccessForOrganization",
344
+ "health:EnableHealthServiceAccessForOrganization",
345
+ "iam:AddClientIDToOpenIDConnectProvider",
346
+ "iam:AddRoleToInstanceProfile",
347
+ "iam:ChangePassword",
348
+ "iam:CreateAccountAlias",
349
+ "iam:CreateInstanceProfile",
350
+ "iam:CreateOpenIDConnectProvider",
41
351
  "iam:CreateSAMLProvider",
42
- "iam:CreateUser",
352
+ "iam:CreateServiceLinkedRole",
353
+ "iam:CreateVirtualMFADevice",
354
+ "iam:DeactivateMFADevice",
43
355
  "iam:DeleteAccessKey",
356
+ "iam:DeleteAccountAlias",
357
+ "iam:DeleteAccountPasswordPolicy",
358
+ "iam:DeleteGroup",
359
+ "iam:DeleteGroupPolicy",
360
+ "iam:DeleteInstanceProfile",
44
361
  "iam:DeleteLoginProfile",
45
362
  "iam:DeleteOpenIDConnectProvider",
363
+ "iam:DeletePolicy",
364
+ "iam:DeletePolicyVersion",
46
365
  "iam:DeleteRole",
366
+ "iam:DeleteRolePermissionsBoundary",
47
367
  "iam:DeleteRolePolicy",
48
368
  "iam:DeleteSAMLProvider",
369
+ "iam:DeleteSSHPublicKey",
370
+ "iam:DeleteServerCertificate",
371
+ "iam:DeleteServiceLinkedRole",
372
+ "iam:DeleteServiceSpecificCredential",
373
+ "iam:DeleteSigningCertificate",
49
374
  "iam:DeleteUser",
50
375
  "iam:DeleteUserPolicy",
376
+ "iam:DeleteVirtualMFADevice",
377
+ "iam:DetachGroupPolicy",
51
378
  "iam:DetachRolePolicy",
52
379
  "iam:DetachUserPolicy",
53
- "iam:PutRolePolicy",
54
- "iam:PutUserPolicy",
55
- "iam:SetDefaultPolicyVersion",
56
- "iam:UpdateAccessKey",
57
- "iam:UpdateAssumeRolePolicy",
58
- # Secrets & Credentials
380
+ "iam:EnableMFADevice",
381
+ "iam:RemoveClientIDFromOpenIDConnectProvider",
382
+ "iam:RemoveRoleFromInstanceProfile",
383
+ "iam:RemoveUserFromGroup",
384
+ "iam:ResyncMFADevice",
385
+ "iam:SetSecurityTokenServicePreferences",
386
+ "iam:UpdateAccountPasswordPolicy",
387
+ "iam:UpdateGroup",
388
+ "iam:UpdateLoginProfile",
389
+ "iam:UpdateOpenIDConnectProviderThumbprint",
390
+ "iam:UpdateRole",
391
+ "iam:UpdateRoleDescription",
392
+ "iam:UpdateSAMLProvider",
393
+ "iam:UpdateSSHPublicKey",
394
+ "iam:UpdateServerCertificate",
395
+ "iam:UpdateServiceSpecificCredential",
396
+ "iam:UpdateSigningCertificate",
397
+ "iam:UploadServerCertificate",
398
+ "iam:UploadSigningCertificate",
399
+ "imagebuilder:PutComponentPolicy",
400
+ "imagebuilder:PutImagePolicy",
401
+ "imagebuilder:PutImageRecipePolicy",
402
+ "iot:AttachPolicy",
403
+ "iot:AttachPrincipalPolicy",
404
+ "iot:DetachPolicy",
405
+ "iot:DetachPrincipalPolicy",
406
+ "iot:SetDefaultAuthorizer",
407
+ "iot:SetDefaultPolicyVersion",
408
+ "iotsitewise:CreateAccessPolicy",
409
+ "iotsitewise:DeleteAccessPolicy",
410
+ "iotsitewise:UpdateAccessPolicy",
411
+ "kms:CreateGrant",
59
412
  "kms:DisableKey",
60
413
  "kms:PutKeyPolicy",
414
+ "kms:RetireGrant",
415
+ "kms:RevokeGrant",
61
416
  "kms:ScheduleKeyDeletion",
62
- "secretsmanager:DeleteSecret",
63
- "secretsmanager:GetSecretValue",
64
- "secretsmanager:PutSecretValue",
65
- "ssm:DeleteParameter",
66
- "ssm:PutParameter",
67
- # Compute & Containers
68
- "ec2:DeleteSnapshot",
69
- "ec2:DeleteVolume",
70
- "ec2:DeleteVpc",
71
- "ec2:ModifyInstanceAttribute",
72
- "ec2:TerminateInstances",
73
- "ecr:DeleteRepository",
74
- "ecs:DeleteCluster",
75
- "ecs:DeleteService",
76
- "eks:DeleteCluster",
417
+ "lakeformation:BatchGrantPermissions",
418
+ "lakeformation:BatchRevokePermissions",
419
+ "lakeformation:GrantPermissions",
420
+ "lakeformation:PutDataLakeSettings",
421
+ "lakeformation:RevokePermissions",
422
+ "lambda:AddLayerVersionPermission",
423
+ "lambda:AddPermission",
77
424
  "lambda:DeleteFunction",
78
425
  "lambda:DeleteFunctionConcurrency",
426
+ "lambda:DisableReplication",
427
+ "lambda:EnableReplication",
79
428
  "lambda:PutFunctionConcurrency",
80
- # Database & Storage
81
- "dynamodb:DeleteTable",
82
- "efs:DeleteFileSystem",
83
- "elasticache:DeleteCacheCluster",
84
- "fsx:DeleteFileSystem",
429
+ "lambda:RemoveLayerVersionPermission",
430
+ "lambda:RemovePermission",
431
+ "license-manager:UpdateServiceSettings",
432
+ "logs:DeleteResourcePolicy",
433
+ "logs:PutResourcePolicy",
434
+ "mediastore:DeleteContainerPolicy",
435
+ "mediastore:PutContainerPolicy",
436
+ "opsworks:SetPermission",
437
+ "opsworks:UpdateUserProfile",
438
+ "organizations:DeleteOrganization",
439
+ "organizations:LeaveOrganization",
440
+ "organizations:RemoveAccountFromOrganization",
441
+ "quicksight:CreateAdmin",
442
+ "quicksight:CreateGroup",
443
+ "quicksight:CreateGroupMembership",
444
+ "quicksight:CreateIAMPolicyAssignment",
445
+ "quicksight:CreateUser",
446
+ "quicksight:DeleteGroup",
447
+ "quicksight:DeleteGroupMembership",
448
+ "quicksight:DeleteIAMPolicyAssignment",
449
+ "quicksight:DeleteUser",
450
+ "quicksight:DeleteUserByPrincipalId",
451
+ "quicksight:RegisterUser",
452
+ "quicksight:UpdateDashboardPermissions",
453
+ "quicksight:UpdateGroup",
454
+ "quicksight:UpdateIAMPolicyAssignment",
455
+ "quicksight:UpdateTemplatePermissions",
456
+ "quicksight:UpdateUser",
457
+ "ram:AcceptResourceShareInvitation",
458
+ "ram:AssociateResourceShare",
459
+ "ram:CreateResourceShare",
460
+ "ram:DeleteResourceShare",
461
+ "ram:DisassociateResourceShare",
462
+ "ram:EnableSharingWithAwsOrganization",
463
+ "ram:RejectResourceShareInvitation",
464
+ "ram:UpdateResourceShare",
465
+ "rds:AuthorizeDBSecurityGroupIngress",
85
466
  "rds:DeleteDBCluster",
86
467
  "rds:DeleteDBInstance",
468
+ "redshift:AuthorizeSnapshotAccess",
469
+ "redshift:CreateSnapshotCopyGrant",
87
470
  "redshift:DeleteCluster",
88
- # S3 & Backup
89
- "backup:DeleteBackupVault",
90
- "glacier:DeleteArchive",
471
+ "redshift:JoinGroup",
472
+ "redshift:ModifyClusterIamRoles",
473
+ "redshift:RevokeSnapshotAccess",
474
+ "route53resolver:PutResolverRulePolicy",
475
+ "s3:BypassGovernanceRetention",
476
+ "s3:DeleteAccessPointPolicy",
91
477
  "s3:DeleteBucket",
92
478
  "s3:DeleteBucketPolicy",
93
479
  "s3:DeleteObject",
480
+ "s3:ObjectOwnerOverrideToBucketOwner",
481
+ "s3:PutAccessPointPolicy",
482
+ "s3:PutAccountPublicAccessBlock",
483
+ "s3:PutBucketAcl",
94
484
  "s3:PutBucketPolicy",
485
+ "s3:PutBucketPublicAccessBlock",
95
486
  "s3:PutLifecycleConfiguration",
96
- # Network & Security
97
- "ec2:ApplySecurityGroupsToClientVpnTargetNetwork",
98
- "ec2:AssociateClientVpnTargetNetwork",
99
- "ec2:AssociateSecurityGroupVpc",
100
- "ec2:AttachVpnGateway",
101
- "ec2:AuthorizeClientVpnIngress",
102
- "ec2:AuthorizeSecurityGroupIngress",
103
- "ec2:CreateClientVpnRoute",
104
- "ec2:CreateVpnConnection",
105
- "ec2:DeleteSecurityGroup",
106
- "ec2:DeleteVpnConnection",
107
- "ec2:DisassociateRouteTable",
108
- "ec2:RevokeSecurityGroupEgress",
109
- # Access & Logging
110
- "cloudtrail:DeleteTrail",
111
- "cloudtrail:StopLogging",
112
- "cloudwatch:DeleteLogGroup",
113
- "config:DeleteConfigurationRecorder",
114
- "guardduty:DeleteDetector",
115
- # Account & Organization
116
- "account:CloseAccount",
117
- "account:CreateAccount",
118
- "account:DeleteAccount",
119
- "organizations:DeleteOrganization",
120
- "organizations:LeaveOrganization",
121
- "organizations:RemoveAccountFromOrganization",
487
+ "s3:PutObjectAcl",
488
+ "s3:PutObjectVersionAcl",
489
+ "secretsmanager:DeleteResourcePolicy",
490
+ "secretsmanager:DeleteSecret",
491
+ "secretsmanager:PutResourcePolicy",
492
+ "secretsmanager:PutSecretValue",
493
+ "secretsmanager:ValidateResourcePolicy",
494
+ "servicecatalog:CreatePortfolioShare",
495
+ "servicecatalog:DeletePortfolioShare",
496
+ "sns:AddPermission",
497
+ "sns:CreateTopic",
498
+ "sns:RemovePermission",
499
+ "sns:SetTopicAttributes",
500
+ "sqs:AddPermission",
501
+ "sqs:CreateQueue",
502
+ "sqs:RemovePermission",
503
+ "sqs:SetQueueAttributes",
504
+ "ssm:DeleteParameter",
505
+ "ssm:ModifyDocumentPermission",
506
+ "ssm:PutParameter",
507
+ "sso-directory:AddMemberToGroup",
508
+ "sso-directory:CreateAlias",
509
+ "sso-directory:CreateGroup",
510
+ "sso-directory:CreateUser",
511
+ "sso-directory:DeleteGroup",
512
+ "sso-directory:DeleteUser",
513
+ "sso-directory:DisableUser",
514
+ "sso-directory:EnableUser",
515
+ "sso-directory:RemoveMemberFromGroup",
516
+ "sso-directory:UpdateGroup",
517
+ "sso-directory:UpdatePassword",
518
+ "sso-directory:UpdateUser",
519
+ "sso-directory:VerifyEmail",
520
+ "sso:AssociateDirectory",
521
+ "sso:AssociateProfile",
522
+ "sso:CreateApplicationInstance",
523
+ "sso:CreateApplicationInstanceCertificate",
524
+ "sso:CreatePermissionSet",
525
+ "sso:CreateProfile",
526
+ "sso:CreateTrust",
527
+ "sso:DeleteApplicationInstance",
528
+ "sso:DeleteApplicationInstanceCertificate",
529
+ "sso:DeletePermissionSet",
530
+ "sso:DeletePermissionsPolicy",
531
+ "sso:DeleteProfile",
532
+ "sso:DisassociateDirectory",
533
+ "sso:DisassociateProfile",
534
+ "sso:ImportApplicationInstanceServiceProviderMetadata",
535
+ "sso:PutPermissionsPolicy",
536
+ "sso:StartSSO",
537
+ "sso:UpdateApplicationInstanceActiveCertificate",
538
+ "sso:UpdateApplicationInstanceDisplayData",
539
+ "sso:UpdateApplicationInstanceResponseConfiguration",
540
+ "sso:UpdateApplicationInstanceResponseSchemaConfiguration",
541
+ "sso:UpdateApplicationInstanceSecurityConfiguration",
542
+ "sso:UpdateApplicationInstanceServiceProviderConfiguration",
543
+ "sso:UpdateApplicationInstanceStatus",
544
+ "sso:UpdateDirectoryAssociation",
545
+ "sso:UpdatePermissionSet",
546
+ "sso:UpdateProfile",
547
+ "sso:UpdateSSOConfiguration",
548
+ "sso:UpdateTrust",
549
+ "storagegateway:DeleteChapCredentials",
550
+ "storagegateway:SetLocalConsolePassword",
551
+ "storagegateway:SetSMBGuestPassword",
552
+ "storagegateway:UpdateChapCredentials",
553
+ "waf-regional:DeletePermissionPolicy",
554
+ "waf-regional:GetChangeToken",
555
+ "waf-regional:PutPermissionPolicy",
556
+ "waf:DeletePermissionPolicy",
557
+ "waf:GetChangeToken",
558
+ "waf:PutPermissionPolicy",
559
+ "wafv2:CreateWebACL",
560
+ "wafv2:DeletePermissionPolicy",
561
+ "wafv2:DeleteWebACL",
562
+ "wafv2:PutPermissionPolicy",
563
+ "wafv2:UpdateWebACL",
564
+ "worklink:UpdateDevicePolicyConfiguration",
565
+ "workmail:ResetPassword",
566
+ "workmail:ResetUserPassword",
567
+ "xray:PutEncryptionConfig",
122
568
  }
123
569
  )
124
570
 
571
+ # ============================================================================
572
+ # Combined Actions Set (for backward compatibility)
573
+ # ============================================================================
574
+
575
+ DEFAULT_SENSITIVE_ACTIONS: Final[frozenset[str]] = (
576
+ CREDENTIAL_EXPOSURE_ACTIONS | DATA_ACCESS_ACTIONS | PRIV_ESC_ACTIONS | RESOURCE_EXPOSURE_ACTIONS
577
+ )
578
+
579
+
580
+ # ============================================================================
581
+ # Category Metadata
582
+ # ============================================================================
583
+
584
+ SENSITIVE_ACTION_CATEGORIES = {
585
+ "credential_exposure": {
586
+ "name": "Credential Exposure",
587
+ "description": "Actions that expose credentials, secrets, API keys, or authentication tokens",
588
+ "actions": CREDENTIAL_EXPOSURE_ACTIONS,
589
+ "severity": "critical",
590
+ },
591
+ "data_access": {
592
+ "name": "Data Access",
593
+ "description": "Actions that retrieve sensitive data from databases, storage, or services",
594
+ "actions": DATA_ACCESS_ACTIONS,
595
+ "severity": "high",
596
+ },
597
+ "priv_esc": {
598
+ "name": "Privilege Escalation",
599
+ "description": "Actions that enable privilege escalation through IAM modifications",
600
+ "actions": PRIV_ESC_ACTIONS,
601
+ "severity": "critical",
602
+ },
603
+ "resource_exposure": {
604
+ "name": "Resource Exposure",
605
+ "description": "Actions that modify resource policies or permissions, potentially exposing resources",
606
+ "actions": RESOURCE_EXPOSURE_ACTIONS,
607
+ "severity": "high",
608
+ },
609
+ }
610
+
125
611
 
126
- def get_sensitive_actions() -> frozenset[str]:
612
+ # ============================================================================
613
+ # Helper Functions
614
+ # ============================================================================
615
+
616
+
617
+ def get_sensitive_actions(
618
+ categories: list[str] | None = None,
619
+ ) -> frozenset[str]:
127
620
  """
128
- Get all sensitive actions.
621
+ Get sensitive actions filtered by category.
622
+
623
+ Args:
624
+ categories: List of category IDs to include. If None, returns all actions.
625
+ Valid categories: 'credential_exposure', 'data_access',
626
+ 'priv_esc', 'resource_exposure'
129
627
 
130
628
  Returns:
131
- Frozenset of all sensitive actions for O(1) membership testing
629
+ Frozenset of sensitive actions matching the specified categories
630
+
631
+ Examples:
632
+ >>> # Get all sensitive actions (default behavior)
633
+ >>> all_actions = get_sensitive_actions()
634
+
635
+ >>> # Get only privilege escalation actions
636
+ >>> priv_esc = get_sensitive_actions(['priv_esc'])
637
+
638
+ >>> # Get credential exposure and data access actions
639
+ >>> sensitive = get_sensitive_actions(['credential_exposure', 'data_access'])
640
+ """
641
+ if categories is None:
642
+ return DEFAULT_SENSITIVE_ACTIONS
643
+
644
+ result_actions: set[str] = set()
645
+ for category in categories:
646
+ if category in SENSITIVE_ACTION_CATEGORIES:
647
+ result_actions.update(SENSITIVE_ACTION_CATEGORIES[category]["actions"])
648
+
649
+ return frozenset(result_actions)
650
+
651
+
652
+ def get_category_for_action(action: str) -> str | None:
653
+ """
654
+ Get the category for a specific action.
655
+
656
+ Args:
657
+ action: The AWS action to look up (e.g., 'iam:PassRole')
658
+
659
+ Returns:
660
+ Category ID if found, None otherwise
661
+
662
+ Examples:
663
+ >>> get_category_for_action('iam:PassRole')
664
+ 'priv_esc'
665
+
666
+ >>> get_category_for_action('s3:GetObject')
667
+ 'data_access'
132
668
  """
133
- return DEFAULT_SENSITIVE_ACTIONS
669
+ for category_id, category_data in SENSITIVE_ACTION_CATEGORIES.items():
670
+ if action in category_data["actions"]:
671
+ return category_id
672
+ return None