#!/usr/bin/perl # # Plugin to monitor KDC server requests. # Based on kdc-log-analyze.pl script from heimdal. # # Contributed by Jan Rękorajski # # Example configuration: # # [heimdal_kdc_*] # env.logdir /var/log # env.logfile secure # env.realms REALM1.COM REALM2.COM # use strict; use Munin::Plugin; my $LOGDIR = $ENV{'logdir'} || '/var/log'; my $LOGFILE = $ENV{'logfile'} || 'secure'; my @REALMS = $ENV{'realms'} ? split(' ', $ENV{'realms'}) : (); my $pos = undef; my $as_req = 0; my $no_such_princ = 0; my $tgs_req = 0; my $tgs_xrealm_out = 0; my $tgs_xrealm_in = 0; my $referrals = 0; my $pa_failed = 0; my %ip; $ip{'4'} = $ip{'6'} = 0; sub islocalrealm { my ($princ) = @_; my $realm; foreach $realm (@REALMS) { return 1 if ($princ eq $realm); return 1 if ($princ =~ /[^@]+\@${realm}/); } return 0; } sub parseLogfile { my ($fname, $start) = @_; my ($LOGFILE,$rotated) = tail_open($fname,$start); my $line; while (<$LOGFILE>) { chomp ($_); if (/AS-REQ (.*) from IPv([46]):([0-9\.:a-fA-F]+) for (.*)$/) { $as_req++; $ip{$2}++; } elsif (/TGS-REQ (.+) from IPv([46]):([0-9\.:a-fA-F]+) for (.*?)( \[.*\]){0,1}$/) { $tgs_req++; $ip{$2}++; my $source = $1; my $dest = $4; if (!islocalrealm($source)) { $tgs_xrealm_in++; } if ($dest =~ /krbtgt\/([^@]+)@[^@]+/) { if (!islocalrealm($1)) { $tgs_xrealm_out++; } } } elsif (/: No such entry in the database/) { $no_such_princ++; } elsif (/Lookup .* succeeded$/) { # Nothing } elsif (/returning a referral to realm (.*) for server (.*) that was not found/) { $referrals++; } elsif (/Failed to decrypt PA-DATA -- (.+)$/) { $pa_failed++; } } return tail_close($LOGFILE); } if ( $ARGV[0] and $ARGV[0] eq "autoconf" ) { print "no\n"; exit 0; } if ( $ARGV[0] and $ARGV[0] eq "config" ) { print "graph_title Heimdal KDC requests\n"; print "graph_args --base 1000\n"; print "graph_vlabel requests / \${graph_period}\n"; print "graph_scale yes\n"; print "graph_category Heimdal\n"; print "ipv4.label IPv4 requests\n"; print "ipv4.type ABSOLUTE\n"; print "ipv4.min 0\n"; print "ipv6.label IPv6 requests\n"; print "ipv6.type ABSOLUTE\n"; print "ipv6.min 0\n"; print "lookupfail.label Failed lookups\n"; print "lookupfail.type ABSOLUTE\n"; print "lookupfail.min 0\n"; print "asreq.label AS-REQ requests\n"; print "asreq.type ABSOLUTE\n"; print "asreq.min 0\n"; print "tgsreq.label TGS-REQ requests\n"; print "tgsreq.type ABSOLUTE\n"; print "tgsreq.min 0\n"; print "pafail.label Preauth failed requests\n"; print "pafail.type ABSOLUTE\n"; print "pafail.min 0\n"; print "xrout.label Cross-realm tgs out\n"; print "xrout.type ABSOLUTE\n"; print "xrout.min 0\n"; print "xrin.label Cross-realm tgs in\n"; print "xrin.type ABSOLUTE\n"; print "xrin.min 0\n"; print "referrals.label Referrals\n"; print "referrals.type ABSOLUTE\n"; print "referrals.min 0\n"; exit 0; } my $logfile = "$LOGDIR/$LOGFILE"; if (! -f $logfile) { print "ipv4.value U\n"; print "ipv6.value U\n"; print "lookupfail.value U\n"; print "asreq.value U\n"; print "tgsreq.value U\n"; print "pafail.value U\n"; print "xrout.value U\n"; print "xrin.value U\n"; print "referrals.value U\n"; exit 1; } ($pos) = restore_state(); if (!defined($pos)) { # No state file present. Avoid startup spike: Do not read log # file up to now, but remember how large it is now, and next # time read from there. $pos = (stat $logfile)[7]; # File size } else { $pos = parseLogfile ($logfile, $pos); } print "ipv4.value $ip{'4'}\n"; print "ipv6.value $ip{'6'}\n"; print "lookupfail.value $no_such_princ\n"; print "asreq.value $as_req\n"; print "tgsreq.value $tgs_req\n"; print "pafail.value $pa_failed\n"; print "xrout.value $tgs_xrealm_out\n"; print "xrin.value $tgs_xrealm_in\n"; print "referrals.value $referrals\n"; save_state($pos); # vim:syntax=perl