mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-19 01:44:16 +00:00
85 lines
2.7 KiB
Python
85 lines
2.7 KiB
Python
import json
|
|
from typing import Any, Dict, List, Tuple
|
|
|
|
from prowler.lib.logger import logger
|
|
from lib.models import ResourceEdge, ResourceNode
|
|
|
|
|
|
def _parse_trust_principals(assume_role_policy: Any) -> List[str]:
|
|
"""
|
|
Return a flat list of principal strings from an IAM assume-role policy document.
|
|
The policy may be a dict already or a JSON string.
|
|
"""
|
|
if not assume_role_policy:
|
|
return []
|
|
|
|
if isinstance(assume_role_policy, str):
|
|
try:
|
|
assume_role_policy = json.loads(assume_role_policy)
|
|
except (json.JSONDecodeError, ValueError):
|
|
return []
|
|
|
|
principals = []
|
|
for statement in assume_role_policy.get("Statement", []):
|
|
principal = statement.get("Principal", {})
|
|
if isinstance(principal, str):
|
|
principals.append(principal)
|
|
elif isinstance(principal, dict):
|
|
for v in principal.values():
|
|
if isinstance(v, list):
|
|
principals.extend(v)
|
|
else:
|
|
principals.append(v)
|
|
elif isinstance(principal, list):
|
|
principals.extend(principal)
|
|
|
|
return principals
|
|
|
|
|
|
def extract(client) -> Tuple[List[ResourceNode], List[ResourceEdge]]:
|
|
"""
|
|
Extract IAM role nodes and their trust-relationship edges.
|
|
|
|
Edges produced:
|
|
- trusted-principal → role [iam] (who can assume this role)
|
|
"""
|
|
nodes: List[ResourceNode] = []
|
|
edges: List[ResourceEdge] = []
|
|
|
|
for role in client.roles:
|
|
props: Dict[str, Any] = {
|
|
"path": getattr(role, "path", None),
|
|
"create_date": str(getattr(role, "create_date", "") or ""),
|
|
}
|
|
|
|
nodes.append(
|
|
ResourceNode(
|
|
id=role.arn,
|
|
type="iam_role",
|
|
name=role.name,
|
|
service="iam",
|
|
region="global",
|
|
account_id=client.audited_account,
|
|
properties={k: v for k, v in props.items() if v},
|
|
)
|
|
)
|
|
|
|
# Trust-relationship edges: principal → role (principal CAN assume role)
|
|
try:
|
|
for principal in _parse_trust_principals(role.assume_role_policy):
|
|
if principal and principal != "*":
|
|
edges.append(
|
|
ResourceEdge(
|
|
source_id=principal,
|
|
target_id=role.arn,
|
|
edge_type="iam",
|
|
label="can-assume",
|
|
)
|
|
)
|
|
except Exception as e:
|
|
logger.debug(
|
|
f"inventory iam_extractor: could not parse trust policy for {role.arn}: {e}"
|
|
)
|
|
|
|
return nodes, edges
|