Skip to content

feat(iam) policy evaluation stack (WIP!) - #135

Draft
snazy wants to merge 5 commits into
floci-io:mainfrom
snazy:iam-policy-evaluation-stack
Draft

feat(iam) policy evaluation stack (WIP!)#135
snazy wants to merge 5 commits into
floci-io:mainfrom
snazy:iam-policy-evaluation-stack

Conversation

@snazy

@snazy snazy commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@snazy snazy changed the title feat(Iam) policy evaluation stack (WIP!) feat(iam) policy evaluation stack (WIP!) Aug 26, 2026
@hectorvent hectorvent added enhancement New feature or request iam Identity and Access Management (IAM) labels Aug 27, 2026
@snazy
snazy force-pushed the iam-policy-evaluation-stack branch 3 times, most recently from 96040ce to 19613cc Compare September 8, 2026 08:19
@snazy
snazy force-pushed the iam-policy-evaluation-stack branch 6 times, most recently from 449e15d to 8830baf Compare September 8, 2026 21:22
Adds the disabled-by-default IAM allow-policy domain model, a restricted Nessie CEL-Java Conditions profile, principal resolution, role expansion, and pure policy evaluation. The CEL environment exposes only the Version 1 declarations and runtime overloads, with unsupported or failed conditions non-granting.

- [x] New feature (`feat:`)

Models the supported Cloud Storage IAM Conditions subset without introducing a general authentication system or changing the default no-auth emulator behavior. Conditional bindings require Uniform Bucket-Level Access.

Bucket-policy APIs and enforcement are introduced by later commits. ACL authorization, project-policy inheritance, custom roles, full UBLA lifecycle behavior, and CEL profile expansion (including `extract` and regex) remain out of scope.

Focused CEL, evaluator, normalizer, principal-resolver, configuration, and UBLA tests cover the new pure evaluation surface.
## Summary

Preserves the canonical service-account principal when STS exchanges a valid Floci-issued impersonated token for a downscoped token. Principal resolution keeps the downscoped marker so GCS can apply Credential Access Boundary checks before later IAM evaluation.

## Type of change

- [x] New feature (`feat:`)

## GCP Compatibility

Carries identity attribution without storing the source bearer token. External source tokens remain principal-less, and invalid or expired Floci-issued sources retain their existing OAuth-shaped failure behavior.

## Follow-up

No IAM policy is added to STS itself. Recursive downscoping remains rejected until CAB-rule intersection can prove that a requested boundary cannot broaden existing authority.

## Validation

Focused credential-token, principal-resolver, and STS REST tests cover propagation, anonymous external sources, invalid sources, expiry, and recursive-exchange rejection.
## Summary

Adds bucket IAM policy validation, policy bootstrap on bucket creation, IAM-aware `testIamPermissions`, and opt-in authorization checks for supported bucket operations. Enforcement stays disabled by default and uses the shared policy evaluator only when explicitly enabled.

## Type of change

- [x] New feature (`feat:`)

## GCP Compatibility

Preserves disabled-mode behavior, requires Uniform Bucket-Level Access for conditional bindings, and rejects every bucket patch that would remove or disable UBLA while such bindings remain configured. Policy validation and response shapes use existing Cloud Storage IAM endpoints.

## Follow-up

Project-scoped bucket create/list authorization, ACL behavior while UBLA is active, and the complete UBLA lifecycle remain deliberately deferred.

## Validation

Focused REST integration tests cover bucket IAM get/set/testPermissions, policy bootstrap, conditional-policy validation including absent, null, and partial UBLA patches, disabled-mode continuity, and enforce-mode permissions.
## Summary

Applies IAM permission checks to the audited Cloud Storage object surface: JSON and XML reads, updates, deletes, uploads, listing, compose, copy, rewrite, move, and restore. Source and destination authorization is ordered before mutations, including replacement-delete checks.

## Type of change

- [x] New feature (`feat:`)

## GCP Compatibility

Keeps existing GCS endpoint shapes and CAB ordering while mapping each supported operation to its required object permissions. Restore requires `storage.objects.restore` and `storage.objects.create`, plus `storage.objects.delete` when replacing a live object. Denied requests are verified to leave no storage side effect.

## Follow-up

ACL endpoints, signed-URL identity, batch framing, retention/context-specific permissions, and hierarchical-namespace behavior are excluded until they have separately scoped permission mappings and compatibility evidence.

## Validation

Focused REST integration tests cover allow and deny cases for JSON/XML operations, alternate downloads, XML listing and deletion, multipart and resumable uploads, restore, source/destination flows, replacement uploads, and no-side-effect denials.
Completes CAB-first IAM evaluation for principal-bearing downscoped credentials, accepts the Storage client default policy version, documents the boundary, and adds an enforce-mode Java SDK compatibility path from IAM Credentials through `DownscopedCredentials` to Cloud Storage.

- [x] New feature (`feat:`)

A downscoped token minted from a valid Floci-issued impersonated token retains that service-account identity for GCS IAM evaluation only after its CAB permits the request. The normal compatibility matrix remains disabled-mode; the focused SDK scenario restarts only the Java emulator in enforce mode. The IAM, GCS, README, service-index, and setup documentation now distinguish default no-auth behavior from the supported enforce-mode REST surface.

External source tokens remain principal-less, nested downscoping remains rejected, and CAB parsing remains limited to the documented `startsWith` forms. Broader CAB expressions and rule intersection require a separate compatibility design.

Focused token, STS-to-GCS, policy-normalization, object-authorization, and Java SDK compatibility coverage verifies allowed access plus distinct CAB and IAM denials.
@snazy
snazy force-pushed the iam-policy-evaluation-stack branch from 8830baf to 8b4ca5d Compare September 9, 2026 06:22
@snazy

snazy commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

@greptile-apps please review

@greptile-apps

greptile-apps Bot commented Sep 9, 2026

Copy link
Copy Markdown

Greptile Summary

This PR introduces opt-in IAM allow-policy enforcement for supported GCS REST operations, including principal resolution, role and condition evaluation, bucket-policy bootstrapping, downscoped-token identity propagation, overwrite authorization, and UBLA configuration handling.

  • Applies CAB checks before IAM evaluation for supported object operations.
  • Adds bucket IAM enforcement and conditional-policy validation.
  • Adds CEL-based IAM condition evaluation and policy normalization.
  • Extends REST, gRPC, integration, and Java SDK compatibility coverage.
  • Two UBLA validation inconsistencies need correction before merge.

Confidence Score: 3/5

The PR is not yet safe to merge because gRPC can invalidate a conditional bucket policy and valid partial REST IAM-configuration updates can be rejected.

Two concrete update paths mishandle the interaction between UBLA and conditional IAM policies: gRPC omits required transition validation, while REST validates the partial request rather than the merged configuration.

Files Needing Attention: src/main/java/io/floci/gcp/services/gcs/GcsGrpcController.java, src/main/java/io/floci/gcp/services/iam/IamBucketPolicyService.java

Important Files Changed

Filename Overview
src/main/java/io/floci/gcp/services/gcs/GcsGrpcController.java Adds gRPC IAM-configuration update support but bypasses the conditional-policy transition validation used by REST.
src/main/java/io/floci/gcp/services/iam/IamBucketPolicyService.java Coordinates bucket policies and conditions, but incorrectly interprets unrelated partial IAM configuration patches as UBLA removal.
src/main/java/io/floci/gcp/services/iam/GcsIamAuthorizationService.java Composes CAB and IAM permission checks and defers overwrite-delete authorization for atomic evaluation.
src/main/java/io/floci/gcp/services/gcs/GcsService.java Adds atomic overwrite checks and server-managed UBLA lock normalization.
src/main/java/io/floci/gcp/services/iam/NessieIamConditionEvaluator.java Implements a bounded, cached CEL environment for supported IAM conditions.
src/main/java/io/floci/gcp/services/credentials/CredentialTokenService.java Preserves impersonated principals in downscoped tokens and rejects recursive downscoping.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  R[Incoming GCS request] --> P{Protocol}
  P -->|REST object or bucket| C[CAB and IAM authorization]
  C --> E[Resolve principal and bucket policy]
  E --> A{Permission granted?}
  A -->|No| D[Return permission denied]
  A -->|Yes| M[Execute GCS mutation or read]
  P -->|gRPC bucket update| F[Resolve FieldMask into IAM configuration]
  F --> U[Persist through GcsService]
  C --> V[REST UBLA and conditional-policy validation]
  V --> M
  F -. missing equivalent validation .-> U
Loading

Reviews (1): Last reviewed commit: "feat(iam): support IAM-aware downscoped ..." | Re-trigger Greptile

Comment on lines +131 to +133
return GcsGrpcMapper.toProto(service.updateBucketWithResolvedFields(bucketId,
GcsGrpcMapper.bucketUpdateFields(
request.getBucket(), request.getUpdateMask().getPathsList())));
current, request.getBucket(), request.getUpdateMask().getPathsList())));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 gRPC Bypasses Policy Validation

The gRPC UpdateBucket path writes the resolved IAM configuration without calling validateIamConfigurationUpdate, while both REST update paths perform that validation. A gRPC client can therefore disable uniform bucket-level access while conditional IAM bindings remain stored, leaving the bucket in an invalid state that REST rejects. Route the resolved gRPC patch through the same validation before persisting it. This also violates the repository directive to check compatibility across alternate gRPC and REST protocol paths.

Context Used: AGENTS.md (source)

Comment on lines +78 to +82
if (uniformBucketLevelAccessEnabled(bucket)
&& patch != null
&& patch.containsKey("iamConfiguration")
&& !uniformBucketLevelAccessEnabled(patch.get("iamConfiguration"))
&& hasConditionalBindings(getPolicy(bucket))) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Partial Updates Disable UBLA

This check treats every partial iamConfiguration patch that does not explicitly contain uniformBucketLevelAccess.enabled=true as disabling UBLA. On a bucket with UBLA and conditional bindings, a valid patch that only changes publicAccessPrevention is rejected even though GcsService.updateBucket merges the patch and preserves the current UBLA setting. Check whether the patch actually removes or disables UBLA, or validate the merged configuration instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request iam Identity and Access Management (IAM)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants