bin/metrics-ldap.rb
#!/usr/bin/env ruby
# frozen_string_literal: false
#
# ldap-metrics.rb
#
# AUTHOR
# Matt Ford
# - matt@dancingfrog.co.uk
# - matt@bashton.com
#
# DESCRIPTION
# This plugin uses the LDAP cn=monitor database to generate
# output suitable for graphite
#
# It requires that the monitoring module is loaded and that a monitoring
# database has been set up.
#
# ldapmodify the following:
# dn: cn=module{0},cn=config
# changetype: modify
# add: olcModuleLoad
# olcModuleLoad: back_monitor
#
# ldapadd the following:
# dn: olcDatabase=Monitor,cn=config
# objectClass: olcDatabaseConfig
# objectClass: olcMonitorConfig
# olcDatabase: Monitor
# olcAccess: to dn.subtree="cn=Monitor" by dn.base="cn=suitable,dc=user" read by * none
#
# LICENSE:
# Copyright (c) 2014, Bashton Ltd
# Released under the same terms as Sensu (the MIT license); see LICENSE
# for details.
#
require 'sensu-plugin/metric/cli'
require 'sensu-plugin/utils'
require 'socket'
require 'net/ldap'
class LDAPGraphite < Sensu::Plugin::Metric::CLI::Graphite
include Sensu::Plugin::Utils
option :scheme,
description: 'Metric naming scheme, text to prepend to metric',
short: '-s SCHEME',
long: '--scheme SCHEME',
default: "#{Socket.gethostname}.ldap_metrics"
option :host,
short: '-h HOST',
long: '--host HOST',
description: 'Host',
default: 'localhost'
option :port,
short: '-t PORT',
long: '--port PORT',
description: 'Port to connect to OpenLDAP on',
default: 389,
proc: proc(&:to_i)
option :base,
short: '-b BASE',
long: '--base BASE',
description: 'Base',
default: 'cn=Monitor'
option :user,
short: '-u USER',
long: '--user USER',
description: 'User to bind as',
required: true
option :password,
short: '-p PASSWORD',
long: '--password PASSWORD',
description: 'Password used to bind',
required: true
option :insecure,
short: '-i',
long: '--insecure',
description: 'Do not use encryption'
def get_metrics(host)
ldap = Net::LDAP.new host: host,
port: config[:port],
auth: {
method: :simple,
username: config[:user],
password: config[:password]
}
unless config[:insecure]
ldap.encryption(method: :simple_tls)
end
begin
if ldap.bind
metrics = {
conn_total: {
title: 'connections.total',
search: 'cn=Total,cn=Connections',
attribute: 'monitorCounter'
},
conn_cur: {
title: 'connections.current',
search: 'cn=Current,cn=Connections',
attribute: 'monitorCounter'
},
stats_bytes: {
title: 'statistics.bytes',
search: 'cn=Bytes,cn=Statistics',
attribute: 'monitorCounter'
},
stats_PDU: {
title: 'statistics.pdu',
search: 'cn=PDU,cn=Statistics',
attribute: 'monitorCounter'
},
stats_entries: {
title: 'statistics.entries',
search: 'cn=Entries,cn=Statistics',
attribute: 'monitorCounter'
},
stats_referrals: {
title: 'statistics.referrals',
search: 'cn=Referrals,cn=Statistics',
attribute: 'monitorCounter'
}
}
monitor_ops = %w[add modify delete search compare bind unbind]
%w[initiated completed].each do |state|
monitor_ops.each do |op|
metrics["ops_#{op}_#{state}".to_sym] = {
title: "operations.#{op}.#{state}",
search: "cn=#{op},cn=Operations",
attribute: "monitorOp#{state}"
}
end
end
metrics.each do |_key, metric|
ldap.search(base: "#{metric[:search]},#{config[:base]}",
attributes: [metric[:attribute]],
return_result: true,
scope: Net::LDAP::SearchScope_BaseObject) do |entry|
metric[:value] = entry[metric[:attribute]]
end
end
return metrics # rubocop:disable Style/RedundantReturn
else
message = "Cannot connect to #{host}:#{config[:port]}"
if config[:user]
message += " as #{config[:user]}"
end
critical message
end
end
rescue StandardError
message = "Cannot connect to #{host}:#{config[:port]}"
message += " as #{config[:user]}"
critical message
end
def run
get_metrics(config[:host]).each do |_key, metric|
output [config[:scheme], metric[:title]].join('.'), metric[:value]
end
ok
end
end