DSCResources/DSC-data-driven-deployment/modules/ConfigurationHelper.psm1
# Set Global Module Verbose $VerbosePreference = 'Continue' function Invoke-StoredProcedure{ [CmdletBinding()] param ( [ValidateNotNull()] $storedProcName, [ValidateNotNull()] [hashtable] $parameters=@{}, [hashtable] $outparams=@{}, [ValidateNotNull()] $conn,[switch]$help) function Put-OutputParameters($cmd, $outparams){ foreach($outp in $outparams.Keys){ $cmd.Parameters.Add("@$outp", (Get-Paramtype $outparams[$outp])).Direction=[System.Data.ParameterDirection]::Output } } function Get-OutputParameters($cmd,$outparams){ foreach($p in $cmd.Parameters){ if ($p.Direction -eq [System.Data.ParameterDirection]::Output){ $outparams[$p.ParameterName.Replace("@","")]=$p.Value } } } $close=($conn.State -eq [System.Data.ConnectionState]'Closed') if ($close) { $conn.Open() } $cmd=New-Object System.Data.SqlClient.SqlCommand($sql,$conn) $cmd.CommandType=[System.Data.CommandType]'StoredProcedure' $cmd.CommandText=$storedProcName foreach($p in $parameters.Keys){ $cmd.Parameters.AddWithValue("@$p",[string]$parameters[$p]).Direction= [System.Data.ParameterDirection]::Input } Put-OutputParameters $cmd $outparams $ds=New-Object System.Data.DataSet $da=New-Object System.Data.SqlClient.SqlDataAdapter($cmd) [Void]$da.fill($ds) $open=($conn.State -eq [System.Data.ConnectionState]'Open') if ($open) { $conn.Close() } Get-OutputParameters $cmd $outparams return @{data=$ds;outputparams=$outparams} } function Add-PSCredential { [CmdletBinding()] param ( $Credential = (Get-Credential), [ValidateNotNull()] [System.String] $CredentialName, [ValidateNotNull()] [System.String] $SQLServer) Try { # Look at the object type of the $Credential parameter to determine how to handle it switch ( $Credential.GetType().Name ) { PSCredential { continue } String { $Credential = Get-Credential -credential $Credential } default { Throw "You must specify a credential object to export to disk." } } $export = "" | Select-Object Username, EncryptedPassword $export.PSObject.TypeNames.Insert(0,’ExportedPSCredential’) $UserName = $Credential.Username # Encrypt SecureString password using Data Protection API # Only the current user account can decrypt this cipher $export.EncryptedPassword = $Credential.Password | ConvertFrom-SecureString $connString = "Data Source=$SQLServer;Initial Catalog=DSCCentral;Integrated Security=True" Write-Verbose -Message "Connecting to $connString" $output =Invoke-StoredProcedure -storedProcName "dbo.NewCredential" -parameters @{CredentialName=$CredentialName;UserName=$UserName ;Password=$export.EncryptedPassword} -conn $connString Write-Verbose "Credentials saved to: $SQLServer" } Catch {Write-Error "Error saving Credentials to: $SQLServer"} } function Get-PSCredential{ [CmdletBinding()] param ( [ValidateNotNull()] [System.String] $UserName, [ValidateNotNull()] [System.String] $Password) Try { $SecurePass = $Password | ConvertTo-SecureString $Credential = New-Object System.Management.Automation.PSCredential $UserName, $SecurePass Return $Credential } Catch {Write-Error "Error Converting Password to SecureString"} } Function Get-Cert { [CmdletBinding()] Param ( [System.String]$RemoteMachine, [System.String]$SaveLocation = "F:\publicKeys" ) if (!(Test-Path $SaveLocation)) { New-Item -path $SaveLocation -type Directory } $CertStore = New-Object System.Security.Cryptography.X509Certificates.X509Store -ArgumentList "\\$($RemoteMachine)\My", "LocalMachine" $CertStore.Open('ReadOnly') $certificate = $CertStore.Certificates | Where-Object {$_.EnhancedKeyUsageList.friendlyName -eq "Document Encryption"} If ($certificate) { [byte[]]$Bytes = $certificate.Export('Cert') [string]$SaveLiteralPath = "$SaveLocation\$RemoteMachine.$env:UserDNSDomain.cer" Remove-Item -Path $SaveLiteralPath -Force -ErrorAction Ignore Set-Content -Path $SaveLiteralPath -Value $Bytes -Encoding Byte -Force | out-null } Else {Write-Error "No Certificates exist with Document Encryption Property on $RemoteMachine"} } function Convert-HashToJson { [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [hashtable] $Hash ) $paramCustomObject = New-Object –TypeName PSObject -Property $Hash $paramSerializedAsJson = $paramCustomObject | ConvertTo-Json Return $paramSerializedAsJson } function Convert-PSObjectToJson { [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [PSCustomObject] $InputObject ) $paramSerializedAsJson = $InputObject | ConvertTo-Json Return $paramSerializedAsJson } #Code provided by David Wyatt http://stackoverflow.com/questions/3740128/pscustomobject-to-hashtable function Convert-PSObjectToHashtable { param ( [Parameter(ValueFromPipeline)] $InputObject ) process { if ($null -eq $InputObject) { return $null } if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string]) { $collection = @( foreach ($object in $InputObject) { Convert-PSObjectToHashtable $object } ) Write-Output -NoEnumerate $collection } elseif ($InputObject -is [psobject]) { $hash = @{} foreach ($property in $InputObject.PSObject.Properties) { $hash[$property.Name] = Convert-PSObjectToHashtable $property.Value } $hash } else { $InputObject } } } function Convert-JSONtoHash { [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [System.string] $InputObject ) $InputObjectRehydratedAsPSCustomObj = $InputObject | ConvertFrom-Json $InputObjectRehydratedAsHash = Convert-PSObjectToHashtable $InputObjectRehydratedAsPSCustomObj return $InputObjectRehydratedAsHash } function Add-NewConfigurationToQueue { [CmdletBinding()] Param ( [ValidateNotNull()] [PSCustomObject] $Configuration, [ValidateNotNull()] [System.String] $SQLServer ) $connString = "Data Source=$SQLServer;Initial Catalog=DSCCentral;Integrated Security=True" Write-Verbose -Message "Connecting to $connString" $JSONConfig =Convert-PSObjectToJson -InputObject $Configuration $output = Invoke-StoredProcedure -storedProcName "dbo.EnqueueConfiguration" -parameters @{Configuration=$JSONConfig} -conn $connString } Function Add-NewParentConfiguration { [CmdletBinding()] param ( [ValidateNotNull()] [System.String] $ParentConfigurationName, [ValidateNotNull()] [PSCustomObject] $Payload, [ValidateNotNull()] [System.String] $ScriptName, [ValidateNotNull()] [System.String] $ScriptPath, [ValidateNotNull()] [System.String] $SQLServer) $JSONPayload = $Payload | ConvertTo-Json $connString = "Data Source=$SQLServer;Initial Catalog=DSCCentral;Integrated Security=True" Write-Verbose -Message "Connecting to $connString" $output = Invoke-StoredProcedure -storedProcName "dbo.NewParentConfiguration" -parameters @{ParentConfigurationName=$ParentConfigurationName;Payload=$JSONPayload;ScriptName=$ScriptName;ScriptPath=$ScriptPath} -conn $connString } Function Add-NewNodeConfigurationDefault { [CmdletBinding()] param ( [ValidateNotNull()] [System.String] $NodeConfigurationName, [ValidateNotNull()] [PSCustomObject] $Payload, [ValidateNotNull()] [System.String] $SQLServer) $JSONPayload = $Payload | ConvertTo-Json $connString = "Data Source=$SQLServer;Initial Catalog=DSCCentral;Integrated Security=True" Write-Verbose -Message "Connecting to $connString" $output = Invoke-StoredProcedure -storedProcName "dbo.NewNodeConfigurationDefault" -parameters @{NodeConfigurationName=$NodeConfigurationName;Payload=$JSONPayload;} -conn $connString } Function Add-NewNodeConfiguration { [CmdletBinding()] param ( [ValidateNotNull()] [System.String] $ParentConfigurationName, [ValidateNotNull()] [System.String] $NodeName, [ValidateNotNull()] [PSCustomObject] $Payload, [ValidateNotNull()] [System.String] $SQLServer) $JSONPayload = $Payload | ConvertTo-Json $connString = "Data Source=$SQLServer;Initial Catalog=DSCCentral;Integrated Security=True" Write-Verbose -Message "Connecting to $connString" $output = Invoke-StoredProcedure -storedProcName "dbo.NewNodeConfiguration" -parameters @{ParentConfigurationName = $ParentConfigurationName; NodeName = $NodeName; Payload = $JSONPayload;} -conn $connString } Function Add-NewNodeConfigurationCredential { [CmdletBinding()] param ( [ValidateNotNull()] [System.String] $NodeName, [ValidateNotNull()] [PSCustomObject] $CredentialName, [ValidateNotNull()] [System.String] $SQLServer) $JSONPayload = $Payload | ConvertTo-Json $connString = "Data Source=$SQLServer;Initial Catalog=DSCCentral;Integrated Security=True" Write-Verbose -Message "Connecting to $connString" $output = Invoke-StoredProcedure -storedProcName "dbo.NewNodeConfigurationCredential" -parameters @{NodeName=$NodeName;CredentialName=$CredentialName;} -conn $connString } Function Add-NewParentConfigurationCredential { [CmdletBinding()] param ( [ValidateNotNull()] [System.String] $ParentConfigurationName, [ValidateNotNull()] [PSCustomObject] $CredentialName, [ValidateNotNull()] [System.String] $SQLServer) $JSONPayload = $Payload | ConvertTo-Json $connString = "Data Source=$SQLServer;Initial Catalog=DSCCentral;Integrated Security=True" Write-Verbose -Message "Connecting to $connString" $output = Invoke-StoredProcedure -storedProcName "dbo.NewParentConfigurationCredential" -parameters @{ParentConfigurationName=$ParentConfigurationName;CredentialName=$CredentialName;} -conn $connString } Function Get-ConfigurationfromQueue { [CmdletBinding()] param ( [ValidateNotNull()] [System.String] $BatchSize, [ValidateNotNull()] [System.String] $SQLServer) $connString = "Data Source=$SQLServer;Initial Catalog=DSCCentral;Integrated Security=True" Write-Verbose -Message "Connecting to $connString" $output = Invoke-StoredProcedure -storedProcName "dbo.DequeueConfiguration" -parameters @{BatchSize=$BatchSize;} -conn $connString if($output.data.tables.configuration) {$JSONConfig =Convert-JsontoHash -InputObject $output.data.tables.configuration $JSONConfig.add('ConfigurationQueueID',$output.data.tables.rows.ConfigurationQueueID) } Else{$JSONConfig = $False} return @($JSONConfig) } Function Get-ConfigurationToProcess { [CmdletBinding()] param ( [ValidateNotNull()] [System.String] $SQLServer) $BatchSize =1 $RehydratedConfig=Get-ConfigurationfromQueue -BatchSize $BatchSize -SQLServer $SQLServer If (!$RehydratedConfig) { RETURN @($False) } $ConfigurationDatafromDB = [Hashtable]@{} $ParentConfig = Get-ParentConfigurationfromDB -ParentConfigurationName $RehydratedConfig.Configuration -SQLServer $SQLServer $ConfigurationScriptDetails = Get-ConfigurationScriptDetails -ParentConfigurationName $RehydratedConfig.Configuration -SQLServer $SQLServer $ConfigurationDatafromDB.Add("ScriptName",$ConfigurationScriptDetails.ScriptName) $ConfigurationDatafromDB.Add("ScriptPath",$ConfigurationScriptDetails.ScriptPath) $ConfigurationDatafromDB.Add("ConfigurationQueueID",$RehydratedConfig.ConfigurationQueueID) $ConfigurationDatafromDB.Add("AllNodes",@()) $ConfigCredOut =Get-CredentialsforParentConfiguration -SQLServer $SQLServer -ParentConfigurationName $RehydratedConfig.Configuration Foreach ($Row in $ConfigCredOut) { $Credential = Get-PSCredential -UserName $Row.Username -Password $Row.Password $ParentConfig.Add($Row.CredentialName,$Credential) } $parentConfig.Add("NodeName","*") $ConfigurationDatafromDB.AllNodes += $parentConfig foreach ($Node in $RehydratedConfig.NodeName) { $NodeConfigfromDB =Get-NodeConfigurationfromDB -NodeName $Node -ParentConfigurationName $RehydratedConfig.Configuration -SQLServer $SQLServer $NodeConfigfromDB.Add("NodeName",$Node) $NodeCredOut = Get-CredentialsforNode -SQLServer $SQLServer -ParentConfigurationName $RehydratedConfig.Configuration -NodeName $Node Foreach ($Row in $NodeCredOut) { $Credential = Get-PSCredential -UserName $Row.Username -Password $Row.Password $NodeConfigfromDB.Add($Row.CredentialName,$Credential) } $ConfigurationDatafromDB.AllNodes += $NodeConfigfromDB } RETURN @($ConfigurationDatafromDB) } Function Get-CredentialsforParentConfiguration { [CmdletBinding()] param ( [ValidateNotNull()] [System.String] $SQLServer, [ValidateNotNull()] [System.String] $ParentConfigurationName ) $connString = "Data Source=$SQLServer;Initial Catalog=DSCCentral;Integrated Security=True" Write-Verbose -Message "Connecting to $connString" $output = Invoke-StoredProcedure -storedProcName "[dbo].[GetCredentialsforParentConfiguration]" -parameters @{ParentConfigurationName=$ParentConfigurationName;} -conn $connString return $output.data.tables.rows } Function Get-CredentialsforNode { [CmdletBinding()] param ( [ValidateNotNull()] [System.String] $SQLServer, [ValidateNotNull()] [System.String] $NodeName, [ValidateNotNull()] [System.String] $ParentConfigurationName ) $connString = "Data Source=$SQLServer;Initial Catalog=DSCCentral;Integrated Security=True" Write-Verbose -Message "Connecting to $connString" $output = Invoke-StoredProcedure -storedProcName "[dbo].[GetCredentialsforNode]" -parameters @{NodeName=$NodeName;ParentConfigurationName=$ParentConfigurationName;} -conn $connString Return $output.data.tables.rows } Function Get-NodeConfigurationfromDB { [CmdletBinding()] param ( [ValidateNotNull()] [System.String] $NodeName, [ValidateNotNull()] [System.String] $ParentConfigurationName, [ValidateNotNull()] [System.String] $SQLServer) $connString = "Data Source=$SQLServer;Initial Catalog=DSCCentral;Integrated Security=True" Write-Verbose -Message "Connecting to $connString" $output = Invoke-StoredProcedure -storedProcName "dbo.GetNodeConfiguration" -parameters @{NodeName=$NodeName;ParentConfigurationName=$ParentConfigurationName;} -conn $connString if($output.data.tables.Payload) {$JSONConfig =Convert-JsontoHash -InputObject $output.data.tables.Payload} Else{$JSONConfig = 0} return @($JSONConfig) } Function Get-ParentConfigurationfromDB { [CmdletBinding()] param ( [ValidateNotNull()] [System.String] $ParentConfigurationName, [ValidateNotNull()] [System.String] $SQLServer) $connString = "Data Source=$SQLServer;Initial Catalog=DSCCentral;Integrated Security=True" Write-Verbose -Message "Connecting to $connString" $output = Invoke-StoredProcedure -storedProcName "dbo.GetParentConfiguration" -parameters @{ParentConfigurationName=$ParentConfigurationName;} -conn $connString if($output.data.tables.Payload) {$JSONConfig =Convert-JsontoHash -InputObject $output.data.tables.Payload} Else{$JSONConfig = $False} return @($JSONConfig) } Function Get-ConfigurationScriptDetails { [CmdletBinding()] param ( [ValidateNotNull()] [System.String] $ParentConfigurationName, [ValidateNotNull()] [System.String] $SQLServer) $connString = "Data Source=$SQLServer;Initial Catalog=DSCCentral;Integrated Security=True" Write-Verbose -Message "Connecting to $connString" $output = Invoke-StoredProcedure -storedProcName "dbo.GetConfigurationScript" -parameters @{ParentConfigurationName=$ParentConfigurationName;} -conn $connString return @($output.data.tables.rows) } Function Update-ConfigurationStatus { [CmdletBinding()] param ( [ValidateNotNull()] [ValidateSet($True,$False)] [System.String] $Success, [ValidateNotNull()] [System.String] $ConfigurationQueueID, [ValidateNotNull()] [System.String] $SQLServer) $connString = "Data Source=$SQLServer;Initial Catalog=DSCCentral;Integrated Security=True" Write-Verbose -Message "Connecting to $connString" if ($Success){$output = Invoke-StoredProcedure -storedProcName "dbo.ConfigurationProcessedWithSuccess" -parameters @{ConfigurationQueueID=$ConfigurationQueueID;} -conn $connString} else{$output = Invoke-StoredProcedure -storedProcName "dbo.ConfigurationProcessedWithFailure" -parameters @{ConfigurationQueueID=$ConfigurationQueueID;} -conn $connString} return @($output.data.tables.rows) } |