From bab67784fa5d32f04eaf7d025cd8bf2b53b1a953 Mon Sep 17 00:00:00 2001 From: Philipp Dorschner Date: Fri, 28 Aug 2020 09:10:23 +0200 Subject: [PATCH] Adds MSSQL connector --- .../exception/Exit-IcingaThrowException.psm1 | 6 +- .../Icinga_IcingaExceptionEnums.psm1 | 7 ++ lib/mssql/Close-IcingaMSSQLConnection.psm1 | 33 +++++ lib/mssql/New-IcingaMSSQLCommand.psm1 | 43 +++++++ lib/mssql/Open-IcingaMSSQLConnection.psm1 | 114 ++++++++++++++++++ lib/mssql/Send-IcingaMSSQLCommand.psm1 | 32 +++++ 6 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 lib/mssql/Close-IcingaMSSQLConnection.psm1 create mode 100644 lib/mssql/New-IcingaMSSQLCommand.psm1 create mode 100644 lib/mssql/Open-IcingaMSSQLConnection.psm1 create mode 100644 lib/mssql/Send-IcingaMSSQLCommand.psm1 diff --git a/lib/icinga/exception/Exit-IcingaThrowException.psm1 b/lib/icinga/exception/Exit-IcingaThrowException.psm1 index d634a1b3..a0d866b1 100644 --- a/lib/icinga/exception/Exit-IcingaThrowException.psm1 +++ b/lib/icinga/exception/Exit-IcingaThrowException.psm1 @@ -5,7 +5,7 @@ function Exit-IcingaThrowException() [string]$StringPattern, [string]$CustomMessage, [string]$ExceptionThrown, - [ValidateSet('Permission', 'Input', 'Configuration', 'Unhandled', 'Custom')] + [ValidateSet('Permission', 'Input', 'Configuration', 'Connection', 'Unhandled', 'Custom')] [string]$ExceptionType = 'Unhandled', [switch]$Force ); @@ -36,6 +36,10 @@ function Exit-IcingaThrowException() $ExceptionTypeString = 'Invalid Configuration'; $ExceptionMessageLib = $IcingaExceptions.Configuration; }; + 'Connection' { + $ExceptionTypeString = 'Connection error'; + $ExceptionMessageLib = $IcingaExceptions.Connection; + }; 'Unhandled' { $ExceptionTypeString = 'Unhandled'; }; diff --git a/lib/icinga/exception/Icinga_IcingaExceptionEnums.psm1 b/lib/icinga/exception/Icinga_IcingaExceptionEnums.psm1 index 526a71cf..7c82ef34 100644 --- a/lib/icinga/exception/Icinga_IcingaExceptionEnums.psm1 +++ b/lib/icinga/exception/Icinga_IcingaExceptionEnums.psm1 @@ -19,6 +19,8 @@ ConversionUnitMissing = 'Unable to parse input value. You have to add an unit to your input value. Example: "10GB". Allowed units are: "B, KB, MB, GB, TB, PB, KiB, MiB, GiB, TiB, PiB".'; CimClassNameUnknown = 'The provided class name you try to fetch with Get-CimInstance is not known on this system.'; WmiObjectClassUnknown = 'The provided class name you try to fetch with Get-WmiObject is not known on this system.'; + MSSQLCredentialHandling = 'The connection to MSSQL was not possbible because your login credential was not correct.'; + MSSQLCommandMissing = 'Failed to build a SQL query' }; [hashtable]$Configuration = @{ @@ -30,6 +32,10 @@ PerfCounterCategoryMissing = 'The specified Performance Counter category was not found on this system. This could either be a configuration error on your local Windows machine or a wrong usage of the plugin. Please check on different Windows machines if this issue persis. In case it only occurs on certain machines it is likely that the counter is simply not present and the plugin can not be processed.'; } +[hashtable]$Connection = @{ + MSSQLConnectionError = 'Could not open a connection to SQL Server. This failure may be caused by the fact that under the default settings SQL Server does not allow remote connections or the host is unreachable.'; +} + <# # Once we defined a new enum hashtable above, simply add it to this list # to make it available within the entire module. @@ -41,6 +47,7 @@ Permission = $Permission; Inputs = $Inputs; Configuration = $Configuration; + Connection = $Connection; } Export-ModuleMember -Variable @( 'IcingaExceptions' ); diff --git a/lib/mssql/Close-IcingaMSSQLConnection.psm1 b/lib/mssql/Close-IcingaMSSQLConnection.psm1 new file mode 100644 index 00000000..df322540 --- /dev/null +++ b/lib/mssql/Close-IcingaMSSQLConnection.psm1 @@ -0,0 +1,33 @@ +<# +.SYNOPSIS + Closes a open connection to a MSSQL server +.DESCRIPTION + This Cmdlet will close an open connection to a MSSQL server. +.FUNCTIONALITY + Closes an open connection to a MSSQL server. +.EXAMPLE + PS>Close-IcingaMSSQLConnection $OpenMSSQLConnection; +.INPUTS + System.Data.SqlClient.SqlConnection +.OUTPUTS +.LINK + https://github.com/Icinga/icinga-powershell-framework +#> +function Close-IcingaMSSQLConnection() +{ + param ( + [System.Data.SqlClient.SqlConnection]$SqlConnection = $null + ); + + if ($null -eq $SqlConnection) { + return; + } + + Write-IcingaDebugMessage ` + -Message 'Closing client connection for endpoint {0}' ` + -Objects $SqlConnection; + + $SqlConnection.Close(); + $SqlConnection.Dispose(); + $SqlConnection = $null; +} diff --git a/lib/mssql/New-IcingaMSSQLCommand.psm1 b/lib/mssql/New-IcingaMSSQLCommand.psm1 new file mode 100644 index 00000000..976475e6 --- /dev/null +++ b/lib/mssql/New-IcingaMSSQLCommand.psm1 @@ -0,0 +1,43 @@ +<# +.SYNOPSIS + Builds a SQL query +.DESCRIPTION + This Cmdlet will build a SQL query + and returns it as an string. +.FUNCTIONALITY + Build a SQL query +.EXAMPLE + PS>New-IcingaMSSQLCommand -SqlConnection $SqlConnection -SqlQuery "SELECT object_name FROM sys.dm_os_performance_counters"; +.PARAMETER SqlConnection + An open SQL connection object e.g. $SqlConnection = Open-IcingaMSSQLConnection -IntegratedSecurity; +.PARAMETER SqlQuery + A SQL query as string. +.INPUTS + System.Data.SqlClient.SqlConnection + System.String +.OUTPUTS + System.Data.SqlClient.SqlCommand +.LINK + https://github.com/Icinga/icinga-powershell-framework +#> +function New-IcingaMSSQLCommand() +{ + param ( + [System.Data.SqlClient.SqlConnection]$SqlConnection = $null, + [string]$SqlQuery = $null + ); + + $SqlCommand = New-Object System.Data.SqlClient.SqlCommand; + $SqlCommand.Connection = $SqlConnection; + + if ($null -eq $SqlCommand.Connection) { + Exit-IcingaThrowException -ExceptionType 'Input' ` + -ExceptionThrown $IcingaExceptions.Inputs.MSSQLCommandMissing ` + -CustomMessage 'It seems the -SqlConnection is empty or invalid' ` + -Force; + } + + $SqlCommand.CommandText = $SqlQuery; + + return $SqlCommand; +} diff --git a/lib/mssql/Open-IcingaMSSQLConnection.psm1 b/lib/mssql/Open-IcingaMSSQLConnection.psm1 new file mode 100644 index 00000000..9e437d45 --- /dev/null +++ b/lib/mssql/Open-IcingaMSSQLConnection.psm1 @@ -0,0 +1,114 @@ +<# +.SYNOPSIS + Opens a connection to a MSSQL server +.DESCRIPTION + This Cmdlet will open a connection to a MSSQL server + and returns that connection object. +.FUNCTIONALITY + Opens a connection to a MSSQL server +.EXAMPLE + PS>Open-IcingaMSSQLConnection -IntegratedSecurity -Address localhost; +.EXAMPLE + PS>Open-IcingaMSSQLConnection -Username Exampleuser -Password (ConvertTo-IcingaSecureString 'examplePassword') -Address 123.125.123.2; +.PARAMETER Username + The username for connecting to the MSSQL database +.PARAMETER Password + The password for connecting to the MSSQL database as secure string +.PARAMETER Address + The IP address or FQDN to the MSSQL server to connect to (default: localhost) +.PARAMETER Port + The port of the MSSQL server/instance to connect to with the provided credentials (default: 1433) +.PARAMETER SqlDatabase + The name of a specific database to connect to. Leave empty to connect "globaly" +.PARAMETER IntegratedSecurity + Allows this plugin to use the credentials of the current PowerShell session inherited by + the user the PowerShell is running with. If this is set and the user the PowerShell is + running with can access to the MSSQL database you will not require to provide username + and password +.OUTPUTS + System.Data.SqlClient.SqlConnection +.LINK + https://github.com/Icinga/icinga-powershell-framework +#> +function Open-IcingaMSSQLConnection() +{ + param ( + [string]$Username, + [securestring]$Password, + [string]$Address = "localhost", + [int]$Port = 1433, + [string]$SqlDatabase, + [switch]$IntegratedSecurity = $FALSE + ); + + if ($IntegratedSecurity -eq $FALSE) { + if ([string]::IsNullOrEmpty($Username)) { + Exit-IcingaThrowException ` + -ExceptionType 'Input' ` + -ExceptionThrown $IcingaExceptions.Inputs.MSSQLCredentialHandling ` + -CustomMessage '-Username not set and -IntegratedSecurity is false' ` + -Force; + } elseif ($null -eq $Password) { + Exit-IcingaThrowException ` + -ExceptionType 'Input' ` + -ExceptionThrown $IcingaExceptions.Inputs.MSSQLCredentialHandling ` + -CustomMessage '-Password not set and -IntegratedSecurity is false' ` + -Force; + } + + $Password.MakeReadOnly(); + $SqlCredential = New-Object System.Data.SqlClient.SqlCredential($Username, $Password); + } + + try { + $SqlConnection = New-Object System.Data.SqlClient.SqlConnection; + $SqlConnection.ConnectionString = "Server=$Address,$Port;"; + + if ($null -ne $SqlDatabase) { + $SqlConnection.ConnectionString += "Database=$SqlDatabase;"; + } + + if ($IntegratedSecurity -eq $TRUE) { + $SqlConnection.ConnectionString += "Integrated Security=True;"; + } + + $SqlConnection.Credential = $SqlCredential; + + Write-IcingaDebugMessage ` + -Message 'Open client connection for endpoint {0}' ` + -Objects $SqlConnection; + + $SqlConnection.Open(); + } catch { + Exit-IcingaThrowException ` + -InputString $_.Exception.Message ` + -StringPattern $Username ` + -ExceptionType 'Input' ` + -ExceptionThrown $IcingaExceptions.Inputs.MSSQLCredentialHandling; + + Exit-IcingaThrowException ` + -InputString $_.Exception.Message ` + -StringPattern 'error: 40' ` + -ExceptionType 'Connection' ` + -ExceptionThrown $IcingaExceptions.Connection.MSSQLConnectionError; + + Exit-IcingaThrowException ` + -InputString $_.Exception.Message ` + -StringPattern 'error: 0' ` + -ExceptionType 'Connection' ` + -ExceptionThrown $IcingaExceptions.Connection.MSSQLConnectionError; + + Exit-IcingaThrowException ` + -InputString $_.Exception.Message ` + -StringPattern 'error: 25' ` + -ExceptionType 'Connection' ` + -ExceptionThrown $IcingaExceptions.Connection.MSSQLConnectionError; + # Last resort + Exit-IcingaThrowException ` + -InputString $_.Exception.Message ` + -ExceptionType 'Custom' ` + -Force; + } + + return $SqlConnection; +} diff --git a/lib/mssql/Send-IcingaMSSQLCommand.psm1 b/lib/mssql/Send-IcingaMSSQLCommand.psm1 new file mode 100644 index 00000000..d9cf840c --- /dev/null +++ b/lib/mssql/Send-IcingaMSSQLCommand.psm1 @@ -0,0 +1,32 @@ +<# +.SYNOPSIS + Executes a SQL query +.DESCRIPTION + This Cmdlet will send a SQL query to a given database and + execute the query and returns the output. +.FUNCTIONALITY + Executes a SQL query +.EXAMPLE + PS> Send-IcingaMSSQLCommand -SqlCommand $SqlCommand; +.PARAMETER SqlCommand + The SQL query which will be executed, e.g. $SqlCommand = New-IcingaMSSQLCommand +.INPUTS + System.Data.SqlClient.SqlCommand +.OUTPUTS + System.Data.DataSet +.LINK + https://github.com/Icinga/icinga-powershell-framework +#> +function Send-IcingaMSSQLCommand() +{ + param ( + [System.Data.SqlClient.SqlCommand]$SqlCommand = $null + ); + + $Adapter = New-Object System.Data.SqlClient.SqlDataAdapter $SqlCommand; + + $Data = New-Object System.Data.DataSet; + $Adapter.Fill($Data) | Out-Null; + + return $Data.Tables; +}