Skip to content

Draft: implement space-owned service-account lifecycle and runtime identity - #5520

Draft
rkoster wants to merge 65 commits into
cloudfoundry:mainfrom
rkoster:service-accounts-poc
Draft

rkoster wants to merge 65 commits into
cloudfoundry:mainfrom
rkoster:service-accounts-poc

Conversation

@rkoster

@rkoster rkoster commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Community RFC draft: cloudfoundry/community#1645.

Draft implementation of the service-account proposal, exercised end-to-end in a CF lab.

Intentional proposal revision: accounts are space-owned, with one immutable owning space and same-space app assignment only. This supersedes the gist's org ownership/cross-space use grants. Names remain foundation-unique and immutable, with permanent deletion tombstones.

  • Add /v3/service_accounts create/list/show/update/delete and account app listing, plus GET/PATCH /v3/apps/:guid/relationships/service_account.
  • Space managers/platform admins manage accounts; app writers assign within the owning space. Bind does not implicitly grant roles.
  • Provision canonical secretless UAA clients (cf:service-account:<name>, exact <name>.svc.identity DNS SAN) and roleless CAPI OAuth principals on first bind through retryable pollable jobs. Reuse active provisioning jobs and reject client/principal collisions and conflicting lifecycle operations.
  • Reconcile disable/enable/delete, retaining roles on disable and rejecting direct account deletion while desired or active process/task references exist. Space/org deletion cascades workloads, managed clients, principals/roles and accounts, retaining name reservations; cleanup failures preserve the parent and support retry.
  • Account clients reference an operator-defined UAA trust bundle (required worker setting identity_ca_ref → tls-client-auth-ca-ref, UAA build(deps): bump json_pure from 2.7.6 to 2.8.1 #4076 named bundles). Inline CA certificates are not supported. CA rotation changes the bundle's contents in UAA; registered clients never change. Any difference in an existing client, including a different bundle name, is a collision.
  • Add an atomic rolling seven-day creation budget per authenticated principal across all spaces. Operator configuration supports unlimited (-1); platform admins and admin automation are exempt. Failed requests consume no budget; account deletion and audit-event retention do not refund it.
  • Snapshot launch identity for processes/runtime tasks, propagate typed certificate properties and non-secret VCAP_SERVICE_ACCOUNT, exclude staging, and reject unsupported/unready runtime identity. Assignment changes require explicit restart.
  • Add lifecycle/assignment audit events, API documentation, generated Ruby BBS bindings, and MySQL collation/partial-migration recovery exercised in the lab.

Verification

History intentionally preserves small failing-test RED and passing-implementation GREEN commits.

  • RFC follow-ups: budget RED 93fffd2bc → GREEN a1a6dc0b5; cascade RED 052cd6293 / corrected runtime fixture RED c3c53dfec → GREEN ec582b703.

  • Trust bundle references: RED 097b64980 → GREEN 37de53e7f, later made the only supported trust: RED 45074e465 → GREEN bbf68fabf (removed inline CA, trust-drift reconciliation and the management-client put that an intermediate lab run had required). 161 related unit/request examples pass, changed files lint-clean.

  • Follow-up verification: 38 budget/request examples (including concurrent cross-space creation), 105 lifecycle/action/request regressions, 42 space/org deletion request regressions; all passing. Nine changed Ruby files lint-clean. Creation ledger migration exercised on PostgreSQL.

  • Local milestone: 721 targeted request/unit examples passed; 57 changed Ruby files lint-clean; API documentation build passed.

  • Subsequent lab fixes: MySQL migration/assignment regressions (8 examples) and full managed-client provisioning action (15 examples) passed with lint checks.

  • Live two-app and runtime-task validation: same account SAN, independent keys; certificate-authenticated token acquisition; zero visible apps without roles and two after an explicit role grant; disable blocks new tokens; enable retains roles; unbind without restart retains launch identity, restart removes the SAN and old-account authentication fails.

  • Native CLI demo completed the flow using go run ./main.go, including provisioning jobs and lifecycle operations.

Draft dependencies and open criteria

  • Companion drafts: BBS contract #168, capi-release #702, Diego #1216, CLI #3875.
  • UAA authentication baseline: Harden the RFC 8705 mTLS token endpoint - Supersedes #3972 uaa#4076. Live tokens currently include cnf; the draft requires bearer issuance without it. Per-client RFC 8705 policy feedback: Harden the RFC 8705 mTLS token endpoint - Supersedes #3972 uaa#4076 (review). CAPI registration will also need explicit tls_client_certificate_bound_access_tokens: false once UAA honors it.
  • The dedicated lab provisioning client requires clients.admin in addition to read/write to register CAPI authorities. Namespace-limited client administration is not yet demonstrated; managed account clients receive no management authorities.
  • Authoritative BBS contract source is separate revision 869b0650f4147bb24d790f52153ef571fc11bda0, now published in BBS draft #168. Generated bindings originate there. Upstream module publication/version alignment remains a merge prerequisite.
  • No automatic mixed-version capability negotiation: keep runtime disabled until all participating BBS/rep/cells support the contract. Default-off gates are deliberate.
  • Remaining live criteria include timed renewal, near-leaf-expiry token lifetime cap, staging certificate inspection, broader negative matrices and Windows runtime. Lab CAPI calls used internal HTTP; UAA mTLS used verified direct TLS.
  • Disable/unbind/restart are not immediate cryptographic revocation. Route-policy integration and external WIF/OSB are subsequent work.

Trust bundle references validated end to end in the lab, last with the reference-only build bbf68fabf (UAA #4076 head bec01f667, worker identity_ca_ref: diego-instance-identity): disable returned 401 and enable recreated the client by reference; a new account was provisioned by reference and its app received tokens after restart; each app requesting the other account's client got 401. Both apps ended with 300-second tokens without cnf. The creation budget and cascade follow-ups are locally verified only. Account-backed OSB bindings and account route grants remain future integration work.

This is a discussion/implementation draft, not a claim of full RFC acceptance. Tested source head: bbf68fabf.

rkoster added 30 commits October 5, 2026 18:30

This branch has not been deployed

No deployments
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