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
24 changes: 21 additions & 3 deletions app/messages/app_manifest_message.rb
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,12 @@ def manifest_features_update_message
end

def audit_hash
override_env = original_yaml['env'] ? { 'env' => Presenters::Censorship::PRIVATE_DATA_HIDDEN } : {}
override_cnb = original_yaml['cnb-credentials'] ? { 'cnb-credentials' => Presenters::Censorship::PRIVATE_DATA_HIDDEN } : {}
original_yaml.merge(override_env).merge(override_cnb)
result = original_yaml.dup
result['env'] = Presenters::Censorship::PRIVATE_DATA_HIDDEN if result.key?('env')
result['cnb-credentials'] = Presenters::Censorship::PRIVATE_DATA_HIDDEN if result.key?('cnb-credentials')
obfuscate_buildpack_urls(result)
redact_service_parameters(result)
result
end

def app_lifecycle_hash
Expand Down Expand Up @@ -164,6 +167,21 @@ def app_lifecycle_hash

attr_reader :original_yaml

def obfuscate_buildpack_urls(result)
result['buildpack'] = CloudController::UrlSecretObfuscator.obfuscate(result['buildpack']) if result['buildpack']
result['buildpacks'] = result['buildpacks'].map { |b| CloudController::UrlSecretObfuscator.obfuscate(b) } if result['buildpacks']
end

def redact_service_parameters(result)
return unless result['services']

result['services'] = result['services'].map do |svc|
next svc unless svc.is_a?(Hash) && svc.key?('parameters')

svc.merge('parameters' => Presenters::Censorship::PRIVATE_DATA_HIDDEN)
end
end

def manifest_buildpack_message
@manifest_buildpack_message ||= ManifestBuildpackMessage.new(buildpack:)
end
Expand Down
3 changes: 2 additions & 1 deletion app/repositories/service_generic_binding_event_repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,9 @@ def record_show(service_binding, user_audit_info)
private

def censor_request_attributes(request)
attrs = request.dup.stringify_keys
attrs = request.dup.stringify_keys
attrs['data'] = Presenters::Censorship::PRIVATE_DATA_HIDDEN if attrs.key?('data')
attrs['parameters'] = Presenters::Censorship::PRIVATE_DATA_HIDDEN if attrs.key?('parameters')
attrs
end

Expand Down
72 changes: 72 additions & 0 deletions spec/unit/messages/app_manifest_message_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,78 @@ module VCAP::CloudController
expect(message.audit_hash).to eq(expected_hash)
end
end

context 'when "buildpack" contains credentials in the URL' do
let(:parsed_yaml) do
{
'buildpack' => 'https://user:secret@git.example.com/buildpack.git'
}
end

it 'obfuscates the credentials in the buildpack URL' do
message = AppManifestMessage.create_from_yml(parsed_yaml)
expect(message.audit_hash['buildpack']).to eq('https://***:***@git.example.com/buildpack.git')
end
end

context 'when "buildpack" does not contain credentials' do
let(:parsed_yaml) { { 'buildpack' => 'ruby_buildpack' } }

it 'leaves the buildpack value unchanged' do
message = AppManifestMessage.create_from_yml(parsed_yaml)
expect(message.audit_hash['buildpack']).to eq('ruby_buildpack')
end
end

context 'when "buildpacks" contains credential URLs' do
let(:parsed_yaml) do
{
'buildpacks' => [
'https://user:secret@git.example.com/bp1.git',
'ruby_buildpack'
]
}
end

it 'obfuscates credentials in each buildpack URL' do
message = AppManifestMessage.create_from_yml(parsed_yaml)
expect(message.audit_hash['buildpacks']).to eq([
'https://***:***@git.example.com/bp1.git',
'ruby_buildpack'
])
end
end

context 'when "services" contain parameters' do
let(:parsed_yaml) do
{
'services' => [
{ 'name' => 'my-service', 'parameters' => { 'key' => 'secret-value' } },
{ 'name' => 'other-service' }
]
}
end

it 'redacts parameters from each service binding' do
message = AppManifestMessage.create_from_yml(parsed_yaml)
services = message.audit_hash['services']
expect(services[0]).to eq({ 'name' => 'my-service', 'parameters' => '[PRIVATE DATA HIDDEN]' })
expect(services[1]).to eq({ 'name' => 'other-service' })
end
end

context 'when "services" is a list of plain strings' do
let(:parsed_yaml) do
{
'services' => %w[my-service other-service]
}
end

it 'leaves the services list unchanged' do
message = AppManifestMessage.create_from_yml(parsed_yaml)
expect(message.audit_hash['services']).to eq(%w[my-service other-service])
end
end
end

describe '#manifest_process_scale_messages' do
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
require 'spec_helper'
require 'repositories/service_generic_binding_event_repository'

module VCAP::CloudController
module Repositories
RSpec.describe ServiceGenericBindingEventRepository do
let(:user_guid) { 'user-guid' }
let(:user_email) { 'some-email' }
let(:user_name) { 'some-username' }
let(:user_audit_info) { UserAuditInfo.new(user_guid:, user_name:, user_email:) }
let(:service_binding) { create(:service_binding, name: 'some-binding-name') }
let(:repository) { described_class.new(described_class::SERVICE_APP_CREDENTIAL_BINDING) }

describe '#record_start_create' do
it 'censors metadata.request.parameters' do
request = { 'big' => 'data', 'parameters' => { 'secret' => 'value' } }

event = repository.record_start_create(service_binding, user_audit_info, request)

expect(event.metadata[:request]).to eq(
{
'big' => 'data',
'parameters' => '[PRIVATE DATA HIDDEN]'
}
)
end
end

describe '#record_create' do
it 'censors metadata.request.parameters' do
request = { 'big' => 'data', parameters: { 'secret' => 'value' } }

event = repository.record_create(service_binding, user_audit_info, request)

expect(event.metadata[:request]).to eq(
{
'big' => 'data',
'parameters' => '[PRIVATE DATA HIDDEN]'
}
)
end
end

describe '#record_update' do
it 'censors metadata.request.parameters' do
request = { 'big' => 'data', 'parameters' => { 'secret' => 'value' } }

event = repository.record_update(service_binding, user_audit_info, request)

expect(event.metadata[:request]).to eq(
{
'big' => 'data',
'parameters' => '[PRIVATE DATA HIDDEN]'
}
)
end
end
end
end
end
Loading