iam-policy-validator 1.14.6__py3-none-any.whl → 1.15.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 (43) hide show
  1. {iam_policy_validator-1.14.6.dist-info → iam_policy_validator-1.15.0.dist-info}/METADATA +34 -23
  2. {iam_policy_validator-1.14.6.dist-info → iam_policy_validator-1.15.0.dist-info}/RECORD +42 -29
  3. iam_policy_validator-1.15.0.dist-info/entry_points.txt +4 -0
  4. iam_validator/__version__.py +1 -1
  5. iam_validator/checks/__init__.py +2 -0
  6. iam_validator/checks/action_validation.py +91 -27
  7. iam_validator/checks/not_action_not_resource.py +163 -0
  8. iam_validator/checks/resource_validation.py +132 -81
  9. iam_validator/checks/wildcard_resource.py +136 -6
  10. iam_validator/commands/__init__.py +3 -0
  11. iam_validator/commands/cache.py +66 -24
  12. iam_validator/commands/completion.py +94 -15
  13. iam_validator/commands/mcp.py +210 -0
  14. iam_validator/commands/query.py +489 -65
  15. iam_validator/core/aws_service/__init__.py +5 -1
  16. iam_validator/core/aws_service/cache.py +20 -0
  17. iam_validator/core/aws_service/fetcher.py +180 -11
  18. iam_validator/core/aws_service/storage.py +14 -6
  19. iam_validator/core/aws_service/validators.py +32 -41
  20. iam_validator/core/check_registry.py +100 -35
  21. iam_validator/core/config/aws_global_conditions.py +13 -0
  22. iam_validator/core/config/check_documentation.py +104 -51
  23. iam_validator/core/config/config_loader.py +39 -3
  24. iam_validator/core/config/defaults.py +6 -0
  25. iam_validator/core/constants.py +11 -4
  26. iam_validator/core/models.py +39 -14
  27. iam_validator/mcp/__init__.py +162 -0
  28. iam_validator/mcp/models.py +118 -0
  29. iam_validator/mcp/server.py +2928 -0
  30. iam_validator/mcp/session_config.py +319 -0
  31. iam_validator/mcp/templates/__init__.py +79 -0
  32. iam_validator/mcp/templates/builtin.py +856 -0
  33. iam_validator/mcp/tools/__init__.py +72 -0
  34. iam_validator/mcp/tools/generation.py +888 -0
  35. iam_validator/mcp/tools/org_config_tools.py +263 -0
  36. iam_validator/mcp/tools/query.py +395 -0
  37. iam_validator/mcp/tools/validation.py +376 -0
  38. iam_validator/sdk/__init__.py +64 -63
  39. iam_validator/sdk/context.py +3 -2
  40. iam_validator/sdk/policy_utils.py +31 -5
  41. iam_policy_validator-1.14.6.dist-info/entry_points.txt +0 -2
  42. {iam_policy_validator-1.14.6.dist-info → iam_policy_validator-1.15.0.dist-info}/WHEEL +0 -0
  43. {iam_policy_validator-1.14.6.dist-info → iam_policy_validator-1.15.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,162 @@
1
+ """IAM Policy Validator MCP Server.
2
+
3
+ This module provides an MCP (Model Context Protocol) server for AI assistants
4
+ to interact with the IAM Policy Validator. It exposes tools for:
5
+ - Validating IAM policies
6
+ - Generating policies from templates or descriptions
7
+ - Querying AWS service definitions
8
+ - Managing session-wide policy configurations
9
+
10
+ The server uses FastMCP and provides a security-first approach to policy generation.
11
+
12
+ Configuration:
13
+ The MCP server uses the same configuration format as the CLI validator.
14
+ You can load configuration from a YAML file using --config or set it
15
+ programmatically using SessionConfigManager.
16
+ """
17
+
18
+ from typing import TYPE_CHECKING
19
+
20
+ from iam_validator.mcp.models import (
21
+ ActionDetails,
22
+ GenerationResult,
23
+ PolicySummary,
24
+ ValidationResult,
25
+ )
26
+ from iam_validator.mcp.session_config import (
27
+ CustomInstructionsManager,
28
+ SessionConfigManager,
29
+ merge_conditions,
30
+ )
31
+
32
+ if TYPE_CHECKING:
33
+ from fastmcp import FastMCP
34
+
35
+
36
+ def create_server() -> "FastMCP":
37
+ """Create and configure the MCP server.
38
+
39
+ Returns:
40
+ FastMCP: Configured MCP server instance
41
+
42
+ Raises:
43
+ ImportError: If fastmcp is not installed
44
+ """
45
+ try:
46
+ from iam_validator.mcp.server import create_server as _create_server
47
+
48
+ return _create_server()
49
+ except ImportError as e:
50
+ raise ImportError(
51
+ "fastmcp is required for MCP server. Install with: uv sync --extra mcp"
52
+ ) from e
53
+
54
+
55
+ def run_server() -> None:
56
+ """Run the MCP server.
57
+
58
+ This is the entry point for the iam-validator-mcp command.
59
+ Supports configuration and custom instructions at startup.
60
+
61
+ Usage:
62
+ iam-validator-mcp
63
+ iam-validator-mcp --config /path/to/config.yaml
64
+ iam-validator-mcp --instructions "Always require MFA for sensitive actions"
65
+ iam-validator-mcp --instructions-file /path/to/instructions.md
66
+
67
+ Custom instructions can also be set via:
68
+ - Environment variable: IAM_VALIDATOR_MCP_INSTRUCTIONS
69
+ - Config file: custom_instructions key in YAML config
70
+
71
+ Raises:
72
+ ImportError: If fastmcp is not installed
73
+ """
74
+ import argparse
75
+ import sys
76
+ from pathlib import Path
77
+
78
+ parser = argparse.ArgumentParser(
79
+ prog="iam-validator-mcp",
80
+ description="IAM Policy Validator MCP Server for AI assistants",
81
+ )
82
+ parser.add_argument(
83
+ "--config",
84
+ type=str,
85
+ metavar="FILE",
86
+ help="Path to configuration YAML file to load at startup",
87
+ )
88
+ parser.add_argument(
89
+ "--instructions",
90
+ type=str,
91
+ metavar="TEXT",
92
+ help="Custom instructions to append to default LLM instructions",
93
+ )
94
+ parser.add_argument(
95
+ "--instructions-file",
96
+ type=str,
97
+ metavar="FILE",
98
+ help="Path to file containing custom instructions (markdown, txt)",
99
+ )
100
+ args = parser.parse_args()
101
+
102
+ # Load config if provided (may include custom_instructions)
103
+ if args.config:
104
+ config_path = Path(args.config)
105
+ if not config_path.exists():
106
+ print(f"Error: Config file not found: {args.config}", file=sys.stderr)
107
+ sys.exit(1)
108
+
109
+ try:
110
+ config, warnings = SessionConfigManager.load_from_file(str(config_path))
111
+
112
+ for warning in warnings:
113
+ print(f"Warning: {warning}", file=sys.stderr)
114
+
115
+ print(f"Loaded config from: {args.config}", file=sys.stderr)
116
+
117
+ except Exception as e:
118
+ print(f"Error loading config: {e}", file=sys.stderr)
119
+ sys.exit(1)
120
+
121
+ # Load custom instructions from CLI arguments (overrides config/env)
122
+ if args.instructions_file:
123
+ instructions_path = Path(args.instructions_file)
124
+ if not instructions_path.exists():
125
+ print(
126
+ f"Error: Instructions file not found: {args.instructions_file}",
127
+ file=sys.stderr,
128
+ )
129
+ sys.exit(1)
130
+
131
+ try:
132
+ CustomInstructionsManager.load_from_file(str(instructions_path))
133
+ print(f"Loaded instructions from: {args.instructions_file}", file=sys.stderr)
134
+ except Exception as e:
135
+ print(f"Error loading instructions: {e}", file=sys.stderr)
136
+ sys.exit(1)
137
+
138
+ elif args.instructions:
139
+ CustomInstructionsManager.set_instructions(args.instructions, source="cli")
140
+ print("Custom instructions set from CLI argument", file=sys.stderr)
141
+
142
+ try:
143
+ from iam_validator.mcp.server import run_server as _run_server
144
+
145
+ _run_server()
146
+ except ImportError as e:
147
+ raise ImportError(
148
+ "fastmcp is required for MCP server. Install with: uv sync --extra mcp"
149
+ ) from e
150
+
151
+
152
+ __all__ = [
153
+ "create_server",
154
+ "run_server",
155
+ "ValidationResult",
156
+ "GenerationResult",
157
+ "PolicySummary",
158
+ "ActionDetails",
159
+ "SessionConfigManager",
160
+ "CustomInstructionsManager",
161
+ "merge_conditions",
162
+ ]
@@ -0,0 +1,118 @@
1
+ """Pydantic models for MCP tool request/response types.
2
+
3
+ This module defines MCP-specific models that extend the core validation models
4
+ for use with the FastMCP server implementation.
5
+ """
6
+
7
+ from typing import Any
8
+
9
+ from pydantic import BaseModel, Field
10
+
11
+ from iam_validator.core.models import ValidationIssue
12
+
13
+
14
+ class ValidationResult(BaseModel):
15
+ """Result of policy validation.
16
+
17
+ Used by validation tools to return validation status and issues found.
18
+ """
19
+
20
+ is_valid: bool = Field(
21
+ description="Whether the policy passed validation (no errors or warnings)"
22
+ )
23
+ issues: list[ValidationIssue] = Field(
24
+ default_factory=list, description="List of validation issues found"
25
+ )
26
+ policy_file: str | None = Field(
27
+ default=None, description="Path to the policy file that was validated"
28
+ )
29
+ policy_type_detected: str | None = Field(
30
+ default=None,
31
+ description="The policy type used for validation: 'identity', 'resource', or 'trust'. "
32
+ "Shows auto-detected type when policy_type was not explicitly provided.",
33
+ )
34
+
35
+
36
+ class GenerationResult(BaseModel):
37
+ """Result of policy generation.
38
+
39
+ Returned by all policy generation tools (from description, template, or actions).
40
+ Always includes validation results and security notes.
41
+ """
42
+
43
+ policy: dict[str, Any] = Field(description="The generated IAM policy document")
44
+ validation: ValidationResult = Field(description="Validation results for the generated policy")
45
+ security_notes: list[str] = Field(
46
+ default_factory=list,
47
+ description="Security warnings and auto-applied conditions (e.g., 'Auto-added MFA condition')",
48
+ )
49
+ template_used: str | None = Field(
50
+ default=None, description="Name of the template used for generation (if applicable)"
51
+ )
52
+
53
+
54
+ class PolicySummary(BaseModel):
55
+ """Summary of a policy's structure and contents.
56
+
57
+ Provides high-level statistics about a policy for quick analysis.
58
+ """
59
+
60
+ total_statements: int = Field(description="Total number of statements in the policy")
61
+ allow_statements: int = Field(description="Number of statements with Effect: Allow")
62
+ deny_statements: int = Field(description="Number of statements with Effect: Deny")
63
+ services_used: list[str] = Field(
64
+ default_factory=list, description="List of AWS services referenced (e.g., ['s3', 'ec2'])"
65
+ )
66
+ actions_count: int = Field(description="Total number of unique actions across all statements")
67
+ has_wildcards: bool = Field(
68
+ description="Whether the policy contains wildcard actions or resources"
69
+ )
70
+ has_conditions: bool = Field(description="Whether the policy contains any conditions")
71
+
72
+
73
+ class ActionDetails(BaseModel):
74
+ """Details about an AWS action.
75
+
76
+ Returned by query tools to provide comprehensive information about an IAM action.
77
+ """
78
+
79
+ action: str = Field(description="Full action name (e.g., 's3:GetObject')")
80
+ service: str = Field(description="AWS service prefix (e.g., 's3', 'ec2')")
81
+ access_level: str = Field(
82
+ description="Access level category: Read, Write, List, Tagging, or Permissions management"
83
+ )
84
+ resource_types: list[str] = Field(
85
+ default_factory=list,
86
+ description="Resource types this action can be applied to (e.g., ['bucket', 'object'])",
87
+ )
88
+ condition_keys: list[str] = Field(
89
+ default_factory=list,
90
+ description="Condition keys that can be used with this action",
91
+ )
92
+ description: str | None = Field(
93
+ default=None, description="Human-readable description of what the action does"
94
+ )
95
+
96
+
97
+ class EnforcementResult(BaseModel):
98
+ """Result of security enforcement on a policy.
99
+
100
+ Returned by the security enforcement layer after applying required conditions
101
+ and validating security constraints.
102
+ """
103
+
104
+ policy: dict[str, Any] = Field(
105
+ description="The policy after security enforcement (with auto-added conditions)"
106
+ )
107
+ warnings: list[str] = Field(
108
+ default_factory=list,
109
+ description="Security warnings for issues that were auto-fixed (e.g., 'Added MFA condition')",
110
+ )
111
+ errors: list[str] = Field(
112
+ default_factory=list,
113
+ description="Security errors that could not be auto-fixed (generation should fail)",
114
+ )
115
+ conditions_added: list[str] = Field(
116
+ default_factory=list,
117
+ description="List of conditions that were automatically added (e.g., 'aws:MultiFactorAuthPresent')",
118
+ )