multi-cloud asset inventory

every resource in your cloud — and how they connect.

disco calls each cloud's per-service sdk directly, so it finds what resource explorer, resource graph, and cloud asset inventory leave out. Then it maps the edges between them.

no cloud credentials stored · no trackers · free for 3 cloud accounts

blast radius from a single iam role — depth and direction are selectable, and cross-account trust edges stay visible even when the far side isn't scanned.

coverage

~300 aws services · ~1,800 resource types
~150 azure services · ~420 resource types
~40 gcp services · ~250 resource types
11 typed edge kinds in the graph

approximate. run disco coverage services for the live list from your build.

why teams run it

you've been handed an estate you didn't build

A console shows you one account at a time. A bill tells you what it cost, in line items named after services rather than after anything you can point at. Between them you can eventually reconstruct what is running — that reconstruction is a week of somebody's time, it is out of date when it lands, and it has to be redone for the next account.

Listing the resources is the easy half. The work is the edges: which subnet that instance sits in, which role that function assumes, which account trusts which. disco resolves those after the walk and stores them as typed relationships, so the estate arrives as a graph you can follow rather than a pile of exports you have to join by hand.

you can't answer "what breaks if i change this?"

graph blast walks outward from any resource and groups the result by distance ring. graph path gives the shortest path between any two. Edges are typed, not inferred — 11 kinds including attached-to, routes-to, assumes, and bounded-by.

Partial-id lookup means an id pasted straight out of a ticket resolves, and iam principals auto-expand in both directions, because a principal mostly receives edges rather than emitting them.

you can't tell what changed since last week

Every scan is recorded. diff reports what appeared and what went stale between any two of them, and history reads one resource's version chain forward.

"what appeared" is a time query, not a diff you eyeball: --discovered-since and --discovered-before bound first-seen time into a half-open interval, so last week's new resources are a filter on the inventory itself.

Resources the cloud creates and owns are marked as such, so the inventory separates what your team put there from what the provider did — and a count of your estate stays a count of your estate.

you can't find what nobody owns

graph complete --orphans-only surfaces the resources with no edges pointing at them: unattached ebs volumes, key pairs no instance uses, iam principals with nothing attached.

tag-coverage reports the per-key coverage rate, and keys at zero percent still appear — an absent tag is the signal, so dropping it from the report would hide exactly the thing you need.

you can't say what it looked like last quarter

A scan stores the resource, not a headline about it — identity, location, lifecycle, tags, and the provider's own attributes. So the record answers questions asked after the fact: what this security group allowed in june, which accounts had public buckets then, when that role first appeared. history reads one resource's versions forward and diff compares any two scans, and both read the state that was actually stored rather than reconstruct it.

That makes the inventory itself the evidence. An export is a record with timestamps and a version chain behind every row, which is a different artifact from a screenshot of a console taken the week someone asked. Nothing has to be staged for the review, because nothing was waiting to be collected.

Service quotas can ride along too — always on azure, opt-in on aws, and planned for gcp — so a raised limit shows up in the same history as everything else. Separately, disco keeps an append-only, hash-chained log of what was done in disco — who connected an account, who exported, who changed a role.

how it works

Four steps, and the first one never hands us a credential.

  1. 01connect an account

    a role, not a key

    aws gets a cloudformation stack that creates a cross-account role with an external id. azure uses lighthouse. gcp uses workload identity federation. We keep the account id and the principal you granted, and nothing else — a cloud credential is not something we can hold.

  2. 02scan

    per-service walk, then resolve

    The scanner walks each service's own sdk, then a resolve phase writes the typed edges between what it found. A denied or unreachable service degrades to a warning and a partial-scan status rather than failing the run, so a scan through a restrictive scp still gives you a usable graph.

    When a scan fails, the account says so. A revoked role or a removed delegation is classified as lost access rather than filed as a generic error, and the account carries that state until it is fixed — so an inventory that has quietly stopped updating cannot pass itself off as current.

  3. 03explore

    filter, then follow the edges

    Filter the inventory by provider, type, account, service, managed, or untagged. Open a resource for its identity, location, lifecycle, tags, and attributes — then switch to the relationships tab and walk outward with depth and direction selectors.

  4. 04wire it into your pipeline

    an api, webhooks, and sarif

    A rest api with 67 operations, specified in openapi 3.1. Slack notifications and hmac-signed webhooks on scan complete. disco check --output sarif drops straight into github code scanning. And the json output is byte-identical across runs, so you can commit it and diff it like any other artifact.

also used for

security & compliance

  • opa/rego policy evaluation with sarif output and exit-code gating
  • append-only, hash-chained audit log of in-product actions, exported with the soc 2 and iso 27001 controls each action evidences
  • one request pulls the whole evidence bundle — audit slice, scans, resource snapshot, connected accounts, webhooks, and members, under a sha-256 digest
  • evidence snapshots you sign with your own ed25519 key — canonical manifest, database digest, detached signature
  • sso via oidc and saml, plus auditor and compliance-admin roles

incident response

  • blast radius from a compromised principal, grouped by hop
  • cross-account and cross-project trust edges resolve to the real resource when both sides are scanned
  • when only one side is scanned you still get a stub, so the boundary never silently disappears
  • session listing and revocation, per account and per workspace

finops

  • FOCUS 1.4 cost allocation — upload the export, match billing lines to discovered resources
  • per-account billed cost, with the unattributed remainder shown rather than folded away
  • tag coverage rate, the precondition for chargeback and showback
  • untagged filters on the inventory itself

transparency

no analytics, no third-party trackers, no ad tech — and the policy is machine-readable, not a promise.

The product publishes its own subprocessors, the data it collects, and how long it keeps them, generated from the same constants the application enforces. A test fails the build if any tracking flag flips true.

The scanner engine — the part that assumes roles in your cloud — is open source under mit. Audit it yourself: github.com/icearp/disco-cli

start with one account and see what turns up.

3 cloud accounts, unlimited seats, no card.