Skip to content

Commit

Permalink
Merge pull request #3268 from NikCharlebois/Get-M365DSCConfigurationC…
Browse files Browse the repository at this point in the history
…onflictReport

Added the ability to validate exported configuration for conflicts and issues
  • Loading branch information
NikCharlebois authored May 11, 2023
2 parents 3db959f + a61d8a7 commit e2073d1
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 9 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
* Updated DSCParser to version 1.0.9.
* Updated Microsoft.PowerApps.Administration.PowerShell to version 2.0.162.
* Updated MSCloudLoginAssistant to version 1.0.110.
* MISC
* Added a new Get-M365DSCConfigurationConflict cmdlet to help validate configurations and added
the -Validate switch to the Export-M365DSCConfiguration cmdlet.

# 1.23.503.1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,7 @@ function Get-M365DSCAzureADAppPermissionsAsString
$StringContent = '@('
foreach ($permission in $Permissions)
{
$StringContent += "MSFT_AADApplicationPermission { `r`n"
$StringContent += "MSFT_AADApplicationPermission {`r`n"
$StringContent += " Name = '" + $permission.Name + "'`r`n"
$StringContent += " Type = '" + $permission.Type + "'`r`n"
$StringContent += " SourceAPI = '" + $permission.SourceAPI + "'`r`n"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ $Global:M365DSCEmojiHourglass = [char]::ConvertFromUtf32(0x231B)
$Global:M365DSCEmojiInformation = [char]::ConvertFromUtf32(0x2139)
$Global:M365DSCEmojiLightbulb = [char]::ConvertFromUtf32(0x1F4A1)
$Global:M365DSCEmojiLock = [char]::ConvertFromUtf32(0x1F512)
$Global:M365DSCMagnifyingGlass = [char]::ConvertFromUtf32(0x1f50d)
$Global:M365DSCEmojiPackage = [char]::ConvertFromUtf32(0x1F4E6)
$Global:M365DSCEmojiPencil = [char]::ConvertFromUtf32(0x270F)
$Global:M365DSCEmojiPlanet = [char]::ConvertFromUtf32(0x1F30F)
Expand Down
23 changes: 22 additions & 1 deletion Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ function Start-M365DSCConfigurationExtract

[Parameter()]
[Switch]
$ManagedIdentity
$ManagedIdentity,

[Parameter()]
[Switch]
$Validate
)

# Start by checking to see if a new Version of the tool is available in the
Expand Down Expand Up @@ -696,6 +700,23 @@ function Start-M365DSCConfigurationExtract
}
}

# Check if configuration validation needs to be performed
if ($Validate.IsPresent)
{
Write-Host "$($Global:M365DSCMagnifyingGlass) Starting configuration validation..." -NoNewline
[Array]$results = Get-M365DSCConfigurationConflict -ConfigurationContent $DSCContent.ToString()
Write-Host "Results:"
if ($results.Count -gt 0)
{
foreach ($issue in $results)
{
Write-Host " - [" -NoNewline
Write-Host "$($issue.Reason)" -ForegroundColor Red -NoNewline
Write-Host "]: $($issue.InstanceName)"
}
}
}

$shouldOpenOutputDirectory = $false
#region Prompt the user for a location to save the extract and generate the files
if ([System.String]::IsNullOrEmpty($Path))
Expand Down
84 changes: 78 additions & 6 deletions Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -1001,8 +1001,11 @@ Specifies the path of the PFX file which is used for authentication.
.Parameter Filters
Specifies resource level filters to apply in order to reduce the number of instances exported.
.Parameter Identity
Specifies use of managed identity for authentication
.Parameter ManagedIdentity
Specifies use of managed identity for authentication.
.Parameter Validate
Specifies that the configuration needs to be validated for conflicts or issues after its extraction is completed.
.Example
Export-M365DSCConfiguration -Components @("AADApplication", "AADConditionalAccessPolicy", "AADGroupsSettings") -Credential $Credential
Expand Down Expand Up @@ -1125,7 +1128,11 @@ function Export-M365DSCConfiguration

[Parameter(ParameterSetName = 'Export')]
[Switch]
$ManagedIdentity
$ManagedIdentity,

[Parameter(ParameterSetName = 'Export')]
[Switch]
$Validate
)

# Define the exported resource instances' names Global variable
Expand Down Expand Up @@ -1272,7 +1279,8 @@ function Export-M365DSCConfiguration
-CertificatePassword $CertificatePassword `
-ManagedIdentity:$ManagedIdentity `
-GenerateInfo $GenerateInfo `
-Filters $Filters
-Filters $Filters `
-Validate:$Validate
}
elseif ($null -ne $Components)
{
Expand All @@ -1290,7 +1298,8 @@ function Export-M365DSCConfiguration
-CertificatePassword $CertificatePassword `
-ManagedIdentity:$ManagedIdentity `
-GenerateInfo $GenerateInfo `
-Filters $Filters
-Filters $Filters `
-Validate:$Validate
}
elseif ($null -ne $Mode)
{
Expand All @@ -1309,7 +1318,8 @@ function Export-M365DSCConfiguration
-ManagedIdentity:$ManagedIdentity `
-GenerateInfo $GenerateInfo `
-AllComponents `
-Filters $Filters
-Filters $Filters `
-Validate:$Validate
}

# Clear the exported resource instances' names Global variable
Expand Down Expand Up @@ -4172,6 +4182,67 @@ function Remove-M365DSCAuthenticationParameter
return $BoundParameters
}

<#
.Description
This function analyzes an M365DSC configuration file and returns information about potential issues (e.g., duplicate primary keys).
.Example
Get-M365DSCConfigurationConflict -ConfigurationContent "content"
.Functionality
Public
#>
function Get-M365DSCConfigurationConflict
{
[CmdletBinding()]
[OutputType([Array])]
param
(
[Parameter(Mandatory = $true)]
[System.String]
$ConfigurationContent
)

$results = @()
Write-Verbose -Message "Converting configuration's content into a PowerShell Object using DSCParser"
$parsedContent = ConvertTo-DSCObject -Content $ConfigurationContent

$resourcesPrimaryIdentities = @()
$resourcesInModule = Get-DSCResource -Module 'Microsoft365DSC'
foreach ($component in $parsedContent)
{
$resourceDefinition = $resourcesInModule | Where-Object -FilterScript {$_.Name -eq $component.ResourceName}
[Array]$mandatoryProperties = $resourceDefinition.Properties | Where-Object -FilterScript {$_.IsMandatory}
$primaryKeyValues = ""
foreach ($mandatoryKey in $mandatoryProperties.Name)
{
$primaryKeyValues += "$($component.$mandatoryKey)|"
}
$entryValue = "[$($component.ResourceName)]$primaryKeyValues"
if ($resourcesPrimaryIdentities.Contains($entryValue))
{
Write-Verbose -Message "Found primary key conflict in resource {$($component.ResourceInstanceName)}"
$currentEntry = @{
ResourceName = $component.ResourceName
InstanceName = $component.ResourceInstanceName
AdditionalProperties = @{}
Reason = "DuplicatePrimaryKey"
}

foreach ($mandatoryKey in $mandatoryProperties.Name)
{
$currentEntry.AdditionalProperties.Add($mandatoryKey, $component.$mandatoryKey)
}
$results += $currentEntry
}
else
{
$resourcesPrimaryIdentities += $entryValue
}
}
return $results
}

Export-ModuleMember -Function @(
'Assert-M365DSCBlueprint',
'Confirm-ImportedCmdletIsAvailable',
Expand All @@ -4184,6 +4255,7 @@ Export-ModuleMember -Function @(
'Get-M365DSCAuthenticationMode',
'Get-M365DSCComponentsForAuthenticationType',
'Get-M365DSCComponentsWithMostSecureAuthenticationType',
'Get-M365DSCConfigurationConflict',
'Get-M365DSCExportContentForResource',
'Get-M365DSCOrganization',
'Get-M365DSCTenantDomain',
Expand Down
3 changes: 2 additions & 1 deletion docs/docs/user-guide/cmdlets/Export-M365DSCConfiguration.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ This function does not generate any output.
| Credential | False | PSCredential | | | Specifies the credentials to be used for authentication. |
| CertificatePassword | False | PSCredential | | | Specifies the password of the PFX file which is used for authentication. |
| CertificatePath | False | String | | | Specifies the path of the PFX file which is used for authentication. |
| ManagedIdentity | False | SwitchParameter | | | |
| ManagedIdentity | False | SwitchParameter | | | Specifies whether or not to use Managed Identity to authenticate. |
| Validate | False | SwitchParameter | | Specifies that we want the exported configuration to be validated for any conflicts. (e.g., duplicate primary keys) |

## Examples

Expand Down

0 comments on commit e2073d1

Please sign in to comment.