And also if we run this command in our Nagios Server. The output will be as follows:
=====================
./check_sharepoint.pl -H corro.tower.lan -u ********* -p ********* -w 3 -c 6 -http -s "New Document"
UNKNOWN: libcurl lacks ntlm support
============================
command:
===================
corro.tower.lan -u $USER47$ -p $USER48$ -w 3 -c 6 -http -s "New Document"
=======================
Plugin:
=================
#!/usr/bin/env perl
#
# Nagios plugin for functional sharepoint monitoring
#
# License: GPL v3
# Author: Michael van den Berg
#
# Copyright (c) 2012 PCS-IT Services B.V. (
www.pcs-it.nl)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <
http://www.gnu.org/licenses/>.
#
use Getopt::Long qw(:config no_ignore_case_always auto_version);
use Switch;
use WWW::Curl::Easy;
use strict 'vars';
our $VERSION = 1.2;
(my $script_name = $0) =~ s/.\///;
# Help message
my $help_info = <<END;
\n$script_name v$VERSION
Copyright (c) 2012 PCS-IT Services B.V. (
www.pcs-it.nl)
Usage: $script_name -H <hostname> -u <username> -p <password>
-w [warn time] -c [crit time] -t [timeout]
-s [search string] -l [path] -v -form -http
END
# Extra option information
my $help_extra = <<END;
Nagios script for checking of SharePoint web services
Options:
-H Address or hostname of SharePoint site (required)
-u Username (required)
-p Password (required)
-w Warning threshold in seconds
-c Critical threshold in seconds
-t Connection timeout in seconds (default is 60 seconds)
-s Search for custom string on page
-l Specific location or path instead of site root
-v Verbose. HTTP headers in output. 2x (-v -v) includes HTML. 3x both
-form Use forms based authentication (default is ntlm)
-http Connect via standard http (default is https)
Examples:
Check site behind a TMG server using forms based authentication with warning and critital times
$script_name -H portal.hostname.com -u username -p password -form -w 5 -c 10
Check site with integtrated authentication at a specific location within the site
$script_name -H portal.hostname.com -u username -p password -l '/Sites/Wiki%20Pages/default.aspx'
Check site with integtrated authentication that contins the string 'random string'
$script_name -H portal.hostname.com -u username -p password -s 'random string'
Notes:
- If you use special characters in your usernames and/or passwords, authentication will
have a better chance of working if you enclose them in quotes.
- If a URL path is included using the -l option it is must be encoded (e.g. - /Wiki%20Pages/default.aspx)
- Connections are always assumed to be https unless the -http option is used
- Forms authentication is always assumed to be via a ISA/TMG server.
- libcurl must have NTML listed in its features in order for integrated (NTML) authentication
to work. Runing 'curl-config --features' will show if this is present.
END
# Nagios exit codes
my $OKAY = 0;
my $WARNING = 1;
my $CRITICAL = 2;
my $UNKNOWN = 3;
# Default values
my $result = $UNKNOWN; # Default exit code
my $message = "Status UNKNOWN"; # Default output to nagios
my $timeout = 60;
my $address;
my $encoded_path;
my $verbose_level = 0;
# The meta tag 'GENERATOR' is used to determine a successful Shrepoint page loaded. (IIS header field is not used - it shows even on failures)
my $search_string = "<meta name=\"GENERATOR\" content=\"Microsoft SharePoint\" \/>";
# Command arguments
GetOptions ('H=s' => \my $host, # required
'u=s' => \my $username, # required
'p=s' => \my $password, # required
'w:i' => \my $warn,
'c:i' => \my $crit,
's:s' => \$search_string,
'l:s' => \my $site_path, # Assume that the supplied path is already URI encoded (e.g. - space = %20, etc)
't:i' => \$timeout,
'version|V' => \my $show_version,
'v+' => \$verbose_level,
'form' => \my $forms_auth,
'http' => \my $http,
'help|?' => \my $help_message);
# If we don't have the required command line arguments, exit with UNKNOWN.
if(defined $show_version){
print STDOUT "$script_name $VERSION\n";
exit $UNKNOWN;
}elsif((!defined $host || !defined $username || !defined $password) && !defined $help_message){
print STDOUT "$script_name: Not all required options were supplied.\n$help_info\ntry: '$script_name -help' for more information\n";
exit $UNKNOWN;
}elsif(defined $help_message){
print STDOUT "$help_info \n $help_extra";
exit $UNKNOWN
}
# Check that libcurl has ntlm support - if it isn't and forms is not use, quit with UNKNOWN
my $curl_features = `curl-config --features`;
my $ntlm_present = ($curl_features =~ m/NTLM/) ? 1 : 0;
if (!defined $forms_auth && !$ntlm_present){
print STDOUT "UNKNOWN: libcurl lacks ntlm support\n";
exit $UNKNOWN;
}
my $proto = (!defined $http) ? "https" : "http"; # https is the default protocol
# Build up curl
my $curl = WWW::Curl::Easy->new;
$curl->setopt(CURLOPT_HEADER,1);
$curl->setopt(CURLOPT_FOLLOWLOCATION, 1);
$curl->setopt(CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)'); # MS is funny about supported browsers sometimes..
$curl->setopt(CURLOPT_SSL_VERIFYPEER, 0); # Don't do any SSL checking, just keep going (even on bad certs)
$curl->setopt(CURLOPT_CONNECTTIMEOUT, $timeout);
$curl->setopt(CURLOPT_TIMEOUT, $timeout);
# Auth type is ntlm by default
if(!defined $forms_auth){
$address = (defined $site_path) ? $host . $site_path : $host;
$curl->setopt(CURLOPT_URL, $proto.'://'.$address);
$curl->setopt(CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
$curl->setopt(CURLOPT_USERNAME, $username);
$curl->setopt(CURLOPT_PASSWORD, $password);
}else{
# Form authentication assumes a reverse proxy via ISA/TMG server. Submission will be using post method, with
# the 'from public computer' option, and '/' for the target page after logon if no location is supplied.
$address = $host . $site_path;
if(defined $site_path){
($encoded_path = $site_path) =~ s/([^A-Za-z0-9.])/sprintf("Z%02X", ord($1))/seg; # Encode the location for redirect after logon (in special MS format)
}else{
$encoded_path = "Z2F"; # Default to site root if no custom location supplied
}
$curl->setopt(CURLOPT_URL, $proto.'://'.$host.'/CookieAuth.dll?Logon');
$curl->setopt(CURLOPT_POST, 1);
$curl->setopt(CURLOPT_POSTFIELDS, 'curl='.$encoded_path.'&flags=0&forcedownlevel=0&trusted=0&username='.$username.'&password='.$password.'&SubmitCreds=Log+On');
$curl->setopt(CURLOPT_COOKIEJAR, '/dev/null');
}
# returned html body for parsing (libcurl returns a file reference..)
my $response_body = '';
open(my $file_body, ">", \$response_body);
$curl->setopt(CURLOPT_WRITEDATA,$file_body);
# Now we execute the actual loading of the sharepoint website
my $retcode = $curl->perform;
my $response_code = $curl->getinfo(CURLINFO_HTTP_CODE);
my $total_time = $curl->getinfo(CURLINFO_TOTAL_TIME);
# Perfdata will have page load times in seconds
my $perfdata = "|'Response Time'=$total_time"."s;$warn;$crit;0";
if ($retcode == 0) {
# Parse return data on http success since 200 doesn't always mean it everything went well
if ($response_code == 200){
switch($response_body){
case m/id=\"password\" onfocus=\"g_fFcs=0\"/ { # Forms auth will return 200 and the form again on a failure
$message = "CRITICAL: Authentication failed for account '$username'\n";
$result = $CRITICAL;
}
case m/$search_string/{ # We look for the default sharepoint search string (or supplied custom one) to gauge if the site loaded
if($response_body =~ m/Error: Access Denied/){
# Logon was successful but the user account supplied doesn't rights within sharepoint to view the site page
$message = "CRITICAL: Access denied for user '$username' (no site permissions).\n";
$result = $CRITICAL;
}elsif((defined $warn && $total_time >= $warn && $total_time < $crit) || (defined $warn && !defined $crit && $total_time >= $warn)){
# Page load was successful but load time exceeded warning threshold
$message = "WARNING: '$proto://$address' polled in $total_time seconds$perfdata\n";
$result = $WARNING;
}elsif(defined $crit && $total_time >= $crit){
# Page load was successful but load time exceeded crititcal threshold
$message = "CRITICAL: $proto://$address' polled in $total_time seconds$perfdata\n";
$result = $CRITICAL;
}else{
# Page load was successful and within required load times
$message = "OK: '$proto://$address' polled in $total_time seconds$perfdata\n";
$result = $OKAY;
}
}
else{
# The site loaded but the identifying search string (or sharepoint default content meta data tag) was not found.
$message = "CRITICAL: Identifying search string '$search_string' not found!\n";
$result = $CRITICAL;
}
}
}else{
# Standard http response codes made to nagios friendly output. If something isn't in the list then spit out a generic error
switch($response_code){
case 400{
$message = "CRITICAL: HTTP 400 Error - Bad request at '$proto://$address'\n";
$result = $CRITICAL;
}
case 401{
# Usually an NTML authentication failure, but not always (ntlm could be missing from libcurl)
$message = "CRITICAL: Authentication failed for account '$username'\n";
$result = $CRITICAL;
}
case 403{
$message = "CRITICAL: HTTP 403 Error - forbidden at '$proto://$address'\n";
$result = $CRITICAL ;
}
case 404{
$message = "CRITICAL: HTTP 404 Error - Page not found '$proto://$address'\n";
$result = $CRITICAL;
}
case 500{
$message = "CRITICAL: HTTP 500 Error - Internal server error at '$proto://$address'\n";
$result = $CRITICAL ;
}
else{
$message = "CRITICAL: Unknown error connecting to '$proto://$address'\n";
$result = $CRITICAL;
}
}
}
} else {
# Curl failures (DNS lookup failure, timeout, etc. These will always crit
$message = "CRITICAL: ".$curl->strerror($retcode)." for '$proto://$address'\n";
$result = $CRITICAL;
if($verbose_level > 0){ # verbose
$message = $message . $curl->strerror($retcode)." (".$curl->errbuf.")\n";
}
}
## Verbose ##
if($verbose_level > 0 && $retcode == 0){
# Get the body + header and split them
$response_body =~ /<!DOCTYPE/; # Really hope everyone has that <!DOCTYPE at the top so we know where the header ends and the HTML starts
my $header_end_pos = $+[0];
my $http_headers = substr $response_body,9,($header_end_pos - 19);
my $html_body = substr $response_body, ($header_end_pos - 2);
# Tack the html and/or header on depended on the verbose level
if($verbose_level == 1){$message = $message . "\n***** Begin HTTP Headers *****\n" . $http_headers . "***** End HTTP Headers *****\n\n";}
if($verbose_level == 2){$message = $message . "\n***** Begin HTML *****\n" . $html_body . "\n***** End HTML Body *****\n\n";}
if($verbose_level == 3){
$message = $message . "\n***** Begin HTTP Headers *****\n" . $http_headers . "***** End HTTP Headers *****" .
"\n***** Begin HTML *****\n" . $html_body . "\n***** End HTML Body *****\n\n";
}
}
# Cleanup
undef $curl;
#Exit with output and Nagios exit code
print STDOUT $message;
exit $result;
#EOF
========================================
Please help me.
Regards,
Srinija.