Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e7231e0
Test service account worker configuration rendering (red)
rkoster Oct 5, 2026
84b1895
Render dedicated service account worker trust and credentials
rkoster Oct 5, 2026
bd7d883
Test service account API gate and discovery rendering (red)
rkoster Oct 5, 2026
333cda0
Render default-off service account API and runtime gates
rkoster Oct 5, 2026
ed47d22
Test service account clock runtime rendering (red)
rkoster Oct 5, 2026
7dbf40b
Render service account runtime discovery in clock config
rkoster Oct 5, 2026
d2f5bb7
Bump cloud_controller_ng for space-owned service account POC
rkoster Oct 5, 2026
fefb8c4
Make packaged application directories readable by runtime user
rkoster Oct 6, 2026
9fa307b
Bump cloud_controller_ng for MySQL service account migration recovery
rkoster Oct 6, 2026
ca65001
Bump cloud_controller_ng for normalized UAA client reconciliation
rkoster Oct 6, 2026
fbd0c3e
Test configurable service account creation budget rendering (red)
rkoster Oct 7, 2026
e2a5bce
Render configurable weekly service account creation limit
rkoster Oct 7, 2026
a186d2d
Bump cloud_controller_ng for creation budget and recursive account cl…
rkoster Oct 7, 2026
5089b31
Test rendering service account trust bundle reference for workers (red)
rkoster Oct 16, 2026
90d4e4b
Render service account trust bundle reference for workers
rkoster Oct 16, 2026
7bc5fe1
Bump cloud_controller_ng for trust bundle references and owned trust …
rkoster Oct 16, 2026
42721a2
Bump cloud_controller_ng for management client updates
rkoster Oct 16, 2026
6845b53
Test requiring a trust bundle reference for worker provisioning (red)
rkoster Oct 16, 2026
1178b26
Require a UAA trust bundle reference for worker provisioning
rkoster Oct 16, 2026
f267b9e
Bump cloud_controller_ng for reference-only account client trust
rkoster Oct 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions jobs/cloud_controller_clock/spec
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ consumes:
optional: true

properties:
cc.service_accounts.runtime_enabled:
description: Enable typed account identity in clock reconciliation after runtime rollout.
default: false
cc.service_accounts.token_endpoint:
description: HTTPS UAA certificate-authenticated token endpoint for account discovery.
default: ""
ssl.skip_cert_verify:
description: "specifies that the job is allowed to skip ssl cert verification"
default: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,9 @@ uaa:
<% end %>

# App staging parameters
service_account_runtime_enabled: <%= p('cc.service_accounts.runtime_enabled') %>
service_account_token_endpoint: <%= yaml_escape(p('cc.service_accounts.token_endpoint')) %>

staging:
timeout_in_seconds: <%= p("cc.staging_timeout_in_seconds") %>
auth:
Expand Down
12 changes: 12 additions & 0 deletions jobs/cloud_controller_ng/spec
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,18 @@ consumes:
optional: true

properties:
cc.service_accounts.creation_limit:
description: Foundation-wide maximum successful service account creations per non-admin authenticated principal over a rolling seven-day window. Platform admins are exempt; -1 means unlimited and 0 prevents non-admin creation. Deletion does not refund budget.
default: -1
cc.service_accounts.provisioning_enabled:
description: Enable asynchronous service account client reconciliation requests.
default: false
cc.service_accounts.runtime_enabled:
description: Enable typed account runtime identity only after all BBS/rep/cells support it.
default: false
cc.service_accounts.token_endpoint:
description: HTTPS UAA certificate-authenticated token endpoint for account discovery.
default: ""
ssl.skip_cert_verify:
description: "specifies that the job is allowed to skip ssl cert verification"
default: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,11 @@ credential_references:
interpolate_service_bindings: <%= p("cc.credential_references.interpolate_service_bindings") %>

# App staging parameters
service_account_provisioning_enabled: <%= p('cc.service_accounts.provisioning_enabled') %>
service_account_creation_limit: <%= p('cc.service_accounts.creation_limit') %>
service_account_runtime_enabled: <%= p('cc.service_accounts.runtime_enabled') %>
service_account_token_endpoint: <%= yaml_escape(p('cc.service_accounts.token_endpoint')) %>

staging:
legacy_md5_buildpack_paths_enabled: <%= p("cc.legacy_md5_buildpack_paths_enabled") %>
timeout_in_seconds: <%= p("cc.staging_timeout_in_seconds") %>
Expand Down
19 changes: 18 additions & 1 deletion jobs/cloud_controller_worker/spec
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,24 @@ consumes:
optional: true

properties:
cc.service_accounts.provisioning_enabled:
description: Enable dedicated managed service account client reconciliation in workers.
default: false
cc.service_accounts.runtime_enabled:
description: Enable typed account runtime identity only after all BBS/rep/cells support it.
default: false
cc.service_accounts.token_endpoint:
description: HTTPS UAA certificate-authenticated token endpoint exposed to bound workloads.
default: ""
cc.service_accounts.management_client_id:
description: Dedicated UAA client with managed account namespace client-management permissions.
default: ""
cc.service_accounts.management_client_secret:
description: Secret of the dedicated UAA account-management client; never exposed to workloads.
default: ""
cc.service_accounts.identity_ca_ref:
description: Required with provisioning. Name of a UAA trust bundle (uaa.mtls.trust_bundles) containing the instance identity CA, referenced by every account client. Rotate the CA by changing the bundle's contents in UAA; clients never change.
default: ""
ssl.skip_cert_verify:
description: "specifies that the job is allowed to skip ssl cert verification"
default: false
Expand Down Expand Up @@ -599,4 +617,3 @@ properties:
when applying manifests. If a service broker fails to complete a service binding request
before the specified duration, the manifest job will fail."
default: 60

13 changes: 13 additions & 0 deletions jobs/cloud_controller_worker/templates/cloud_controller_ng.yml.erb
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,19 @@ uaa:
client_timeout: <%= cc_internal.p("cc.uaa.client_timeout")%>
<% end %>

service_account_runtime_enabled: <%= p('cc.service_accounts.runtime_enabled') %>
service_account_token_endpoint: <%= yaml_escape(p('cc.service_accounts.token_endpoint')) %>
<% if p('cc.service_accounts.provisioning_enabled') %>
<%
identity_ca_ref = p('cc.service_accounts.identity_ca_ref')
raise 'Set cc.service_accounts.identity_ca_ref to a UAA trust bundle name' if identity_ca_ref.to_s.strip.empty?
%>
service_account_provisioning:
client_id: <%= yaml_escape(p('cc.service_accounts.management_client_id')) %>
client_secret: <%= yaml_escape(p('cc.service_accounts.management_client_secret')) %>
identity_ca_ref: <%= identity_ca_ref.to_json %>
<% end %>

# App staging parameters
staging:
timeout_in_seconds: <%= p("cc.staging_timeout_in_seconds") %>
Expand Down
3 changes: 3 additions & 0 deletions packages/cloud_controller_ng/packaging
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ set -e -x
# shellcheck disable=1090
source "${BOSH_PACKAGES_DIR:-/var/vcap/packages}/ruby-4.0/bosh/compile.env"
cp -a * ${BOSH_INSTALL_TARGET}
# Archive-created parent directories may inherit a private build umask.
# The application is read by the unprivileged vcap runtime user.
chmod -R a+rX "${BOSH_INSTALL_TARGET}/cloud_controller_ng"
cd ${BOSH_INSTALL_TARGET}/cloud_controller_ng

mariadb_dir=/var/vcap/packages/mariadb_connector_c
Expand Down
7 changes: 7 additions & 0 deletions spec/cloud_controller_clock/cloud_controller_clock_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ module Test

let(:template) { job.template('config/cloud_controller_ng.yml') }

it 'renders service account runtime discovery for clock-driven reconciliation' do
manifest_properties['cc']['service_accounts'] = { 'runtime_enabled' => true, 'token_endpoint' => 'https://uaa.example.test/oauth/token/mtls' }
result = YAML.safe_load(template.render(manifest_properties, consumes: links))
expect(result['service_account_runtime_enabled']).to be(true)
expect(result['service_account_token_endpoint']).to eq('https://uaa.example.test/oauth/token/mtls')
end

it 'creates the cloud_controller_ng.yml config file' do
expect do
YAML.safe_load(template.render(manifest_properties, consumes: links))
Expand Down
23 changes: 23 additions & 0 deletions spec/cloud_controller_ng/cloud_controller_ng_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,29 @@ module Test
describe 'config/cloud_controller_ng.yml' do
let(:template) { job.template('config/cloud_controller_ng.yml') }

it 'renders an unlimited service account creation budget by default' do
result = YAML.safe_load(template.render(merged_manifest_properties, consumes: links))
expect(result['service_account_creation_limit']).to eq(-1)
end

it 'renders the foundation-wide non-admin service account creation budget' do
merged_manifest_properties['cc']['service_accounts'] = { 'creation_limit' => 25 }
result = YAML.safe_load(template.render(merged_manifest_properties, consumes: links))
expect(result['service_account_creation_limit']).to eq(25)
end

it 'renders explicit service account gates and discovery without exposing management credentials' do
merged_manifest_properties['cc']['service_accounts'] = {
'provisioning_enabled' => true, 'runtime_enabled' => true,
'token_endpoint' => 'https://uaa.example.test/oauth/token/mtls'
}
result = YAML.safe_load(template.render(merged_manifest_properties, consumes: links))
expect(result['service_account_provisioning_enabled']).to be(true)
expect(result['service_account_runtime_enabled']).to be(true)
expect(result['service_account_token_endpoint']).to eq('https://uaa.example.test/oauth/token/mtls')
expect(result).not_to have_key('service_account_provisioning')
end

it 'creates the cloud_controller_ng.yml config file' do
expect do
YAML.safe_load(template.render(merged_manifest_properties, consumes: links))
Expand Down
37 changes: 37 additions & 0 deletions spec/cloud_controller_worker/cloud_controller_worker_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,43 @@ module Test

let(:template) { job.template('config/cloud_controller_ng.yml') }

it 'renders dedicated provisioning credentials and instance trust only when explicitly enabled' do
manifest_properties['cc']['service_accounts'] = {
'provisioning_enabled' => true,
'runtime_enabled' => false,
'management_client_id' => 'account-manager',
'management_client_secret' => 'manager-secret',
'identity_ca_ref' => 'diego-instance-identity',
'token_endpoint' => 'https://uaa.example.test/oauth/token/mtls'
}
result = YAML.safe_load(template.render(manifest_properties, consumes: links))
expect(result['service_account_provisioning']).to eq(
'client_id' => 'account-manager', 'client_secret' => 'manager-secret',
'identity_ca_ref' => 'diego-instance-identity'
)
expect(result['service_account_runtime_enabled']).to be(false)
expect(result['service_account_token_endpoint']).to eq('https://uaa.example.test/oauth/token/mtls')
end

it 'refuses to render provisioning without a UAA trust bundle reference' do
manifest_properties['cc']['service_accounts'] = {
'provisioning_enabled' => true,
'management_client_id' => 'account-manager',
'management_client_secret' => 'manager-secret'
}
expect { template.render(manifest_properties, consumes: links) }.to raise_error(/Set cc.service_accounts.identity_ca_ref/)
end

it 'no longer declares inline instance identity CA certificates' do
expect(YAML.safe_load(File.read(File.join(release_path, 'jobs/cloud_controller_worker/spec')))['properties']).not_to have_key('cc.service_accounts.identity_ca')
end

it 'keeps service account runtime and provisioning disabled by default' do
result = YAML.safe_load(template.render(manifest_properties, consumes: links))
expect(result['service_account_runtime_enabled']).to be(false)
expect(result).not_to have_key('service_account_provisioning')
end

it 'creates the cloud_controller_ng.yml config file' do
expect do
YAML.safe_load(template.render(manifest_properties, consumes: links))
Expand Down
2 changes: 1 addition & 1 deletion src/cloud_controller_ng
Submodule cloud_controller_ng updated 66 files
+64 −0 app/actions/app_assign_service_account.rb
+1 −1 app/actions/process_restart.rb
+25 −0 app/actions/service_account_creation_budget.rb
+116 −0 app/actions/service_account_provision.rb
+36 −1 app/actions/space_delete.rb
+2 −0 app/actions/task_create.rb
+5 −3 app/collection_transformers/username_populator.rb
+43 −0 app/controllers/v3/app_service_accounts_controller.rb
+141 −0 app/controllers/v3/service_accounts_controller.rb
+48 −0 app/jobs/v3/service_account_provision.rb
+24 −0 app/messages/app_service_account_update_message.rb
+27 −0 app/messages/service_account_create_message.rb
+10 −0 app/messages/service_account_update_message.rb
+17 −0 app/messages/service_accounts_list_message.rb
+3 −0 app/models.rb
+3 −0 app/models/runtime/app_model.rb
+8 −0 app/models/runtime/process_model.rb
+6 −0 app/models/runtime/service_account_annotation_model.rb
+6 −0 app/models/runtime/service_account_label_model.rb
+45 −0 app/models/runtime/service_account_model.rb
+4 −0 app/models/runtime/task_model.rb
+29 −0 app/presenters/v3/service_account_presenter.rb
+21 −0 app/repositories/service_account_event_repository.rb
+9 −0 config/routes.rb
+20 −0 db/migrations/20261005120000_create_service_accounts.rb
+33 −0 db/migrations/20261005120100_add_app_service_account.rb
+16 −0 db/migrations/20261005120200_add_service_account_metadata.rb
+8 −0 db/migrations/20261005120300_add_task_service_account_snapshot.rb
+8 −0 db/migrations/20261005120400_add_process_service_account_snapshot.rb
+10 −0 db/migrations/20261007120000_create_service_account_creations.rb
+153 −0 docs/v3/source/includes/api_resources/_service_accounts.md
+1 −0 docs/v3/source/index.html.md
+15 −0 errors/v3.yml
+2 −1 lib/cloud_controller/backends/staging_environment_builder.rb
+9 −0 lib/cloud_controller/config_schemas/api_schema.rb
+2 −0 lib/cloud_controller/config_schemas/clock_schema.rb
+8 −0 lib/cloud_controller/config_schemas/worker_schema.rb
+22 −0 lib/cloud_controller/dependency_locator.rb
+2 −3 lib/cloud_controller/diego/app_recipe_builder.rb
+4 −0 lib/cloud_controller/diego/environment.rb
+59 −0 lib/cloud_controller/diego/service_account_identity.rb
+4 −0 lib/cloud_controller/diego/task_environment.rb
+2 −7 lib/cloud_controller/diego/task_recipe_builder.rb
+23 −0 lib/cloud_controller/uaa/service_account_client.rb
+3 −2 lib/diego/bbs/models/certificate_properties_pb.rb
+202 −0 spec/request/app_service_accounts_spec.rb
+52 −0 spec/request/service_account_roles_spec.rb
+346 −0 spec/request/service_accounts_spec.rb
+69 −0 spec/unit/actions/app_assign_service_account_spec.rb
+32 −0 spec/unit/actions/organization_delete_spec.rb
+18 −0 spec/unit/actions/process_restart_spec.rb
+32 −0 spec/unit/actions/service_account_creation_budget_spec.rb
+172 −0 spec/unit/actions/service_account_provision_spec.rb
+84 −0 spec/unit/actions/space_delete_spec.rb
+8 −0 spec/unit/actions/task_create_spec.rb
+71 −0 spec/unit/jobs/v3/service_account_provision_spec.rb
+7 −0 spec/unit/lib/cloud_controller/backends/staging_environment_builder_spec.rb
+14 −0 spec/unit/lib/cloud_controller/diego/app_recipe_builder_spec.rb
+15 −0 spec/unit/lib/cloud_controller/diego/environment_spec.rb
+58 −0 spec/unit/lib/cloud_controller/diego/service_account_identity_spec.rb
+9 −0 spec/unit/lib/cloud_controller/diego/task_environment_spec.rb
+8 −0 spec/unit/lib/cloud_controller/diego/task_recipe_builder_spec.rb
+96 −0 spec/unit/lib/cloud_controller/service_account_provisioner_configuration_spec.rb
+49 −0 spec/unit/models/runtime/service_account_assignment_spec.rb
+63 −0 spec/unit/models/runtime/service_account_model_spec.rb
+12 −0 spec/unit/service_account_migration_spec.rb