From de2979f1ccf7aba930064bf2f52fff1bd1640193 Mon Sep 17 00:00:00 2001 From: freedbygrace Date: Mon, 20 Mar 2023 08:44:01 -0400 Subject: [PATCH] Added TLS 1.2 Configuration for web calls for Windows release history. --- Content/Settings/Settings.xml | Bin 10898 -> 0 bytes Functions/Get-WindowsReleaseHistory.ps1 | 83 ++++++++++++++--- Functions/Invoke-SQLDBQuery.ps1 | 119 +++++++++++++----------- 3 files changed, 134 insertions(+), 68 deletions(-) delete mode 100644 Content/Settings/Settings.xml diff --git a/Content/Settings/Settings.xml b/Content/Settings/Settings.xml deleted file mode 100644 index 9416716bc70b1b619bed5697fc4d6e38390b2684..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10898 zcmdU#{Zkvq8OQh6bSD49l`@0f2?Fefqzz6g15RiGyB4wAgoenHFeDbJNEkCt{`Dl^ z&pujq_jGy*rgk!#lXQ3cyua>q_w!F{?lbqwb=?bBxR4X=;5(82S$UE%AFO`cQ;= z;iWjywPQ(fE-FpkF^PeJJI;}@KZIgM;VyLbg+7IQ=JA~S)op*C;%^J*@lcnAcxZ~^ z_xgT5q>fxE&7QP+p=)R!4vj`%P~ho_cFjwdYS-iq+P?4QYYX;Jn9qe_;651gZki}d z^>4T1wku=;dLVwfLk?T|g&*YW4y}*oI`RYbkjlN_wxqR}TJ^o|FS?CH508W=YGGY> zQXOFLR9=BPd%{>qGi|TUrv9gr z!3Fq(1>l<^91?kT8!OsWYZ%u+i_xK>qpZuqA_qFQz(Erv2XSQ#M8af~|VjEixT);6eUw|?z z&a~!Ic>+tZ`kszmUB6ItKNO$e=|7wlI^WYuV0NW}u6_&U?S`(IZ+4|?xWFq7#xibS z*FV=4;)`t8(s`iwbw=aA!k6+no!^=>tKM>dcdrw^kYYi8eIibud4AeD|3p_el|#_G z={(c~*1vZ1lJHE?*l|DVbNkx7Z0sbmkb1GZP%(KXQAY0s*j_|%1 zGdZp|)x|XYZ=#7@(+&4e_od{%Da$?a9vgb4o5TCS#}A#xrRO&I`E`9i*TRmlSJkX> z{0Hj!Z_3NOI*CRW>06>e1v(qn(KL>T^?|a*x_X5j-!G6K;E7B}9tkl(l_8gMbxycW z^%=N*_teADk%Hxg){q}r10M%7a02WPIvTDSWJyqARN4!XXr z%>He5=ZWCyyE=*&?#wCYAzhV(yP{~-g-ki;)?^90LVsq|Ch20){X^@mQ=${Z7YpqL zJ{7Jq&8J?IXc5WKXU~7*4fvg%|;b!lnVyChu--sR-sKwn;-Nyns#dZbsBRwDKbkIS@ zsva3`$VOye;)yPi{L|E~#;%5r0ZE9!RBKfjtM_&-4{1GP`^v|!mm3${V_{2kBYMws zBi5NMH(HN{4~EKoU%0JX9#=c?$-n8?kghC(h(tQMYCL%d5j@&{!LzJ+!hhTy^;?g| zV90ClD2BRlEDvF+K7GmGRJTe^dhEGm_eqqF!mgCy$V;=ptq$R~l$RPMDjT9kyyetP zYs>Dh^5k{XH|!3VpCb`fg*xx z&Yq5l7_Uv>??{#py$sc`<20JX;zMa~5NcJzyIUch^}V?~ z`5E|@74OT!P?l;^q(!NK;$Q|B^YEIqOg@d%G`shn>KpSQCU5K%iHx(WU0+yJy^8&( zK{1`IE3cE;**C_CnnhdlDlcw$@3lHa6kQ6kP_+&n4w$S-^x}T^%1H9U0`R#zR1TUiyq?S z8c|A?34GAIv16bkq>tZ{o<8?D^ZfMxa!c; zgq_0lO0y>Fw$Ha3Lhej6b-u%}OgtHaNn*5dTf6JItLdR>Ireni+mRlqD0HekV;Fc1 zgq+HXP?5+z>`Ycvt-%!5R81~{tGPe>wfwTaE-F0NppUVNXiqIB!LO<>2=ICLJP8VF z)-y4i7?e6jrgnK1TVP7_fpye# zNoR(nU&_O`eQc(6FI2sC>5SftF2$amAL*RwRbTz)l0I$StLfYJ&^2EXy1H(iZGc?L zs%kZMV5u)iS*~+oSC34yaR8PyD$S~4zBg)f%a3tBGtJVeW^K9l=pnab9-a2$XB?p{EmXRN{A<$zcAM+)G2?YZ}_rmz=Z9o&d#)! zo+Hi#s=a|o`dB#bDo?Otng_)7yzi7pcgzqUYkK)eJ=2P-Ysyew_v`Znz205f`9Rs} zu0E^6yDREt?UX5vi(sSxmi52g+_CL_`qaNq1gF=_A=`r6RfqFL$MrKqn#J>+60+S* z=Z3btIGt+Le8yuE&HGhpchHu%^XA+@y+gTMcqzZ;jXB=#Lx+>Pfhuo!`w@??*Y&in zAu!MlyOap`*Kv>eEi$fx$6ERuN$l!oe=*5 D`^w%_ diff --git a/Functions/Get-WindowsReleaseHistory.ps1 b/Functions/Get-WindowsReleaseHistory.ps1 index 3bd99d6..334aaed 100644 --- a/Functions/Get-WindowsReleaseHistory.ps1 +++ b/Functions/Get-WindowsReleaseHistory.ps1 @@ -152,6 +152,16 @@ Function Get-WindowsReleaseHistory #Create an object that will contain the functions output. $OutputObjectList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]' + + #region Adjust security protocol type(s) + [System.Net.SecurityProtocolType]$DesiredSecurityProtocol = [System.Net.SecurityProtocolType]::TLS12 + + $LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to set the desired security protocol to `"$($DesiredSecurityProtocol.ToString().ToUpper())`". Please Wait..." + Write-Verbose -Message ($LoggingDetails.LogMessage) + + $Null = [System.Net.ServicePointManager]::SecurityProtocol = ($DesiredSecurityProtocol) + #endregion + } Catch { @@ -192,7 +202,7 @@ Function Get-WindowsReleaseHistory $OGTitle = ($MetadataList[0].Attributes | Where-Object {($_.Name -ieq 'Content')}).Value - $HistoryTableList = $HTMLDocumentObject.SelectNodes('//table') | Where-Object {($_.ID -imatch '(^HistoryTable_\d+$)')} + $Global:HistoryTableList = $HTMLDocumentObject.SelectNodes('//table') | Where-Object {($_.ID -imatch '(^HistoryTable_\d+$)')} $RootNodeList = $HTMLDocumentObject.SelectNodes('//strong') @@ -215,19 +225,67 @@ Function Get-WindowsReleaseHistory $OutputObjectProperties.ReleaseHistory = New-Object -TypeName 'System.Collections.Generic.List[PSObject]' <# - $HistoryTableChildNodeList = ($HistoryTableList | Where-Object {($_.InnerText -imatch ".*$($OutputObjectProperties.Build).*")}).ChildNodes | Where-Object {([String]::IsNullOrEmpty($_.InnerText) -eq $False) -and ([String]::IsNullOrWhiteSpace($_.InnerText) -eq $False)} | Sort-Object -Property @('InnerText') -Unique + $HistoryTableRowList = ($HistoryTableList.ChildNodes | Where-Object {($_.ChildNodes.Count -gt 0)}) - For ($HistoryTableChildNodeIndex = 0; $HistoryTableChildNodeIndex -lt $HistoryTableChildNodeList.Count; $HistoryTableChildNodeIndex++) - { - $HistoryTableChildNode = $HistoryTableChildNodeList[$HistoryTableChildNodeIndex] - - $InnerTextLines = $HistoryTableChildNode.InnerText.Split("`n", [System.StringSplitOptions]::RemoveEmptyEntries).Trim() + For ($HistoryTableRowListIndex = 0; $HistoryTableRowListIndex -lt $HistoryTableRowList.Count; $HistoryTableRowListIndex++) + { + $HistoryTableRow = $HistoryTableRowList[$HistoryTableRowListIndex] - For ($InnerTextLineIndex = 0; $InnerTextLineIndex -lt $InnerTextLines.Count; $InnerTextLineIndex++) + Switch ($HistoryTableRowListIndex) { - $InnerTextLine = $InnerTextLines[$InnerTextLineIndex] + {($_ -eq 0)} + { + $HistoryTableRowNodeList = $HistoryTableRow.ChildNodes | Where-Object {([String]::IsNullOrEmpty($_.InnerText) -eq $False) -and ([String]::IsNullOrWhiteSpace($_.InnerText) -eq $False)} + + $HistoryTableRowPropertyList = ($HistoryTableRowNodeList | ForEach-Object {($TextInfo.ToTitleCase($_.InnerText) -ireplace '(\s+)', '')}) -As [System.Collections.Generic.List[String]] + } - #$InnerTextLine + Default + { + Switch ($HistoryTableRowPropertyList.Count -gt 0) + { + {($_ -eq $True)} + { + $ReleaseHistoryObjectProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary' + + $HistoryTableRowData = $HistoryTableRow.ChildNodes | Where-Object {($_.ChildNodes.Count -gt 0)} + + For ($HistoryTableRowPropertyListIndex = 0; $HistoryTableRowPropertyListIndex -lt $HistoryTableRowPropertyList.Count; $HistoryTableRowPropertyListIndex++) + { + $HistoryTableRowPropertyName = $HistoryTableRowPropertyList[$HistoryTableRowPropertyListIndex] + + $HistoryTableRowPropertyValue = $HistoryTableRowData[$HistoryTableRowPropertyListIndex] + + Switch ($Null -ine $HistoryTableRowPropertyValue) + { + {($_ -eq $True)} + { + $ValuesMatchingRowNodeList = $HistoryTableRowNodeList | Where-Object {($_.InnerText -imatch ".*$($HistoryTableRowPropertyValue.InnerText).*")} + + $ValuesMatchingRowNodeListCount = ($ValuesMatchingRowNodeList | Measure-Object).Count + + Switch ($ValuesMatchingRowNodeListCount -eq 0) + { + {($_ -eq $True)} + { + $ReleaseHistoryObjectProperties."$($HistoryTableRowPropertyName)" = $HistoryTableRowPropertyValue.InnerText + } + + Default + { + $ReleaseHistoryObjectProperties."$($HistoryTableRowPropertyName)" = $Null + } + } + } + } + } + + $ReleaseHistoryObject = New-Object -TypeName 'PSObject' -Property ($ReleaseHistoryObjectProperties) + + $OutputObjectProperties.ReleaseHistory.Add($ReleaseHistoryObject) + } + } + } } } #> @@ -239,12 +297,13 @@ Function Get-WindowsReleaseHistory } } + $Null = $OutputObjectProperties.ReleaseHistory = $OutputObjectProperties.ReleaseHistory.ToArray() | Where-Object {($Null -ine $_)} } #Write the object to the powershell pipeline $OutputObjectList = $OutputObjectList.ToArray() - $Global:WindowsReleaseHistory = $OutputObjectList | Sort-Object -Property @('Version') + $Global:WindowsReleaseHistory = $OutputObjectList | Sort-Object -Property @('Version') | Group-Object -Property @('Name') } Default @@ -296,5 +355,5 @@ Function Get-WindowsReleaseHistory #endregion <# - Get-WindowsReleaseHistory -Force:$False -Verbose + Get-WindowsReleaseHistory -Verbose #> \ No newline at end of file diff --git a/Functions/Invoke-SQLDBQuery.ps1 b/Functions/Invoke-SQLDBQuery.ps1 index e8767d2..717557d 100644 --- a/Functions/Invoke-SQLDBQuery.ps1 +++ b/Functions/Invoke-SQLDBQuery.ps1 @@ -11,18 +11,25 @@ Function Invoke-SQLDBQuery The database connection will be opened, each database query will be executed, the results will be stored, and the database connection will be closed. .PARAMETER Server + The FQDN or IP Address of a MS SQL database server. .PARAMETER Instance + A valid instance name of the desired MS SQL database server instance. (Optional) .PARAMETER Port + A valid port number of the MS SQL database server. (Optional) .PARAMETER UserID + A valid SQL authentication username (If not specified, Windows authentication will be used.) .PARAMETER Password + A valid SQL authentication password (If not specified, Windows authentication will be used.) .PARAMETER Database + A valid database name that resides on the specified MS SQL database server. .PARAMETER DBQueryList + One or more valid SQL queries for the specified database. .EXAMPLE $DBQueryResults = Invoke-SQLDBQuery -Server 'MyDBServer.mydomain.com' -UserID 'SQLAuthUser' -Password 'SQLAuthUserPassword' -Database 'YourDatabaseName' -DBQueryList @('Select * From YourTableName') -Verbose @@ -30,7 +37,7 @@ Function Invoke-SQLDBQuery Write-Output -InputObject ($DBQueryResults) .EXAMPLE - $DBQueryList = [System.Collections.Generic.List[String]]@() + $DBQueryList = New-Object -TypeName 'System.Collections.Generic.List[String]' $DBQueryList.Add(@" Select Distinct dbo.v_Add_Remove_Programs.DisplayName0 As 'DisplayName' @@ -51,6 +58,26 @@ Order By $DBQueryResults = Invoke-SQLDBQuery -Server 'MyDBServer.mydomain.com' -Port '4530' -Database 'YourDatabaseName' -DBQueryList @('Select * From YourTableName1', 'Select * From YourTableName2') Write-Output -InputObject ($DBQueryResults) + + .EXAMPLE + $InvokeSQLDBQueryParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary' + $InvokeSQLDBQueryParameters.Server = "MyDBServer.mydomain.com" + $InvokeSQLDBQueryParameters.Instance = "MyDBInstance" + $InvokeSQLDBQueryParameters.Port = "1433" + $InvokeSQLDBQueryParameters.UserID = "sa" + $InvokeSQLDBQueryParameters.Password = "Password1" + $InvokeSQLDBQueryParameters.Database = "YourDatabaseName" + $InvokeSQLDBQueryParameters.DBQueryList = New-Object -TypeName 'System.Collections.Generic.List[String]' + $InvokeSQLDBQueryParameters.DBQueryList.Add('Select * From YourTableName1') + $InvokeSQLDBQueryParameters.DBQueryList.Add('Select * From YourTableName2') + $InvokeSQLDBQueryParameters.ExportJSON = $True + $InvokeSQLDBQueryParameters.ExportDirectory = "$($Env:Public)\Desktop\SQLDBQueryResults" + $InvokeSQLDBQueryParameters.ContinueOnError = $True + $InvokeSQLDBQueryParameters.Verbose = $True + + $InvokeSQLDBQueryResult = Invoke-SQLDBQuery @InvokeSQLDBQueryParameters + + Write-Output -InputObject ($InvokeSQLDBQueryResult) .LINK https://www.SQLshack.com/connecting-powershell-to-SQL-server/ @@ -59,7 +86,7 @@ Order By https://stackoverflow.com/questions/64681003/fetch-a-whole-row-from-SQL-server-with-powershell #> - [CmdletBinding(ConfirmImpact = 'Low', HelpURI = '', DefaultParameterSetName = '_AllParameterSets', SupportsShouldProcess = $True, PositionalBinding = $True)] + [CmdletBinding(ConfirmImpact = 'Low', HelpURI = '', DefaultParameterSetName = '_AllParameterSets', SupportsShouldProcess = $True)] Param ( [Parameter(Mandatory=$True)] @@ -139,39 +166,7 @@ Order By #Define Default Action Preferences $ErrorActionPreference = 'Stop' - - $LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - The following parameters and values were provided to the `'$($CmdletName)`' function." - Write-Verbose -Message $LogMessage - - $FunctionProperties = Get-Command -Name $CmdletName - - $FunctionParameters = $FunctionProperties.Parameters.Keys | Where-Object {($_ -inotmatch '(^Password$)|(^UserID$)|(^DBQueryList$)')} - - ForEach ($Parameter In $FunctionParameters) - { - If (!([String]::IsNullOrEmpty($Parameter))) - { - $ParameterProperties = Get-Variable -Name $Parameter -ErrorAction SilentlyContinue - $ParameterValueCount = $ParameterProperties.Value | Measure-Object | Select-Object -ExpandProperty Count - - If ($ParameterValueCount -gt 1) - { - $ParameterValueStringFormat = ($ParameterProperties.Value | ForEach-Object {"`"$($_)`""}) -Join ", " - $LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - $($ParameterProperties.Name):`r`n`r`n$($ParameterValueStringFormat)" - } - Else - { - $ParameterValueStringFormat = ($ParameterProperties.Value | ForEach-Object {"`"$($_)`""}) -Join ', ' - $LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - $($ParameterProperties.Name): $($ParameterValueStringFormat)" - } - - If (!([String]::IsNullOrEmpty($ParameterProperties.Name))) - { - Write-Verbose -Message $LogMessage - } - } - } - + $LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Execution of $($CmdletName) began on $($FunctionStartTime.ToString($DateTimeLogFormat))" Write-Verbose -Message $LogMessage @@ -185,10 +180,10 @@ Order By $LoggingDetails.Add('ErrorMessage', $Null) #Create a database connection string builder - $DBConnectionStringBuilder = [System.Data.SQLClient.SQLConnectionStringBuilder]::New() + $DBConnectionStringBuilder = New-Object -TypeName 'System.Data.SQLClient.SQLConnectionStringBuilder' #Create a database data source builder - $DataSourceBuilder = [System.Text.StringBuilder]::New() + $DataSourceBuilder = New-Object -TypeName 'System.Text.StringBuilder' #Dynamically build the connection string based on parameter values Switch ($True) @@ -219,26 +214,34 @@ Order By } } - $DBConnection = [System.Data.SQLClient.SQLConnection]::New() + $DBConnection = New-Object -TypeName 'System.Data.SQLClient.SQLConnection' - Switch (([String]::IsNullOrEmpty($UserID) -eq $True) -or ([String]::IsNullOrWhiteSpace($UserID) -eq $True) -or ([String]::IsNullOrEmpty($Password) -eq $True) -or ([String]::IsNullOrWhiteSpace($Password) -eq $True)) + Switch ((([String]::IsNullOrEmpty($UserID) -eq $False) -and ([String]::IsNullOrWhiteSpace($UserID) -eq $False)) -and (([String]::IsNullOrEmpty($Password) -eq $False) -or ([String]::IsNullOrWhiteSpace($Password) -eq $False))) { {($_ -eq $True)} { - $DBConnectionStringBuilder.PSBase.IntegratedSecurity = $True + $DBConnectionStringBuilder.PSBase.IntegratedSecurity = $False + + $CredentialParameters = New-Object -TypeName 'System.Collections.Generic.List[Object]' + $CredentialParameters.Add($UserID) + $CredentialParameters.Add((ConvertTo-SecureString -String $Password -AsPlainText -Force)) + + $Credential = New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList ($CredentialParameters.ToArray()) + + $Null = $Credential.Password.MakeReadOnly() + + $DBConnectionCredentialParameters = New-Object -TypeName 'System.Collections.Generic.List[Object]' + $DBConnectionCredentialParameters.Add($Credential.UserName) + $DBConnectionCredentialParameters.Add($Credential.Password) + + $DBConnectionCredential = New-Object -TypeName 'System.Data.SQLClient.SQLCredential' -ArgumentList ($DBConnectionCredentialParameters.ToArray()) + + $DBConnection.Credential = ($DBConnectionCredential) } Default { - $DBConnectionStringBuilder.PSBase.IntegratedSecurity = $False - - $Credential = [System.Management.Automation.PSCredential]::New($UserID, (ConvertTo-SecureString -String $Password -AsPlainText -Force)) - - $Null = $Credential.Password.MakeReadOnly() - - $DBConnectionCredential = [System.Data.SQLClient.SQLCredential]::New($Credential.UserName, $Credential.Password) - - $DBConnection.Credential = ($DBConnectionCredential) + $DBConnectionStringBuilder.PSBase.IntegratedSecurity = $True } } @@ -271,7 +274,7 @@ Order By [String]$DBQuery = $DBQueryList[$DBQueryListIndex] [Int]$DBQueryNumber = $DBQueryListIndex + 1 - $DBCommand = [System.Data.SQLClient.SQLCommand]::New() + $DBCommand = New-Object -TypeName 'System.Data.SQLClient.SQLCommand' $DBCommand.Connection = ($DBConnection) $DBCommand.CommandText = ($DBQuery) @@ -280,10 +283,14 @@ Order By $Null = $DBCommand.ExecuteScalar() - $DBQueryResults = [System.Data.DataTable]::New() + $DBQueryResults = New-Object -TypeName 'System.Data.DataTable' + + $DBDataAdapterParameters = New-Object -TypeName 'System.Collections.Generic.List[Object]' + $DBDataAdapterParameters.Add($DBCommand) - $DBDataAdapter = [System.Data.SQLClient.SQLDataAdapter]::New($DBCommand) - $Null = $DBDataAdapter.Fill($DBQueryResults) + $DBDataAdapter = New-Object -TypeName 'System.Data.SQLClient.SQLDataAdapter' -ArgumentList ($DBDataAdapterParameters.ToArray()) + + $Null = $DBDataAdapter.Fill($DBQueryResults) $DBQueryRowCount = $DBQueryResults.Rows.Count @@ -305,10 +312,10 @@ Order By $LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - " + "Attempting to add the result(s) from database query #$($DBQueryNumber) to property `"$($ResultSetPropertyName)`". Please Wait..." Write-Verbose -Message ($LoggingDetails.LogMessage) - $PropertyInclusionList = [System.Collections.Generic.List[Object]]@() + $PropertyInclusionList = New-Object -TypeName 'System.Collections.Generic.List[Object]' $Null = $PropertyInclusionList.Add('*') - $PropertyExclusionList = [System.Collections.Generic.List[Object]]@() + $PropertyExclusionList = New-Object -TypeName 'System.Collections.Generic.List[Object]' $Null = $PropertyExclusionList.AddRange(('HasErrors', 'ItemArray', 'RowError', 'RowState', 'Table')) $DBQueryRows = $DBQueryResults.Rows | Select-Object -Property ($PropertyInclusionList) -ExcludeProperty ($PropertyExclusionList) @@ -353,7 +360,7 @@ Order By {($ExportJSON.IsPresent)} { $ExportParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary' - $ExportParameters.Add('Compress', $False) + $ExportParameters.Add('Compress', $True) $ExportParameters.Add('Encoding', [System.Text.Encoding]::Default) $ExportParameters.Add('Depth', 10)