How to find untagged AWS resources across every account
The short answer
Use the Resource Groups Tagging API (`get-resources`) for a per-account sweep, AWS Resource Explorer for a fast cross-region view, or AWS Config for a queryable inventory across an Organization. Whichever you use, rank the results by monthly cost before you start tagging — a small share of resources usually drives most of the bill.
Finding untagged resources is easy. The mistake is treating the resulting list as a to-do list in the order it comes back.
Three ways to get the list
Resource Groups Tagging API. Works per account and region, no setup:
aws resourcegroupstaggingapi get-resources \
--region eu-west-1 \
--query 'ResourceTagMappingList[?length(Tags)==`0`].ResourceARN'
AWS Resource Explorer. Indexes resources across regions in an account and supports searching for resources missing a given tag key. Needs to be turned on first.
AWS Config. The right answer once you are dealing with an Organization, because the aggregator gives you one queryable inventory across every account.
TODO — add the advanced Config query you use, and note which resource types are not covered by each method. The gaps are the interesting part.
Why the count is the wrong number
An estate with two million untagged resources sounds like a two-year project, and framed that way it never gets started. But resource count and resource cost are only loosely related: a single RDS cluster can cost more than tens of thousands of small objects.
Sort the untagged list by monthly spend and the shape of the work changes completely. Tagging the resources at the top of that list restores cost attribution for most of the bill in a matter of weeks — and that is the thing you actually wanted. The long tail can be handled by policy over time, because it costs almost nothing while it waits.
Then stop it happening again
TODO — expand: tag policies in AWS Organizations, tagging enforced at creation, and how to handle resource types that do not support tags at all.
A cleanup you run by hand is a cleanup you will run again next quarter. The point of tagging at creation is that the list you just built stops growing while you work through it.