Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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:
description: Instance identity CA PEM trusted for exact account DNS SAN authentication.
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

Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,15 @@ 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') %>
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: <%= p('cc.service_accounts.identity_ca').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
24 changes: 24 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,30 @@ 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' => "-----BEGIN CERTIFICATE-----\nidentity-ca\n-----END CERTIFICATE-----",
'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' => manifest_properties['cc']['service_accounts']['identity_ca']
)
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 '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
+112 −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
+148 −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
+19 −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
+140 −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
+86 −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