#!/usr/bin/env ruby # vim: set noet sw=2 ts=2 sts=2: require 'prometheus/client' require 'prometheus/client/formats/text' require 'ostruct' require_relative 'probe' module BlackboxSshd end class BlackboxSshd::Collector attr_reader :registry, :prober def initialize registry: nil, prober: nil @registry = registry || Prometheus::Client::Registry.new @registry.gauge :sshd_up, docstring: 'Server is up and connection from clients are generally possible', labels: %i[] @registry.gauge :sshd_host_certificate_serial, docstring: 'Host Certificates serial', labels: %i[] @registry.gauge :sshd_probe_duration, docstring: 'Time elapsed to probe the SSH-Server', labels: %i[] @registry.gauge :sshd_host, docstring: 'Provides informations about the remote host.', labels: %i[protocol software] @registry.gauge :sshd_host_key, docstring: 'Provides informations about the host key in labels. 1=key used, 0=no key (possible a certificate)', labels: %i[key] @registry.gauge :sshd_host_certificate, docstring: 'Provides informations about the host_certificate in labels. 1=certificate used, 0=no certificate used (possible simple key)', labels: %i[key ca id] @registry.gauge :sshd_host_certificate_valid_to, docstring: 'Certificate will usable till this time, then it will expire.' @registry.gauge :sshd_host_certificate_valid_from, docstring: 'Certificate is usable from this time.' @registry.gauge :sshd_host_supported_signature_algorithm, docstring: 'Server supported signature algorithm. Only 1. If not supported, it will not listed.', labels: %i[supported] @registry.gauge :sshd_host_supported_authentications, docstring: 'Server supported authentication methods. Only 1. If not supported, it will not listed.', labels: %i[supported] @metrics = OpenStruct.new @registry.instance_variable_get( :@metrics) @prober = prober || BlackboxSshd::Prober.new end def collect hostident r = @prober.probe hostident @metrics.sshd_host.set 1, labels: {protocol: r[:protocol], software: r[:remote_software]} if hc = r[:host_cert] @metrics.sshd_host_certificate_serial.set hc.delete(:serial) @metrics.sshd_host_certificate_valid_from.set hc.delete(:valid_from).to_f @metrics.sshd_host_certificate_valid_to.set hc.delete(:valid_to).to_f @metrics.sshd_host_certificate.set 1, labels: hc else @metrics.sshd_host_certificate.set 0, labels: {key: '', ca: '', id: ''} end if hk = r[:host_key] @metrics.sshd_host_key.set 1, labels: {key: hk} else @metrics.sshd_host_key.set 0, labels: {key: ""} end r[:server_sig_algs].reverse.each_with_index do |alg, i| @metrics.sshd_host_supported_signature_algorithm.set i+1, labels: {supported: alg} end r[:authentications].reverse.each_with_index do |alg, i| @metrics.sshd_host_supported_authentications.set i+1, labels: {supported: alg} end @metrics.sshd_up.set 0 == r[:status].exitstatus ? 1 : 0 @metrics.sshd_probe_duration.set r[:duration] self end def self.collect hostident, **opts new(**opts).collect hostident end end if __FILE__ == $0 collector = BlackboxSshd::Collector.collect ARGV[0] puts Prometheus::Client::Formats::Text.marshal( collector.registry) end