icinga-powershell-framework/core/include/ServerProtocol.ps1

223 lines
7 KiB
PowerShell
Raw Normal View History

2018-11-06 11:14:49 -05:00
$ServerProtocoll = New-Object -TypeName PSObject;
$ServerProtocoll | Add-Member -membertype NoteProperty -name 'static' -value $FALSE;
$ServerProtocoll | Add-Member -membertype NoteProperty -name 'Client' -value $Null;
$ServerProtocoll | Add-Member -membertype NoteProperty -name 'Network' -value (Get-Icinga-Lib -Include 'NetworkProtocol');
$ServerProtocoll | Add-Member -membertype NoteProperty -name 'Response' -value (Get-Icinga-Lib -Include 'APIResponse');
$ServerProtocoll | Add-Member -membertype NoteProperty -name 'Timer' -value $Null;
$ServerProtocoll | Add-Member -membertype NoteProperty -name 'Message' -value $Null;
$ServerProtocoll | Add-Member -membertype NoteProperty -name 'Commands' -value @{};
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'Create' -value {
param([System.Net.Sockets.TcpClient]$Client);
$this.Client = $Client;
$this.Client.SendTimeout = 2000
$this.Client.NoDelay = $TRUE;
$this.Timer = [System.Diagnostics.Stopwatch]::StartNew();
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
'New incoming TCP Client connection'
);
$this.Network.Create($Client.GetStream());
# Just in case we received connections over HTTP, send a short answer message
# back and close the client request
if ($this.Network.encrypted -eq $FALSE) {
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Warning,
'Received client connection over HTTP. Rejecting client request.'
);
$this.Response.HTTPSRequired();
$this.Network.WriteMessage(
$this.Response.Compile()
);
$this.Close();
return $FALSE;
}
return $TRUE;
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'ParseRequest' -value {
# Tell our network protocol to read all messages until
# EOF is reached
[SecureString]$message = $this.Network.ReadMessage(-1);
if ($message -eq $null) {
return;
}
[hashtable]$ApiMessage = $Icinga2.Utils.WebHelper.ParseApiMessage($message);
if ($ApiMessage -eq $null -Or $ApiMessage.Count -eq 0) {
$this.SendInternalServerError();
return;
}
if ($Icinga2.Config.'authentication.enabled') {
[int]$Authenticated = $Icinga2.Utils.AuthHelper.Login(
$ApiMessage.credentials.user,
$ApiMessage.credentials.password,
$ApiMessage.credentials.domain
);
if ($Authenticated -eq 0) {
$this.SendAuthenticationRequired();
return;
}
}
if ($ApiMessage.headers.ContainsKey('content-length')) {
[int]$ContentLength = ($ApiMessage.headers['content-length'] - $ApiMessage.content.Length);
$ApiMessage.content += $Icinga2.Utils.SecureString.ConvertFrom(
$this.Network.ReadMessage(
$ContentLength
)
);
}
$this.Message = $ApiMessage;
$this.ParseQuery();
$this.ExecuteQuery();
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'ParseQuery' -value {
[string]$QueryString = $this.Message.base.query;
if ($QueryString[0] -eq '?') {
$QueryString = $QueryString.Substring(
1,
$QueryString.Length - 1
);
}
[array]$SplitCommand = $QueryString.Split('&');
foreach ($command in $SplitCommand) {
[hashtable]$data = $Icinga2.Utils.WebHelper.ParseUrlCommand($command);
if ($this.Commands.ContainsKey(($data.GetEnumerator() | Select-Object -First 1).Key) -eq $FALSE) {
$this.Commands += $data;
}
}
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'ExecuteQuery' -value {
switch($this.IsUrlPathValid(0)) {
'' {
switch($this.IsUrlPathValid(1)) {
'v1' {
switch($this.IsUrlPathValid(2)) {
'data' {
$this.ParseDataV1();
};
'modules' {
$this.ParseModulesV1();
};
default {
$this.SendBadRequest(
'Unsupported Cmdlets specified. The following Cmdlets are supported: data, modules'
);
};
}
};
default {
$this.SendBadRequest(
'Unsupported API version specified. The following versions are supported: v1'
);
};
}
};
default {
$this.SendInternalServerError();
};
}
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'GetExecutionTime' -value {
return $this.Timer.Elapsed.TotalSeconds;
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'ParseDataV1' -value {
[hashtable]$data =
@{
data = New-Icinga-Monitoring -Include $this.Commands.include -Exclude $this.Commands.exclude;
execution = $this.GetExecutionTime();
};
$this.Response.setContent($data);
$this.SendOkResponse();
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'ParseModulesV1' -value {
[hashtable]$modules =
@{
modules = New-Icinga-Monitoring -ListModules $TRUE;
execution = $this.GetExecutionTime();
};
$this.Response.setContent($modules);
$this.SendOkResponse();
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'IsUrlPathValid' -value {
param([int]$Index);
[string]$path = $this.Message.base.segments[$Index];
if ([string]::IsNullOrEmpty($path) -eq $TRUE) {
return 'default';
}
return $path.Replace('/', '');
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'SendOkResponse' -value {
$this.Network.WriteMessage(
$this.Response.Compile()
);
$this.Close();
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'SendInternalServerError' -value {
$this.Response.InternalServerError();
$this.Network.WriteMessage(
$this.Response.Compile()
);
$this.Close();
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'SendAuthenticationRequired' -value {
$this.Response.AuthenticationRequired();
$this.Network.WriteMessage(
$this.Response.Compile()
);
$this.Close();
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'SendBadRequest' -value {
param([string]$message);
$this.Response.CustomBadRequest($message);
$this.Network.WriteMessage(
$this.Response.Compile()
);
$this.Close();
}
$ServerProtocoll | Add-Member -membertype ScriptMethod -name 'Close' -value {
try {
$this.Timer.Stop();
$Icinga2.Log.Write(
$Icinga2.Enums.LogState.Debug,
'Closing TCP Client connection'
)
$this.Client.Close();
$this.Client.Dispose()
$this.Client = $Null;
} catch {
# Nothing to handle. If the connection is closed already, ignore it.
}
}
return $ServerProtocoll;