From 259e035c7ba579c8f6d6d75b0f3b984c54645740 Mon Sep 17 00:00:00 2001 From: Keith Hitchcock Date: Wed, 22 Mar 2017 12:22:08 -0400 Subject: [PATCH 1/4] Version 1.1.0.0 * Version increase to 1.1.0.0 to handle bug fixes and updates to the documentation website, final updates before public announcement/release * Added help information to the DSCEA functions * Logic change to Get-DSCEAreport.ps1 to handle version increases moving forward regarding C:\ProgramData\DSCEA\logo.png * $PSVersionErrorsFile fix to date format * Added Third Party Notices.txt --- DSCEA.psd1 | 2 +- docs/_data/sidebars/mydoc_sidebar.yml | 4 ++ docs/index.md | 10 +-- docs/pages/mydoc/mydoc_release_1100.md | 14 +++++ docs/pages/mydoc/mydoc_use_cases.md | 9 ++- functions/Convert-DSCEAresultsToCSV.ps1 | 37 +++++++++++ functions/Get-DSCEAreport.ps1 | 20 +++--- functions/Start-DSCEAscan.ps1 | 84 +++++++++++++++++++++++-- 8 files changed, 161 insertions(+), 19 deletions(-) create mode 100644 docs/pages/mydoc/mydoc_release_1100.md diff --git a/DSCEA.psd1 b/DSCEA.psd1 index 61903ef..9128a5e 100644 --- a/DSCEA.psd1 +++ b/DSCEA.psd1 @@ -12,7 +12,7 @@ RootModule = 'DSCEA.psm1' # Version number of this module. -ModuleVersion = '1.0.0.1' +ModuleVersion = '1.1.0.0' # ID used to uniquely identify this module GUID = '2f4af4e9-785e-46b2-829b-b1c49d8d3fbf' diff --git a/docs/_data/sidebars/mydoc_sidebar.yml b/docs/_data/sidebars/mydoc_sidebar.yml index 10df620..26ae703 100644 --- a/docs/_data/sidebars/mydoc_sidebar.yml +++ b/docs/_data/sidebars/mydoc_sidebar.yml @@ -27,6 +27,10 @@ entries: output: web folderitems: + - title: 1.1.0.0 Release notes + url: /mydoc_release_1100.html + output: web + - title: 1.0.0.1 Release notes url: /mydoc_release_1001.html output: web diff --git a/docs/index.md b/docs/index.md index f1a6aaf..65b636a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,7 +16,6 @@ DSCEA is an Open-Source Project, hosted at [https://github.com/Microsoft/DSCEA]( ## Report Examples DSCEA currently supports displaying scan result data in either Power BI or HTML -

Display DSCEA scan results within Power BI

[ ![](https://raw.githubusercontent.com/Microsoft/DSCEA/master/docs/images/PowerBIHome_Small.png) ](https://raw.githubusercontent.com/Microsoft/DSCEA/master/docs/images/PowerBIHome_Large.png) @@ -26,6 +25,7 @@ DSCEA currently supports displaying scan result data in either Power BI or HTML

HTML Report - Show all non-compliant items that were detected

[ ![](https://raw.githubusercontent.com/Microsoft/DSCEA/master/docs/images/DetailedComplianceReport_Small.png) ](https://raw.githubusercontent.com/Microsoft/DSCEA/master/docs/images/DetailedComplianceReport_Large.png) + ## Examples ### **Example 1: Scan multiple systems for compliance to settings defined within a localhost.mof file located in your current directory** @@ -81,16 +81,18 @@ This command is executed from a directory that contains DSCEA scan result XML fi This command is executed from a directory that contains DSCEA scan result XML files. It generates a report containing a list of all items that were found to be non-compliant. If all systems that are scanned are found to be compliant, this report will show no results. -### **Example 8: Generate HTML Report based on scan results - Show the compliance state of a single item across all systems that were scanned** +### **Example 9: Generate HTML Report based on scan results - Show the compliance state of a single item across all systems that were scanned** +
PS C:\Users\username\Documents\DSCEA> Get-DSCEAreport -ItemName MicrosoftAntiMalwareService
This command is executed from a directory that contains DSCEA scan result XML files. It generates a report containing the compliance state for the Microsoft AntiMalware Service across all systems that were scanned. The item name specified must match one of the resource names that was defined within the MOF file that was used to perform the scan. -### **Example 9: Generate HTML Report based on scan results - Show the compliance state of all items for a single system** +### **Example 10: Generate HTML Report based on scan results - Show the compliance state of all items for a single system** +
PS C:\Users\username\Documents\DSCEA> Get-DSCEAreport -ComputerName dsctest-1
This command is executed from a directory that contains DSCEA scan result XML files. It generates a report containing the compliance state for all items that were scanned on system dsctest-1. In addition, Get-DSCEAreport supports the **-InFile** parameter, which can be used to specify the full file path of the results XML file to be used for report generation. In the previous examples of Get-DSCEAreport, the XML file used is the most recent XML file detected within the current directory. -Get-DSCEAreport also supports the **-OutPath** parameter, which can be used to specify the path to store the generated HTML files. This path must point to a pre-existing folder. \ No newline at end of file +Get-DSCEAreport also supports the **-OutPath** parameter, which can be used to specify the path to store the generated HTML files. This path must point to a pre-existing folder. diff --git a/docs/pages/mydoc/mydoc_release_1100.md b/docs/pages/mydoc/mydoc_release_1100.md new file mode 100644 index 0000000..59b7e41 --- /dev/null +++ b/docs/pages/mydoc/mydoc_release_1100.md @@ -0,0 +1,14 @@ +--- +title: 1.1.0.0 Release notes +sidebar: mydoc_sidebar +permalink: mydoc_release_1100.html +folder: mydoc +--- + +## Changelog + +* Version increase to 1.1.0.0 to handle bug fixes and updates to the documentation website, final updates before public announcement/release +* Added help information to the DSCEA functions +* Logic change to Get-DSCEAreport.ps1 to handle version increases moving forward regarding C:\ProgramData\DSCEA\logo.png +* $PSVersionErrorsFile fix to date format +* Added Third Party Notices.txt \ No newline at end of file diff --git a/docs/pages/mydoc/mydoc_use_cases.md b/docs/pages/mydoc/mydoc_use_cases.md index 7d40f0e..2911f2f 100644 --- a/docs/pages/mydoc/mydoc_use_cases.md +++ b/docs/pages/mydoc/mydoc_use_cases.md @@ -11,7 +11,10 @@ DSCEA's primary use case is to verify that your systems are actually configured ## Use Case Examples -Real world examples of how DSCEA can be used include (Add links to MSFT blog posts): +Real world examples of how DSCEA can be used include -* Use DSCEA to verify a single setting, for example if a registry key is set appropriately across your entire environment -* Scan the systems in your environment against all of the items that make up your organization's security baseline \ No newline at end of file +* Verify a single setting, for example if a registry key is set appropriately across your entire environment - [Link to blog post](https://blogs.technet.microsoft.com/ralphkyttle/2017/03/21/introducing-dscea/) +* Audit your systems to ensure that they meet the base level system configuration settings that are required to be a part of your environment +* Scan the systems in your environment against all of the items that make up your organization's security baseline +* Verify that settings configured via Group Policy are being applied correctly to the systems in your environment +* Verify settings configured on Windows Server 2016 Nano servers (which do not support Group Policy) diff --git a/functions/Convert-DSCEAresultsToCSV.ps1 b/functions/Convert-DSCEAresultsToCSV.ps1 index ae24d62..d6dc939 100644 --- a/functions/Convert-DSCEAresultsToCSV.ps1 +++ b/functions/Convert-DSCEAresultsToCSV.ps1 @@ -1,4 +1,41 @@ function Convert-DSCEAresultsToCSV { +<# +.SYNOPSIS +Creates CSV data file from DSCEA results + +.DESCRIPTION +Used to convert the raw XML output from a DSCEA scan to a more consumable format of CSV + +.PARAMETER InputXML +The file name (full file path) of the XML file you would like to convert to CSV. If one is not provided, Convert-DSCEAresultsToCSV looks to the current directory for the most recently created XML file. + +.PARAMETER OutFile +The new file name (full file path) of the output CSV file. The file path must include a pre-existing folder. If one is not provided, Convert-DSCEAresultsToCSV will create output.csv in the current directory. + +.LINK +https://microsoft.github.io/DSCEA + +.EXAMPLE +Convert-DSCEAresultsToCSV + +Description +----------- +Looks in the current directory for the most recently created XML file, parses the file and converts it to a CSV file in the same directory + +.EXAMPLE +Convert-DSCEAresultsToCSV -InputXML C:\Users\username\Documents\DSCEA\results.20170311-2307-31.xml + +Description +----------- +Converts C:\Users\username\Documents\DSCEA\results.20170311-2307-31.xml to a CSV file, saved in the current directory + +.EXAMPLE +Convert-DSCEAresultsToCSV -InputXML C:\Users\username\Documents\DSCEA\results.20170311-2307-31.xml -OutFile C:\Users\username\Documents\DSCEA\output.csv + +Description +----------- +Converts C:\Users\username\Documents\DSCEA\results.20170311-2307-31.xml to a CSV file saved at C:\Users\username\Documents\DSCEA\output.csv +#> [CmdLetBinding()] param ( diff --git a/functions/Get-DSCEAreport.ps1 b/functions/Get-DSCEAreport.ps1 index afba1b9..0d0d6e6 100644 --- a/functions/Get-DSCEAreport.ps1 +++ b/functions/Get-DSCEAreport.ps1 @@ -1,22 +1,28 @@ function Get-DSCEAreport { <# .SYNOPSIS -Generate a HTML based report after Start-DSCEAscan has been run +Generates a HTML based report after Start-DSCEAscan has been run .DESCRIPTION -Used to create viewable reports after Start-DSCEAscan has created a results.xml file which will be parsed +Used to create viewable reports after Start-DSCEAscan has created a results.xml file which will be parsed. .PARAMETER ItemName -This is the item name from the configuration file, used to generate a report of every machine's compliance against that item +Switch parameter - This is the item name from the configuration file, used to generate a report of every machine's compliance against that item .PARAMETER ComputerName -The computer name here will cause the report to display all items (true/false) pertaining to ComputerName +Switch parameter - Supplying a computer name will cause the report to display all items (true/false) pertaining to ComputerName .PARAMETER Overall -Switch parameter indicating that the report generated will display true/false per computer in regards to the entire configuration file +Switch parameter - Indicating that the report generated will display all up true/false per computer in regards to compliance against the entire configuration file .PARAMETER Detailed -Switch parameter indicating that the report generated will display non-compliant configuration file items detected, grouped by computer +Switch parameter - Indicating that the report generated will display all non-compliant configuration file items detected, grouped by computer + +.PARAMETER InFile +The file name (full file path) of the XML file you would like to convert. If one is not provided, Get-DSCEAreport looks to the current directory for the most recently created XML file. + +.PARAMETER OutPath +The full file path to use as a location to store HTML reports. The file path must be a pre-existing folder. If one is not provided, Get-DSCEAreport will create the HTML file in the current directory. .LINK https://microsoft.github.io/DSCEA @@ -40,7 +46,7 @@ Get-DSCEAreport -Overall Description ----------- -This command returns true/false per machine if they comply with the entire configuration file +This command returns true/false per machine regarding whether they comply with the entire configuration file .EXAMPLE Get-DSCEAreport -Detailed diff --git a/functions/Start-DSCEAscan.ps1 b/functions/Start-DSCEAscan.ps1 index 59266cb..d6cb35d 100644 --- a/functions/Start-DSCEAscan.ps1 +++ b/functions/Start-DSCEAscan.ps1 @@ -1,18 +1,91 @@ function Start-DSCEAscan { <# .SYNOPSIS -Will run Test-DscConfiguration -ReferenceConfiguration against the remote systems supplied and saves the results to a XML file +Will run Test-DscConfiguration -ReferenceConfiguration using the provided MOF file against the remote systems supplied and saves the scan results to a XML file .DESCRIPTION -Run this function after you have defined the remote systems to scan and have created a localhost.MOF file that defines the settings you want to check against +Run this function after you have defined the remote systems to scan and have created a MOF file that defines the settings you want to check against -.NOTES +.PARAMETER MofFile +The file name (full file path) to the MOF file you are looking to use with DSCEA to perform a scan. If no value is provided, Start-DSCEAscan will look into the current directory for a file named localhost.mof + +.PARAMETER ComputerName +Comma seperated list of computer names that you want to scan + +.PARAMETER InputFile +The file name (full file path) to a text file that contains a list of computers you want to scan. Either use the ComputerName paramter or InputFile, DSCEA does not currently support using both. + +.PARAMETER CimSession +Provide DSCEA with a CimSession object to perform compliance scans against remote systems that are either not members of the same domain as the management system, are workgroup systems or require other credentials + +.PARAMETER ResultsFile +The file name for the DSCEA scan results XML file. If no value is provided, a time based file name will be auto-generated. + +.PARAMETER OutputPath +The full file path for the DSCEA scan results XML file. The defined path must already exist. If no value is provided, the result XML file will be saved to the current directory. + +.PARAMETER LogsPath +The full file path for the any DSCEA scna log files. The defined path must already exist. If no value is provided, log files will be saved to the current directory. + +.PARAMETER JobTimeout +Individual system timeout (seconds) If no value is provided, the default value of 600 seconds will be used. + +.PARAMETER ScanTimeout +Total DSCEA scan timeout (seconds) If no value is provided, the default value of 3600 seconds will be used. + +.PARAMETER Force +The force parameter attempts to close any running DSC related processes on systems being scanned before a scan begins to avoid LCM conflicts. Force is not enabled by default. .LINK https://microsoft.github.io/DSCEA .EXAMPLE -. Start-DscEaScan +Start-DSCEAscan -MofFile .\localhost.mof -ComputerName dsctest-1, dsctest-2, dsctest-3 + +Description +----------- +This command executes a DSCEA scan against 3 remote systems, dsctest-1, dsctest-2 and dsctest-3 using a locally defined MOF file that exists in the current directory. This MOF file specifies the settings to check for during the scan. Start-DSCEAscan returns a XML results file containing raw data that can be used with other functions, such as Get-DSCEAreport to create reports with consumable information. + +.EXAMPLE +Start-DSCEAscan -MofFile C:\Users\username\Documents\DSCEA\localhost.mof -ComputerName dsctest-1, dsctest-2, dsctest-3 + +Description +----------- +This command executes a DSCEA scan against 3 remote systems, dsctest-1, dsctest-2 and dsctest-3 using a locally defined MOF file that exists at “C:\Users\username\Documents\DSCEA”. This MOF file specifies the settings to check for during the scan. Start-DSCEAscan returns a XML results file containing raw data that can be used with other functions, such as Get-DSCEAreport to create reports with consumable information. + +.EXAMPLE +Start-DSCEAscan -MofFile .\localhost.mof -InputFile C:\Users\username\Documents\DSCEA\computers.txt + +Description +----------- +This command executes a DSCEA scan against the systems listed within “C:\Users\username\Documents\DSCEA\computers.txt” using a locally defined MOF file that exists in the current directory. This MOF file specifies the settings to check for during the scan. Start-DSCEAscan returns a XML results file containing raw data that can be used with other functions, such as Get-DSCEAreport to create reports with consumable information. + +.EXAMPLE +Start-DSCEAscan -MofFile C:\Users\username\Documents\DSCEA\localhost.mof -InputFile C:\Users\username\Documents\DSCEA\computers.txt + +Description +----------- +This command executes a DSCEA scan against the systems listed within “C:\Users\username\Documents\DSCEA\computers.txt” using a locally defined MOF file that exists at “C:\Users\username\Documents\DSCEA”. This MOF file specifies the settings to check for during the scan. Start-DSCEAscan returns a XML results file containing raw data that can be used with other functions, such as Get-DSCEAreport to create reports with consumable information. + +.EXAMPLE +Start-DSCEAscan -MofFile C:\Users\username\Documents\DSCEA\localhost.mof -ComputerName dsctest-1, dsctest-2, dsctest-3 -OutputPath C:\Temp\DSCEA\Output -ResultsFile "results.xml" -LogsPath C:\Temp\DSCEA\Logs -JobTimeout 10 -ScanTimeout 60 -Force -Verbose + +Description +----------- +This command executes a DSCEA scan against 3 remote systems, dsctest-1, dsctest-2 and dsctest-3 using a locally defined MOF file that exists at “C:\Users\username\Documents\DSCEA”. This MOF file specifies the settings to check for during the scan. Start-DSCEAscan returns a XML results file containing raw data that can be used with other functions, such as Get-DSCEAreport to create reports with consumable information. +This example specifies custom values for -OutputPath and -LogsPath, which must be directories that are pre-existing to store results and logs from the scan. This scan also specifies custom values for -ResultsFile to provide the file name of the scan results file, -JobTimeout and -ScanTimeout which provide new timeout values for individual system timeouts and the overall scan timeout, a -Force option which attempts to close any running DSC related processes on systems being scanned before a scan begins to avoid LCM conflicts and -Verbose, which will provide full verbose output of the scan process. + +.EXAMPLE +$UserName = 'LocalUser' +$Password = ConvertTo-SecureString -String "P@ssw0rd" -AsPlainText -Force +$Servers = "dsctest-4,dsctest-5,dsctest-6" +$Cred = New-Object System.Management.Automation.PsCredential -ArgumentList $UserName, $Password +$Sessions = New-CimSession -Authentication Negotiate -ComputerName $Servers -Credential $Cred +Start-DscEaScan -CimSession $Sessions -MofFile C:\Users\username\Documents\DSCEA\localhost.mof -Verbose + +Description +----------- +This command utilizes New-CimSession and executes a DSCEA scan against 3 remote non-domain systems, dsctest-4, dsctest-5 and dsctest-6 using a locally defined MOF file that exists at “C:\Users\username\Documents\DSCEA”. This MOF file specifies the settings to check for during the scan. Start-DSCEAscan returns a XML results file containing raw data that can be used with other functions, such as Get-DSCEAreport to create reports with consumable information. #> [CmdletBinding()] param @@ -26,6 +99,7 @@ param [ValidateNotNullOrEmpty()] [string]$MofFile = 'localhost.mof', + [parameter(Mandatory=$true,ParameterSetName='ComputerFile')] [string]$InputFile, [ValidateNotNullOrEmpty()] @@ -39,8 +113,10 @@ param [ValidateNotNullOrEmpty()] [string]$ResultsFile = "results.$(Get-Date -Format 'yyyyMMdd-HHmm-ss').xml", + [parameter(Mandatory=$true,ParameterSetName='ComputerNames')] [string[]]$ComputerName, + [parameter(Mandatory=$true,ParameterSetName='CimSession')] [Microsoft.Management.Infrastructure.CimSession[]]$CimSession ) From 1cbd679a7bbcda0eff8cba7f918b3e930e8f1f56 Mon Sep 17 00:00:00 2001 From: Anthony Watherston Date: Fri, 24 Mar 2017 09:05:45 +1100 Subject: [PATCH 2/4] Initial commit --- configs/SampleConfigWithExternalResource.ps1 | 82 +++++++++++++++++++ functions/Get-MOFRequiredModules.ps1 | 55 +++++++++++++ .../HelperModule/Get-MOFRequiredModules.psm1 | 66 +++++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 configs/SampleConfigWithExternalResource.ps1 create mode 100644 functions/Get-MOFRequiredModules.ps1 create mode 100644 functions/HelperModule/Get-MOFRequiredModules.psm1 diff --git a/configs/SampleConfigWithExternalResource.ps1 b/configs/SampleConfigWithExternalResource.ps1 new file mode 100644 index 0000000..5345651 --- /dev/null +++ b/configs/SampleConfigWithExternalResource.ps1 @@ -0,0 +1,82 @@ +configuration MemberServerSecuritySettings { + param([string[]]$ComputerName='localhost') + + Import-DscResource -ModuleName PSDesiredStateConfiguration,xSMBShare + + Node $ComputerName { + + #Anti-Malware + Service 'MicrosoftAntimalwareService' { + Name = 'MsMpSvc' + StartupType = 'Automatic' + State = 'Running' + } + + #User Account Control - (1 of 2) + Registry 'ConsentPromptBehaviorAdmin' { + Ensure = 'Present' + Key = 'HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System' + ValueName = 'ConsentPromptBehaviorAdmin' + ValueType = 'Dword' + ValueData = '5' + } + + #User Account Control - (2 of 2) + Registry 'PromptOnSecureDesktop' { + Ensure = 'Present' + Key = 'HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System' + ValueName = 'PromptOnSecureDesktop' + ValueType = 'Dword' + ValueData = '1' + } + + #Interactive logon: Number of previous logons to cache (in case domain controller is not available) + Registry 'Numberofpreviouslogonstocache' { + Ensure = 'Present' + Key = 'HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon' + ValueName = 'CachedLogonsCount' + ValueType = 'Dword' + ValueData = '2' + } + + #Checks to ensure that certain Windows Roles or Windows Features have not been installed + WindowsFeature 'ActiveDirectoryDomainServices' { + Name = 'AD-Domain-Services' + Ensure = 'Absent' + } + + #Ensure DNS service is not installed + WindowsFeature 'DNSServer' { + Name = 'DNS' + Ensure = 'Absent' + } + + #Ensure DHCP service is not installed + WindowsFeature 'DHCPServer' { + Name = 'DHCP' + Ensure = 'Absent' + } + + #Ensure FaxServer service is not installed + WindowsFeature 'WindowsRoleFax' { + Name = 'Fax' + Ensure = 'Absent' + } + + #Create a temp folder to share + File TempFolder { + DestinationPath = "C:\Temp" + Type = "Directory" + Ensure = "Present" + } + + #Create a shared folder + xSMBShare TempShare { + Ensure = "Present" + Path = "C:\Temp" + Name = "TempShare" + } + } +} + +MemberServerSecuritySettings -OutputPath .\ \ No newline at end of file diff --git a/functions/Get-MOFRequiredModules.ps1 b/functions/Get-MOFRequiredModules.ps1 new file mode 100644 index 0000000..1919936 --- /dev/null +++ b/functions/Get-MOFRequiredModules.ps1 @@ -0,0 +1,55 @@ +function Get-MOFRequiredModules { + [CmdletBinding()] + Param($mofFile) + + $DSCResources = Get-DscResource + $DScModuleArray = @() + $ModulesToCopy = @() + + foreach ($Resource in $DscResources) + { + if (!(($Resource.ModuleName -eq "PSDesiredStateConfiguration") -or ($Resource.ImplementedAs -eq 'Binary'))) + { + if ($DScModuleArray -notcontains $Resource.ModuleName) + { + $DSCModuleArray += $Resource.ModuleName + } + } + } + + #Scan the mof file for sections ModuleName + $requiredModulesinMof = @() + Switch -Regex (Get-Content $mofFile) + { + "ModuleName" {$requiredModulesInMof += $_.Split("`"")[1]} + #Default {Write-Output $_} + } + + foreach ($requiredModule in $requiredModulesInMof) + { + if ($requiredModule -in $DSCModuleArray) + { + $ModulesToCopy += [pscustomobject]@{ + ModuleName = $requiredModule + #ModulePath = $DSCResources | Where ModuleName -eq $requiredModule | Select -ExpandProperty ParentPath + } + } + } + + return $ModulesToCopy + +} + +function Copy-DSCResource +{ + [cmdletBinding()] + Param($CimSession,$ModulestoCopy) + + foreach ($Module in $ModulestoCopy) + { + $Source = 'C:\Program Files\WindowsPowerShell\Modules'+$Module.ModuleName + Write-Verbose $Source + } + +} + diff --git a/functions/HelperModule/Get-MOFRequiredModules.psm1 b/functions/HelperModule/Get-MOFRequiredModules.psm1 new file mode 100644 index 0000000..4ddbe9b --- /dev/null +++ b/functions/HelperModule/Get-MOFRequiredModules.psm1 @@ -0,0 +1,66 @@ +function Get-MOFRequiredModules { + [CmdletBinding()] + Param($mofFile) + + $DSCResources = Get-DscResource + $DScModuleArray = @() + $ModulesToCopy = @() + + foreach ($Resource in $DscResources) + { + if (!(($Resource.ModuleName -eq "PSDesiredStateConfiguration") -or ($Resource.ImplementedAs -eq 'Binary'))) + { + if ($DScModuleArray -notcontains $Resource.ModuleName) + { + $DSCModuleArray += $Resource.ModuleName + } + } + } + + #Scan the mof file for sections ModuleName + $requiredModulesinMof = @() + Switch -Regex (Get-Content $mofFile) + { + "ModuleName" {$requiredModulesInMof += $_.Split("`"")[1]} + #Default {Write-Output $_} + } + + foreach ($requiredModule in $requiredModulesInMof) + { + if ($requiredModule -in $DSCModuleArray) + { + $ModulesToCopy += [pscustomobject]@{ + ModuleName = $requiredModule + #ModulePath = $DSCResources | Where ModuleName -eq $requiredModule | Select -ExpandProperty ParentPath + } + } + } + + return $ModulesToCopy + +} + +function Copy-DSCResource +{ + [cmdletBinding()] + Param($CimSession,$ModulestoCopy) + + foreach ($Module in $ModulestoCopy) + { + $Source = 'C:\Program Files\WindowsPowerShell\Modules\'+$Module.ModuleName + Write-Verbose "Module location: $Source" + $Destination = 'C:\Program Files\WindowsPowerShell\Modules\' + try + { + Copy-Item -ToSession $CimSession -Path $Source -Destination -Recurse -Force -ErrorAction STOP + } + catch + { + Write-Output $Error[0].Exception + break + } + } + +} + + From 698a4f2725a6fa00881f145e61f58dd76f01cc3e Mon Sep 17 00:00:00 2001 From: Anthony Watherston Date: Fri, 24 Mar 2017 15:54:16 +1100 Subject: [PATCH 3/4] functions to copy determine and copy modules --- DSCEA.psd1 | 2 +- functions/Get-MOFRequiredModules.ps1 | 19 +++++- .../HelperModule/Get-MOFRequiredModules.psm1 | 66 ------------------- functions/Start-DSCEAscan.ps1 | 19 ++++++ 4 files changed, 36 insertions(+), 70 deletions(-) delete mode 100644 functions/HelperModule/Get-MOFRequiredModules.psm1 diff --git a/DSCEA.psd1 b/DSCEA.psd1 index 9128a5e..c0bba4e 100644 --- a/DSCEA.psd1 +++ b/DSCEA.psd1 @@ -68,7 +68,7 @@ PowerShellVersion = '5.0' # NestedModules = @() # Functions to export from this module -FunctionsToExport = ('Convert-DSCEAresultsToCSV','Get-DSCEAreport','Send-DSCEACSVtoSQL','Start-DSCEAscan') +FunctionsToExport = ('Convert-DSCEAresultsToCSV','Get-DSCEAreport','Send-DSCEACSVtoSQL','Start-DSCEAscan','Get-MOFRequiredModules','Copy-DSCResource') # Cmdlets to export from this module CmdletsToExport = '*' diff --git a/functions/Get-MOFRequiredModules.ps1 b/functions/Get-MOFRequiredModules.ps1 index 1919936..83aab6d 100644 --- a/functions/Get-MOFRequiredModules.ps1 +++ b/functions/Get-MOFRequiredModules.ps1 @@ -43,13 +43,26 @@ function Copy-DSCResource { [cmdletBinding()] - Param($CimSession,$ModulestoCopy) + Param($PSSession,$ModulestoCopy) foreach ($Module in $ModulestoCopy) { - $Source = 'C:\Program Files\WindowsPowerShell\Modules'+$Module.ModuleName - Write-Verbose $Source + $Source = 'C:\Program Files\WindowsPowerShell\Modules\'+$Module.ModuleName + Write-Verbose "Module location: $Source" + $Destination = 'C:\Program Files\WindowsPowerShell\Modules\' + try + { + Write-Verbose "Copying" + Copy-Item -ToSession $PSSession -Path $Source -Destination $Destination -Recurse -Force -ErrorAction STOP -Verbose + Write-Verbose "Copied" + } + catch + { + Write-Output $Error[0].Exception + break + } } } + diff --git a/functions/HelperModule/Get-MOFRequiredModules.psm1 b/functions/HelperModule/Get-MOFRequiredModules.psm1 deleted file mode 100644 index 4ddbe9b..0000000 --- a/functions/HelperModule/Get-MOFRequiredModules.psm1 +++ /dev/null @@ -1,66 +0,0 @@ -function Get-MOFRequiredModules { - [CmdletBinding()] - Param($mofFile) - - $DSCResources = Get-DscResource - $DScModuleArray = @() - $ModulesToCopy = @() - - foreach ($Resource in $DscResources) - { - if (!(($Resource.ModuleName -eq "PSDesiredStateConfiguration") -or ($Resource.ImplementedAs -eq 'Binary'))) - { - if ($DScModuleArray -notcontains $Resource.ModuleName) - { - $DSCModuleArray += $Resource.ModuleName - } - } - } - - #Scan the mof file for sections ModuleName - $requiredModulesinMof = @() - Switch -Regex (Get-Content $mofFile) - { - "ModuleName" {$requiredModulesInMof += $_.Split("`"")[1]} - #Default {Write-Output $_} - } - - foreach ($requiredModule in $requiredModulesInMof) - { - if ($requiredModule -in $DSCModuleArray) - { - $ModulesToCopy += [pscustomobject]@{ - ModuleName = $requiredModule - #ModulePath = $DSCResources | Where ModuleName -eq $requiredModule | Select -ExpandProperty ParentPath - } - } - } - - return $ModulesToCopy - -} - -function Copy-DSCResource -{ - [cmdletBinding()] - Param($CimSession,$ModulestoCopy) - - foreach ($Module in $ModulestoCopy) - { - $Source = 'C:\Program Files\WindowsPowerShell\Modules\'+$Module.ModuleName - Write-Verbose "Module location: $Source" - $Destination = 'C:\Program Files\WindowsPowerShell\Modules\' - try - { - Copy-Item -ToSession $CimSession -Path $Source -Destination -Recurse -Force -ErrorAction STOP - } - catch - { - Write-Output $Error[0].Exception - break - } - } - -} - - diff --git a/functions/Start-DSCEAscan.ps1 b/functions/Start-DSCEAscan.ps1 index d6cb35d..fda4a36 100644 --- a/functions/Start-DSCEAscan.ps1 +++ b/functions/Start-DSCEAscan.ps1 @@ -122,7 +122,10 @@ param #Begin DSCEA Engine Write-Verbose "DSCEA Scan has started" + #Scan the Mof file for modules other than built in $MofFile = (Get-Item $MofFile).FullName + $ModulesRequired = Get-MOFRequiredModules -mofFile $MofFile + $runspacePool = [RunspaceFactory]::CreateRunspacePool(1, 10).Open() #Min Runspaces, Max Runspaces $scriptBlock = { param ( @@ -137,6 +140,8 @@ param [switch]$Force, + $ModulesRequired, + [Microsoft.Management.Infrastructure.CimSession]$CimSession ) @@ -172,10 +177,22 @@ param Repair-DSCEngine -ComputerName $computer -ErrorAction SilentlyContinue } } + #Copy resources if required + if ($ModulesRequired -ne $null) { + if($CimSession) { + $session = New-PSSession -ComputerName $CimSession.ComputerName + } + else { + $session = New-PSSession -ComputerName $Computer + } + Copy-DSCResource -PSSession $session -ModulestoCopy $ModulesRequired + Remove-PSSession $session + } if($PSBoundParameters.ContainsKey('CimSession')) { $DSCJob = Test-DSCConfiguration -ReferenceConfiguration $mofFile -CimSession $CimSession -AsJob | Wait-Job -Timeout $JobTimeout } else { + $DSCJob = Test-DSCConfiguration -ReferenceConfiguration $mofFile -CimSession $computer -AsJob | Wait-Job -Timeout $JobTimeout } if (!$DSCJob) { @@ -209,6 +226,7 @@ param CimSession = $_ MofFile = $MofFile JobTimeout = $JobTimeout + ModulesRequired = $ModulesRequired } if($PSBoundParameters.ContainsKey('Force')) { $params += @{Force = $true} @@ -251,6 +269,7 @@ param Computer = $_ MofFile = $MofFile JobTimeout = $JobTimeout + ModulesRequired = $ModulesRequired } if ($PSBoundParameters.ContainsKey('Force')) { $params += @{Force = $true} From 19e2aa10c3bb11a3ccac0f7283f2ca75c44537ce Mon Sep 17 00:00:00 2001 From: Keith Hitchcock Date: Tue, 28 Mar 2017 05:32:25 -0400 Subject: [PATCH 4/4] manual merge --- functions/Start-DSCEAscan.ps1 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/functions/Start-DSCEAscan.ps1 b/functions/Start-DSCEAscan.ps1 index 03b689e..d02fb0d 100644 --- a/functions/Start-DSCEAscan.ps1 +++ b/functions/Start-DSCEAscan.ps1 @@ -121,9 +121,7 @@ param [Microsoft.Management.Infrastructure.CimSession[]]$CimSession, [parameter(Mandatory=$true,ParameterSetName='Path')] - [string]$Path, - - [Microsoft.Management.Infrastructure.CimSession[]]$CimSession + [string]$Path ) #Begin DSCEA Engine