icinga-powershell-framework/core/include/ClientProtocol.ps1
2018-11-06 17:14:49 +01:00

225 lines
No EOL
7.1 KiB
PowerShell

$ClientProtocol = New-Object -TypeName PSObject;
$ClientProtocol | Add-Member -membertype NoteProperty -name 'fqdn' -value '';
$ClientProtocol | Add-Member -membertype ScriptMethod -name 'setFQDN' -value {
param([string]$fqdn);
$this.fqdn = $fqdn;
}
$ClientProtocol | Add-Member -membertype ScriptMethod -name 'SetConnectionState' -value {
param([string]$remoteAddress, [bool]$reachable);
if ($Icinga2.Cache.Checker.RemoteServices -eq $null) {
$Icinga2.Cache.Checker.RemoteServices = @{ };
}
if ($Icinga2.Cache.Checker.RemoteServices.ContainsKey($remoteAddress) -eq $FALSE) {
$Icinga2.Cache.Checker.RemoteServices.Add($remoteAddress, $reachable);
return;
}
$Icinga2.Cache.Checker.RemoteServices[$remoteAddress] = $reachable;
}
$ClientProtocol | Add-Member -membertype ScriptMethod -name 'GetConnectionState' -value {
param([string]$remoteAddress);
if ($Icinga2.Cache.Checker.RemoteServices.ContainsKey($remoteAddress) -eq $FALSE) {
return $TRUE;
}
return $Icinga2.Cache.Checker.RemoteServices[$remoteAddress];
}
$ClientProtocol | Add-Member -membertype ScriptMethod -name 'NewRequest' -value {
param([array]$headers, [string]$content, [string]$remoteAddress, [string]$url);
$url = [string]::Format(
'{0}{1}',
$remoteAddress,
$url
);
$httpRequest = [System.Net.HttpWebRequest]::Create(
$url
);
$httpRequest.Method = 'POST';
$httpRequest.Accept = 'application/json';
$httpRequest.ContentType = 'application/json';
$httpRequest.Headers.Add(
[string]::Format(
'X-Windows-CheckResult: {0}',
$this.fqdn
)
);
# Add possible custom header
foreach ($header in $headers) {
$httpRequest.Headers.Add($header);
}
$httpRequest.TimeOut = 60000;
# If we are using self-signed certificates for example, the HTTP request will
# fail caused by the SSL certificate. With this we can allow even faulty
# certificates. This should be used with caution
if (-Not $Icinga2.Config.'checker.ssl.verify') {
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
}
try {
# Only send data in case we want to send some data
if ($content -ne '') {
$transmitBytes = [System.Text.Encoding]::UTF8.GetBytes($content);
$httpRequest.ContentLength = $transmitBytes.Length;
[System.IO.Stream]$httpOutput = [System.IO.Stream]$httpRequest.GetRequestStream()
$httpOutput.Write($transmitBytes, 0, $transmitBytes.Length)
$httpOutput.Close()
}
} catch [System.Net.WebException] {
$this.SetConnectionState($remoteAddress, $FALSE);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
[string]::Format('Exception while trying to connect to "{0}". Possible a connection error. Message: {1}',
$url,
$_.Exception.Message
)
);
return $null;
} catch {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
$_.Exception.Message
);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
$_.Exception.StackTrace
);
return $null;
}
try {
$this.SetConnectionState($remoteAddress, $TRUE);
return $this.readResponseStream($httpRequest.GetResponse());
} catch [System.Net.WebException] {
# Print an exception message and the possible body in case we received one
# to make troubleshooting easier
[string]$errorResponse = $this.readResponseStream($_.Exception.Response);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
$_.Exception.Message
);
if ($errorResponse -ne '') {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
$errorResponse
);
}
$exceptionMessage = $_.Exception.Response;
if ($exceptionMessage.StatusCode) {
return [int][System.Net.HttpStatusCode]$exceptionMessage.StatusCode;
} else {
return 900;
}
}
return $null;
}
$ClientProtocol | Add-Member -membertype ScriptMethod -name 'readResponseStream' -value {
param([System.Object]$response);
try {
if ($response) {
$responseStream = $response.getResponseStream();
$streamReader = New-Object IO.StreamReader($responseStream);
$result = $streamReader.ReadToEnd();
$response.close()
$streamReader.close()
return $result;
}
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
'The received response from the remote server is NULL. This might be caused by SSL errors or wrong Webserver configuration.'
);
} catch {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Exception,
$_.Exception.Message
);
}
return $null;
}
$ClientProtocol | Add-Member -membertype ScriptMethod -name 'parseWindowsHelloResponse' -value {
param($json);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format(
'Remote Server Output: {0}',
$json
)
);
$Icinga2.Cache.Checker.AuthToken = $json.token;
if ($Icinga2.Cache.Checker.ModuleConfig -eq $null) {
$Icinga2.Cache.Checker.ModuleConfig = @{};
}
$Icinga2.Cache.Checker.ModuleArguments = $json.module_arguments;
[hashtable]$activeModules = @{};
foreach ($module in $json.modules) {
if ($Icinga2.Cache.Checker.ModuleConfig.ContainsKey($module.name)) {
$Icinga2.Cache.Checker.ModuleConfig[$module.name] = $module.check_interval;
} else {
$Icinga2.Cache.Checker.ModuleConfig.Add($module.name, $module.check_interval);
}
$activeModules.Add($module.name, $TRUE);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format(
'Adding module {0} with check intervall {1}',
$module.name,
$module.check_interval
)
);
}
# We might have disabled some modules. Lets handle this by setting the
# execution timer to -1
foreach ($module in $Icinga2.Cache.Checker.ModuleConfig.Keys) {
if ($activeModules.ContainsKey($module) -eq $FALSE) {
$activeModules.Add($module, $FALSE);
}
}
# We require a second loop to ensure we won't crash because of a changed hashtable
foreach($module in $activeModules.Keys) {
if ($activeModules[$module] -eq $FALSE) {
if ($Icinga2.Cache.Checker.ModuleConfig.ContainsKey($module)) {
$Icinga2.Cache.Checker.ModuleConfig.Remove($module);
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
[string]::Format(
'Disabling module {0}',
$module
)
);
}
}
}
}
return $ClientProtocol;