Skip to content

Commit 4bb4fa3

Browse files
authored
Secure PrometheusExporter scraping with SSL (#350)
1 parent b109334 commit 4bb4fa3

File tree

4 files changed

+53
-8
lines changed

4 files changed

+53
-8
lines changed

exe/prometheus_exporter

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ def run
7171
opt.on('--logger-path PATH', String, '(optional) Path to file for logger output. Defaults to STDERR') do |o|
7272
options[:logger_path] = o
7373
end
74+
75+
opt.on('--tls-key-file PATH', String, "(optional) Enable server TLS using a private key PATH") do |o|
76+
options[:tls_key_file] = o
77+
end
78+
opt.on('--tls-cert-file PATH', String, "(optional) Enable server TLS using a certificate PATH") do |o|
79+
options[:tls_cert_file] = o
80+
end
7481
end.parse!
7582

7683
logger = Logger.new(options[:logger_path])

lib/prometheus_exporter/client.rb

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ def initialize(
6161
custom_labels: nil,
6262
logger: Logger.new(STDERR),
6363
log_level: Logger::WARN,
64-
process_queue_once_and_stop: false
64+
process_queue_once_and_stop: false,
65+
tls_ca_file: nil,
66+
tls_cert_file: nil,
67+
tls_key_file: nil
6568
)
6669
@logger = logger
6770
@logger.level = log_level
@@ -90,6 +93,12 @@ def initialize(
9093

9194
@custom_labels = custom_labels
9295
@process_queue_once_and_stop = process_queue_once_and_stop
96+
97+
@tls_ca_file = tls_ca_file
98+
@tls_cert_file = tls_cert_file
99+
@tls_key_file = tls_key_file
100+
101+
@ssl_context = build_ssl_context if use_ssl?
93102
end
94103

95104
def custom_labels=(custom_labels)
@@ -232,6 +241,12 @@ def ensure_socket!
232241
if !@socket
233242
@socket = TCPSocket.new @host, @port, connect_timeout: @connect_timeout
234243

244+
if use_ssl?
245+
@socket = OpenSSL::SSL::SSLSocket.new(@socket, @ssl_context)
246+
@socket.sync_close = true
247+
@socket.connect
248+
end
249+
235250
@socket.write("POST /send-metrics HTTP/1.1\r\n")
236251
@socket.write("Transfer-Encoding: chunked\r\n")
237252
@socket.write("Host: #{@host}\r\n")
@@ -249,6 +264,20 @@ def ensure_socket!
249264
raise
250265
end
251266

267+
def use_ssl?
268+
@tls_ca_file && @tls_cert_file && @tls_key_file
269+
end
270+
271+
def build_ssl_context
272+
require "openssl"
273+
ssl_context = OpenSSL::SSL::SSLContext.new()
274+
ssl_context.cert = OpenSSL::X509::Certificate.new(File.read(@tls_cert_file))
275+
ssl_context.key = OpenSSL::PKey::RSA.new(File.read(@tls_key_file))
276+
ssl_context.ca_file = @tls_ca_file
277+
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
278+
ssl_context
279+
end
280+
252281
def wait_for_empty_queue_with_timeout(timeout_seconds)
253282
start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
254283
while @queue.length > 0

lib/prometheus_exporter/server/runner.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ def start
5959
verbose: verbose,
6060
auth: auth,
6161
realm: realm,
62+
tls_cert_file: tls_cert_file,
63+
tls_key_file: tls_key_file,
6264
)
6365
@server.start
6466
end
@@ -67,7 +69,7 @@ def stop
6769
@server.stop
6870
end
6971

70-
attr_accessor :unicorn_listen_address, :unicorn_pid_file
72+
attr_accessor :unicorn_listen_address, :unicorn_pid_file, :tls_cert_file, :tls_key_file
7173
attr_writer :prefix,
7274
:port,
7375
:bind,

lib/prometheus_exporter/server/web_server.rb

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,20 @@ def initialize(opts)
6262

6363
@collector = opts[:collector] || Collector.new(logger: @logger)
6464

65-
@server =
66-
WEBrick::HTTPServer.new(
67-
Port: @port,
68-
BindAddress: @bind,
69-
Logger: @logger,
70-
AccessLog: @access_log,
65+
webrick_options = { Port: @port, BindAddress: @bind, Logger: @logger, AccessLog: @access_log }
66+
67+
if opts[:tls_cert_file] && opts[:tls_key_file]
68+
require "webrick/https"
69+
require "openssl"
70+
71+
webrick_options[:SSLEnable] = true
72+
webrick_options[:SSLCertificate] = OpenSSL::X509::Certificate.new(
73+
File.read(opts[:tls_cert_file]),
7174
)
75+
webrick_options[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.read(opts[:tls_key_file]))
76+
end
77+
78+
@server = WEBrick::HTTPServer.new(webrick_options)
7279

7380
@server.mount_proc "/" do |req, res|
7481
res["Content-Type"] = "text/plain; charset=utf-8"

0 commit comments

Comments
 (0)