Skip to content

cloudsec: fleet overview, provider manifests, CSV exports, inventory provider filter#312

Merged
maximelb merged 2 commits into
masterfrom
cloudsec-cli-refresh
Jul 14, 2026
Merged

cloudsec: fleet overview, provider manifests, CSV exports, inventory provider filter#312
maximelb merged 2 commits into
masterfrom
cloudsec-cli-refresh

Conversation

@maximelb

Copy link
Copy Markdown
Contributor

Catches the limacharlie cloudsec CLI + SDK up to the current /cloudsec gateway surface (which grew fleet, manifests, CSV export, and inventory-provider routes over the last week).

New

  • cloudsec fleet overview / CloudSec.get_fleet_overview() — the multi-org fleet posture board (GET /cloudsec/fleet/overview): one row per authorized org + first-page cross-tenant rollups, narrowable with repeatable --oid and/or an org --group. With user-scoped credentials the CLI mints a temporary multi-org JWT (refresh_jwt(oid_override=""), new) so the fleet is not collapsed to the single configured org; the client's own JWT is restored afterwards. Org API keys just use their org-scoped claims.
  • cloudsec provider manifest [--type gcp] / get_provider_manifests() — per-provider coverage manifests (collectors, posture checks, support levels, known gaps, org scan freshness).
  • cloudsec export {findings,inventory,compliance,query} [-o file.csv] / export_*_csv() — the ?format=csv streaming exports (server walks the full filtered set, 100k-row cap, trailing # comment on truncation). Client.request() grows raw_response=True to return non-JSON bodies as text.
  • cloudsec inventory list --provider / list_inventory(provider=...) — the new inventory provider-sweep filter.

Polish

  • Help/explain texts: valid findings sort keys (lc_risk default / severity / first_seen), refreshed provider examples (entra, auth0, github, openai, anthropic, limacharlie...), new commands in the group help and --ai-help registry.
  • doc/cli/cloud-security.md (new page, linked from the doc index) + a CloudSec section in doc/sdk/other-classes.md; CHANGELOG entry.

Tests

  • New unit tests: fleet overview JWT swap/restore (incl. error path + org-key path), provider manifests, CSV export query-param + raw_response plumbing, inventory provider filter, CLI export-to-file/stdout, export query arg validation, and the client raw_response text path.
  • Full unit suite: 3615 passed, 5 skipped.

No backward-compat concerns per Maxime — the cloudsec CLI surface is pre-GA.

🤖 Generated with Claude Code

…provider filter

Catch the CLI/SDK up to the current /cloudsec gateway surface:

- 'cloudsec fleet overview' / CloudSec.get_fleet_overview(): the multi-org
  fleet posture board (GET /cloudsec/fleet/overview), with --oid/--group
  narrowing. User-scoped credentials mint a temporary multi-org JWT
  (refresh_jwt(oid_override="")) so the fleet spans every accessible org,
  restoring the client's own token afterwards.
- 'cloudsec provider manifest [--type]' / get_provider_manifests(): the
  per-provider coverage manifests (GET /cloudsec/{oid}/providers/manifest).
- 'cloudsec export {findings,inventory,compliance,query} [-o file]' /
  export_*_csv(): the ?format=csv streaming exports. Client.request grows
  raw_response=True to return non-JSON bodies as text.
- 'cloudsec inventory list --provider' / list_inventory(provider=...): the
  new provider sweep filter.
- Help-text refresh: valid sort keys (lc_risk/severity/first_seen), current
  provider examples, group/explain coverage for the new commands.
- doc/: new CLI Cloud Security page + CloudSec SDK section; CHANGELOG entry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lcbill
lcbill previously approved these changes Jul 14, 2026
Adversarial review of the first cut found the JWT-swap approach was at the
wrong depth: request()'s internal 401-retry re-minted an ORG-scoped token
and could silently collapse the fleet to one org, refresh_jwt's side
effects (_on_refresh_auth, shared _jwt mutation, cache) leaked the
more-privileged multi-org token beyond the call, and the swap window was
not concurrency-safe on a shared Client.

Redesign:
- Client.mint_jwt(oid=..., expiry=...): a pure mint — returns a token
  without setting the client JWT, firing the refresh callback, or writing
  the JWT cache. OAuth id_token refresh extracted to
  _refreshed_oauth_id_token() (shared with _refresh_jwt_oauth).
- get_fleet_overview sends the multi-org token as a request-local
  Authorization header (is_no_auth bypasses the client's own token and its
  401 downgrade path), caches it across paginated calls, re-mints it once
  on a 401, and never touches client state.
- refresh_jwt reverted to exactly its master behavior (the '' override is
  no longer needed).
- CLI: inventory list/export share one _inventory_filter_options decorator.

Unit suite: 3619 passed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@maximelb

Copy link
Copy Markdown
Contributor Author

Post-review hardening pushed (0ecc952) after an 8-angle adversarial self-review:

Fixed

  • Silent fleet downgrade on 401 (confirmed by 4 independent review angles): the first cut swapped the multi-org JWT onto the shared client, so request()'s internal 401-retry could re-mint an org-scoped token and return a single-org "fleet" with no error. Redesigned: new Client.mint_jwt() is a pure mint (no client-JWT mutation, no _on_refresh_auth firing, no cache writes) and the fleet call sends it as a request-local Authorization header (is_no_auth), re-minting the multi-org token itself on a 401. Also fixes the callback-leak and shared-client concurrency concerns, and refresh_jwt is reverted to exactly its master behavior.
  • Multi-org token now cached across paginated fleet calls (one mint per sweep instead of one per page).
  • inventory list / export inventory now share one _inventory_filter_options decorator (no drift).

Reviewed, accepted as-is

  • export_*_csv methods mirror their list_* twins' signatures — kept for the clean str-vs-dict return typing.
  • Global --filter/--output are inert on cloudsec export (raw CSV bypasses the formatter by design).
  • CSV is buffered in memory (bounded by the server's 100k-row cap); streaming would need a deeper client seam.

Unit suite after redesign: 3619 passed, 5 skipped.

@maximelb
maximelb marked this pull request as ready for review July 14, 2026 21:40
@maximelb
maximelb merged commit e8813ef into master Jul 14, 2026
7 checks passed
@maximelb
maximelb deleted the cloudsec-cli-refresh branch July 14, 2026 21:40
maximelb added a commit that referenced this pull request Jul 19, 2026
…tity, policy, simulate, finding classes) (#315)

Catches `limacharlie cloudsec` up to the Cloud Security gateway surface
added since PR #312 (2026-07-14). Seven new routes plus one new inventory
selector were live on the gateway with no CLI/SDK coverage; this adds all
of them, giving full 44/44 route coverage.

New SDK methods (limacharlie/sdk/cloudsec.py) + CLI commands:
- get_identity(urn)              -> GET  /ciem/identity   -> `ciem identity <urn>`
- get_finding_classes()          -> GET  /findings/classes-> `finding classes`
- get_topology()                 -> GET  /topology        -> `topology`
- get_policy_vocabulary()        -> GET  /policy/vocabulary-> `policy vocabulary`
- suggest_policy_values(...)     -> POST /policy/suggest   -> `policy suggest`
- simulate_resource_match(...)   -> POST /simulate/resources-> `simulate resources`
- simulate_finding_match(...)    -> POST /simulate/findings -> `simulate findings`

Plus the inventory `account_unscoped` escape hatch, exposed as
`inventory list --all-accounts` and `export inventory --all-accounts`
(honored on both the JSON and CSV paths), and the new `device_posture`
finding class added to the finding-list help text.

The `policy` (vocabulary + autocomplete) and `simulate` (matcher preview)
groups are the CLI companions to the classification-policy authoring UI:
they read the server-driven vocabulary and preview an in-edit
cloudsec_policy matcher against the estate before it is saved. Nothing is
persisted by either.

Field names, HTTP methods, boolean forwarding, and the target/dimension
enums were verified against the lc_api-go gateway route whitelists and the
legion_graph RPC handlers. Full unit suite green (3654 passed).


Claude-Session: https://claude.ai/code/session_01C5xJgttYUj7hEWPduBHvm2

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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.

2 participants