Skip to content

CloudAsset

Section 3 · From docs/INVENTORY_REFERENCE.md on GitHub

cloudg.schema.models.CloudAsset, a Pydantic v2 model (extra="allow", populate_by_name=True). One node of the map: a cloud resource, an identity, a security service (or its absence), an account, an organization unit, a policy, or a Kubernetes object.

3.1 Fields

Field Type Default Meaning
id str new UUID4 Internal ID, unique within one map, regenerated each run. Edge endpoints reference it.
arn str \| None None Stable native or synthetic identifier (formats). Deduplication key: two assets with the same arn are merged. Every inventory asset sets it.
name str required Display name: the Name tag, the resource name, or the identifier when the resource has no name. Not unique.
asset_type AssetType required One of 156 values; see INVENTORY_CATALOG.md. Unclassifiable resources are OTHER.
provider CloudProvider required AWS, AZURE or GCP (upper case). Kubernetes objects inside EKS are AWS, inside GKE GCP.
region str "global" Region / location. "global" for account-wide resources (IAM, S3 buckets as listed, CloudFront, Route 53, organizations, accounts, Entra principals). Azure uses the ARM location (eastus), GCP the CAI location (us-central1, us-central1-a, global).
account_id str \| None None AWS account ID, Azure subscription ID, or GCP project ID. None for tenant-wide identities (Entra principals) and GCP organization / folder level resources.
tags dict[str, str] {} Tags / labels, values stringified. Kubernetes objects carry their labels here.
metadata dict[str, Any] {} Normalised attributes. Contents depend on the type; see Common metadata keys and the per-type reference. Always JSON-serialisable.
raw_data dict[str, Any] {} Raw API payload used during linking. Excluded from serialisation (exclude=True): never present in model_dump() or any file.
collected_at datetime now (UTC) When the asset object was built.
is_internet_exposed bool False Reachable from the internet according to the collector (public IP with an open security group, internet-facing load balancer, public bucket / function URL / API, GCP firewall open to 0.0.0.0/0, allUsers bindings, Azure public network access without a deny ACL, Kubernetes LoadBalancer services and ingresses with a hostname, ...).
display_id str (computed) arn or id Serialised by model_dump(); ignored by InventoryResult.load().

Because the model allows extra fields, a collector or plugin may attach additional top-level fields; they survive model_dump() and load().

3.2 Example

A Lambda function from the example run (metadata abridged to the keys that matter here):

{
  "id": "60cac611-8a80-469e-bca6-ee3cf1cdc35b",
  "arn": "arn:aws:lambda:us-east-1:123456789012:function:orders-worker",
  "name": "orders-worker",
  "asset_type": "LAMBDA_FUNCTION",
  "provider": "AWS",
  "region": "us-east-1",
  "account_id": "123456789012",
  "tags": {},
  "metadata": {
    "runtime": "python3.12",
    "handler": "h.h",
    "package_type": "Zip",
    "image_uri": null,
    "memory_size": 128,
    "timeout": 3,
    "vpc_config": null,
    "role_arn": "arn:aws:iam::123456789012:role/orders-worker",
    "environment_keys": ["DB_PASSWORD", "QUEUE_URL"],
    "event_sources": ["arn:aws:sqs:us-east-1:123456789012:orders"],
    "function_url_auth": null,
    "policy_allows_public": false,
    "relations": [
      {"target": "arn:aws:iam::123456789012:role/orders-worker",
       "edge": "ASSUMES_ROLE", "relationship": "RUNS_ON", "description": "execution role"},
      {"target": "https://sqs.us-east-1.amazonaws.com/123456789012/orders",
       "edge": "REFERENCES", "relationship": "DEPENDS_ON", "description": "environment reference"},
      {"target": "arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/orders-worker",
       "edge": "LOGS_TO", "relationship": "LOGS_TO"},
      {"target": "arn:aws:sqs:us-east-1:123456789012:orders",
       "edge": "INVOKES", "relationship": "TRIGGERED_BY", "reverse": true,
       "description": "event source mapping",
       "properties": {"state": "Enabled", "batch_size": 10}}
    ],
    "aliases": ["arn:aws:lambda:us-east-1:123456789012:function:orders-worker:$LATEST"]
  },
  "collected_at": "2026-10-04T15:34:54.643569",
  "is_internet_exposed": false,
  "display_id": "arn:aws:lambda:us-east-1:123456789012:function:orders-worker"
}

Things to notice:

  • environment_keys lists variable names. Values are never collected. The queue URL in QUEUE_URL reached the map only as a relation target, because identifier-shaped values (ARNs, SQS queue URLs judged by their parsed host) are extracted as references and everything else is dropped.
  • The relations are the collector's declarations. The linker turned four of them into edges except the log group one, which did not resolve (the log group did not exist) and therefore appears in unresolved_references (section 11).
  • reverse: true on the event source mapping means the edge points from the queue to the function: SQS INVOKES Lambda (TRIGGERED_BY).

3.3 Placeholder assets

Some assets stand for something that was referenced rather than collected:

Kind arn asset_type Distinguishing metadata
Security service not enabled (AWS) cloudg:aws:<service>:<region>:<account>:not-enabled the service's type (VULNERABILITY_SCANNER, THREAT_DETECTOR, ...) security_service, enabled: false, status: "not enabled", alias aws-security:<service>:<region>:<account>
Defender plan off (Azure) the pricing resource ID THREAT_DETECTOR security_service: "defender-<plan>", enabled: false
External account arn:aws:iam::<id>:root, /subscriptions/<id>, //cloudresourcemanager.googleapis.com/projects/<id> CLOUD_ACCOUNT external: true, discovered_via: "cross-account reference"
Entra principal entra:principal/<objectId> IDENTITY_USER, IDENTITY_GROUP or SERVICE_PRINCIPAL placeholder: true, principal_type, discovered_via: "entra-principal-reference"
GCP principal gcp-principal:<member> or k8s-gke://… IDENTITY_USER, IDENTITY_GROUP, SERVICE_PRINCIPAL, K8S_SERVICE_ACCOUNT, ... discovered_via: "iam_policy" or "workload_reference"

GCP parity placeholders:

Kind arn asset_type Distinguishing metadata
Security service not enabled (GCP) cloudg:gcp:<service>:<parent>:not-enabled, where parent is projects/<id>, folders/<id> or organizations/<id> the service's type (SECURITY_HUB, THREAT_DETECTOR, CONFIG_RECORDER, VULNERABILITY_SCANNER, DATA_SECURITY_SCANNER, CLOUDTRAIL) security_service (scc, event-threat-detection, artifact-analysis, dlp-discovery, audit-logs, ...), enabled: false, status: "not enabled", alias gcp-security:<service>:<parent>
GCP principal named by a deny rule, PAM entitlement or group membership gcp-principal:<member> as above discovered_via: "relation_reference"

Azure placeholders added with the parity work:

Kind arn asset_type Distinguishing metadata
Defender plan not listed (Azure) cloudg:azure:defender-<plan>:<subscription>:not-enabled THREAT_DETECTOR security_service: "defender-<plan>", enabled: false, status: "not enabled", alias azure-security:defender-<plan>:<subscription>. Created for every plan of STANDARD_PLANS the pricings query did not return.
Sentinel not enabled (Azure) cloudg:azure:sentinel:<subscription>:not-enabled THREAT_DETECTOR as above with security_service: "sentinel"; created when no Log Analytics workspace of the subscription is onboarded.
External source repository repo:<url> (lower case, no .git, no credentials) SOURCE_CONNECTION external: true, repository_url, host, discovered_via: "repository-reference". The target of READS_FROM from web app source control, Flux, ACR tasks, Static Web Apps, Data Factory Git and dev center catalogs.
Entra principal from a directory role entra:principal/<objectId> SERVICE_PRINCIPAL placeholder: true, discovered_via: "entra-principal-reference"; a role holder Microsoft Graph did not list.

Example, Inspector not enabled:

{
  "id": "07911321-f52d-438c-91b1-3be831c2451b",
  "arn": "cloudg:aws:inspector2:us-east-1:123456789012:not-enabled",
  "name": "Inspector (not enabled)",
  "asset_type": "VULNERABILITY_SCANNER",
  "provider": "AWS",
  "region": "us-east-1",
  "account_id": "123456789012",
  "tags": {},
  "metadata": {
    "security_service": "inspector2",
    "enabled": false,
    "status": "not enabled",
    "aliases": ["aws-security:inspector2:us-east-1:123456789012"]
  },
  "collected_at": "2026-10-04T15:34:07.879548",
  "is_internet_exposed": false,
  "display_id": "cloudg:aws:inspector2:us-east-1:123456789012:not-enabled"
}

Example, an external account created because a role trusts it:

{
  "id": "277ef061-8a0c-4e1e-9451-a50aa57198f8",
  "arn": "arn:aws:iam::999999999999:root",
  "name": "external account 999999999999",
  "asset_type": "CLOUD_ACCOUNT",
  "provider": "AWS",
  "region": "global",
  "account_id": "999999999999",
  "metadata": {
    "account_id": "999999999999",
    "external": true,
    "discovered_via": "cross-account reference"
  },
  "is_internet_exposed": false
}