1#!/usr/local/bin/ruby
2#
3# Xymon server script
4# Check a dokuwiki installation for any update or error
5# Require the associated plugin to be installed on the target wikis
6# Erwan Martin <public@fzwte.net>
7#
8# Runs on FreeBSD and certainly elsewhere since it's ruby
9#
10# License: Public Domain
11#
12
13require 'cgi'
14require 'pp'
15require "xmlrpc/client"
16require 'openssl'
17
18xymon        = ENV['XYMON']
19xymonsrv     = ENV['XYMSRV']
20xymonhome    = ENV['XYMONHOME']
21xymongrep    = xymonhome+'/bin/xymongrep'
22column = 'dokuwikicheck DOKUWIKI*'
23
24wikis_to_check = [];
25
26#extract the list of dokuwiki installations to check from the xymon config files
27host_lines = %x{#{xymongrep} #{column}}
28hosts = host_lines.split(/\n/)
29hosts.each do |ahost|
30	if ahost =~ /^[\d\.]+\s+([a-zA-Z0-9\-\.\:]+?)\s*\#/
31		xymon_name = $1
32	else
33		next
34	end
35
36	wiki_information = {
37		:xymon_name => xymon_name,
38		:url => '',
39		:user => '',
40		:password => '',
41		:sslcert => '',
42		:sslkey => '',
43		:sslcacert => ''
44	}
45
46	if ahost =~ /DOKUWIKIURL:([^\s]*?)(?:\s|$)/
47		wiki_information[:url] = $1
48	end
49	if ahost =~ /DOKUWIKIUSER:([^\s]*?)(?:\s|$)/
50		wiki_information[:user] = $1
51	end
52	if ahost =~ /DOKUWIKIPASSWORD:([^\s]*?)(?:\s|$)/
53		wiki_information[:password] = $1
54	end
55	if ahost =~ /DOKUWIKISSLCERT:([^\s]*?)(?:\s|$)/
56		wiki_information[:sslcert] = $1
57	end
58	if ahost =~ /DOKUWIKISSLKEY:([^\s]*?)(?:\s|$)/
59		wiki_information[:sslkey] = $1
60	end
61	if ahost =~ /DOKUWIKISSLCACERT:([^\s]*?)(?:\s|$)/
62		wiki_information[:sslcacert] = $1
63	end
64
65	wikis_to_check << wiki_information
66end
67
68#we need to be able to set param to the http client of the ruby xmlrpc client
69module SELF_SSL
70	class Net_HTTP < Net::HTTP
71		def set_sslcontext(value)
72			@ssl_context = value
73		end
74	end
75
76  class XMLRPC_Client < XMLRPC::Client
77    def initialize(*args)
78      super
79      @http = SELF_SSL::Net_HTTP.new( @host, @port,
80                                      @proxy_host,@proxy_port )
81      @http.use_ssl = @use_ssl if @use_ssl
82      @http.read_timeout = @timeout
83      @http.open_timeout = @timeout
84    end
85
86    def get_http()
87        return @http
88    end
89  end
90end
91
92#main loop
93wikis_to_check.each do |wiki_information|
94	xymon_color = 'clear'
95	xymon_message = ''
96	begin
97		#url, user and password
98		raise "No url was provided" if wiki_information[:url].strip.empty?
99		endpoint_url = wiki_information[:url] + '/lib/exe/xmlrpc.php'
100		server = SELF_SSL::XMLRPC_Client.new2(endpoint_url)
101		server.user = wiki_information[:user]
102		server.password = wiki_information[:password]
103		http=server.get_http()
104		object_to_decorate = http
105		if RUBY_VERSION < "1.9"
106			ssl_context = OpenSSL::SSL::SSLContext.new
107			http.set_sslcontext(ssl_context)
108			object_to_decorate = ssl_context
109		end
110
111		#ssl (if provided)
112		#  the equivalent line is:
113		#  openssl s_client -connect host:port -servername host -cert :sslcert -key :sslkey -verify 12 -CAfile :sslcacert
114		if not wiki_information[:sslcert].empty?
115 			certificate = OpenSSL::X509::Certificate.new(File.read(wiki_information[:sslcert]))
116			object_to_decorate.cert = certificate
117		end
118		if not wiki_information[:sslkey].empty?
119			key = OpenSSL::PKey::RSA.new(File.read(wiki_information[:sslkey]))
120			object_to_decorate.key=key
121		end
122		if not wiki_information[:sslcacert].empty?
123			object_to_decorate.ca_file=wiki_information[:sslcacert]
124		end
125		if http.use_ssl?
126			object_to_decorate.verify_mode = OpenSSL::SSL::VERIFY_PEER
127			object_to_decorate.verify_depth = 12
128		end
129		##Uncomment this to see the chain verification in details and to override it
130		#object_to_decorate.verify_callback = Proc.new do |ok, store_context|
131		#   puts ok
132		#   puts store_context
133		#   true
134		#end
135
136
137		#call
138		status_page = server.call("wiki.getPage", "xymon:xymonstatus")
139
140		#find the color in the response
141		if status_page =~ /^xymon_color: (.*?)$/
142			xymon_color = $1
143			xymon_message = status_page
144		else
145			raise "Could not find xymon color in status page\n\n %s" % status_page
146		end
147	rescue Exception => e
148		xymon_message = "Error!\n%s\n\n%s" % [e.message, e.backtrace]
149		xymon_color = "clear"
150	end
151
152	#send the color and message to xymon
153	xymon_message.gsub!(/([\"`])/, "\\\\\\1")
154    xymon_host = wiki_information[:xymon_name]
155    command = "#{xymon} \"#{xymonsrv}\" \"status+90000 #{xymon_host}.dokuwikicheck #{xymon_color} #{xymon_message}\""
156	#puts command
157	%x{#{command}}
158end
159
160
161