Skip to content
Open
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
17 changes: 17 additions & 0 deletions app/controllers/v3/builds_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ def create
unprocessable_package! unless package && permission_queryer.can_manage_apps_in_active_space?(package.space.id)
require_writable_space!(package.space)

ensure_can_set_custom_staging_input!(message, package.space)

FeatureFlag.raise_unless_enabled!(:diego_docker) if package.type == PackageModel::DOCKER_TYPE

lifecycle = LifecycleProvider.provide(package, message)
Expand Down Expand Up @@ -112,6 +114,21 @@ def can_read_build?(space)
permission_queryer.can_update_build_state? || permission_queryer.can_read_from_space?(space.id, space.organization_id)
end

def ensure_can_set_custom_staging_input!(message, space)
return unless custom_staging_input?(message)

unauthorized! unless permission_queryer.can_write_to_active_space?(space.id)
end

def custom_staging_input?(message)
return true if message.requested?(:environment_variables)

lifecycle_data = message.lifecycle_data
return false unless lifecycle_data.is_a?(Hash)

%i[buildpacks stack credentials].any? { |key| lifecycle_data.key?(key) }
end

def create_valid_update_message
message = VCAP::CloudController::BuildUpdateMessage.new(hashed_params[:body])
unprocessable!(message.errors.full_messages) unless message.valid?
Expand Down
8 changes: 8 additions & 0 deletions app/controllers/v3/processes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ def update
message = ProcessUpdateMessage.new(hashed_params[:body])
unprocessable!(message.errors.full_messages) unless message.valid?

ensure_can_set_execution_fields!(message)

ProcessUpdate.new(user_audit_info).update(@process, message, NonManifestStrategy)

render status: :ok, json: Presenters::V3::ProcessPresenter.new(@process)
Expand Down Expand Up @@ -147,6 +149,12 @@ def ensure_can_write
require_writable_space!(@space)
end

def ensure_can_set_execution_fields!(message)
return unless message.requested?(:command) || message.requested?(:user)

unauthorized! unless permission_queryer.can_write_to_active_space?(@space.id)
end

def process_not_found!
resource_not_found!(:process)
end
Expand Down
29 changes: 28 additions & 1 deletion spec/request/builds_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@
code: 201
}
h['space_supporter'] = {
code: 201
code: 403,
errors: CF_NOT_AUTHORIZED
}
h
end
Expand Down Expand Up @@ -169,6 +170,32 @@
end
end

context 'permissions for a plain restage without custom staging input' do
let(:create_request) do
{
package: {
guid: package.guid
}
}
end

let(:api_call) { ->(user_headers) { post '/v3/builds', create_request.to_json, user_headers } }
let(:org) { space.organization }
let(:user) { create(:user) }

let(:expected_codes_and_responses) do
h = Hash.new(
{ code: 422 }.freeze
)
h['admin'] = { code: 201 }
h['space_developer'] = { code: 201 }
h['space_supporter'] = { code: 201 }
h
end

it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS
end

context 'telemetry' do
let(:logger_spy) { spy('logger') }

Expand Down
43 changes: 42 additions & 1 deletion spec/request/processes_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@
h = Hash.new({ code: 403, errors: CF_NOT_AUTHORIZED }.freeze)
h['admin'] = { code: 200, response_object: expected_response }
h['space_developer'] = { code: 200, response_object: expected_response }
h['space_supporter'] = { code: 200, response_object: expected_response }
h['space_supporter'] = { code: 403, errors: CF_NOT_AUTHORIZED }
h['org_auditor'] = { code: 404 }
h['org_billing_manager'] = { code: 404 }
h['no_role'] = { code: 404 }
Expand All @@ -976,6 +976,47 @@
end
end

context 'permissions when the update does not set command or user' do
let(:update_request) do
{
health_check: {
type: 'process',
data: {
timeout: 20,
interval: 5
}
},
readiness_health_check: {
type: 'port',
data: {
invocation_timeout: 10,
interval: 6
}
},
metadata: metadata
}.to_json
end

let(:expected_response_without_command) do
expected_response.merge('command' => 'rackup')
end

let(:api_call) { ->(user_headers) { patch "/v3/processes/#{process.guid}", update_request, user_headers } }

let(:expected_codes_and_responses) do
h = Hash.new({ code: 403, errors: CF_NOT_AUTHORIZED }.freeze)
h['admin'] = { code: 200, response_object: expected_response_without_command }
h['space_developer'] = { code: 200, response_object: expected_response_without_command }
h['space_supporter'] = { code: 200, response_object: expected_response_without_command }
h['org_auditor'] = { code: 404 }
h['org_billing_manager'] = { code: 404 }
h['no_role'] = { code: 404 }
h
end

it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS
end

it 'updates the process' do
patch "/v3/processes/#{process.guid}", update_request, developer_headers.merge('CONTENT_TYPE' => 'application/json')

Expand Down
Loading