Skip to main content

Discovering privileged accounts

Entra ID discovery is real and proven against a live tenant. AWS and GCP are built and unproven. On-premise SSH is not implemented, and says so rather than inventing a result.

Written for whoever runs IT12 min readUpdated

The point of account discovery is to answer a question almost no organisation can answer from memory: which accounts in our estate have administrative privileges, and which of them does nobody own. It is usually the first genuinely alarming thing a privileged access product tells you.

What each scanner actually does today

The four registered scan types and the evidence behind each. The last column is the one to read.
Scan typeWhat it doesHow well proven
azure — Microsoft Entra IDSigns in with client credentials, then enumerates directory role assignments across users, service principals and role-assignable groups through Microsoft Graph.Proven against a live tenant. There is a live-tenant test in the codebase, gated on real credentials, that fails if a tenant returns zero privileged principals — on the reasoning that every tenant has at least one Global Administrator, so an empty result means the enumeration is broken rather than that you are clean.
aws — AWS IAMSigns requests itself and enumerates users, roles, access keys, key last-used times and attached managed policies through the IAM query API. Read-only by construction: there is no mutating call anywhere in the file to reach by accident.Built, and not proven against a live account. The request signing is verified against Amazon's own published test vectors, and the enumeration against a fake server that speaks the real response shape. Those are two different claims and only the first is evidenced. Treat the first scan against your account as a test of our code as well as of your estate.
gcp — Google CloudExchanges a signed assertion for a token, then enumerates service accounts and IAM bindings.Built, and not proven against a live project. Same position as AWS: exercised against a protocol-shaped fake, never against Google.
on_prem_ssh — Linux hosts on your networkNothing. It returns an error.Not implemented. See below — this one is worth understanding rather than working around.

There is no Active Directory scanner. on_prem_ad appears in a comment and nowhere else; asking for it returns Qorionix has no "on_prem_ad" scanner. Supported types are aws, azure, gcp, on_prem_ssh.

The picker tells you before you scan, not after

Privileged Access → Discovery carries a panel headed What Qorionix can scan, and each provider is marked Available or Cannot scan yet. That state is computed per organisation, not per build, because the code ships everywhere and the credential does not: a provider is available to you when you have stored a working credential for it.

The banner above it is the sentence that matters most on this page, and it is there so an empty result cannot be misread:

No provider can scan for this organisation yet, so an empty candidate list does not mean you have no unmanaged privileged accounts — it means nothing has looked for them. AWS, Microsoft Entra ID and Google Cloud each start working as soon as you store a read-only credential for them below.
Privileged Access → Discovery

Storing that credential is Storing cloud credentials, and each provider's requirement sentence names the exact permissions it needs. Start there; a scan without one records an attempt and finds nothing.

Why on-premise SSH is not implemented, in the product's own words

This is the one people ask about most, and the answer is unusually specific. It does not silently return zero and it is not hidden from the list; it is present, marked unavailable, and refuses with a reason:

Qorionix cannot scan an on-premise range. This is not something you can configure: the platform has no SSH client, and it runs in Azure with no route to your internal network. The intended path is to have the Qorionix sensor already installed on your network perform the scan, which is not built yet. Starting a scan now records an attempt and finds nothing.
the on-premise SSH scanner's own description, verbatim

Three things follow from that, and each is worth knowing before you plan around it.

  • It is a routing problem before it is a coding problem. The API runs in a cloud network with no path to your office. A scanner running there could not reach a 10.0.0.0/24 range however well it was written, so building one in the API would produce a feature that fails for every customer.
  • The intended design is the sensor. You already install an endpoint sensor on your machines; that sensor is on the network, holds the credentials locally, and can limit the blast radius to one host at a time. That work is not built.
  • It is deliberately absent from the cloud-credential provider list too, because a configuration screen that stores a credential for a scanner that cannot use it is a screen that does nothing.

So for servers, network devices and anything else inside your perimeter, the inventory is still a manual exercise. The last section of this article is how to do it properly.

Running a scan

Press Start a scan. The dialog asks What should be scanned? and then for a Target — an AWS account id, an Entra tenant id, a GCP project id. The help under the target field is honest about its own weakness: Nothing is validated here, so check it before running the scan.

A scan runs inside the request that starts it, with a four-minute ceiling. There is no queue and no background worker, so a scan either finishes while you wait or times out. Discovery also does not run on a schedule: it happens when somebody starts one.

A scan moves through queued, running, and then either completed or failed. A scan that cannot run does not return an HTTP error — it returns a created scan whose status is failed, carrying a message. That is deliberate, because the attempt is worth recording, and it means a client checking only the status code will think the scan succeeded.

The verbatim messages a failed scan carries
No scanners are configured in this deployment, so discovery cannot run.
Qorionix has no "on_prem_ad" scanner. Supported types are aws, azure, gcp, on_prem_ssh.
The aws scan of "123456789012" did not complete: <underlying error>
The scan found 4 accounts but Qorionix could not record them: <underlying error>

Discovery is admin-only. Reading scans and candidates needs pam:discovery.read; starting one and onboarding a candidate need pam:discovery.write. Neither is granted to member or viewer, and the reason is the same as for targets: a candidate list names real hosts and the privileged accounts on them, which is an attacker's shopping list.

What each scanner does not cover

Each scanner records its own gaps on the scan result rather than leaving you to infer them. They are worth reading before you treat a result as an inventory.

Entra ID
Covers directory role assignments on users, service principals and role-assignable groups. Does not cover application role assignments, Azure RBAC at subscription or resource-group level — so a subscription Owner who holds no directory role is invisible — eligible-but-inactive PIM assignments, or administrative-unit scoping.
AWS
Covers users, roles, access keys and attached managed policies only. Inline policies and policies inherited through a group are not read, so an account whose administrative rights come from an inline policy is reported as standard. Permission boundaries, service control policies, IAM Identity Center users and root-account usage are all out of scope. There is a per-scan request budget so a large account cannot trip your own IAM rate limit; principals past the budget are reported with privilege unknown rather than silently downgraded.
Google Cloud
Covers project-level IAM bindings and service accounts. Does not cover organisation- or folder-level bindings, Google Group expansion, deny policies, conditional bindings — or service-account key enumeration, which is the fact this product most cares about and which is explicitly left for a later pass.

Read those as and therefore rather than as caveats. An AWS scan returning no administrators does not mean you have none; it means none of them got there through an attached managed policy.

Reading the candidate list

Each candidate records what kind of account it is, how privileged it appears, a risk score, and whether it has been onboarded.

Account type
iam_user, iam_role, local_admin, ad_user, ssh_key, db_user, entra_user, entra_service_principal, gcp_service_account, gcp_user, gcp_group, gcp_domain.
Privilege level
admin, elevated, standard, unknown. Candidates are ranked highest risk first, with ties broken by identifier so the order is stable between page loads.
Onboarding status
pending, onboarded, ignored. Re-running a scan updates its existing candidates rather than duplicating them, and will not reset an already-onboarded account back to pending — which would invite a second vault entry for the same login.

One de-duplication limit worth knowing: candidates are unique by scan, identifier and host — not by organisation. Re-running the same scan is safe; two overlapping scans will show you the same account twice.

Onboarding a candidate into the vault

This is the best part of the feature and it works regardless of which scanner found the account. Onboard creates a target and a credential and binds them together in one action, with a hash-chained audit record. That matters because the alternative — the way this used to work — produced exactly the object that makes a vault useless: a secret with no host, no account and no rotation engine, which can never rotate.

  1. Refuses if the candidate is already onboarded, with 409 candidate already onboarded.
  2. Derives the credential type from the account type, so you do not choose it.
  3. Resolves the platform — from your override if you gave one, otherwise from the scan's suggestion. If it cannot work it out, it asks rather than guessing.
  4. Creates the target, or reuses an existing one at the same address. That is the normal case for the second account discovered on the same host.
  5. Creates the credential, naming it account@host unless you say otherwise. This is why the only thing you must supply is the current secret.
  6. Binds the credential to the target and the account, which is what makes rotation possible.
  7. Writes a hash-chained audit entry, pam.discovery.onboard.

The dialog asks for Current secret for this account with the help The password or key that works today. Qorionix stores it encrypted and needs it in order to replace it later. That is the honest framing: onboarding does not discover a secret, it takes the one you have and puts it under management.

You can use the same one-step onboarding from the vault directly, without a scan at all: the add-credential flow lets you describe a new target and create the credential bound to it in one action. That is the path to use for everything on-premise.

Building the on-premise half by hand

The work is manual and it is not large. Most organisations of ten to a thousand people have fewer privileged accounts than they fear and more than they can name. Do it once, properly, and then keep it current as part of onboarding and offboarding.

For Microsoft 365: you have two real sources now

The Entra scanner covers directory roles and service principals. The posture assessment covers the same tenant from a different angle — administrators, applications and their consents, devices — from a single consent, and it is real Graph data too. Run both; they disagree in useful ways, particularly about applications. Start with the finding about administrator accounts used for daily email, which is where most small-organisation privilege problems actually live.

For servers and network devices: use your own records

You do not need to scan for these, because you already know what they are: the domain controllers, the file server, the hypervisor, the firewall, the core switch, the database server. Write the list down, and for each machine write down the local administrative accounts and the service accounts that run on it. The uncomfortable part of this exercise is never finding the machines; it is finding the service account that three systems depend on and nobody remembers creating.

Add each one as a target, run a connection test to prove the credential you have is the credential the machine expects, and then enable rotation where the platform supports it. See Targets and devices. A connection test that fails is itself a discovery: it means the password you have written down is not the password in use.

What to do next

  1. Store a cloud credential for Entra ID first — it is the one scanner with a live-tenant test behind it — and use the Test button before you scan.
  2. Run the scan, then read the coverage gaps above before you treat the result as complete.
  3. Add your servers and devices as targets from your own records, because nothing is going to find them for you.
  4. If a scan returns nothing, A discovery scan finds nothing works through the four reasons in order of likelihood.

Was this article wrong?

If a procedure here does not match what you see, or a limit we described has changed, tell us and we will fix the page. Email us about this article, or see how to get help if you need an answer rather than a correction.

Everything in privileged access