Skip to content

feat(auth): support pure service account mode without impersonation#399

Open
carrotRakko wants to merge 1 commit intosteipete:mainfrom
delight-co:feat/sa-pure-mode
Open

feat(auth): support pure service account mode without impersonation#399
carrotRakko wants to merge 1 commit intosteipete:mainfrom
delight-co:feat/sa-pure-mode

Conversation

@carrotRakko
Copy link

Summary

When a service account is configured via gog auth service-account set, the CLI always sets cfg.Subject (the JWT sub claim), which triggers Domain-Wide Delegation. This makes it impossible to use a service account in "pure" mode — where it accesses only resources explicitly shared with its own email address.

This PR skips setting cfg.Subject when the provided subject matches the service account's own client_email. This enables a common automation pattern: share a Drive folder or Calendar with the SA email, and access only those resources — no DWD required.

Changes

  • internal/googleapi/service_account.go — guard cfg.Subject assignment: only set when subject differs from the SA's client_email
  • internal/googleapi/service_account_test.go — 3 test cases: pure SA mode, impersonation mode, empty subject

Test plan

  • go test ./internal/googleapi/ — all existing + new tests pass
  • go build ./... — compiles cleanly

Closes #346

✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)

Skip setting cfg.Subject when the subject matches the service account's
own client_email.  This lets a service account access only resources
explicitly shared with it, without requiring Domain-Wide Delegation.

Closes steipete#346

✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)
delight-ai-agent added a commit to delight-co/finest-grained-auth-proxy that referenced this pull request Mar 3, 2026
## Summary

- Add service account (SA) key file support alongside existing OAuth
keyring credentials
- When a credential entry specifies `sa_key_file` + `account`, fgap
copies the key to gog's expected path
(`~/.config/gogcli/sa-{base64url(email)}.json`) on first use (lazy
provisioning)
- No keyring password or OAuth token needed — the SA accesses only
resources explicitly shared with its email
- Update Dockerfile to use `delight-co/gogcli` fork `v0.12.0-delight.1`
which adds SA pure mode support (upstream PR:
steipete/gogcli#399)
- Add config example for SA credential type

## Changes

| File | What |
|------|------|
| `fgap/plugins/google/credential.py` | SA credential selection + key
provisioning to gog's expected path |
| `fgap/plugins/google/plugin.py` | Health check support for SA
credentials (file existence check) |
| `config.example.json5` | SA credential config example |
| `Dockerfile` | Switch to `delight-co/gogcli` fork with SA pure mode |
| `tests/test_google_credential.py` | 5 new tests for SA credential
selection + provisioning |
| `tests/test_google_health.py` | 3 new tests for SA health check |

## Design decisions

- **`sa_key_file` (path) over inline JSON**: Config stays clean (no
JSON-in-JSON), secrets stay in files, key rotation = file swap
- **Lazy provisioning**: Copy SA key on first `select_credential` call.
Plugin ABC has no startup hook, so sync file copy at selection time is
the simplest approach
- **First-match-wins**: Same ordering semantics as OAuth credentials —
SA and OAuth entries can coexist, first match wins

## Test plan

- [x] All existing tests pass (381 total)
- [x] New SA credential tests (5): selection, provisioning path,
priority, fallthrough, skip invalid
- [x] New SA health check tests (3): valid file, missing file, mixed
OAuth+SA

✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)

Co-authored-by: Mitsuyuki Osabe <24588751+carrotRakko@users.noreply.github.com>
delight-ai-agent added a commit to delight-co/gogcli that referenced this pull request Mar 3, 2026
## Summary

Mirrors upstream PR steipete#399.

When a service account is configured via `gog auth service-account set`,
the CLI always sets `cfg.Subject` (the JWT `sub` claim), which triggers
Domain-Wide Delegation. This makes it impossible to use a service
account in "pure" mode — where it accesses only resources explicitly
shared with its own email address.

This PR skips setting `cfg.Subject` when the provided subject matches
the service account's own `client_email`. This enables a common
automation pattern: share a Drive folder or Calendar with the SA email,
and access only those resources — no DWD required.

## Changes

- **`internal/googleapi/service_account.go`** — guard `cfg.Subject`
assignment: only set when subject differs from the SA's `client_email`
- **`internal/googleapi/service_account_test.go`** — 3 test cases: pure
SA mode, impersonation mode, empty subject

## Test plan

- [x] `go test ./internal/googleapi/` — all existing + new tests pass
- [x] `go build ./...` — compiles cleanly

✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)

Co-authored-by: Mitsuyuki Osabe <24588751+carrotRakko@users.noreply.github.com>
@delight-ai-agent delight-ai-agent deleted the feat/sa-pure-mode branch March 3, 2026 10:22
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.

feat(drive): Support pure service account mode (no impersonation) for Drive

1 participant