Skip to content

Commit 17e9190

Browse files
kathapphilippthun
andauthored
Add error handling for invalid encryption keys with logging (#4326)
* Add error handling for invalid encryption keys with logging - Wrapped pbkdf2_hmac in a begin-rescue block to catch encryption key errors. - Added detailed error logging for failed key derivation. * New log only for key=nil * Throw appropriate error instead of UnknownError for GET /v3/service_credential_bindings/:binding_guid/details when encryption-key-label is invalid * enhance error handling * add test for rescue_from decryption error * change error name * handle cipher error in central place in applications controller * add test for GET /v3/apps/:guid/environment_variables when the encryption_key_label is invalid * add test for service borker update when the encryption_key_label is invalid * rename error message, remove obsolete parts in test setups * Update spec/request/apps_spec.rb --------- Co-authored-by: Philipp Thun <[email protected]>
1 parent 5610634 commit 17e9190

File tree

6 files changed

+92
-2
lines changed

6 files changed

+92
-2
lines changed

app/controllers/v3/application_controller.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class ApplicationController < ActionController::Base
9393
rescue_from CloudController::Errors::CompoundError, with: :handle_compound_error
9494
rescue_from ActionDispatch::Http::Parameters::ParseError, with: :handle_invalid_request_body
9595
rescue_from Sequel::DatabaseConnectionError, Sequel::DatabaseDisconnectError, with: :handle_db_connection_error
96+
rescue_from OpenSSL::Cipher::CipherError, with: :handle_key_derivation_error
9697

9798
def configuration
9899
Config.config
@@ -219,6 +220,11 @@ def handle_db_connection_error(_)
219220
handle_api_error(error)
220221
end
221222

223+
def handle_key_derivation_error(_)
224+
error = CloudController::Errors::V3::ApiError.new_from_details('InternalServerError', 'Error while processing encrypted data')
225+
handle_api_error(error)
226+
end
227+
222228
def handle_exception(error)
223229
presenter = ErrorPresenter.new(error, Rails.env.test?, V3ErrorHasher.new(error))
224230
logger.info(presenter.log_message)

errors/v3.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,8 @@
1717
name: UaaRateLimited
1818
http_code: 429
1919
message: "The UAA is currently rate limited. Please try again later"
20+
21+
10001:
22+
name: InternalServerError
23+
http_code: 500
24+
message: "%s"

spec/request/apps_spec.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3398,6 +3398,21 @@
33983398
end
33993399
end
34003400
end
3401+
3402+
context 'when the encryption_key_label is invalid' do
3403+
before do
3404+
allow_any_instance_of(ErrorPresenter).to receive(:raise_500?).and_return(false)
3405+
end
3406+
3407+
it 'fails to decrypt the environment variables and returns a 500 error' do
3408+
app_model # ensure that app model is created before run_cipher is mocked to throw an error
3409+
allow(VCAP::CloudController::Encryptor).to receive(:run_cipher).and_raise(OpenSSL::Cipher::CipherError)
3410+
api_call.call(admin_headers)
3411+
3412+
expect(last_response).to have_status_code(500)
3413+
expect(parsed_response['errors'].first['detail']).to match(/Error while processing encrypted data/i)
3414+
end
3415+
end
34013416
end
34023417

34033418
describe 'GET /v3/apps/:guid/permissions' do

spec/request/service_brokers_spec.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,34 @@ def expect_empty_list(user_headers)
899899
expect(response).to include('detail' => 'Service broker not found')
900900
end
901901
end
902+
903+
context 'when updating credentials and the encryption_key_label is invalid' do
904+
let(:broker) { VCAP::CloudController::ServiceBroker.make }
905+
let(:api_call) do
906+
lambda { |headers|
907+
patch "/v3/service_brokers/#{broker.guid}", { authentication: {
908+
type: 'basic',
909+
credentials: {
910+
username: 'your-username',
911+
password: 'your-password'
912+
}
913+
} }.to_json, headers
914+
}
915+
end
916+
917+
before do
918+
allow_any_instance_of(ErrorPresenter).to receive(:raise_500?).and_return(false)
919+
end
920+
921+
it 'fails to decrypt the broker data and returns a 500 error' do
922+
broker # ensure the broker is created before run_cipher is mocked to throw an error
923+
allow(VCAP::CloudController::Encryptor).to receive(:run_cipher).and_raise(OpenSSL::Cipher::CipherError)
924+
api_call.call(admin_headers)
925+
926+
expect(last_response).to have_status_code(500)
927+
expect(parsed_response['errors'].first['detail']).to match(/Error while processing encrypted data/i)
928+
end
929+
end
902930
end
903931

904932
describe 'POST /v3/service_brokers' do

spec/request/service_credential_bindings_spec.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,21 @@ def check_filtered_bindings(*bindings)
624624
}
625625
end
626626

627+
context 'when the encryption_key_label is invalid' do
628+
before do
629+
allow_any_instance_of(ErrorPresenter).to receive(:raise_500?).and_return(false)
630+
end
631+
632+
it 'fails to decrypt the credentials and returns a 500 error' do
633+
app_binding # ensure that binding is created before run_cipher is mocked to throw an error
634+
allow(VCAP::CloudController::Encryptor).to receive(:run_cipher).and_raise(OpenSSL::Cipher::CipherError)
635+
api_call.call(admin_headers)
636+
637+
expect(last_response).to have_status_code(500)
638+
expect(parsed_response['errors'].first['detail']).to match(/Error while processing encrypted data/i)
639+
end
640+
end
641+
627642
context "last binding operation is in 'create succeeded' state" do
628643
before do
629644
app_binding.save_with_attributes_and_new_operation({}, { type: 'create', state: 'succeeded' })

spec/unit/controllers/v3/application_controller_spec.rb

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,18 @@ def not_found
3838
raise CloudController::Errors::NotFound.new_from_details('NotFound')
3939
end
4040

41-
def db_connection_error
42-
raise Sequel::DatabaseConnectionError.new
41+
def key_derivation_error
42+
raise OpenSSL::Cipher::CipherError
4343
end
4444

4545
def db_disconnect_error
4646
raise Sequel::DatabaseDisconnectError.new
4747
end
4848

49+
def db_connection_error
50+
raise Sequel::DatabaseConnectionError.new
51+
end
52+
4953
def warnings_is_nil
5054
add_warning_headers(nil)
5155
render status: :ok, json: {}
@@ -320,6 +324,23 @@ def warnings_incorrect_type
320324
end
321325
end
322326

327+
describe '#handle_key_derivation_error' do
328+
let!(:user) { set_current_user(VCAP::CloudController::User.make) }
329+
330+
before do
331+
allow_any_instance_of(ErrorPresenter).to receive(:raise_500?).and_return(false)
332+
routes.draw do
333+
get 'key_derivation_error' => 'anonymous#key_derivation_error'
334+
end
335+
end
336+
337+
it 'rescues from OpenSSL::Cipher::CipherError and renders an error presenter' do
338+
get :key_derivation_error
339+
expect(response).to have_http_status(:internal_server_error)
340+
expect(response).to have_error_message(/Error while processing encrypted data/)
341+
end
342+
end
343+
323344
describe '#add_warning_headers' do
324345
let!(:user) { set_current_user(VCAP::CloudController::User.make) }
325346

0 commit comments

Comments
 (0)