Skip to content

feat: GCP support for list, elevate, status and revoke - #53

Merged
aaearon merged 5 commits into
mainfrom
feat/gcp-support
Aug 13, 2026
Merged

aaearon merged 5 commits into
mainfrom
feat/gcp-support

Conversation

@aaearon

@aaearon aaearon commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Stacked on #47 (needs SDK v0.8.1). Merge order: #50 → #47 → this.

Adds GCP to eligibility listing, elevation, grant status, and grant revoke. grant env stays AWS-only.

⚠️ Untested against a live GCP tenant. Built from the SCA OpenAPI spec and SDK models only. Flagged in the README.

Scope

The SCA spec includes GCP in the csp enum for /access/{csp}/eligibility, /access/sessions, and POST /access/elevate. GCPEligibleTarget requires organizationId and a workspaceType of PROJECT | FOLDER | GCP_ORGANIZATION, and otherwise allOfs into the same CommonEligibleTarget shape grant already parses.

grant env remains AWS-only because accessCredentials is documented as "relevant only for specific cloud providers" and the spec defines no GCP credential schema. The post-elevation guidance makes no claim about gcloud mechanics that couldn't be verified.

grant request submit explicitly rejects GCP — the on-demand endpoints have no GCP platform name in the spec — rather than silently falling through now that parseProvider accepts gcp.

Bug fix: grant env no longer burns an elevation before validating

Previously grant env --provider azure performed a real elevation — creating an SCA session and recording a session timestamp — and only then returned the AWS-only error. resolveAndElevate now takes a preElevate hook, and env passes requireAWSTarget, so validation happens before the API call. An unresolved CSP is deliberately allowed through so the existing AccessCredentials == nil check still acts as a fallback.

Verified by mutation: reverting the hook to nil produces elevation call count = 1, want 0.

Tests

TestEligibleTarget_GCPUnmarshal (PROJECT/roleInfo, FOLDER/role fallback, GCP_ORGANIZATION), TestListEligibility_GCPRouteAndPagination, TestFetchEligibility_GCPQueriesGCPOnly, TestFetchEligibility_AllProvidersIncludesGCP, TestFetchEligibility_SkipsFailingGCP, TestRootElevate_GCPGuidance, TestEnvDoesNotElevateForNonAWSProvider, TestEnvElevatesOnceForAWS, TestBuildOnDemandRequest_GCPUnsupported, TestRunRequestSubmit_GCPUnsupported, plus GCP cases in TestParseProvider and TestFormatTargetOption.

TestEnvCommand_AzureError was removed. It ran without --provider, so its target's CSP came from the concurrent multi-CSP fan-out — nondeterministic with a third CSP in the list. Superseded by TestEnvDoesNotElevateForNonAWSProvider and TestEnvCommand_AWSNilCredentials.

make test, make lint, make build pass. make test-race fails only on the pre-existing internal/ui races fixed by #52.

grant env performed the elevation first and only then checked whether
credentials came back, so 'grant env --provider azure' created a real SCA
session and recorded a session timestamp before failing with 'no
credentials returned'. The user was left with an active session they
neither wanted nor were told about.

resolveAndElevate now takes a preElevate hook that runs after target
resolution and before the elevation request; env passes requireAWSTarget,
which rejects non-AWS targets with an actionable message. The existing
AccessCredentials == nil check stays as a fallback for AWS returning
nothing.
Adds GCP as a third supported CSP:

- models: CSPGCP and the PROJECT / FOLDER / GCP_ORGANIZATION workspace
  types from the GCPEligibleTarget schema (allOf CommonEligibleTarget, so
  the existing EligibleTarget shape and role/roleInfo fallback already
  parse it)
- supportedCSPs gains GCP, which propagates through the multi-CSP
  fan-out, provider validation, grant list and grant status
- status: parseProvider and formatProviderName accept GCP
- selector: GCP workspace types render with readable prefixes
- root: post-elevation guidance for GCP

Out of scope, deliberately: the SCA API spec defines no GCP credential
shape, so grant env stays AWS-only, and grant request submit rejects GCP
explicitly rather than falling through the on-demand role branching.

Not yet verified against a live GCP tenant; noted in README.
Copilot AI lite review requested due to automatic review settings August 13, 2026 16:10

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends grant-cli’s SCA cloud access support to include GCP across eligibility listing, elevation, grant status, and grant revoke, while keeping grant env AWS-only and preventing it from issuing an elevation before validating provider constraints.

Changes:

  • Add GCP as a supported CSP end-to-end (flags/help, provider parsing, multi-CSP fan-out, post-elevation guidance).
  • Introduce a preElevate hook in the shared elevation flow and use it to block non-AWS targets in grant env before creating an SCA session.
  • Add/expand tests for GCP eligibility unmarshalling, pagination/routing, CLI formatting, and command behavior; update docs/CHANGELOG to reflect the new support and limitations.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
README.md Document GCP support and clarify grant env remains AWS-only; add --provider gcp usage.
internal/ui/selector.go Render GCP workspace types (project/folder/org) in interactive selector.
internal/ui/selector_test.go Add selector formatting test cases for GCP workspace types.
internal/sca/service_test.go Add GCP-specific eligibility route/pagination test coverage.
internal/sca/models/eligibility.go Add CSPGCP and GCP workspace type constants.
internal/sca/models/eligibility_test.go Add unmarshalling tests for GCPEligibleTarget shapes + constant check.
cmd/status.go Accept/filter/format GCP provider for grant status.
cmd/status_test.go Add tests for parseProvider including GCP.
cmd/root.go Include GCP in supported CSPs; add preElevate hook to avoid env burning sessions; add GCP guidance.
cmd/root_elevate_test.go Update provider validation tests; add fetchEligibility and guidance tests covering GCP.
cmd/revoke.go Update provider help text for GCP in grant revoke.
cmd/request_test.go Add tests pinning “GCP unsupported” behavior for request submit flows.
cmd/request_submit.go Explicitly reject GCP for grant request submit and on-demand role discovery.
cmd/list.go Update provider help text to include GCP.
cmd/favorites.go Update provider help text to include GCP.
cmd/env.go Make AWS-only behavior explicit; add requireAWSTarget preflight validation.
cmd/env_test.go Add tests ensuring non-AWS providers don’t elevate; add AWS elevate-count and nil-credentials cases.
CLAUDE.md Update project guidance/docs to reflect GCP support and AWS-only env.
CHANGELOG.md Add entries for GCP support and the grant env validation fix.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread cmd/root.go
Comment on lines 266 to 268
// supportedCSPs lists the cloud providers supported for elevation.
var supportedCSPs = []models.CSP{models.CSPAzure, models.CSPAWS}
var supportedCSPs = []models.CSP{models.CSPAzure, models.CSPAWS, models.CSPGCP}

Addresses the PR #53 review.

The GCP guard in 'grant request submit' only ran on the --provider flag
and inside interactive role discovery, so omitting --provider and passing
--role-id let a GCP workspace through both. rejectGCPWorkspace now runs
immediately after target resolution, independent of the flag and of which
role path is taken, and matches on the CSP tag as well as the GCP
workspace types.

requireAWSTarget now fails closed on an unresolved CSP instead of letting
it reach the elevation, matching the intent of the pre-flight check.

Also drops TestCSPGCP_Constant, which only asserted a constant equals its
own literal.
EligibleTarget.CSP is json:"-" and grant list never re-resolves it, so
`grant list --provider aws -o json` emitted "provider": "". The
single-provider branch of fetchEligibility now sets CSP just like the
multi-CSP branch.
@aaearon
aaearon changed the base branch from chore/dependency-upgrades to main August 13, 2026 20:06
@aaearon
aaearon merged commit b69a336 into main Aug 13, 2026
1 check passed
@aaearon
aaearon deleted the feat/gcp-support branch August 13, 2026 20:10
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