-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1cd5a00
commit 3fda4d1
Showing
8 changed files
with
211 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
|
||
MethodLength: | ||
Max: 200 | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
#! /usr/bin/env ruby | ||
# | ||
# check-dns | ||
# | ||
# DESCRIPTION: | ||
# This plugin checks DNS Zone using dnsruby and whois. | ||
# | ||
# OUTPUT: | ||
# plain text | ||
# | ||
# PLATFORMS: | ||
# Linux, BSD | ||
# | ||
# DEPENDENCIES: | ||
# gem: sensu-plugin | ||
# gem: dnsruby | ||
# gem: whois | ||
# | ||
# USAGE: | ||
# example commands | ||
# | ||
# NOTES: | ||
# Does it behave differently on specific platforms, specific use cases, etc | ||
# | ||
# LICENSE: | ||
# Zubov Yuri <[email protected]> sponsored by Actility, https://www.actility.com | ||
# Released under the same terms as Sensu (the MIT license); see LICENSE | ||
# for details. | ||
# | ||
|
||
require 'sensu-plugin/check/cli' | ||
require 'dnsruby' | ||
require 'whois' | ||
require 'whois/parser' | ||
require 'ipaddr' | ||
require 'resolv' | ||
|
||
# | ||
# DNS | ||
# | ||
class DNSZone < Sensu::Plugin::Check::CLI | ||
option :domain, | ||
description: 'Domain to resolve (or ip if type PTR)', | ||
short: '-d DOMAIN', | ||
long: '--domain DOMAIN' | ||
|
||
option :threshold, | ||
description: 'Percentage of DNS queries that must succeed', | ||
short: '-l PERCENT', | ||
long: '--threshold PERCENT', | ||
proc: proc(&:to_i), | ||
default: 100 | ||
|
||
option :timeout, | ||
description: 'Set timeout for query', | ||
short: '-T TIMEOUT', | ||
long: '--timeout TIMEOUT', | ||
proc: proc(&:to_i), | ||
default: 5 | ||
|
||
option :warn_only, | ||
description: 'Warn instead of critical on failure', | ||
short: '-w', | ||
long: '--warn-only', | ||
boolean: true | ||
|
||
def resolve_ns | ||
Resolv::DNS.new.getresources(config[:domain], Resolv::DNS::Resource::IN::NS).map { |e| e.name.to_s } | ||
end | ||
|
||
def check_whois(entries) | ||
errors = [] | ||
success = [] | ||
record = Whois.whois(config[:domain]) | ||
parser = record.parser | ||
additional_text = "(whois #{parser.nameservers.map(&:name)}) (dig #{entries})" | ||
if Set.new(parser.nameservers.map(&:name)) == Set.new(entries) | ||
success << "Resolved #{config[:domain]} #{config[:type]} equal with whois #{additional_text}" | ||
else | ||
errors << "Resolved #{config[:domain]} #{config[:type]} did not include #{config[:result]} #{additional_text}" | ||
end | ||
[errors, success] | ||
end | ||
|
||
def check_results(entries) | ||
errors = [] | ||
success = [] | ||
|
||
%w[check_whois check_axfr soa_query].each do |check| | ||
result = send(check, entries) | ||
errors.push(*result[0]) | ||
success.push(*result[1]) | ||
end | ||
|
||
result = check_dns_connection(entries, true) | ||
errors.push(*result[0]) | ||
success.push(*result[1]) | ||
|
||
result = check_dns_connection(entries, false) | ||
errors.push(*result[0]) | ||
success.push(*result[1]) | ||
|
||
[errors, success] | ||
end | ||
|
||
def check_dns_connection(entries, use_tcp = false) | ||
errors = [] | ||
success = [] | ||
|
||
entries.each do |ns| | ||
Dnsruby::Resolv.getaddresses(ns).each do |ip| | ||
begin | ||
resolv = Dnsruby::Resolver.new(nameserver: ip.to_s, do_caching: false, use_tcp: use_tcp) | ||
resolv.query_timeout = config[:timeout] | ||
resolv.query(config[:domain], Dnsruby::Types.ANY) | ||
type_of_connection = use_tcp ? 'tcp' : 'udp' | ||
success << "Resolved DNS #{ns}(#{ip}) uses #{type_of_connection}" | ||
rescue StandardError | ||
errors << "Resolved DNS #{ns}(#{ip}) doesn't use #{type_of_connection}" | ||
end | ||
end | ||
end | ||
[errors, success] | ||
end | ||
|
||
def check_axfr(entries) | ||
errors = [] | ||
success = [] | ||
|
||
entries.each do |ns| | ||
Dnsruby::Resolv.new.getaddresses(ns).each do |ip| | ||
begin | ||
resolv = Dnsruby::Resolver.new(nameserver: ip.to_s, do_caching: false) | ||
resolv.query_timeout = config[:timeout] | ||
resolv.query(config[:domain], 'AXFR', 'IN') | ||
|
||
errors << "Resolved DNS #{ns}(#{ip}) has AXFR" | ||
rescue StandardError | ||
success << "Resolved DNS #{ns}(#{ip}) doesn't have AXFR" | ||
end | ||
end | ||
end | ||
[errors, success] | ||
end | ||
|
||
def soa_query(entries) | ||
errors = [] | ||
success = [] | ||
resp = ::Resolv::DNS.new.getresources(config[:domain], Resolv::DNS::Resource::IN::SOA) | ||
primary_serial_number = resp.map(&:serial).first | ||
primary_server = resp.map { |r| r.mname.to_s } | ||
primary_server_name = resp.map { |r| r.rname.to_s } | ||
|
||
entries.each_with_index do |ns, _index| | ||
::Resolv::DNS.new.getaddresses(ns).each do |ip| | ||
serial_number = nil | ||
server_name = nil | ||
server = nil | ||
|
||
::Resolv::DNS.open nameserver: ip.to_s, ndots: 1 do |dns| | ||
resp = dns.getresources(config[:domain], Resolv::DNS::Resource::IN::SOA) | ||
serial_number = resp.map(&:serial).first | ||
server_name = resp.map { |r| r.rname.to_s } | ||
server = resp.map { |r| r.mname.to_s } | ||
end | ||
|
||
if serial_number == primary_serial_number | ||
success << "SOA Query correct for server #{ns}(#{ip})} SOA #{server_name} (#{serial_number}) #{server} - \ | ||
SOA primary server #{primary_server_name} (#{primary_serial_number}) #{primary_server}" | ||
else | ||
errors << "SOA Query wrong for server #{ns}(#{ip})} SOA #{server_name} (#{serial_number}) #{server} - \ | ||
SOA primary server #{primary_server_name} (#{primary_serial_number}) #{primary_server}" | ||
end | ||
end | ||
end | ||
|
||
[errors, success] | ||
end | ||
|
||
def run | ||
unknown 'No domain specified' if config[:domain].nil? | ||
|
||
entries = resolve_ns | ||
errors, success = check_results(entries) | ||
percent = success.count.to_f / (success.count.to_f + errors.count.to_f) * 100 | ||
if percent < config[:threshold] | ||
output = "#{percent.to_i}% of tests succeeded: #{errors.uniq.join(", \n")}" | ||
config[:warn_only] ? warning(output) : critical(output) | ||
else | ||
ok(success.uniq.join(", \n")) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters