Skip to content

Asset drift: live-account comparison against the register with Steampipe (#117) - #167

Open
ms280690 wants to merge 1 commit into
issue-116-asset-registerfrom
issue-117-asset-drift
Open

ms280690 wants to merge 1 commit into
issue-116-asset-registerfrom
issue-117-asset-drift

Conversation

@ms280690

Copy link
Copy Markdown
Collaborator

Closes #117. Stacked on #166 (issue-116-asset-register) for assets.json; retarget once that merges.

Deviation from the issue

Since Steampipe 1.0 the benchmark runner (steampipe check) lives in Powerpipe, so running steampipe-mod-aws-tags would add a second binary and a mod checkout. The mandatory-tag control that mod implements is one query over aws_tagging_resource, so this PR runs that query directly and documents the mods (AWS, GCP, Azure) as the Powerpipe route. Say the word if the mod should be wired anyway.

What

  • .github/actions/steampipe: pinned Steampipe 2.4.7 verified against the published checksums.txt, plugins by version (aws@1.34.0), steampipe query --output json with the ambient credentials; empty query installs only. Update checks and telemetry off. Outputs row-count, output-file.
  • drift.py (stdlib, next to the composite): --live rows.json --register assets.json --account ID --required-tags ... → drift.json and a report with the <!-- asset-drift --> marker: untagged, unmanaged, orphaned, unmatchable and managed lists, one warning annotation per finding, outputs the three counts. Account filtering keeps live rows of that account and register records of that account or with no account.
  • inventory.py (from Asset inventory and tag-grouped diagram from plan and synth output (#115) #165) gains identifier: the cloud-side name stated in the plan (bucket, function_name, identifier, cluster_identifier, cluster_name, table_name, repository_name, domain_name, name) or template (BucketName, FunctionName, RoleName, ...), null when generated at apply time. Schema and docs updated; the feat: inventory — asset inventory and tag-grouped diagram from plan/synth output (PR/CI) #115 suite asserts it.
  • asset-drift.yml (workflow_call): inputs from the issue plus issue and actions-ref. aws-oidc-auth → account id → steampipe query → gh release download asset-register-<ref> from this repo with SHA256SUMS check → drift.py → artefact asset-drift-<account> with retention-days: 90 → per-account tracking issue ("Asset drift: account ") opened, updated or closed. Caller grants id-token: write, contents: read, issues: write.
  • Docs: read-only IAM policy (tag:GetResources, tag:GetTagKeys, tag:GetTagValues, sts:GetCallerIdentity) in docs/oidc-trust-policies.md; steampipe row in docs/approved-actions.md; README rows and section with the egress hosts and the GCP/Azure notes. The docs/egress-allowlist.md row waits for feat(#83): harden-runner block mode with per-job egress allowlists #139 like the other stacks.
  • CI Asset Drift job: the composite installs the binary and the aws plugin (no credentials, no query), then the drift fixtures run.

Tests

tests/asset-drift/run.sh: recorded aws_tagging_resource rows (two accounts) and a register fixture; exact untagged (with missing keys), unmanaged, orphaned, unmatchable and managed sets for one account, counts without the filter, --required-tags owner, report heading and rows, annotations, outputs, usage error. Steampipe install, plugin install and the query JSON shape were verified locally with 2.4.7.

Deferred

  • First run against a real account once the read-only role exists in it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NPH9145e4gFo6bmXvMgBoF

The steampipe composite installs a checksum-verified binary and pinned
plugins, runs one SQL query with the ambient credentials and writes the
JSON result. drift.py compares aws_tagging_resource rows with the org
register: live resources missing required tags (untagged), live resources
whose ARN name matches no register identifier (unmanaged) and register
records whose identifier matches no live ARN (orphaned); records with no
stated identifier are reported as unmatchable rather than orphaned.

To make that match possible, inventory records gain an identifier: the
cloud-side name stated in the plan (bucket, function_name, name, ...) or
template (BucketName, FunctionName, ...), null when apply time generates it.

asset-drift.yml assumes a read-only OIDC role, queries the account,
downloads and verifies the register release, runs the comparison, keeps the
evidence 90 days and maintains one tracking issue per account. The IAM
policy for the role is documented; mods such as steampipe-mod-aws-tags now
run under Powerpipe and are noted rather than wired.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPH9145e4gFo6bmXvMgBoF
@ms280690 ms280690 self-assigned this Oct 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant