Move files into specific directories in source
[mirror/dsa-nagios.git] / dsa-nagios-checks / checks / dsa-check-soas
diff --git a/dsa-nagios-checks/checks/dsa-check-soas b/dsa-nagios-checks/checks/dsa-check-soas
new file mode 100755 (executable)
index 0000000..9d05fff
--- /dev/null
@@ -0,0 +1,93 @@
+#!/usr/bin/ruby
+
+# Copyright 2006 Peter Palfrader
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+require 'resolv'
+require 'optparse'
+require 'yaml'
+
+NAGIOS_STATUS = { :OK => 0, :WARNING => 1, :CRITICAL => 2, :UNKNOWN => -1 };
+@verbose = 0;
+@additional_nameservers = []
+
+def show_help(parser, code=0, io=STDOUT)
+  program_name = File.basename($0, '.*')
+  io.puts "Usage: #{program_name} [options] <domainname> [<domainname> ...]"
+  io.puts parser.summarize
+  exit(code)
+end
+ARGV.options do |opts|
+        opts.on_tail("-h", "--help" , "Display this help screen")                { show_help(opts) }
+        opts.on("-v", "--verbose"   , String, "Be verbose")                      { @verbose += 1 }
+        opts.on("-a", "--add=HOST"  , String, "Also check SOA on <nameserver>")  { |val| @additional_nameservers << val }
+        opts.parse!
+end
+show_help(ARGV.options, 1, STDERR) if ARGV.length == 0
+
+warnings = []
+oks = []
+
+dns = Resolv::DNS.new
+ARGV.each{ |domain|
+       serial = []
+       nameservers = dns.getresources(domain, Resolv::DNS::Resource::IN::NS)
+       nameservernames = nameservers.collect{ |ns| ns.name.to_s }
+       nameservernames = nameservernames.concat @additional_nameservers
+       nameservernames.each{ |nameserver|
+               puts "Testing nameserver #{nameserver} for #{domain}" if @verbose > 0
+               arecords = dns.getresources(nameserver, Resolv::DNS::Resource::IN::A)
+               warnings << "Nameserver #{nameserver} for #{domain} has #{arecords.length} A records" if arecords.length != 1
+               arecords.each{ |a|
+                       puts " Nameserver #{nameserver} is at #{a.address}" if @verbose > 0
+                       begin
+                               resolver = Resolv::DNS.new({:nameserver => a.address.to_s})
+                               soas = resolver.getresources(domain, Resolv::DNS::Resource::IN::SOA)
+                       rescue SystemCallError => e
+                               warnings << "Could not resolve #{domain} on #{nameserver}: #{e.message}"
+                       else
+                               resolver.close
+                               warnings << "Nameserver #{nameserver} for #{domain} returns #{soas.length} SOAs" if soas.length != 1
+                               soas.each{ |soa|
+                                       puts " Nameserver #{nameserver} returns serial #{soa.serial} for #{domain}" if @verbose > 0
+                                       serial << soa.serial unless serial.include? soa.serial
+                               }
+                       end
+               }
+       }
+       case serial.length
+               when 0
+                       warnings << "Found no serials for #{domain}"
+               when 1
+                       oks << "#{domain} is at #{serial.first}"
+               else
+                       warnings << "Nameservers disagree on serials for #{domain}: found #{serial.join(', ')}" if serial.length != 1
+       end
+}
+dns.close
+
+if warnings.length > 0
+       puts warnings.join('; ')
+       exit NAGIOS_STATUS[:WARNING]
+else
+       puts oks.join('; ')
+       exit NAGIOS_STATUS[:OK]
+end