# HG changeset patch # User pesch # Date 1464258442 -7200 # Node ID ebb775c5902161c76444c2630802b6a887eb93e6 # Parent a2ce475700961bb58da8b8aa570f7b5985d8a142 with build diff -r a2ce47570096 -r ebb775c59021 Build.PL --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Build.PL Thu May 26 12:27:22 2016 +0200 @@ -0,0 +1,43 @@ +#! /usr/bin/perl + +use strict; +use warnings; +use Module::Build; + +my $build = Module::Build->new( + module_name => 'Nagios::Check::DNS::check_tlsa_record', + license => 'perl', + dist_name => 'nagios-plugin-tlsa-record', + dist_author => 'Heike Yvonne Pesch ', + dist_abstract => 'short description', + dist_version_from => 'lib/Nagios/Check/DNS/check_tlsa_record.pm', + build_requires => { + 'Module::Build' => '0.4', + }, + requires => { + 'Test::More' => '0.10', + 'Monitoring::Plugin' => '0.39', + }, + checks_files => { + 'bin/check_tlsa-record' => 'nagios/plugins/ius/check_tlsa_record', + }, + bin_scripts => [glob 'bin/*'], + + +); + +if (not defined $build->install_path('nagios')) { + my $base = do { + if ($build->installdirs eq 'vendor') { '/usr/lib' } + elsif (defined $build->install_base) { $build->install_base } + else { '/usr/local/lib' } + }; + $build->install_path(nagios => "$base/nagios"); +} + +$build->bindoc_dirs([@{ $build->bindoc_dirs }, 'blib/nagios/plugins/ius']); +$build->add_build_element('checks'); + +$build->create_build_script(); + +# vim: ft=perl ts=2 sw=2 diff -r a2ce47570096 -r ebb775c59021 bin/check_tlsa-record --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/check_tlsa-record Thu May 26 12:27:22 2016 +0200 @@ -0,0 +1,158 @@ +#! /usr/bin/perl + +use strict; +use warnings; +use feature qw(say); +use Nagios::Check::DNS::check_tlsa_record; +use File::Basename; +use Monitoring::Plugin; + +my $ME = basename $0; +my $blurb = 'This Plugin is intendet to check validity of TLSA Record'; +my $url = 'http://www.schlittermann.de'; +my $author = 'Heike Yvonne Pesch'; +my $email = ''; +my $usage = 'Usage: %s [ -v|--verbose ] [-H ] [-t ] ' + . '[ -c|--critical= ] ' + . '[ -w|--warning= ] ' + . '[ -p|--port= ] ' + . '[ -q|--queryserver= ] '; +my $extra = <<_; + +NOTICE +If you want to use a Hostlist, you have to put entrys like this: + +host +host:port + + +EXAMPLES +$ME -H ssl.schlittermann.de +$ME -H hh.schlittermann.de -p25 +$ME -H hh.schlittermann.de:25 +$ME -f hostlist.txt + +Author: $author $email +For more information visit $url +_ + + +my $nagios_tlsa = Monitoring::Plugin->new( + usage => $usage, + blurb => $blurb, + extra => $extra, + url => $url, + plugin => $ME, + timeout => 120, + +); +$nagios_tlsa->add_arg( + spec => 'host|H=s', + help => q|Host/Domain to check|, + required => 0, +); + +$nagios_tlsa->add_arg( + spec => 'hostlist|f=s', + help => q|Host/Domainlist in file to check|, + required => 0, +); + +$nagios_tlsa->add_arg( + spec => 'expiry|e', + help => q|check expiry of Certificate|, + required => 0, +); + +$nagios_tlsa->add_arg( + spec => 'port|p=i', + help => q|Port of Domain to check the TLSA (default: 443)|, + required => 0, + default => 443, +); + +$nagios_tlsa->add_arg( + spec => 'queryserver|q=s', + required => 0, + help => + q|DNS Server to ask to check the TLSA (default: defined in resolve.conf)|, + +); + +$nagios_tlsa->add_arg( + spec => 'protocol|P=s', + help => q|Protocol to ask to check the TLSA record of domain (default: tcp)|, + required => 0, + default => 'tcp', +); + +$nagios_tlsa->getopts; + +my $domain = $nagios_tlsa->opts->host; +my $port = $nagios_tlsa->opts->port; +my $protocol = $nagios_tlsa->opts->protocol; +my $domainlist = $nagios_tlsa->opts->hostlist; +my $expiry = $nagios_tlsa->opts->expiry; +my $pattern = '^(?\S*\.[a-z]{2,4}?):{0,1}(?[0-9]*$)'; + + +if (!$domain && !$domainlist) { + my $script = basename $0; + my $excuse = "Please set -H or -f \n" + . "For all options try $script --help"; + + say $excuse; + exit 1; +} + +if ($domainlist) +{ + get_domains(); + exit 0; +} + +if ($domain) +{ + + my $pattern = '^(?\S*\.[a-z]{2,4}?):{1}(?[0-9]+$)'; + if ($domain =~ /$pattern/gi) + { + $domain = $+{domain}; + $port = $+{port}; + } + + if (!$port || $port eq '') + { + $port = 443; + } + + if (!$protocol || $protocol ne 'tcp' || $protocol ne 'udp') + { + $protocol = 'tcp'; + } + + my $return = Nagios::Check::DNS::check_tlsa_record::main(($domain, $port, $protocol)); + say $return; +} + +sub get_domains { + open(my $filehandle, '<', $domainlist); + + while (<$filehandle>) { + if (/$pattern/ig) { + $domain = $+{domain}; + + if ("$+{port}" =~ /^\s*$/) { $port = '443'; } + else { $port = $+{port}; } + + my $return = Nagios::Check::DNS::check_tlsa_record::main(($domain, $port)); + say $return; + } + else { + die "$domainlist has wrong or malformed content\n"; + } + + } +} + +# vim: ft=perl ts=2 sw=2 diff -r a2ce47570096 -r ebb775c59021 check_tlsa --- a/check_tlsa Wed May 11 23:41:32 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,218 +0,0 @@ -#! /usr/bin/perl - -use strict; -use warnings; -use feature qw(switch say); -use if $^V >= v5.020 => (experimental => qw(smartmatch)); -use experimental qw(smartmatch); -use Monitoring::Plugin; -use File::Basename; - - -my $ME = basename $0; -my $VERSION = '0.1'; -my $blurb = 'This Plugin is intendet to check validity of TLSA Record'; -my $url = 'http://www.schlittermann.de'; -my $author = 'Heike Yvonne Pesch'; -my $email = ''; -my $usage = 'Usage: %s [ -v|--verbose ] [-H ] [-t ] ' - . '[ -c|--critical= ] ' - . '[ -w|--warning= ] ' - . '[ -p|--port= ] ' - . '[ -q|--queryserver= ] '; -my $extra = <<_; - -NOTICE -If you want to use a Hostlist, you have to put entrys like this: - -host -host:port - - -EXAMPLES -$ME -H ssl.schlittermann.de -$ME -H hh.schlittermann.de -p25 -$ME -H hh.schlittermann.de:25 -$ME -f hostlist.txt - -Author: $author $email -For more information visit $url -_ - -my $check_tlsa = Monitoring::Plugin->new( - usage => $usage, - version => $VERSION, - blurb => $blurb, - extra => $extra, - url => $url, - plugin => $ME, - timeout => 120, -); - -$check_tlsa->add_arg( - spec => 'host|H=s', - help => q|Host/Domain to check|, - required => 0, -); - -$check_tlsa->add_arg( - spec => 'hostlist|f=s', - help => q|Host/Domainlist in file to check|, - required => 0, -); - -$check_tlsa->add_arg( - spec => 'expiry|e', - help => q|check expiry of Certificate|, - required => 0, -); - -$check_tlsa->add_arg( - spec => 'port|p=i', - help => q|Port of Domain to check the TLSA (default: 443)|, - required => 0, - default => 443, -); - -$check_tlsa->add_arg( - spec => 'queryserver|q=s', - required => 0, - help => - q|DNS Server to ask to check the TLSA (default: defined in resolve.conf)|, - -); - -$check_tlsa->add_arg( - spec => 'protocol|P=s', - help => q|Protocol to ask to check the TLSA record of domain (default: tcp)|, - required => 0, - default => 'tcp', -); - -$check_tlsa->getopts; - -my $domain = $check_tlsa->opts->host; -my $domainlist = $check_tlsa->opts->hostlist; -my $expiry = $check_tlsa->opts->expiry; - - -if (!$domain && !$domainlist) { - my $script = basename $0; - my $excuse = "Please set -H or -f \n" - . "For all options try $script --help"; - - say $excuse; - exit 1; -} - -my $port; -my $cert; -my $check_date; -my $pattern = '^(?\S*\.[a-z]{2,4}?):{0,1}(?[0-9]*$)'; - -# @TODO find better way -# nearly the same check is defined in get_domains -if ( defined $domain && $domain =~ /$pattern/) { - $domain = $+{domain}; - $port = $+{port}; -} - -if ( defined $domainlist && $domainlist ne '' && -e $domainlist) { - say get_domains(); -} -else { say check_tlsa(); } - -sub check_tlsa { - my $protocol = $check_tlsa->opts->protocol; - - $port = $check_tlsa->opts->port unless $port; - - if ("$port" eq '25') { - $cert = "openssl s_client -starttls smtp -connect $domain:$port " - . '< /dev/null 2>/dev/null'; - } - else { - $cert = "openssl s_client -connect $domain:$port " - . '< /dev/null 2>/dev/null'; - } - - my $digquery = "dig TLSA _$port._$protocol.$domain +short"; - my $diganswer = qx($digquery); - my $tlsa_usage = substr($diganswer, 0, 1); - my $tlsa_selector = substr($diganswer, 2, 1); - my $tlsa_match_type = substr($diganswer, 4, 1); - my $dig_tlsa = substr($diganswer, 6,); - my $valid_date = ''; - my $hashit; - - $dig_tlsa =~ s/(\S*)\s+(\S*)$/$1$2/; - - for ($tlsa_match_type) { - when ('0') { die 'certs will be compared directly' } - when ('1') { $hashit = 'sha256' } - when ('2') { $hashit = 'sha512' } - default { $hashit = 'sha256' } - } - - my $gentlsa = 'openssl x509 -pubkey | ' - . 'openssl rsa -pubin -inform PEM -outform DER 2>/dev/null| ' - . "openssl $hashit"; - my $certtlsa = "$cert | $gentlsa"; - - $check_date = 'openssl x509 -noout -startdate -enddate'; - $check_date = "$cert|$check_date"; - - my $return; - - my $tlsa_record = qx($certtlsa) or die "nothing found!\n"; - $tlsa_record =~ s/^.*= (.*$)/$1/gi; - $tlsa_record = uc($tlsa_record); - - if (defined $expiry) { - $valid_date = check_cert_expiry(); - } - - if ($valid_date ne '') { - $valid_date = "\n$valid_date"; - } - - if ("$tlsa_record" eq "$dig_tlsa") { - - #this way the script exit when file is given :( - #$return = $check_tlsa->plugin_exit(OK, "$domain: TLSA record is valid") - # . "$domain: TLSA record is valid"; - - #this way it's behaves like I want it to - $return = "OK, $domain: TLSA record is valid $valid_date"; - } - else { - #$check_tlsa->plugin_exit(CRITICAL, "$domain: TLSA record NOT valid"); - $return = "CRITICAL, $domain: TLSA record is NOT valid"; - } - say $return; -} - -sub get_domains { - open(my $filehandle, '<', $domainlist); - - my $pattern = '^(?\S*\.[a-z]{2,4}?):{0,1}(?[0-9]*$)'; - while (<$filehandle>) { - if (/$pattern/ig) { - $domain = $+{domain}; - - if ("$+{port}" =~ /^\s*$/) { $port = '443'; } - else { $port = $+{port}; } - - check_tlsa($domain, $port); - } - else { - die "$domainlist has wrong or malformed content\n"; - } - - } -} - -sub check_cert_expiry { - my $return = qx($check_date); - return $return; -} diff -r a2ce47570096 -r ebb775c59021 hostlist.txt --- a/hostlist.txt Wed May 11 23:41:32 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -ssl.schlittermann.de -hh.schlittermann.de:25 diff -r a2ce47570096 -r ebb775c59021 lib/Nagios/Check/DNS/check_tlsa_record.pm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/Nagios/Check/DNS/check_tlsa_record.pm Thu May 26 12:27:22 2016 +0200 @@ -0,0 +1,142 @@ +use strict; +use warnings; +use feature qw(say switch); +#use if $^V >= v5.0.20 => (experimental => gw(smartmatch)); +use experimental qw(smartmatch); +package Nagios::Check::DNS::check_tlsa_record; + +$Nagios::Check::DNS::check_tlsa_record::VERSION = '0.1'; + +sub main +{ + my $domain = shift; + my $port = shift || 443; + my $protocol = shift || 'tcp'; + my $validate = validate_tsla($domain, $port); + return "$validate"; + +} + +sub dig_tlsa +{ + my $domain = shift; + my $port = shift; + my $protocol = shift || 'tcp'; + my $query = "dig tlsa _$port._$protocol.$domain +short"; + my $dig_return = qx($query); + return $dig_return; +} + +sub get_cert +{ + my $domain = shift; + my $port = shift; + my $same = '< /dev/null 2>/dev/null | openssl x509'; + my $query; + my $cert; + + if ("$port" eq '25') { + $query = "openssl s_client -starttls smtp -connect $domain:$port $same"; + + } + else { + $query = "openssl s_client -connect $domain:$port $same"; + + } + $cert = qx($query); + return $cert; +} + +sub get_tlsa_from_cert +{ + my $cert = shift; + my $hashit = shift || 'sha256'; + my $gentlsa = 'openssl x509 -pubkey | ' + . 'openssl rsa -pubin -inform PEM -outform DER 2>/dev/null| ' + . "openssl $hashit"; + + my $cert_tlsa = "echo \"$cert\" | $gentlsa"; + + + my $tlsa_record = qx($cert_tlsa) or die "nothing found!\n"; + $tlsa_record =~ s/^.*= (.*$)/$1/gi; + $tlsa_record = uc($tlsa_record); + + return $tlsa_record; +} + +sub check_expiry +{ + my $cert = shift; + my $check_date = 'openssl x509 -noout -startdate -enddate'; + my $check_expiry = "echo \"$cert\"|$check_date"; + my $expiry = qx($check_expiry); + + return "$expiry"; +} + +sub get_tlsa_match_type +{ + my $dig_return = shift; + + my $tlsa_usage = substr($dig_return, 0, 1); + my $tlsa_selector = substr($dig_return, 2, 1); + my $tlsa_match_type = substr($dig_return, 4, 1); + my $hashit; + + for ($tlsa_match_type) { + when ('0') { die 'certs will be compared directly' } + when ('1') { $hashit = 'sha256' } + when ('2') { $hashit = 'sha512' } + default { $hashit = 'sha256' } + } + return $hashit; + +} + +sub get_dig_tlsa_record +{ + #my $dig_return = shift; + my $dig_return = shift; + my $dig_tlsa = substr($dig_return, 6,); + $dig_tlsa =~ s/(\S*)\s+(\S*)$/$1$2/; + + return "$dig_tlsa"; +} + +sub get_tlsa_usage +{ + my $dig_return = shift; + my $tlsa_usage = substr($dig_return, 0, 1); + + return "$tlsa_usage"; +} + +sub get_tlsa_selector +{ + my $dig_return = shift; + my $tlsa_selector = substr($dig_return, 2, 1); + + return "$tlsa_selector"; +} + +sub validate_tsla +{ + my $domain = shift; + my $port = shift; + #my $dig_return = shift; + my $cert = get_cert($domain, $port); + my $dig_return = dig_tlsa($domain, $port); + my $dig_tlsa = get_dig_tlsa_record($dig_return); + my $cert_tlsa = get_tlsa_from_cert($cert); + + if ("$dig_tlsa" ne "$cert_tlsa") + { + return "crtical: TLSA Record for $domain is not valid"; + } + return "OK: TLSA Record for $domain is valid"; +} + + +# vim: ft=perl ts=2 sw=2 foldmethod=indent +1; diff -r a2ce47570096 -r ebb775c59021 t/check_tlsa_record.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/t/check_tlsa_record.t Thu May 26 12:27:22 2016 +0200 @@ -0,0 +1,31 @@ +#! /usr/bin/perl + +use strict; +use warnings; +use Test::More qw(no_plan); + +BEGIN { use_ok('Nagios::Check::DNS::check_tlsa_record') }; + +require_ok('Nagios::Check::DNS::check_tlsa_record'); + +#my $return = Nagios::Check::DNS::check_tlsa_record::main(($domain, $port)); +#say $return; + +#my $return = Nagios::Check::DNS::check_tlsa_record::main(); +#say $return; + +#my $return5 = Nagios::Check::DNS::check_tlsa_record::main(qw(hh.schlittermann.de 25 tcp)); +#say $return5; + +#my $return2 = Nagios::Check::DNS::check_tlsa_record::dig_tlsa(qw(hh.schlittermann.de 25 udp)); +#say $return2; +# +#my $return3 = Nagios::Check::DNS::check_tlsa_record::dig_tlsa(qw(hh.schlittermann.de 25)); +#say $return3; +# +#my $return4 = Nagios::Check::DNS::check_tlsa_record::dig_tlsa(qw(hh.schlittermann.de)); +#say $return4; + + + +# vim: ft=perl ts=2 sw=2 diff -r a2ce47570096 -r ebb775c59021 t/hostlist.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/t/hostlist.txt Thu May 26 12:27:22 2016 +0200 @@ -0,0 +1,2 @@ +ssl.schlittermann.de +hh.schlittermann.de:25