# WardenClientCommon.pm # # Copyright (C) 2011-2015 Cesnet z.s.p.o # # Use of this source is governed by a BSD-style license, see LICENSE file. package WardenClientCommon; use strict; use warnings; use SOAP::Lite; use IO::Socket::SSL qw(debug1); use SOAP::Transport::HTTP; use Sys::Syslog qw(:DEFAULT setlogsock); Sys::Syslog::setlogsock('unix'); use Carp; our $VERSION = "2.2"; #------------------------------------------------------------------------------- # errMsg - prints error msg and returns undef or prints warning and returns 1 #------------------------------------------------------------------------------- sub errMsg { my $msg = shift; my $type = shift; defined $type or $type = "err"; # default type is err. Other: warn # is this error report and is Verbose logging mode enabled? if (($type eq "err") && ($WardenClientConf::LOG_VERBOSE)) { # user wants to log debug information $msg .= "\nStack info: " . Carp::longmess(); } # log into STDERR? if ($WardenClientConf::LOG_STDERR) { print STDERR $msg . "\n"; } # log into Syslog? if ($WardenClientConf::LOG_SYSLOG) { openlog("Warden-client:", "pid", "$WardenClientConf::LOG_SYSLOG_FACILITY"); syslog("$type|$WardenClientConf::LOG_SYSLOG_FACILITY", $msg . "\n"); closelog(); } if ($type eq 'warn') { # case of 'warn' return 1; } else { # case of 'err' return; } } # End of errMsg #------------------------------------------------------------------------------- # c2s - connect to server, send request and receive response #------------------------------------------------------------------------------- sub c2s { my $uri = shift; my $ssl_key_file = shift; my $ssl_cert_file = shift; my $ssl_ca_file = shift; my $method = shift; my $data = shift; my $client; my ($server, $port, $service) = $uri =~ /https:\/\/(.+)\:(\d+)\/(.+)/; eval { $client = SOAP::Transport::HTTP::Client->new(); } or return errMsg('Unknown error in c2s() when creating socket, SOAP::Transport::HTTP::Client->new(), ' . $@); eval {$client->timeout($WardenClientConf::CONNECTION_TIMEOUT);} or return errMsg('Unknown error in c2s() when setting socket timeout, ' . $@); eval { $client->ssl_opts(verify_hostname => 1, SSL_use_cert => 1, SSL_verify_mode => 0x03, SSL_key_file => $ssl_key_file, SSL_cert_file => $ssl_cert_file, SSL_ca_file => $ssl_ca_file); return 1; # fix of eval triggering 'or' statement } or return errMsg('Unknown error in c2s() when setting socket SSL options, ' . $@); # setting of URI and serialize SOAP envelope and data object my $soap; eval { $soap = SOAP::Lite->uri($service)->proxy($uri); } or return errMsg('Unknown error in c2s() when serializing SOAP object, ' . $@); my $envelope; if (!defined $data) { eval { $envelope = $soap->serializer->envelope(method => $method); } or return errMsg('Unknown error in c2s() when setting enevelope, ' . $@); } else { eval { $envelope = $soap->serializer->envelope(method => $method, $data); } or return errMsg('Unknown error in c2s() when setting envelope, ' . $@); } # setting of TCP URI and send serialized SOAP envelope and data my $server_uri = "https://$server:$port/$service"; my $result; eval { $result = $client->send_receive(envelope => $envelope, endpoint => $server_uri); } or return errMsg('Unknown error in c2s() sending SOAP data, ' . $@); # check server response if (!defined $result) { errMsg("Server returned empty response. Problem with used SSL ceritificates or Warden server at $server:$port is down."); } else { # deserialized response from server -> create SOAP envelope and data object my $response; eval { $response = $soap->deserializer->deserialize($result); } or return errMsg('Unknown error in SOAP data deserialization. Received data: ' . $result . ', ' . $@); # check SOAP fault status $response->fault ? return errMsg("Server sent error message:: " . $response->faultstring) : return $response; } } #------------------------------------------------------------------------------- # getClientsInfo - retrieve information about other clients from Warden server #------------------------------------------------------------------------------- sub getClientsInfo { my $warden_path = shift; my $etcdir = $warden_path . "/etc/"; my $libdir = $warden_path . "/lib/"; require $libdir . "WardenClientConf.pm"; # read the config file my $conf_file = $etcdir . "warden-client.conf"; WardenClientConf::loadConf($conf_file); # c2s() returns undef on fail my $response = c2s($WardenClientConf::URI, $WardenClientConf::SSL_KEY_FILE, $WardenClientConf::SSL_CERT_FILE, $WardenClientConf::SSL_CA_FILE, "getClientInfo"); defined $response or return; # receive data or return undef # parse returned SOAP data object with clients my @clients; my ($client_id, $hostname, $registered, $requestor, $service, $client_type, $type, $receive_own_events, $description_tags, $ip_net_client); my @response_list = $response->valueof('/Envelope/Body/getClientInfoResponse/client/'); while (scalar @response_list) { my $response_data = shift(@response_list); my %client; $client{'client_id'} = $response_data->{'CLIENT_ID'} ; $client{'hostname'} = $response_data->{'HOSTNAME'}; $client{'registered'} = $response_data->{'REGISTERED'}; $client{'requestor'} = $response_data->{'REQUESTOR'}; $client{'service'} = $response_data->{'SERVICE'}; $client{'client_type'} = $response_data->{'CLIENT_TYPE'}; $client{'type'} = $response_data->{'TYPE'}; $client{'receive_own_events'} = $response_data->{'RECEIVE_OWN_EVENTS'}; $client{'description_tags'} = $response_data->{'DESCRIPTION_TAGS'}; $client{'ip_net_client'} = $response_data->{'IP_NET_CLIENT'}; # push received clients from warden server into @clients which is returned push (@clients,\%client); } return @clients; } #------------------------------------------------------------------------------- # loadConf - load configuration file #------------------------------------------------------------------------------- sub loadConf { my $conf_file = shift; our $BASEDIR = undef; our $URI = undef; our $SSL_KEY = undef; our $SSL_CERT = undef; our $SSL_CA_CERT = undef; our $MAX_RCV_EVENTS_LIMIT = undef; our $CONNECTION_TIMEOUT = undef; our $LOG_STDERR = undef; our $SYSLOG = undef; our $SYSLOG_VERBOSE = undef; our $SYSLOG_FACILITY = undef; unless (do $conf_file) { die("Errors in config file '$conf_file': $@") if $@; die("Can't read config file '$conf_file': $!") unless defined $_; # if $_ defined, it's retvalue of last statement of conf, for which we don't care } } # End of loadConf 1;