Skip to content

feat(m2m): gRPC admin RPCs for ServiceAccount + TrustedIssuer [Phase 1 — PR 4/5]#645

Merged
lakhansamani merged 1 commit into
feat/workload-identity-phase1from
feat/workload-identity-phase1-grpc
Jul 6, 2026
Merged

feat(m2m): gRPC admin RPCs for ServiceAccount + TrustedIssuer [Phase 1 — PR 4/5]#645
lakhansamani merged 1 commit into
feat/workload-identity-phase1from
feat/workload-identity-phase1-grpc

Conversation

@lakhansamani

Copy link
Copy Markdown
Contributor

Summary

Adds the gRPC + REST (grpc-gateway) admin surface for ServiceAccount/TrustedIssuer on top of the service layer from #644. Mirrors the existing Webhook RPC pattern exactly.

Chains on: #644 (merged into this integration branch)

What's in this PR

  • proto/authorizer/v1/admin.proto — 11 new RPCs (CreateServiceAccount, UpdateServiceAccount, DeleteServiceAccount, RotateServiceAccountSecret, GetServiceAccount, ServiceAccounts, AddTrustedIssuer, UpdateTrustedIssuer, DeleteTrustedIssuer, GetTrustedIssuer, TrustedIssuers), each with a REST mapping under /v1/admin/* and buf.validate constraints matching what the service layer already enforces.
  • internal/grpcsrv/handlers/admin.go — 11 thin handler methods delegating to the already-merged AdminProvider.
  • internal/grpcsrv/handlers/admin_project.go — model→proto projection helpers.
  • Regenerated gen/ (proto codegen + OpenAPI spec).
  • 10 new gRPC integration tests (admin_service_accounts_grpc_test.go, admin_trusted_issuers_grpc_test.go) using the existing bufconn test harness.

Security-critical invariant

The ServiceAccount proto message has no client_secret field — it's structurally impossible for GetServiceAccount/ServiceAccounts to leak it. The plaintext secret only ever appears on CreateServiceAccountResponse (reused by rotate), matching the GraphQL API's design in #644.

CreateServiceAccountRequest.allowed_scopes carries buf.validate min_items = 1, so an empty-scope create is rejected at the transport layer (InvalidArgument) before it reaches the service layer's own guard — same outcome, defense in depth.

PR chain

PR 1 — schema + interface + SQL + constants     merged → feat/workload-identity-phase1  ✅ #641
PR 2 — NoSQL provider implementations           merged → feat/workload-identity-phase1  ✅ #642
PR 3 — service layer + admin GraphQL API        merged → feat/workload-identity-phase1  ✅ #644
PR 4 — gRPC admin RPCs                          🔄 this PR
PR 5 — client_credentials grant + tests

Test plan

  • make proto-lint, make proto-gen (gen/ committed, not stale)
  • go build ./..., go vet ./...
  • make lint — lint-go: 0 issues (lint-ts fails on pre-existing unrelated frontend warnings)
  • 10 new gRPC integration tests — all pass
  • Full make test-sqlite — pass

- 11 admin RPCs (create/update/delete/rotate/get/list service accounts,
  add/update/delete/get/list trusted issuers) over gRPC + REST gateway
- client secret surfaced only via CreateServiceAccountResponse; the
  ServiceAccount proto message has no secret field so get/list/update
  cannot leak it
- thin handlers delegate to the existing AdminProvider; projections
  mirror the webhook pattern
@lakhansamani lakhansamani merged commit 5b39fda into feat/workload-identity-phase1 Jul 6, 2026
6 checks passed
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