feat(scanner): add Azure Resource Graph inventory foundation - #250
Conversation
Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.OpenSSF Scorecard
Scanned Files
|
Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
|
@Vishnu2707 PR #250 is ready for a thorough review. The tenant-isolation issue is fixed, tests were added, and all 20 CI checks pass. |
m-khan-97
left a comment
There was a problem hiding this comment.
Reviewed and fetched the branch to run the tests directly (installed azure-mgmt-resourcegraph==8.0.1 locally to confirm the pin is real and importable): 11/11 pass.
This is well-built, self-contained foundational work — it's a new standalone module (scanner/arg_inventory.py) not yet wired into ScanEngine, so there's zero risk to the existing 74-rule scan path. What stood out:
- Tenant/subscription isolation is actually enforced in code, not just asserted in the docs —
_normalise_resourcerejects any row whosesubscriptionIdisn't in the authorised set or whosetenantIddoesn't match, and it's tested (test_rejects_cross_tenant_and_unauthorised_subscription_rows). Given the doc's "Customer Trust Layer" section makes tenant isolation a headline guarantee, I specifically checked this claim holds in the implementation — it does. - Failure semantics are correct and well-tested: COMPLETE only with zero errors, PARTIAL preserves already-collected resources when a later page fails, FAILED when nothing was ever collected. Matches the documented contract exactly, including the repeated-pagination-token guard (infinite-loop protection) and the truncated-without-token case.
_normalise_subscriptionsguards against the classicisinstance(x, str)foot-gun (passing a bare string and having it iterated character-by-character) — small thing, but the kind of bug that's easy to miss and annoying to debug.- Retry-After handling is sensible (parses the header, falls back to capped exponential backoff if it's not a plain number), and retries are correctly scoped to 429/503 only.
The architecture doc is honest about scope — explicitly flags the benchmark numbers as not yet an apples-to-apples comparison until rules actually migrate to the shared snapshot, and Phase 1's non-goals are clearly listed. Good discipline for a foundational PR that could easily have overclaimed.
Approving.
|
Well Done, approved |


Summary
Introduces Azure Resource Graph inventory as Phase 1 of the proposed OpenShield Evidence Graph.
Security boundaries
Verification
resultTruncatedresponses without a continuation token and marks the snapshot partial.The unrelated ChromaDB dependency test was excluded from the local Windows run because that dependency could not be installed cleanly in the isolated environment. GitHub CI ran the repository's complete Linux suite successfully.
Live Azure validation
Validated on 11 August 2026 in Azure Resource Graph Explorer using an active Azure for Students subscription containing five resources. The scope was restricted to that student subscription; two unrelated university production subscriptions were not selected.
The OpenShield inventory projection was executed as a read-only query:
Results:
OpenShield PR #250 ARG inventorywithout exposing resource identifiers in shared evidence.This proves the KQL projection and real Azure ARG execution path. It does not yet prove the local Python client against live university credentials because the local Azure CLI remains authenticated to a different tenant.
Remaining benchmark gates
ArgInventoryClientdirectly with authorised live Azure CLI credentials.No sub-30-second performance guarantee is claimed until these larger-scale gates are complete.
Closes #249