iam-policy-validator 1.11.0__py3-none-any.whl → 1.12.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iam-policy-validator
3
- Version: 1.11.0
3
+ Version: 1.12.0
4
4
  Summary: Validate AWS IAM policies for correctness and security using AWS Service Reference API
5
5
  Project-URL: Homepage, https://github.com/boogy/iam-policy-validator
6
6
  Project-URL: Documentation, https://github.com/boogy/iam-policy-validator/tree/main/docs
@@ -1,8 +1,8 @@
1
1
  iam_validator/__init__.py,sha256=xHdUASOxFHwEXfT_GSr_KrkLlnxZ-pAAr1wW1PwAGko,693
2
2
  iam_validator/__main__.py,sha256=to_nz3n_IerJpVVZZ6WSFlFR5s_06J0csfPOTfQZG8g,197
3
- iam_validator/__version__.py,sha256=QDfo5_PdJfgisRdaZ8ltIgqPu_z6ugxj636N7IepezA,374
3
+ iam_validator/__version__.py,sha256=W6lxpjiojokhUhDmTpeymt8Z-W7jmcwUbVTvLyrpAko,374
4
4
  iam_validator/checks/__init__.py,sha256=OTkPnmlelu4YjMO8krjhu2wXiTV72RzopA5u1SfPQA0,1990
5
- iam_validator/checks/action_condition_enforcement.py,sha256=6LJfO7DCgf10rtPjaZ5P4fmb5hfxJUBS5w1CrOiCu5Q,52442
5
+ iam_validator/checks/action_condition_enforcement.py,sha256=oj3hsh3LwPneYAsQ6iBd61ToIJMr6aDIixKP-zkaqKI,55053
6
6
  iam_validator/checks/action_resource_matching.py,sha256=WiGJmCIJfx5yituMjZxpKmk-99N6nK20ueN02ddy9oM,19296
7
7
  iam_validator/checks/action_validation.py,sha256=QXfNamcstQIO41zNed1-bCmXYkXdV77owu8G2cZ09-A,2517
8
8
  iam_validator/checks/condition_key_validation.py,sha256=QJjG82wxvjdG2m-YuEzAjKRRiWaaPkf_LChdUTvm9g4,3919
@@ -29,7 +29,7 @@ iam_validator/commands/__init__.py,sha256=RBEz-Kgt3aRVn_9B1HRy_XgQMIKzlSSQs4Gtg2
29
29
  iam_validator/commands/analyze.py,sha256=rvLBJ5_A3HB530xtixhaIsC19QON68olEQnn8TievgI,20784
30
30
  iam_validator/commands/base.py,sha256=5baCCMwxz7pdQ6XMpWfXFNz7i1l5dB8Qv9dKKR04Gzs,1074
31
31
  iam_validator/commands/cache.py,sha256=llfyQzPE5Azd5YcW0ohYcYjF_OCyiQ1GoJQ982t71lQ,14294
32
- iam_validator/commands/completion.py,sha256=oPUZkY0U3x-DU3bNB0UmdpXxxKibTBB8_TDPcQLWc10,15175
32
+ iam_validator/commands/completion.py,sha256=1TfkVjeltsf2jAZy5RqaxKVIxpbL_bnZc6k8uvrk6Xg,18915
33
33
  iam_validator/commands/download_services.py,sha256=KKz3ybMLT8DQUf9aFZ0tilJ-o1b6PE8Pf1pC4K6cT8I,9175
34
34
  iam_validator/commands/post_to_pr.py,sha256=CvUXs2xvO-UhluxdfNM6F0TCWD8hDBEOiYw60fm1Dms,2363
35
35
  iam_validator/commands/query.py,sha256=ft8ptWfsNUK4Wprq_A11txdV_chBgqkoAo7SQfzEwK0,17079
@@ -93,8 +93,8 @@ iam_validator/utils/__init__.py,sha256=NveA2F3G1E6-ANZzFr7J6Q6u5mogvMp862iFokmYu
93
93
  iam_validator/utils/cache.py,sha256=wOQKOBeoG6QqC5f0oXcHz63Cjtu_-SsSS-0pTSwyAiM,3254
94
94
  iam_validator/utils/regex.py,sha256=xHoMECttb7qaMhts-c9b0GIxdhHNZTt-UBr7wNhWfzg,6219
95
95
  iam_validator/utils/terminal.py,sha256=FsRaRMH_JAyDgXWBCOgOEhbS89cs17HCmKYoughq5io,724
96
- iam_policy_validator-1.11.0.dist-info/METADATA,sha256=OL4Pb02Cgtv4XL1AXoupb1KYc5fUMXUNfiqquaFyn24,34456
97
- iam_policy_validator-1.11.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
98
- iam_policy_validator-1.11.0.dist-info/entry_points.txt,sha256=8HtWd8O7mvPiPdZR5YbzY8or_qcqLM4-pKaFdhtFT8M,62
99
- iam_policy_validator-1.11.0.dist-info/licenses/LICENSE,sha256=AMnbFTBDcK4_MITe2wiQBkj0vg-jjBBhsc43ydC7tt4,1098
100
- iam_policy_validator-1.11.0.dist-info/RECORD,,
96
+ iam_policy_validator-1.12.0.dist-info/METADATA,sha256=oRx7SWFfzvm7WejCfUXLfGDYYAe-lnIBf74cfwigqT8,34456
97
+ iam_policy_validator-1.12.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
98
+ iam_policy_validator-1.12.0.dist-info/entry_points.txt,sha256=8HtWd8O7mvPiPdZR5YbzY8or_qcqLM4-pKaFdhtFT8M,62
99
+ iam_policy_validator-1.12.0.dist-info/licenses/LICENSE,sha256=AMnbFTBDcK4_MITe2wiQBkj0vg-jjBBhsc43ydC7tt4,1098
100
+ iam_policy_validator-1.12.0.dist-info/RECORD,,
@@ -3,7 +3,7 @@
3
3
  This file is the single source of truth for the package version.
4
4
  """
5
5
 
6
- __version__ = "1.11.0"
6
+ __version__ = "1.12.0"
7
7
  # Parse version, handling pre-release suffixes like -rc, -alpha, -beta
8
8
  _version_base = __version__.split("-", maxsplit=1)[0] # Remove pre-release suffix if present
9
9
  __version_info__ = tuple(int(part) for part in _version_base.split("."))
@@ -125,6 +125,22 @@ Configuration in iam-validator.yaml:
125
125
  - "iam:DeleteUser"
126
126
  - "s3:DeleteBucket"
127
127
  description: "These dangerous actions should never be used"
128
+
129
+ # Per-requirement ignore_patterns: Skip specific requirements for certain files/actions
130
+ - actions:
131
+ - "iam:CreateRole"
132
+ - "iam:PutRolePolicy"
133
+ - "iam:AttachRolePolicy"
134
+ required_conditions:
135
+ - condition_key: "iam:PermissionsBoundary"
136
+ description: "Require permissions boundary for IAM operations"
137
+ ignore_patterns:
138
+ # Ignore this requirement for iam-openid modules (they enforce boundary by default)
139
+ - filepath_regex: ".*modules//?iam-openid.*"
140
+
141
+ Note: ignore_patterns can be specified at TWO levels:
142
+ 1. Check-level (applies to ALL requirements): Useful for broad exclusions
143
+ 2. Requirement-level (applies to ONE requirement): Useful for fine-grained control
128
144
  """
129
145
 
130
146
  import re
@@ -132,6 +148,7 @@ from typing import TYPE_CHECKING, Any, ClassVar
132
148
 
133
149
  from iam_validator.core.aws_service import AWSServiceFetcher
134
150
  from iam_validator.core.check_registry import CheckConfig, PolicyCheck
151
+ from iam_validator.core.ignore_patterns import IgnorePatternMatcher
135
152
  from iam_validator.core.models import Statement, ValidationIssue
136
153
  from iam_validator.utils.regex import compile_and_cache
137
154
 
@@ -181,7 +198,7 @@ class ActionConditionEnforcementCheck(PolicyCheck):
181
198
  Returns:
182
199
  List of ValidationIssue objects found by this check
183
200
  """
184
- del policy_file, kwargs # Not used in current implementation
201
+ del kwargs # Not used in current implementation
185
202
  issues = []
186
203
 
187
204
  # Get action condition requirements from config
@@ -211,16 +228,60 @@ class ActionConditionEnforcementCheck(PolicyCheck):
211
228
  if uses_logical_operators:
212
229
  # Policy-wide detection (all_of/any_of/none_of)
213
230
  policy_issues = await self._check_policy_wide(policy, requirement, fetcher, config)
231
+ # Filter by requirement-level ignore_patterns
232
+ policy_issues = self._filter_requirement_issues(
233
+ policy_issues, requirement.get("ignore_patterns", []), policy_file
234
+ )
214
235
  issues.extend(policy_issues)
215
236
  else:
216
237
  # Per-statement check (simple list)
217
238
  statement_issues = await self._check_per_statement(
218
239
  policy, requirement, fetcher, config
219
240
  )
241
+ # Filter by requirement-level ignore_patterns
242
+ statement_issues = self._filter_requirement_issues(
243
+ statement_issues, requirement.get("ignore_patterns", []), policy_file
244
+ )
220
245
  issues.extend(statement_issues)
221
246
 
222
247
  return issues
223
248
 
249
+ def _filter_requirement_issues(
250
+ self,
251
+ issues: list[ValidationIssue],
252
+ ignore_patterns: list[dict[str, Any]],
253
+ filepath: str,
254
+ ) -> list[ValidationIssue]:
255
+ """
256
+ Filter issues based on requirement-level ignore patterns.
257
+
258
+ This allows each requirement within action_condition_enforcement to have its own
259
+ ignore patterns, enabling fine-grained control over which findings to suppress.
260
+
261
+ Args:
262
+ issues: List of validation issues to filter
263
+ ignore_patterns: List of ignore pattern dictionaries for this requirement
264
+ filepath: Path to the policy file being checked
265
+
266
+ Returns:
267
+ Filtered list of issues (issues matching ignore patterns are removed)
268
+
269
+ Example:
270
+ A requirement can ignore specific files while other requirements check them:
271
+ - actions: ["iam:CreateRole"]
272
+ required_conditions: [...]
273
+ ignore_patterns:
274
+ - filepath_regex: ".*modules/iam-openid.*"
275
+ """
276
+ if not ignore_patterns:
277
+ return issues
278
+
279
+ return [
280
+ issue
281
+ for issue in issues
282
+ if not IgnorePatternMatcher.should_ignore_issue(issue, filepath, ignore_patterns)
283
+ ]
284
+
224
285
  async def _check_policy_wide(
225
286
  self,
226
287
  policy: "IAMPolicy",
@@ -135,7 +135,7 @@ _iam_validator_completion() {{
135
135
  prev="${{COMP_WORDS[COMP_CWORD-1]}}"
136
136
 
137
137
  # Main commands
138
- local commands="validate post-to-pr analyze cache download-services query completion"
138
+ local commands="validate post-to-pr analyze cache sync-services query completion"
139
139
 
140
140
  # Get the command (first non-option argument)
141
141
  local cmd=""
@@ -215,6 +215,7 @@ _iam_validator_completion() {{
215
215
  fi
216
216
 
217
217
  # Complete options for query subcommands
218
+ local opts=""
218
219
  case "$query_subcmd" in
219
220
  action)
220
221
  opts="--service --name --access-level --resource-type --condition --output"
@@ -226,7 +227,23 @@ _iam_validator_completion() {{
226
227
  opts="--service --name --output"
227
228
  ;;
228
229
  esac
229
- COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
230
+
231
+ # Filter out already used options
232
+ local used_opts=""
233
+ for ((i=2; i<COMP_CWORD; i++)); do
234
+ if [[ ${{COMP_WORDS[i]}} == --* ]]; then
235
+ used_opts="$used_opts ${{COMP_WORDS[i]}}"
236
+ fi
237
+ done
238
+
239
+ local available_opts=""
240
+ for opt in $opts; do
241
+ if [[ ! " $used_opts " =~ " $opt " ]]; then
242
+ available_opts="$available_opts $opt"
243
+ fi
244
+ done
245
+
246
+ COMPREPLY=( $(compgen -W "$available_opts" -- "$cur") )
230
247
  return 0
231
248
  ;;
232
249
  validate)
@@ -234,18 +251,36 @@ _iam_validator_completion() {{
234
251
  COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
235
252
  return 0
236
253
  ;;
254
+ post-to-pr)
255
+ opts="--report -r --create-review --no-review --add-summary --no-summary --config -c"
256
+ COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
257
+ return 0
258
+ ;;
237
259
  analyze)
238
- opts="--policy --format --output"
260
+ opts="--path -p --policy-type -t --region --profile --format -f --output -o --no-recursive --fail-on-warnings --github-comment --github-review --github-summary --run-all-checks --check-access-not-granted --check-access-resources --check-no-new-access --check-no-public-access --public-access-resource-type --verbose -v"
239
261
  COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
240
262
  return 0
241
263
  ;;
242
264
  cache)
243
- opts="--clear --info"
244
- COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
265
+ # Check if we need to complete the cache subcommand
266
+ local cache_subcmd=""
267
+ for ((i=2; i<COMP_CWORD; i++)); do
268
+ if [[ ${{COMP_WORDS[i]}} =~ ^(info|list|clear|refresh|prefetch|location)$ ]]; then
269
+ cache_subcmd=${{COMP_WORDS[i]}}
270
+ break
271
+ fi
272
+ done
273
+
274
+ if [[ -z "$cache_subcmd" ]]; then
275
+ # Complete cache subcommand
276
+ COMPREPLY=( $(compgen -W "info list clear refresh prefetch location" -- "$cur") )
277
+ return 0
278
+ fi
279
+ # Cache subcommands have no additional options
245
280
  return 0
246
281
  ;;
247
- download-services)
248
- opts="--output-dir --force"
282
+ sync-services)
283
+ opts="--output-dir --max-concurrent"
249
284
  COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
250
285
  return 0
251
286
  ;;
@@ -272,72 +307,34 @@ complete -F _iam_validator_completion iam-validator
272
307
  # Generated by: iam-validator completion zsh
273
308
 
274
309
  _iam_validator() {{
275
- local -a commands
276
- commands=(
277
- 'validate:Validate IAM policies'
278
- 'post-to-pr:Post validation results to GitHub PR'
279
- 'analyze:Analyze IAM policies'
280
- 'cache:Manage cache'
281
- 'download-services:Download AWS service definitions'
282
- 'query:Query AWS service definitions'
283
- 'completion:Generate shell completion scripts'
284
- )
285
-
286
- local -a query_subcommands
287
- query_subcommands=(
288
- 'action:Query IAM actions'
289
- 'arn:Query ARN formats'
290
- 'condition:Query condition keys'
291
- )
292
-
293
- local -a access_levels
294
- access_levels=(
295
- 'read:Read-only actions'
296
- 'write:Write actions'
297
- 'list:List actions'
298
- 'tagging:Tagging actions'
299
- 'permissions-management:Permission management actions'
300
- )
301
-
302
- local -a formats
303
- formats=(
304
- 'json:JSON output'
305
- 'yaml:YAML output'
306
- 'text:Plain text output'
307
- )
308
-
309
- local -a shells
310
- shells=(
311
- 'bash:Bash completion'
312
- 'zsh:Zsh completion'
313
- )
310
+ local curcontext="$curcontext" state line
311
+ typeset -A opt_args
314
312
 
315
313
  # Cached AWS services
316
314
  local -a aws_services
317
315
  aws_services=({services_list})
318
316
 
319
317
  _arguments -C \\
320
- '1: :->command' \\
321
- '*:: :->args'
318
+ '1: :_iam_validator_commands' \\
319
+ '*::arg:->args'
322
320
 
323
321
  case $state in
324
- command)
325
- _describe 'command' commands
326
- ;;
327
322
  args)
328
323
  case $words[1] in
329
324
  query)
330
- case $CURRENT in
331
- 2)
332
- _describe 'query subcommand' query_subcommands
333
- ;;
334
- *)
335
- case $words[2] in
325
+ local query_state
326
+ _arguments -C \\
327
+ '1: :_iam_validator_query_subcommands' \\
328
+ '*::arg:->query_args' && return 0
329
+
330
+ case $state in
331
+ query_args)
332
+ case $words[1] in
336
333
  action)
337
334
  _arguments \\
338
335
  '--service[AWS service name]:service:($aws_services)' \\
339
336
  '--name[Action name]:action name:' \\
340
- '--access-level[Filter by access level]:access level:($access_levels)' \\
337
+ '--access-level[Filter by access level]:access level:(read write list tagging permissions-management)' \\
341
338
  '--resource-type[Filter by resource type]:resource type:' \\
342
339
  '--condition[Filter by condition key]:condition key:' \\
343
340
  '--output[Output format]:format:(json yaml text)'
@@ -361,7 +358,8 @@ _iam_validator() {{
361
358
  ;;
362
359
  validate)
363
360
  _arguments \\
364
- '(--path -p)'{{--path,-p}}'[Path to policy file or directory]:file:_files' \\
361
+ '*--path[Path to policy file or directory]:file:_files' \\
362
+ '*-p[Path to policy file or directory]:file:_files' \\
365
363
  '--stdin[Read policy from stdin]' \\
366
364
  '(--format -f)'{{--format,-f}}'[Output format]:format:(console enhanced json markdown html csv sarif)' \\
367
365
  '(--output -o)'{{--output,-o}}'[Output file path]:file:_files' \\
@@ -380,30 +378,79 @@ _iam_validator() {{
380
378
  '--summary[Show Executive Summary section]' \\
381
379
  '--severity-breakdown[Show Issue Severity Breakdown section]'
382
380
  ;;
381
+ post-to-pr)
382
+ _arguments \\
383
+ '(--report -r)'{{--report,-r}}'[Path to JSON report file]:file:_files' \\
384
+ '--create-review[Create line-specific review comments]' \\
385
+ '--no-review[Do not create line-specific review comments]' \\
386
+ '--add-summary[Add summary comment]' \\
387
+ '--no-summary[Do not add summary comment]' \\
388
+ '(--config -c)'{{--config,-c}}'[Configuration file]:file:_files'
389
+ ;;
383
390
  analyze)
384
391
  _arguments \\
385
- '--policy[Policy file]:file:_files' \\
386
- '--format[Output format]:format:($formats)' \\
387
- '--output[Output file]:file:_files'
392
+ '*--path[Path to policy file or directory]:file:_files' \\
393
+ '*-p[Path to policy file or directory]:file:_files' \\
394
+ '(--policy-type -t)'{{--policy-type,-t}}'[Type of IAM policy]:policy type:(IDENTITY_POLICY RESOURCE_POLICY SERVICE_CONTROL_POLICY)' \\
395
+ '--region[AWS region]:region:' \\
396
+ '--profile[AWS profile]:profile:' \\
397
+ '(--format -f)'{{--format,-f}}'[Output format]:format:(console json markdown)' \\
398
+ '(--output -o)'{{--output,-o}}'[Output file path]:file:_files' \\
399
+ '--no-recursive[Do not recursively search directories]' \\
400
+ '--fail-on-warnings[Fail validation if warnings are found]' \\
401
+ '--github-comment[Post validation results as GitHub PR comment]' \\
402
+ '--github-review[Create line-specific review comments on PR]' \\
403
+ '--github-summary[Write validation summary to GitHub Actions job summary]' \\
404
+ '--run-all-checks[Run full validation checks if Access Analyzer passes]' \\
405
+ '*--check-access-not-granted[Actions to check are NOT granted]:action:' \\
406
+ '*--check-access-resources[Resources to check]:resource:' \\
407
+ '--check-no-new-access[Path to existing policy]:file:_files' \\
408
+ '--check-no-public-access[Check that resource policy does not allow public access]' \\
409
+ '*--public-access-resource-type[Resource type for public access check]:resource type:' \\
410
+ '(--verbose -v)'{{--verbose,-v}}'[Enable verbose logging]'
388
411
  ;;
389
412
  cache)
390
413
  _arguments \\
391
- '--clear[Clear cache]' \\
392
- '--info[Show cache info]'
414
+ '1: :(info list clear refresh prefetch location)'
393
415
  ;;
394
- download-services)
416
+ sync-services)
395
417
  _arguments \\
396
418
  '--output-dir[Output directory]:directory:_directories' \\
397
- '--force[Force re-download]'
419
+ '--max-concurrent[Maximum concurrent downloads]:number:'
398
420
  ;;
399
421
  completion)
400
- _describe 'shell' shells
422
+ _arguments \\
423
+ '1: :(bash zsh)'
401
424
  ;;
402
425
  esac
403
426
  ;;
404
427
  esac
405
428
  }}
406
429
 
430
+ _iam_validator_commands() {{
431
+ local -a commands
432
+ commands=(
433
+ 'validate:Validate IAM policies'
434
+ 'post-to-pr:Post validation results to GitHub PR'
435
+ 'analyze:Analyze IAM policies using AWS IAM Access Analyzer'
436
+ 'cache:Manage AWS service definition cache'
437
+ 'sync-services:Sync/download all AWS service definitions for offline use'
438
+ 'query:Query AWS service definitions (actions, ARNs, condition keys)'
439
+ 'completion:Generate shell completion scripts (bash or zsh)'
440
+ )
441
+ _describe 'command' commands
442
+ }}
443
+
444
+ _iam_validator_query_subcommands() {{
445
+ local -a subcommands
446
+ subcommands=(
447
+ 'action:Query IAM actions'
448
+ 'arn:Query ARN formats'
449
+ 'condition:Query condition keys'
450
+ )
451
+ _describe 'query subcommand' subcommands
452
+ }}
453
+
407
454
  _iam_validator "$@"
408
455
  """
409
456