DependencyGraph results¶
cloudg.inventory.DependencyGraph(assets, edges, include_hierarchy=False). Every edge with a
known dependency direction (section 6) whose endpoints are both
assets becomes one dependent → dependency arrow.
| Method | Returns |
|---|---|
find(ref) |
CloudAsset \| None. Tries, in order: internal id; exact arn; name when exactly one asset has it; the last / segment of arn when exactly one asset matches. |
depends_on(asset_id, max_depth=10) |
list[DependencyLink], everything the asset needs, breadth-first. |
dependents(asset_id, max_depth=10) |
list[DependencyLink], everything that needs the asset (its blast radius), breadth-first. |
direct_counts(asset_id) |
tuple[int, int]: (direct dependencies, direct dependents), counting parallel edges. |
tree(asset_id, direction="both", max_depth=3) |
nested dict, 12.2. |
shared_dependencies(top=25) |
list[dict], 12.3. |
blast_radius(candidates=None, top=25) |
list[dict], 12.4. |
12.1 DependencyLink¶
| Field | Type | Meaning |
|---|---|---|
asset_id |
str |
The asset reached. |
via_edge |
str |
edge_type of the edge used. |
relationship |
str \| None |
relationship of that edge. |
depth |
int |
Hops from the start, starting at 1. |
parent_id |
str |
The asset it was reached from. |
Each asset appears once per walk, at the depth and under the parent where the breadth-first search first reached it.
12.2 tree¶
| Key | Present | Type | Meaning |
|---|---|---|---|
asset |
always | asset descriptor | The starting asset. |
depends_on |
direction up or both |
list[node] |
What it needs. |
dependents |
direction down or both |
list[node] |
What needs it. |
An asset descriptor is {"id", "name", "arn", "type", "account_id", "region"} (type is
the asset_type value). A node is an asset descriptor plus:
| Key | Type | Meaning |
|---|---|---|
via |
str |
Edge type that links this node to its parent. |
relationship |
str \| None |
Relationship of that edge. |
children |
list[node] |
The next level, empty at max_depth. |
Example, the role orders-worker from the example run, direction="both", abridged:
{
"asset": {
"id": "1bd88609-88f3-46d7-868e-ac65ece6b65a",
"name": "orders-worker",
"arn": "arn:aws:iam::123456789012:role/orders-worker",
"type": "IAM_ROLE",
"account_id": "123456789012",
"region": "global"
},
"depends_on": [
{
"id": "f26a0b92-407e-44d7-8644-f73f462fa7e6",
"name": "arn:aws:iam::123456789012:policy/orders-queue-access",
"arn": "arn:aws:iam::123456789012:policy/orders-queue-access",
"type": "IAM_POLICY",
"account_id": "123456789012",
"region": "global",
"via": "IAM_POLICY_ATTACHMENT",
"relationship": "ROLE_HAS_POLICY",
"children": []
},
{
"id": "c612cd24-42db-4260-b755-3ee3a24da24f",
"name": "orders",
"arn": "arn:aws:sqs:us-east-1:123456789012:orders",
"type": "MESSAGE_QUEUE",
"account_id": "123456789012",
"region": "us-east-1",
"via": "GRANTS_ACCESS",
"relationship": "POLICY_ALLOWS_ACTION",
"children": [
{"name": "289e9c59-…", "type": "KMS_KEY", "via": "REFERENCES", "relationship": "ENCRYPTED_BY_KMS", "children": [], "…": "…"},
{"name": "orders-dlq", "type": "MESSAGE_QUEUE", "via": "REFERENCES", "relationship": "WRITES_TO", "children": [], "…": "…"},
{"name": "order-events", "type": "NOTIFICATION_TOPIC", "via": "INVOKES", "relationship": "STREAMS_TO", "children": [], "…": "…"}
]
}
],
"dependents": [
{
"id": "60cac611-8a80-469e-bca6-ee3cf1cdc35b",
"name": "orders-worker",
"arn": "arn:aws:lambda:us-east-1:123456789012:function:orders-worker",
"type": "LAMBDA_FUNCTION",
"account_id": "123456789012",
"region": "us-east-1",
"via": "ASSUMES_ROLE",
"relationship": "RUNS_ON",
"children": [
{"name": "orders-api", "type": "CONTAINER_SERVICE", "via": "REFERENCES", "relationship": "DEPENDS_ON", "children": [], "…": "…"}
]
}
]
}
Reading it: the role needs its attached policy and the queue its policy grants access to; the
queue in turn needs its KMS key and its DLQ, and depends on the topic that delivers into it
(order-events INVOKES orders is a reverse-direction edge, so the queue depends on the topic).
Downstream, the function runs as the role, and the ECS service references the function.
12.3 shared_dependencies¶
Assets that the most other assets depend on directly, ignoring CONTAINS and PEERING. Only
assets with at least two such dependents are listed; sorted by descending count.
| Key | Type | Meaning |
|---|---|---|
| asset descriptor keys | id, name, arn, type, account_id, region |
|
direct_dependents |
int |
Distinct assets with a direct functional dependency on it. |
[
{"id": "1bd88609-88f3-46d7-868e-ac65ece6b65a", "name": "orders-worker",
"arn": "arn:aws:iam::123456789012:role/orders-worker", "type": "IAM_ROLE",
"account_id": "123456789012", "region": "global", "direct_dependents": 8},
{"id": "756b6990-690f-4136-98c1-69cfd2b7a71d", "name": "web",
"arn": "arn:aws:ec2:us-east-1:123456789012:security-group/sg-05c9fb72915768cb5",
"type": "SECURITY_GROUP", "account_id": "123456789012", "region": "us-east-1",
"direct_dependents": 6}
]
12.4 blast_radius¶
The assets whose failure or change would affect the most others, transitively. Candidates are
the 4 × top assets with the most direct dependents (or the candidates you pass); each is
walked with dependents(max_depth=10). Assets with no dependents are dropped; sorted by
descending transitive_dependents.
| Key | Type | Meaning |
|---|---|---|
| asset descriptor keys | id, name, arn, type, account_id, region |
|
transitive_dependents |
int |
Assets that depend on it directly or indirectly (up to 10 hops). |
accounts_affected |
int |
Distinct accounts among those dependents. |
internet_exposed_dependents |
int |
Internet-exposed assets among them. |
[
{
"id": "8d7d700b-7f64-4821-97b2-45577d1faf7a",
"name": "FullAWSAccess",
"arn": "arn:aws:organizations::123456789012:policy/o-1wietecbs4/service_control_policy/p-FullAWSAccess",
"type": "ORG_POLICY",
"account_id": "123456789012",
"region": "global",
"transitive_dependents": 38,
"accounts_affected": 3,
"internet_exposed_dependents": 4
}
]
An SCP attached to the root topping the list is expected: everything in the governed accounts depends on it.