Skip to content
This repository was archived by the owner on Jun 2, 2021. It is now read-only.

Commit f3a89c1

Browse files
authored
Merge pull request cloudfoundry#1731 from cloudfoundry/optional-logcache-tls
Make logcache tls optional [finishes #173713439]
2 parents 0769108 + e0e1bee commit f3a89c1

4 files changed

Lines changed: 179 additions & 115 deletions

File tree

lib/cloud_controller/config_schemas/api_schema.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ class ApiSchema < VCAP::Config
213213
temporary_ignore_server_unavailable_errors: bool,
214214
},
215215

216-
logcache_tls: {
216+
optional(:logcache_tls) => {
217217
key_file: String,
218218
cert_file: String,
219219
ca_file: String,

lib/logcache/client.rb

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,24 @@ class Client
77
DEFAULT_LIMIT = 100
88

99
def initialize(host:, port:, client_ca_path:, client_cert_path:, client_key_path:, tls_subject_name:, temporary_ignore_server_unavailable_errors:)
10-
client_ca = IO.read(client_ca_path)
11-
client_key = IO.read(client_key_path)
12-
client_cert = IO.read(client_cert_path)
10+
if client_ca_path
11+
client_ca = IO.read(client_ca_path)
12+
client_key = IO.read(client_key_path)
13+
client_cert = IO.read(client_cert_path)
14+
15+
@service = Logcache::V1::Egress::Stub.new(
16+
"#{host}:#{port}",
17+
GRPC::Core::ChannelCredentials.new(client_ca, client_key, client_cert),
18+
channel_args: { GRPC::Core::Channel::SSL_TARGET => tls_subject_name }
19+
)
20+
else
21+
@service = Logcache::V1::Egress::Stub.new(
22+
"#{host}:#{port}",
23+
:this_channel_is_insecure
24+
)
25+
end
1326

1427
@temporary_ignore_server_unavailable_errors = temporary_ignore_server_unavailable_errors
15-
@service = Logcache::V1::Egress::Stub.new(
16-
"#{host}:#{port}",
17-
GRPC::Core::ChannelCredentials.new(client_ca, client_key, client_cert),
18-
channel_args: { GRPC::Core::Channel::SSL_TARGET => tls_subject_name }
19-
)
2028
end
2129

2230
def container_metrics(source_guid:, envelope_limit: DEFAULT_LIMIT, start_time:, end_time:)

spec/logcache/client_spec.rb

Lines changed: 140 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -10,133 +10,172 @@ module Logcache
1010

1111
let(:host) { 'doppler.service.cf.internal' }
1212
let(:port) { '8080' }
13-
let(:tls_subject_name) { 'my-logcache' }
14-
let(:client_ca_path) { File.join(Paths::FIXTURES, 'certs/log_cache_ca.crt') }
15-
let(:client_cert_path) { File.join(Paths::FIXTURES, 'certs/log_cache.crt') }
16-
let(:client_key_path) { File.join(Paths::FIXTURES, 'certs/log_cache.key') }
17-
let(:credentials) { instance_double(GRPC::Core::ChannelCredentials) }
18-
let(:channel_arg_hash) do
19-
{
20-
channel_args: { GRPC::Core::Channel::SSL_TARGET => tls_subject_name }
21-
}
22-
end
23-
let(:client) do
24-
Logcache::Client.new(host: host, port: port, client_ca_path: client_ca_path,
25-
client_cert_path: client_cert_path, client_key_path: client_key_path, tls_subject_name: tls_subject_name,
26-
temporary_ignore_server_unavailable_errors: false)
27-
end
2813
let(:expected_request_options) { { 'headers' => { 'Authorization' => 'bearer oauth-token' } } }
29-
let(:client_ca) { File.open(client_ca_path).read }
30-
let(:client_key) { File.open(client_key_path).read }
31-
let(:client_cert) { File.open(client_cert_path).read }
32-
33-
describe '#container_metrics' do
34-
let(:instance_count) { 2 }
35-
let!(:process) { VCAP::CloudController::ProcessModel.make(instances: instance_count) }
36-
37-
before do
38-
expect(GRPC::Core::ChannelCredentials).to receive(:new).
39-
with(client_ca, client_key, client_cert).
40-
and_return(credentials)
41-
expect(Logcache::V1::Egress::Stub).to receive(:new).
42-
with("#{host}:#{port}", credentials, channel_arg_hash).
43-
and_return(logcache_service)
44-
allow(Logcache::V1::ReadRequest).to receive(:new).and_return(logcache_request)
45-
end
4614

47-
it 'calls Logcache with the correct parameters and returns envelopes' do
48-
expect(
49-
client.container_metrics(source_guid: process.guid, envelope_limit: 1000, start_time: 100, end_time: 101)
50-
).to eq([:fake_envelope_1, :fake_envelope_2])
51-
52-
expect(Logcache::V1::ReadRequest).to have_received(:new).with(
53-
source_id: process.guid,
54-
limit: 1000,
55-
descending: true,
56-
start_time: 100,
57-
end_time: 101,
58-
envelope_types: [:GAUGE]
59-
)
60-
expect(logcache_service).to have_received(:read).with(logcache_request)
15+
describe 'with TLS' do
16+
let(:tls_subject_name) { 'my-logcache' }
17+
let(:client_ca_path) { File.join(Paths::FIXTURES, 'certs/log_cache_ca.crt') }
18+
let(:client_cert_path) { File.join(Paths::FIXTURES, 'certs/log_cache.crt') }
19+
let(:client_key_path) { File.join(Paths::FIXTURES, 'certs/log_cache.key') }
20+
let(:credentials) { instance_double(GRPC::Core::ChannelCredentials) }
21+
let(:channel_arg_hash) do
22+
{
23+
channel_args: { GRPC::Core::Channel::SSL_TARGET => tls_subject_name }
24+
}
6125
end
62-
end
26+
let(:client) do
27+
Logcache::Client.new(host: host, port: port, client_ca_path: client_ca_path,
28+
client_cert_path: client_cert_path, client_key_path: client_key_path, tls_subject_name: tls_subject_name,
29+
temporary_ignore_server_unavailable_errors: false)
30+
end
31+
let(:client_ca) { File.open(client_ca_path).read }
32+
let(:client_key) { File.open(client_key_path).read }
33+
let(:client_cert) { File.open(client_cert_path).read }
34+
35+
describe '#container_metrics' do
36+
let(:instance_count) { 2 }
37+
let!(:process) { VCAP::CloudController::ProcessModel.make(instances: instance_count) }
38+
39+
before do
40+
expect(GRPC::Core::ChannelCredentials).to receive(:new).
41+
with(client_ca, client_key, client_cert).
42+
and_return(credentials)
43+
expect(Logcache::V1::Egress::Stub).to receive(:new).
44+
with("#{host}:#{port}", credentials, channel_arg_hash).
45+
and_return(logcache_service)
46+
allow(Logcache::V1::ReadRequest).to receive(:new).and_return(logcache_request)
47+
end
6348

64-
describe 'when logcache is unavailable' do
65-
let(:instance_count) { 0 }
66-
let(:bad_status) { GRPC::BadStatus.new(14) }
67-
let!(:process) { VCAP::CloudController::ProcessModel.make(instances: instance_count) }
68-
69-
before do
70-
expect(GRPC::Core::ChannelCredentials).to receive(:new).
71-
with(client_ca, client_key, client_cert).
72-
and_return(credentials)
73-
expect(Logcache::V1::Egress::Stub).to receive(:new).
74-
with("#{host}:#{port}", credentials, channel_arg_hash).
75-
and_return(logcache_service)
76-
allow(client).to receive(:sleep)
77-
allow(Logcache::V1::ReadRequest).to receive(:new).and_return(logcache_request)
78-
allow(logcache_service).to receive(:read).and_raise(bad_status)
49+
it 'calls Logcache with the correct parameters and returns envelopes' do
50+
expect(
51+
client.container_metrics(source_guid: process.guid, envelope_limit: 1000, start_time: 100, end_time: 101)
52+
).to eq([:fake_envelope_1, :fake_envelope_2])
53+
54+
expect(Logcache::V1::ReadRequest).to have_received(:new).with(
55+
source_id: process.guid,
56+
limit: 1000,
57+
descending: true,
58+
start_time: 100,
59+
end_time: 101,
60+
envelope_types: [:GAUGE]
61+
)
62+
expect(logcache_service).to have_received(:read).with(logcache_request)
63+
end
7964
end
8065

81-
context 'and operator has enabled temporary_ignore_server_unavailable_errors' do
82-
let(:client) do
83-
Logcache::Client.new(host: host, port: port, client_ca_path: client_ca_path,
84-
client_cert_path: client_cert_path, client_key_path: client_key_path, tls_subject_name: tls_subject_name,
85-
temporary_ignore_server_unavailable_errors: true)
66+
describe 'when logcache is unavailable' do
67+
let(:instance_count) { 0 }
68+
let(:bad_status) { GRPC::BadStatus.new(14) }
69+
let!(:process) { VCAP::CloudController::ProcessModel.make(instances: instance_count) }
70+
71+
before do
72+
expect(GRPC::Core::ChannelCredentials).to receive(:new).
73+
with(client_ca, client_key, client_cert).
74+
and_return(credentials)
75+
expect(Logcache::V1::Egress::Stub).to receive(:new).
76+
with("#{host}:#{port}", credentials, channel_arg_hash).
77+
and_return(logcache_service)
78+
allow(client).to receive(:sleep)
79+
allow(Logcache::V1::ReadRequest).to receive(:new).and_return(logcache_request)
80+
allow(logcache_service).to receive(:read).and_raise(bad_status)
8681
end
8782

88-
it 'returns an empty envelope' do
89-
expect(
83+
context 'and operator has enabled temporary_ignore_server_unavailable_errors' do
84+
let(:client) do
85+
Logcache::Client.new(host: host, port: port, client_ca_path: client_ca_path,
86+
client_cert_path: client_cert_path, client_key_path: client_key_path, tls_subject_name: tls_subject_name,
87+
temporary_ignore_server_unavailable_errors: true)
88+
end
89+
90+
it 'returns an empty envelope' do
91+
expect(
92+
client.container_metrics(source_guid: process.guid, envelope_limit: 1000, start_time: 100, end_time: 101)
93+
).to be_a(Logcache::EmptyEnvelope)
94+
end
95+
96+
# TODO: fix calling the function under test separately
97+
it 'retries the request three times' do
9098
client.container_metrics(source_guid: process.guid, envelope_limit: 1000, start_time: 100, end_time: 101)
91-
).to be_a(Logcache::EmptyEnvelope)
99+
100+
expect(logcache_service).to have_received(:read).with(logcache_request).exactly(3).times
101+
end
92102
end
93103

94-
# TODO: fix calling the function under test separately
95-
it 'retries the request three times' do
96-
client.container_metrics(source_guid: process.guid, envelope_limit: 1000, start_time: 100, end_time: 101)
104+
context 'and operator has disabled temporary_ignore_server_unavailable_errors' do
105+
let(:client) do
106+
Logcache::Client.new(host: host, port: port, client_ca_path: client_ca_path,
107+
client_cert_path: client_cert_path, client_key_path: client_key_path, tls_subject_name: tls_subject_name,
108+
temporary_ignore_server_unavailable_errors: false)
109+
end
110+
111+
it 'retries the request three times and raises an exception' do
112+
expect {
113+
client.container_metrics(source_guid: process.guid, envelope_limit: 1000, start_time: 100, end_time: 101)
114+
}.to raise_error(bad_status)
97115

98-
expect(logcache_service).to have_received(:read).with(logcache_request).exactly(3).times
116+
expect(logcache_service).to have_received(:read).with(logcache_request).exactly(3).times
117+
end
99118
end
100119
end
101120

102-
context 'and operator has disabled temporary_ignore_server_unavailable_errors' do
103-
let(:client) do
104-
Logcache::Client.new(host: host, port: port, client_ca_path: client_ca_path,
105-
client_cert_path: client_cert_path, client_key_path: client_key_path, tls_subject_name: tls_subject_name,
106-
temporary_ignore_server_unavailable_errors: false)
121+
describe 'when the logcache service has any other error' do
122+
let(:bad_status) { GRPC::BadStatus.new(13) }
123+
let!(:process) { VCAP::CloudController::ProcessModel.make(instances: instance_count) }
124+
let(:instance_count) { 2 }
125+
126+
before do
127+
expect(GRPC::Core::ChannelCredentials).to receive(:new).
128+
with(client_ca, client_key, client_cert).
129+
and_return(credentials)
130+
expect(Logcache::V1::Egress::Stub).to receive(:new).
131+
with("#{host}:#{port}", credentials, channel_arg_hash).
132+
and_return(logcache_service)
133+
allow(client).to receive(:sleep)
134+
allow(Logcache::V1::ReadRequest).to receive(:new).and_return(logcache_request)
135+
allow(logcache_service).to receive(:read).and_raise(bad_status)
107136
end
108137

109-
it 'retries the request three times and raises an exception' do
138+
it 'raises the exception' do
110139
expect {
111140
client.container_metrics(source_guid: process.guid, envelope_limit: 1000, start_time: 100, end_time: 101)
112141
}.to raise_error(bad_status)
113-
114-
expect(logcache_service).to have_received(:read).with(logcache_request).exactly(3).times
115142
end
116143
end
117144
end
118145

119-
describe 'when the logcache service has any other error' do
120-
let(:bad_status) { GRPC::BadStatus.new(13) }
121-
let!(:process) { VCAP::CloudController::ProcessModel.make(instances: instance_count) }
122-
let(:instance_count) { 2 }
123-
124-
before do
125-
expect(GRPC::Core::ChannelCredentials).to receive(:new).
126-
with(client_ca, client_key, client_cert).
127-
and_return(credentials)
128-
expect(Logcache::V1::Egress::Stub).to receive(:new).
129-
with("#{host}:#{port}", credentials, channel_arg_hash).
130-
and_return(logcache_service)
131-
allow(client).to receive(:sleep)
132-
allow(Logcache::V1::ReadRequest).to receive(:new).and_return(logcache_request)
133-
allow(logcache_service).to receive(:read).and_raise(bad_status)
146+
describe 'without TLS' do
147+
let(:client) do
148+
Logcache::Client.new(host: host, port: port, temporary_ignore_server_unavailable_errors: false,
149+
client_ca_path: nil, client_cert_path: nil, client_key_path: nil, tls_subject_name: nil)
134150
end
135151

136-
it 'raises the exception' do
137-
expect {
138-
client.container_metrics(source_guid: process.guid, envelope_limit: 1000, start_time: 100, end_time: 101)
139-
}.to raise_error(bad_status)
152+
describe '#container_metrics' do
153+
let(:instance_count) { 2 }
154+
let!(:process) { VCAP::CloudController::ProcessModel.make(instances: instance_count) }
155+
156+
before do
157+
expect(GRPC::Core::ChannelCredentials).not_to receive(:new)
158+
expect(Logcache::V1::Egress::Stub).to receive(:new).
159+
with("#{host}:#{port}", :this_channel_is_insecure).
160+
and_return(logcache_service)
161+
allow(Logcache::V1::ReadRequest).to receive(:new).and_return(logcache_request)
162+
end
163+
164+
it 'calls Logcache with the correct parameters and returns envelopes' do
165+
expect(
166+
client.container_metrics(source_guid: process.guid, envelope_limit: 1000, start_time: 100, end_time: 101)
167+
).to eq([:fake_envelope_1, :fake_envelope_2])
168+
169+
expect(Logcache::V1::ReadRequest).to have_received(:new).with(
170+
source_id: process.guid,
171+
limit: 1000,
172+
descending: true,
173+
start_time: 100,
174+
end_time: 101,
175+
envelope_types: [:GAUGE]
176+
)
177+
expect(logcache_service).to have_received(:read).with(logcache_request)
178+
end
140179
end
141180
end
142181
end

spec/unit/lib/cloud_controller/dependency_locator_spec.rb

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,28 @@
471471
describe '#traffic_controller_compatible_logcache_client' do
472472
let(:logcache_client) { instance_double(Logcache::Client) }
473473
before do
474+
allow(Logcache::Client).to receive(:new).and_return(logcache_client)
475+
end
476+
477+
it 'returns the tc-decorated client without TLS' do
478+
TestConfig.override(
479+
{
480+
logcache_tls: nil
481+
}
482+
)
483+
expect(locator.traffic_controller_compatible_logcache_client).to be_an_instance_of(Logcache::TrafficControllerDecorator)
484+
expect(Logcache::Client).to have_received(:new).with(
485+
host: 'http://doppler.service.cf.internal',
486+
port: 8080,
487+
client_ca_path: nil,
488+
client_cert_path: nil,
489+
client_key_path: nil,
490+
tls_subject_name: nil,
491+
temporary_ignore_server_unavailable_errors: false
492+
)
493+
end
494+
495+
it 'returns the tc-decorated client with TLS certificates' do
474496
TestConfig.override(
475497
{
476498
logcache: {
@@ -486,11 +508,6 @@
486508
}
487509
}
488510
)
489-
490-
allow(Logcache::Client).to receive(:new).and_return(logcache_client)
491-
end
492-
493-
it 'returns the tc-decorated client' do
494511
expect(locator.traffic_controller_compatible_logcache_client).to be_an_instance_of(Logcache::TrafficControllerDecorator)
495512
expect(Logcache::Client).to have_received(:new).with(
496513
host: 'some-logcache-host',

0 commit comments

Comments
 (0)