The Scope List Is Assembled by People. The Billing Hierarchy Is Maintained by Machinery.
The cloud invoice is a document with a financial guarantee behind it, because a provider that missed an account would be giving away compute. Your provider's own account hierarchy API enumerates everything opened inside it, and the invoice is the independent check on that enumeration, maintained by a different department for a different reason. The scope list a posture assessment runs against comes from a third source: whoever was in the room.
The assessment measures what it was told about
A posture assessment begins with a scope list, and the scope list is assembled by people. The cloud platform lead names the accounts the platform team operates. Somebody forwards a page from an internal wiki. The list is complete as far as the people who built it can see.
The assessment then does what it was asked. Every account on the list is read, graded and written up, and the report is accurate about all of them. The part of the estate that never entered the conversation produces silence, and silence reads on a dashboard the same way a clean result does.
This article rests on a hypothesis, and it is worth stating as one: the account count a posture assessment gets pointed at runs lower than the account count the organization pays for. The claim is about direction only. How wide the gap runs on any given estate is a fact about that estate, and the test costs an email and an afternoon.
Each way of building a scope list leaves a hole with a predictable shape:
- The accounts the platform team operates, a precise answer to a narrower question than the one being asked.
- A page in an internal wiki, last edited by an engineer who has since moved teams.
- Last year's scope carried forward, which inherits every omission from the year before it.
- A configuration management database, populated back when a request form was the only way to open an account.
Three enumerations, and what each one guarantees
Start inside the platform. AWS Organizations, Azure management groups and Google Cloud Resource Manager each enumerate the accounts, subscriptions and projects sitting under the organization hierarchy, including the ones that consumed nothing this month. That is the first list to pull, a platform team can produce it the same day, and it is authoritative for everything created through the hierarchy.
The bill is the independent check on it. Every account that exists and consumes anything appears on the invoice, and the reason is accounting: the billing hierarchy is maintained continuously by machinery with a direct financial stake in catching every account. It is held by a different department, built for a different purpose, and derived from a different system, which is what makes it a genuine second opinion on the first list.
The third source is the expense ledger, and it reaches where the other two stop. An environment paid for on a corporate card and an acquisition still running on its own payer sit outside the organization hierarchy and outside the consolidated invoice, and they surface in accounts payable as vendor lines. Those two are the shadows this exercise most wants, so the ledger belongs in the reconciliation from the first run.
A hand-maintained inventory decays because an omission inside it costs nothing. A wiki page missing an account still renders. A spreadsheet missing one still adds up. On the bill, an omission has a cost attached, which is what makes it worth setting against a list somebody assembled from memory.
Asset inventory is the first of the CIS Critical Security Controls. In CWS's view it is also the control most easily marked complete on the strength of a document nobody has tested against an independent source. Three independent sources exist, all of them inside your own organization, and each has a limit worth naming before the control depends on it:
- The organizations API enumerates what was created inside the hierarchy. An account opened on a separate payer sits outside it entirely.
- An account that consumed nothing in the period may produce no billing line, so the first run should cover more than a single month.
- Consolidated billing covers accounts under a payer the finance team administers. An acquisition still running on its own payer sits outside that, which is the normal state until consolidation finishes.
- Credit funded and free tier accounts, where the amount payable is zero and the account is entirely real.
The billing hierarchy is maintained by machinery that loses money on every omission. A scope list assembled in a meeting is maintained by whoever remembered.
What lives in the gap
On CWS multi-cloud posture assessment work across AWS, Azure and Google Cloud, the agreed scope list gets reconciled against the customer's own cloud billing hierarchy before the scope is frozen. The accounts that surface in the gap are ordinary. They arrive through a small number of organizational routes, and what they share matters more than how many there are.
The route reduces to one sentence. Somebody had the authority to open an account and no obligation to register it. It covers the trial that quietly became production, the account opened for a project that ended while the workload it produced kept running, and the team that built its own environment because the central request queue ran to weeks. Calling these policy violations gets the history backwards, because the policy that would have been violated was written after the account was opened.
What makes them worth the effort of finding is everything they missed by being created off the path.
- The guardrails that come with a new account are applied at creation. This account predates them, or was opened outside the process that applies them.
- Its logs land somewhere your detection team never reads, so activity inside it generates no alert.
- It carries no owner tag, and the engineer who opened it may have changed teams twice since.
- It is connected to the rest of the estate by a network path, a role trust relationship or a shared credential. Unmanaged does not mean isolated.
One authority creates accounts. A different one, held by nobody in particular, is supposed to register them.
Running the reconciliation
The mechanics are ordinary. Pull the account list from the organization hierarchy, export the billable identifiers from the billing hierarchy for a full period, and ask accounts payable for cloud vendor lines over the same period. Take the union at whatever unit your provider issues identifiers in, account, subscription or project, put it beside the assessment scope, and match on the identifier. Display names get edited and identifiers stay put.
The organizing question is whether every identifier in that union has a disposition written against it. Three dispositions are enough, and the third one carries the work.
- The identifier is on both lists and the assessment read it. This one is finished.
- The identifier is excluded on purpose, somebody wrote down the reason and their name sits against it. A recorded exclusion is a position you can defend to an auditor a year later.
- The account is a mystery to the room: what it runs and who operates it are both open questions. This third group is the entire output of the exercise. Each entry leaves with a name against it and a date by which that person answers.
Two rules, and what the bill adds to the assessment
Run the reconciliation before the assessment scope is frozen, so accounts found this way get measured in the cycle that found them. Otherwise the discovery waits a year, and somebody has to establish all over again what the account was.
Report the count of open unknowns wherever the posture score is reported. A count that climbs quarter on quarter says something about how accounts get created, and reporting it puts that sentence in front of the people who can change it.
An account discovered on the bill arrives with metadata already attached: the month it started appearing, the services it consumes, and what it costs. Cost is a crude proxy for how much runs inside an account, and it is the honest one available while the account is still a mystery. Resist the pull toward the largest lines, though. A small recurring charge can be one virtual machine holding a copy of a production database, taken for a migration test.
Reconciling three independent enumerations against the assessment scope, the three dispositions, and pinning the cadence to the billing cycle are CWS design. All three sit outside published guidance, and each is offered as a position to argue with.
Making it monthly, and closing the door
Run once, this finds accounts. Run monthly, it keeps the gap closed, and the cadence already exists: the billing cycle turns over whether security takes part or not.
The person who reconciles the cloud invoice sits in finance, and a variance check against the previous month is already part of their job. A new account identifier reaches them before it reaches security. This control is largely a standing request to forward a list they already produce.
The monthly version compares one month to the last, which keeps it small: identifiers on this month's bill that were absent from last month's. In a settled estate that is a short list. It gets long in the month after an acquisition closes, which is the month you most want to be reading it.
New accounts will keep appearing outside the process. The gap reopens because creating an account takes minutes and registering one takes a form. The durable fix is organizational: the obligation to register attaches to the authority to create. Until it does, the monthly reconciliation is the compensating control.
Write four things down and the control survives the people who set it up:
- Who exports the billing list, and on which day of the month.
- Who receives it and performs the match.
- Where exclusions are recorded, with a name and a date against each one.
- Which report carries the count of open unknowns, so it stays visible to whoever owns the estate.
Finance runs a variance check on the cloud bill every month. A new account shows up there before it shows up anywhere in security.