iam-policy-validator 1.7.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.
Potentially problematic release.
This version of iam-policy-validator might be problematic. Click here for more details.
- iam_policy_validator-1.7.0.dist-info/METADATA +1057 -0
- iam_policy_validator-1.7.0.dist-info/RECORD +83 -0
- iam_policy_validator-1.7.0.dist-info/WHEEL +4 -0
- iam_policy_validator-1.7.0.dist-info/entry_points.txt +2 -0
- iam_policy_validator-1.7.0.dist-info/licenses/LICENSE +21 -0
- iam_validator/__init__.py +27 -0
- iam_validator/__main__.py +11 -0
- iam_validator/__version__.py +7 -0
- iam_validator/checks/__init__.py +43 -0
- iam_validator/checks/action_condition_enforcement.py +884 -0
- iam_validator/checks/action_resource_matching.py +441 -0
- iam_validator/checks/action_validation.py +72 -0
- iam_validator/checks/condition_key_validation.py +92 -0
- iam_validator/checks/condition_type_mismatch.py +259 -0
- iam_validator/checks/full_wildcard.py +71 -0
- iam_validator/checks/mfa_condition_check.py +112 -0
- iam_validator/checks/policy_size.py +147 -0
- iam_validator/checks/policy_type_validation.py +305 -0
- iam_validator/checks/principal_validation.py +776 -0
- iam_validator/checks/resource_validation.py +138 -0
- iam_validator/checks/sensitive_action.py +254 -0
- iam_validator/checks/service_wildcard.py +107 -0
- iam_validator/checks/set_operator_validation.py +157 -0
- iam_validator/checks/sid_uniqueness.py +170 -0
- iam_validator/checks/utils/__init__.py +1 -0
- iam_validator/checks/utils/policy_level_checks.py +143 -0
- iam_validator/checks/utils/sensitive_action_matcher.py +294 -0
- iam_validator/checks/utils/wildcard_expansion.py +87 -0
- iam_validator/checks/wildcard_action.py +67 -0
- iam_validator/checks/wildcard_resource.py +135 -0
- iam_validator/commands/__init__.py +25 -0
- iam_validator/commands/analyze.py +531 -0
- iam_validator/commands/base.py +48 -0
- iam_validator/commands/cache.py +392 -0
- iam_validator/commands/download_services.py +255 -0
- iam_validator/commands/post_to_pr.py +86 -0
- iam_validator/commands/validate.py +600 -0
- iam_validator/core/__init__.py +14 -0
- iam_validator/core/access_analyzer.py +671 -0
- iam_validator/core/access_analyzer_report.py +640 -0
- iam_validator/core/aws_fetcher.py +940 -0
- iam_validator/core/check_registry.py +607 -0
- iam_validator/core/cli.py +134 -0
- iam_validator/core/condition_validators.py +626 -0
- iam_validator/core/config/__init__.py +81 -0
- iam_validator/core/config/aws_api.py +35 -0
- iam_validator/core/config/aws_global_conditions.py +160 -0
- iam_validator/core/config/category_suggestions.py +104 -0
- iam_validator/core/config/condition_requirements.py +155 -0
- iam_validator/core/config/config_loader.py +472 -0
- iam_validator/core/config/defaults.py +523 -0
- iam_validator/core/config/principal_requirements.py +421 -0
- iam_validator/core/config/sensitive_actions.py +672 -0
- iam_validator/core/config/service_principals.py +95 -0
- iam_validator/core/config/wildcards.py +124 -0
- iam_validator/core/constants.py +74 -0
- iam_validator/core/formatters/__init__.py +27 -0
- iam_validator/core/formatters/base.py +147 -0
- iam_validator/core/formatters/console.py +59 -0
- iam_validator/core/formatters/csv.py +170 -0
- iam_validator/core/formatters/enhanced.py +440 -0
- iam_validator/core/formatters/html.py +672 -0
- iam_validator/core/formatters/json.py +33 -0
- iam_validator/core/formatters/markdown.py +63 -0
- iam_validator/core/formatters/sarif.py +251 -0
- iam_validator/core/models.py +327 -0
- iam_validator/core/policy_checks.py +656 -0
- iam_validator/core/policy_loader.py +396 -0
- iam_validator/core/pr_commenter.py +424 -0
- iam_validator/core/report.py +872 -0
- iam_validator/integrations/__init__.py +28 -0
- iam_validator/integrations/github_integration.py +815 -0
- iam_validator/integrations/ms_teams.py +442 -0
- iam_validator/sdk/__init__.py +187 -0
- iam_validator/sdk/arn_matching.py +382 -0
- iam_validator/sdk/context.py +222 -0
- iam_validator/sdk/exceptions.py +48 -0
- iam_validator/sdk/helpers.py +177 -0
- iam_validator/sdk/policy_utils.py +425 -0
- iam_validator/sdk/shortcuts.py +283 -0
- iam_validator/utils/__init__.py +31 -0
- iam_validator/utils/cache.py +105 -0
- iam_validator/utils/regex.py +206 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""Command-line interface for IAM Policy Validator."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import asyncio
|
|
5
|
+
import logging
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
from iam_validator.__version__ import __version__
|
|
10
|
+
from iam_validator.commands import ALL_COMMANDS
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def setup_logging(log_level: str | None = None, verbose: bool = False) -> None:
|
|
14
|
+
"""Setup logging configuration.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
log_level: Log level from CLI argument (debug, info, warning, error, critical)
|
|
18
|
+
verbose: Enable verbose logging (deprecated, use --log-level debug instead)
|
|
19
|
+
|
|
20
|
+
Environment Variables:
|
|
21
|
+
LOG_LEVEL: Set log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
|
22
|
+
|
|
23
|
+
Priority:
|
|
24
|
+
1. --log-level CLI argument (highest priority)
|
|
25
|
+
2. LOG_LEVEL environment variable
|
|
26
|
+
3. --verbose flag (sets DEBUG level)
|
|
27
|
+
4. Default: WARNING (lowest priority)
|
|
28
|
+
"""
|
|
29
|
+
# Check for LOG_LEVEL environment variable
|
|
30
|
+
env_log_level = os.getenv("LOG_LEVEL", "").upper()
|
|
31
|
+
|
|
32
|
+
# Map string to logging level
|
|
33
|
+
level_map = {
|
|
34
|
+
"DEBUG": logging.DEBUG,
|
|
35
|
+
"INFO": logging.INFO,
|
|
36
|
+
"WARNING": logging.WARNING,
|
|
37
|
+
"ERROR": logging.ERROR,
|
|
38
|
+
"CRITICAL": logging.CRITICAL,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Priority: CLI --log-level > LOG_LEVEL env var > --verbose flag > default (WARNING)
|
|
42
|
+
if log_level:
|
|
43
|
+
level = level_map[log_level.upper()]
|
|
44
|
+
elif env_log_level in level_map:
|
|
45
|
+
level = level_map[env_log_level]
|
|
46
|
+
elif verbose:
|
|
47
|
+
level = logging.DEBUG
|
|
48
|
+
else:
|
|
49
|
+
level = logging.WARNING
|
|
50
|
+
|
|
51
|
+
logging.basicConfig(
|
|
52
|
+
level=level,
|
|
53
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
54
|
+
datefmt="%Y-%m-%d %H:%M:%S",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def main() -> int:
|
|
59
|
+
"""Main entry point for the CLI.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Exit code
|
|
63
|
+
"""
|
|
64
|
+
parser = argparse.ArgumentParser(
|
|
65
|
+
description="Validate AWS IAM policies for correctness and security",
|
|
66
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# Add version argument
|
|
70
|
+
parser.add_argument(
|
|
71
|
+
"--version",
|
|
72
|
+
action="version",
|
|
73
|
+
version=f"iam-validator {__version__}",
|
|
74
|
+
help="Show version information and exit",
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# Add global log level argument
|
|
78
|
+
parser.add_argument(
|
|
79
|
+
"--log-level",
|
|
80
|
+
choices=["debug", "info", "warning", "error", "critical"],
|
|
81
|
+
default=None,
|
|
82
|
+
help="Set logging level (default: warning)",
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
subparsers = parser.add_subparsers(dest="command", help="Command to run")
|
|
86
|
+
|
|
87
|
+
# Register all commands
|
|
88
|
+
command_map = {}
|
|
89
|
+
for command in ALL_COMMANDS:
|
|
90
|
+
cmd_parser = subparsers.add_parser(
|
|
91
|
+
command.name,
|
|
92
|
+
help=command.help,
|
|
93
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
94
|
+
epilog=command.epilog,
|
|
95
|
+
)
|
|
96
|
+
command.add_arguments(cmd_parser)
|
|
97
|
+
command_map[command.name] = command
|
|
98
|
+
|
|
99
|
+
# Parse arguments
|
|
100
|
+
args = parser.parse_args()
|
|
101
|
+
|
|
102
|
+
if not args.command:
|
|
103
|
+
parser.print_help()
|
|
104
|
+
return 1
|
|
105
|
+
|
|
106
|
+
# Setup logging
|
|
107
|
+
log_level = getattr(args, "log_level", None)
|
|
108
|
+
verbose = getattr(args, "verbose", False)
|
|
109
|
+
setup_logging(log_level, verbose)
|
|
110
|
+
|
|
111
|
+
# Execute command
|
|
112
|
+
try:
|
|
113
|
+
command = command_map[args.command]
|
|
114
|
+
exit_code = asyncio.run(command.execute(args))
|
|
115
|
+
return exit_code
|
|
116
|
+
except KeyboardInterrupt:
|
|
117
|
+
logging.warning("Interrupted by user")
|
|
118
|
+
return 130 # Standard exit code for SIGINT
|
|
119
|
+
except asyncio.CancelledError:
|
|
120
|
+
logging.warning("Operation cancelled")
|
|
121
|
+
return 130
|
|
122
|
+
except FileNotFoundError as e:
|
|
123
|
+
logging.error(f"File not found: {e}")
|
|
124
|
+
return 1
|
|
125
|
+
except PermissionError as e:
|
|
126
|
+
logging.error(f"Permission denied: {e}")
|
|
127
|
+
return 1
|
|
128
|
+
except Exception as e:
|
|
129
|
+
logging.error(f"Unexpected error: {e}", exc_info=True)
|
|
130
|
+
return 1
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
if __name__ == "__main__":
|
|
134
|
+
sys.exit(main())
|