From 647f42858956dbfdf0fea58734b2e038692f5761 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Mon, 9 Sep 2024 16:20:20 -0700 Subject: [PATCH 1/9] Fixes for M365DSCResourceGenerator handling of non-Graph CmdLets - If a CmdLet has a single parameter set which is not marked as default use that one - Skip the ProgressAction parameter - Skip generating fake values for unknown types --- .../M365DSCResourceGenerator.psm1 | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/ResourceGenerator/M365DSCResourceGenerator.psm1 b/ResourceGenerator/M365DSCResourceGenerator.psm1 index 453d98495e..803062322d 100644 --- a/ResourceGenerator/M365DSCResourceGenerator.psm1 +++ b/ResourceGenerator/M365DSCResourceGenerator.psm1 @@ -911,10 +911,24 @@ class MSFT_DeviceManagementConfigurationPolicyAssignments } else { - $ParametersToFilterOut = @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction', 'ErrorVariable', 'WarningVariable', 'InformationVariable', 'OutVariable', 'OutBuffer', 'PipelineVariable', 'WhatIf', 'Confirm') + $ParametersToFilterOut = @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction', 'ErrorVariable', 'WarningVariable', 'InformationVariable', 'OutVariable', 'OutBuffer', 'PipelineVariable', 'WhatIf', 'Confirm', 'ProgressAction') $cmdlet = Get-Command ($cmdletVerb + "-" + $cmdletNoun) $defaultParameterSetProperties = $cmdlet.ParameterSets | Where-Object -FilterScript {$_.IsDefault} + + if ($null -eq $defaultParameterSetProperties) + { + # No default parameter set, if there is only a single parameter set then use that + if ($cmdlet.ParameterSets.Count -eq 1) + { + $defaultParameterSetProperties = $cmdlet.ParameterSets[0] + } + else + { + throw "CmdLet '$($cmdletVerb + "-" + $cmdletNoun)' does not have a default parameter set" + } + } + $properties = $defaultParameterSetProperties.Parameters | Where-Object -FilterScript {-not $ParametersToFilterOut.Contains($_.Name) -and -not $_.Name.StartsWith('MsftInternal')} #region Get longest parametername @@ -1128,6 +1142,12 @@ class MSFT_DeviceManagementConfigurationPolicyAssignments $propertyValue = $null $propertyDriftValue = $null + + if ($null -eq $fakeValues.$key) + { + continue + } + switch ($fakeValues.$key.GetType().Name) { "String" From 12af335345f29d7f3c146c851fa830b3c7faa53b Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Mon, 9 Sep 2024 21:04:40 -0700 Subject: [PATCH 2/9] Initial version --- ...MSFT_SCUnifiedAuditLogRetentionPolicy.psm1 | 452 ++++++++++++++++++ ...CUnifiedAuditLogRetentionPolicy.schema.mof | 18 + .../readme.md | 8 + .../settings.json | 8 + ...nifiedAuditLogRetentionPolicy-Example.psm1 | 26 + ...SCUnifiedAuditLogRetentionPolicy.Tests.ps1 | 187 ++++++++ 6 files changed, 699 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/SCUnifiedAuditLogRetentionPolicy/1-SCUnifiedAuditLogRetentionPolicy-Example.psm1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCUnifiedAuditLogRetentionPolicy.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.psm1 new file mode 100644 index 0000000000..9197227083 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.psm1 @@ -0,0 +1,452 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret + ) + + New-M365DSCConnection -Workload 'SecurityComplianceCenter' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + try + { + $instances = Get-UnifiedAuditLogRetentionPolicy -ErrorAction SilentlyContinue + if ($null -eq $instances) + { + return $nullResult + } + + $instance = $instances | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 + if ($null -eq $instance) + { + return $nullResult + } + + Write-Verbose -Message "Found an instance with Name {$Name}" + $results = @{ + Identity = $instance.Identity + Description = $instance.Description + Name = $instance.Name + Operations = $instance.Operations + Priority = $instance.Priority + RecordTypes = $instance.RecordTypes + RetentionDuration = $instance.RetentionDuration + UserIds = $instance.UserIds + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + } + return [System.Collections.Hashtable] $results + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String[]] + $Operations, + + [Parameter(Mandatory = $true)] + [System.Int32] + $Priority, + + [Parameter()] + [System.String[]] + $RecordTypes, + + [Parameter(Mandatory = $true)] + [ValidateSet("SevenDays", "OneMonth", "ThreeMonths", "SixMonths", "NineMonths", "TwelveMonths", "ThreeYears", "FiveYears", "SevenYears", "TenYears")] + [System.String] + $RetentionDuration, + + [Parameter()] + [System.String[]] + $UserIds, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret + ) + + New-M365DSCConnection -Workload 'SecurityComplianceCenter' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + $CreateParameters = ([Hashtable]$BoundParameters).Clone() + + $CreateParameters.Remove('Verbose') | Out-Null + + $keys = $CreateParameters.Keys + foreach ($key in $keys) + { + if ($null -ne $CreateParameters.$key -and $CreateParameters.$key.GetType().Name -like '*cimInstance*') + { + $keyValue = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $CreateParameters.$key + $CreateParameters.Remove($key) | Out-Null + $CreateParameters.Add($keyName, $keyValue) + } + } + Write-Verbose -Message "Creating {$Name} with Parameters:`r`n$(Convert-M365DscHashtableToString -Hashtable $CreateParameters)" + New-UnifiedAuditLogRetentionPolicy @CreateParameters | Out-Null + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating {$Name}" + + if ([String]::IsNullOrEmpty($Identity)) + { + throw "Identity is required for updating an existing UnifiedAuditLogRetentionPolicy" + } + + $UpdateParameters = ([Hashtable]$BoundParameters).Clone() + $UpdateParameters.Remove('Verbose') | Out-Null + $UpdateParameters.add('Identity', $currentInstance.Identity) + + $keys = $UpdateParameters.Keys + foreach ($key in $keys) + { + if ($null -ne $UpdateParameters.$key -and $UpdateParameters.$key.GetType().Name -like '*cimInstance*') + { + $keyValue = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $UpdateParameters.$key + $UpdateParameters.Remove($key) | Out-Null + $UpdateParameters.Add($keyName, $keyValue) + } + } + + Set-UnifiedAuditLogRetentionPolicy @UpdateParameters | Out-Null + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing {$Name}" + Remove-UnifiedAuditLogRetentionPolicy -Identity $currentInstance.Identity + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter()] + [System.String[]] + $Operations, + + [Parameter()] + [System.Int32] + $Priority, + + [Parameter()] + [System.String[]] + $RecordTypes, + + [Parameter()] + [ValidateSet("SevenDays", "OneMonth", "ThreeMonths", "SixMonths", "NineMonths", "TwelveMonths", "ThreeYears", "FiveYears", "SevenYears", "TenYears")] + [System.String] + $RetentionDuration, + + [Parameter()] + [System.String[]] + $UserIds, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message "Testing configuration of {$Name}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + $ValuesToCheck.Remove('Name') | Out-Null + + if ($CurrentValues.Ensure -eq 'Absent') + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + #Convert any DateTime to String + foreach ($key in $ValuesToCheck.Keys) + { + if (($null -ne $CurrentValues[$key]) ` + -and ($CurrentValues[$key].GetType().Name -eq 'DateTime')) + { + $CurrentValues[$key] = $CurrentValues[$key].toString() + } + } + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'SecurityComplianceCenter' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + [array]$getValue = Get-UnifiedAuditLogRetentionPolicy -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($getValue.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $getValue) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $config.Name + if (-not [String]::IsNullOrEmpty($config.displayName)) + { + $displayedKey = $config.displayName + } + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + Name = $config.Name + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.schema.mof new file mode 100644 index 0000000000..003d6303a5 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.schema.mof @@ -0,0 +1,18 @@ +[ClassVersion("1.0.0.0"), FriendlyName("SCUnifiedAuditLogRetentionPolicy")] +class MSFT_SCUnifiedAuditLogRetentionPolicy : OMI_BaseResource +{ + [Read, Description("The identity of the policy")] String Identity; + [Write, Description("")] String Description; + [Key, Description("")] String Name; + [Write, Description("")] String[] Operations; + [Key, Description("")] UInt32 Priority; + [Write, Description("")] String[] RecordTypes; + [Key, Description(""), ValueMap{"SevenDays", "OneMonth", "ThreeMonths", "SixMonths", "NineMonths", "TwelveMonths", "ThreeYears", "FiveYears", "SevenYears", "TenYears"}, Values{"SevenDays", "OneMonth", "ThreeMonths", "SixMonths", "NineMonths", "TwelveMonths", "ThreeYears", "FiveYears", "SevenYears", "TenYears"}] String RetentionDuration; + [Write, Description("")] String[] UserIds; + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/readme.md new file mode 100644 index 0000000000..0c7a7e744d --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/readme.md @@ -0,0 +1,8 @@ + +# SCUnifiedAuditLogRetentionPolicy + +## Description + + +New-UnifiedAuditLogRetentionPolicy [-Name] -Priority -RetentionDuration [-Description ] [-Operations ] [-RecordTypes ] [-UserIds ] [-WhatIf] [-Confirm] [] + diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/settings.json new file mode 100644 index 0000000000..846a655d8a --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/settings.json @@ -0,0 +1,8 @@ +{ + "resourceName": "SCUnifiedAuditLogRetentionPolicy", + "description": "This resource configures an +New-UnifiedAuditLogRetentionPolicy [-Name] -Priority -RetentionDuration [-Description ] [-Operations ] [-RecordTypes ] [-UserIds ] [-WhatIf] [-Confirm] [] +.", + "permissions":[] + +} diff --git a/Modules/Microsoft365DSC/Examples/SCUnifiedAuditLogRetentionPolicy/1-SCUnifiedAuditLogRetentionPolicy-Example.psm1 b/Modules/Microsoft365DSC/Examples/SCUnifiedAuditLogRetentionPolicy/1-SCUnifiedAuditLogRetentionPolicy-Example.psm1 new file mode 100644 index 0000000000..68174500f2 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/SCUnifiedAuditLogRetentionPolicy/1-SCUnifiedAuditLogRetentionPolicy-Example.psm1 @@ -0,0 +1,26 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter(Mandatory = $true)] + [PSCredential] + $Credscredential + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + SCUnifiedAuditLogRetentionPolicy 'Example' + { + Credential = $Credscredential; + Ensure = "Absent"; + Name = "Test Policy"; + Priority = 1; + RetentionDuration = "7Days"; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCUnifiedAuditLogRetentionPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCUnifiedAuditLogRetentionPolicy.Tests.ps1 new file mode 100644 index 0000000000..3b4aa46172 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCUnifiedAuditLogRetentionPolicy.Tests.ps1 @@ -0,0 +1,187 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource "SCUnifiedAuditLogRetentionPolicy" -GenericStubModule $GenericStubPath +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName Get-PSSession -MockWith { + } + + Mock -CommandName Remove-PSSession -MockWith { + } + + Mock -CommandName Set-UnifiedAuditLogRetentionPolicy -MockWith { + } + + Mock -CommandName New-UnifiedAuditLogRetentionPolicy -MockWith { + } + + Mock -CommandName Remove-UnifiedAuditLogRetentionPolicy -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The SCUnifiedAuditLogRetentionPolicy should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = "Present" + Credential = $Credential; + } + + Mock -CommandName Get-UnifiedAuditLogRetentionPolicy -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + It 'Should Create the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-UnifiedAuditLogRetentionPolicy -Exactly 1 + } + } + + Context -Name "The SCUnifiedAuditLogRetentionPolicy exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Absent' + Credential = $Credential; + } + + Mock -CommandName Get-UnifiedAuditLogRetentionPolicy -MockWith { + return @{ + Priority = 3 + Name = "FakeStringValue" + Description = "FakeStringValue" + + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should Remove the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-UnifiedAuditLogRetentionPolicy -Exactly 1 + } + } + Context -Name "The SCUnifiedAuditLogRetentionPolicy Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-UnifiedAuditLogRetentionPolicy -MockWith { + return @{ + Priority = 3 + Name = "FakeStringValue" + Description = "FakeStringValue" + + } + } + } + + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The SCUnifiedAuditLogRetentionPolicy exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-UnifiedAuditLogRetentionPolicy -MockWith { + return @{ + Priority = 2 + Name = "FakeStringValue" + Description = "FakeStringValueDrift #Drift" + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Set-UnifiedAuditLogRetentionPolicy -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-UnifiedAuditLogRetentionPolicy -MockWith { + return @{ + Priority = 3 + Name = "FakeStringValue" + Description = "FakeStringValue" + + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From b1a6280554103659b64ae9f667d6a2b47ab14b69 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Tue, 10 Sep 2024 08:23:37 -0700 Subject: [PATCH 3/9] Add unit tests --- ...MSFT_SCUnifiedAuditLogRetentionPolicy.psm1 | 38 +++++-- ...SCUnifiedAuditLogRetentionPolicy.Tests.ps1 | 59 ++++++---- Tests/Unit/Stubs/Microsoft365.psm1 | 104 ++++++++++++++++++ 3 files changed, 169 insertions(+), 32 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.psm1 index 9197227083..3f7fed04c2 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.psm1 @@ -4,10 +4,23 @@ function Get-TargetResource [OutputType([System.Collections.Hashtable])] param ( + [Parameter()] + [System.String] + $Description, + [Parameter(Mandatory = $true)] [System.String] $Name, + [Parameter(Mandatory = $true)] + [System.Int32] + $Priority, + + [Parameter(Mandatory = $true)] + [ValidateSet("SevenDays", "OneMonth", "ThreeMonths", "SixMonths", "NineMonths", "TwelveMonths", "ThreeYears", "FiveYears", "SevenYears", "TenYears")] + [System.String] + $RetentionDuration, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -53,13 +66,13 @@ function Get-TargetResource $nullResult.Ensure = 'Absent' try { - $instances = Get-UnifiedAuditLogRetentionPolicy -ErrorAction SilentlyContinue + $instances = @(Get-UnifiedAuditLogRetentionPolicy -ErrorAction SilentlyContinue) if ($null -eq $instances) { return $nullResult } - $instance = $instances | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 + $instance = $instances | Where-Object { $_.Name -eq $Name -and $_.Priority -eq $Priority -and $_.RetentionDuration -eq $RetentionDuration} | Select-Object -First 1 if ($null -eq $instance) { return $nullResult @@ -105,7 +118,7 @@ function Set-TargetResource [System.String] $Description, - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $Name, @@ -171,7 +184,14 @@ function Set-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - $currentInstance = Get-TargetResource @PSBoundParameters + $GetParameters = ([Hashtable]$PSBoundParameters).Clone() + + $GetParameters.Remove('Description') | Out-Null + $GetParameters.Remove('Operations') | Out-Null + $GetParameters.Remove('RecordTypes') | Out-Null + $GetParameters.Remove('UserIds') | Out-Null + + $currentInstance = Get-TargetResource @GetParameters $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters @@ -198,14 +218,10 @@ function Set-TargetResource { Write-Verbose -Message "Updating {$Name}" - if ([String]::IsNullOrEmpty($Identity)) - { - throw "Identity is required for updating an existing UnifiedAuditLogRetentionPolicy" - } - $UpdateParameters = ([Hashtable]$BoundParameters).Clone() $UpdateParameters.Remove('Verbose') | Out-Null - $UpdateParameters.add('Identity', $currentInstance.Identity) + $UpdateParameters.Remove('Name') | Out-Null + $UpdateParameters.Add('Identity', $currentInstance.Identity) | Out-Null $keys = $UpdateParameters.Keys foreach ($key in $keys) @@ -410,6 +426,8 @@ function Export-TargetResource Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline $params = @{ Name = $config.Name + Priority = $config.Priority + RetentionDuration = $config.RetentionDuration Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCUnifiedAuditLogRetentionPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCUnifiedAuditLogRetentionPolicy.Tests.ps1 index 3b4aa46172..3bb7ce1bde 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCUnifiedAuditLogRetentionPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCUnifiedAuditLogRetentionPolicy.Tests.ps1 @@ -50,13 +50,16 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Write-Host -MockWith { } $Script:exportedInstances =$null - $Script:ExportMode = $false + $Script:ExportMode = $false } # Test contexts Context -Name "The SCUnifiedAuditLogRetentionPolicy should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ - Ensure = "Present" + Name = "Test Policy" + Priority = 42 + RetentionDuration = "SevenDays" + Ensure = "Present" Credential = $Credential; } @@ -70,7 +73,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - It 'Should Create the group from the Set method' { + It 'Should Create the Unified Audit Log Retention Policy from the Set method' { Set-TargetResource @testParams Should -Invoke -CommandName New-UnifiedAuditLogRetentionPolicy -Exactly 1 } @@ -79,16 +82,19 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The SCUnifiedAuditLogRetentionPolicy exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ - Ensure = 'Absent' + Name = "Test Policy" + Priority = 42 + RetentionDuration = "SevenDays" + Ensure = "Absent" Credential = $Credential; } Mock -CommandName Get-UnifiedAuditLogRetentionPolicy -MockWith { return @{ - Priority = 3 - Name = "FakeStringValue" - Description = "FakeStringValue" - + Identity = "TestIdentity" + Priority = $testParams.Priority + Name = $testParams.Name + RetentionDuration = $testParams.RetentionDuration } } } @@ -97,7 +103,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { (Get-TargetResource @testParams).Ensure | Should -Be 'Present' } - It 'Should return true from the Test method' { + It 'Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } @@ -109,16 +115,18 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The SCUnifiedAuditLogRetentionPolicy Exists and Values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - Ensure = 'Present' + Name = "Test Policy" + Priority = 42 + RetentionDuration = "SevenDays" + Ensure = 'Present' Credential = $Credential; } Mock -CommandName Get-UnifiedAuditLogRetentionPolicy -MockWith { return @{ - Priority = 3 - Name = "FakeStringValue" - Description = "FakeStringValue" - + Name = "Test Policy" + Priority = 42 + RetentionDuration = "SevenDays" } } } @@ -132,15 +140,21 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The SCUnifiedAuditLogRetentionPolicy exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - Ensure = 'Present' + Name = "Test Policy" + Priority = 42 + RetentionDuration = "SevenDays" + Description = "FakeStringValueDrift" + Ensure = 'Present' Credential = $Credential; } Mock -CommandName Get-UnifiedAuditLogRetentionPolicy -MockWith { return @{ - Priority = 2 - Name = "FakeStringValue" - Description = "FakeStringValueDrift #Drift" + Identity = "TestIdentity" + Name = $testParams.Name + Priority = $testParams.Priority + RetentionDuration = $testParams.RetentionDuration + Description = $testParams.RetentionDescription + "#Drift" } } } @@ -169,10 +183,11 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-UnifiedAuditLogRetentionPolicy -MockWith { return @{ - Priority = 3 - Name = "FakeStringValue" - Description = "FakeStringValue" - + Priority = 3 + Name = "FakeStringValue" + Description = "FakeStringValue" + RetentionDuration = "SevenDays" + Identity = "FakeIdentity" } } } diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index d8d8db6694..e77af1f80f 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -2057,6 +2057,29 @@ function Get-TransportRule $Identity ) } + +function Get-UnifiedAuditLogRetentionPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Operation, + + [Parameter()] + [System.String] + $RecordType, + + [Parameter()] + [System.String] + $RetentionDuration, + + [Parameter()] + [System.String] + $UserId + ) +} + function Get-UnifiedGroup { [CmdletBinding()] @@ -6186,6 +6209,41 @@ function New-TransportRule $ExceptIfHeaderContainsMessageHeader ) } + +function New-UnifiedAuditLogRetentionPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.UInt32] + $Priority, + + [Parameter()] + [System.String] + $RetentionDuration, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String[]] + $Operations, + + [Parameter()] + [System.String[]] + $RecordTypes, + + [Parameter()] + [System.String[]] + $UserIds + ) +} + function Remove-ActiveSyncDevice { [CmdletBinding()] @@ -7058,6 +7116,17 @@ function Remove-TransportRule $Identity ) } + +function Remove-UnifiedAuditLogRetentionPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Identity + ) +} + function Set-AcceptedDomain { [CmdletBinding()] @@ -13943,6 +14012,41 @@ function Set-UnifiedGroup $HiddenFromAddressListsEnabled ) } + +function Set-UnifiedAuditLogRetentionPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.UInt32] + $Priority, + + [Parameter()] + [System.String] + $RetentionDuration, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String[]] + $Operations, + + [Parameter()] + [System.String[]] + $RecordTypes, + + [Parameter()] + [System.String[]] + $UserIds + ) +} + function Set-User { [CmdletBinding()] From 043e85633706f41c10b940d8138f73ef0d145ac0 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Tue, 10 Sep 2024 08:36:35 -0700 Subject: [PATCH 4/9] Update example --- .../1-CreateNewUnifiedAuditLogRetentionPolicy.ps1} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename Modules/Microsoft365DSC/Examples/{SCUnifiedAuditLogRetentionPolicy/1-SCUnifiedAuditLogRetentionPolicy-Example.psm1 => Resources/SCUnifiedAuditLogRetentionPolicy/1-CreateNewUnifiedAuditLogRetentionPolicy.ps1} (81%) diff --git a/Modules/Microsoft365DSC/Examples/SCUnifiedAuditLogRetentionPolicy/1-SCUnifiedAuditLogRetentionPolicy-Example.psm1 b/Modules/Microsoft365DSC/Examples/Resources/SCUnifiedAuditLogRetentionPolicy/1-CreateNewUnifiedAuditLogRetentionPolicy.ps1 similarity index 81% rename from Modules/Microsoft365DSC/Examples/SCUnifiedAuditLogRetentionPolicy/1-SCUnifiedAuditLogRetentionPolicy-Example.psm1 rename to Modules/Microsoft365DSC/Examples/Resources/SCUnifiedAuditLogRetentionPolicy/1-CreateNewUnifiedAuditLogRetentionPolicy.ps1 index 68174500f2..19b7665df7 100644 --- a/Modules/Microsoft365DSC/Examples/SCUnifiedAuditLogRetentionPolicy/1-SCUnifiedAuditLogRetentionPolicy-Example.psm1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SCUnifiedAuditLogRetentionPolicy/1-CreateNewUnifiedAuditLogRetentionPolicy.ps1 @@ -8,7 +8,7 @@ Configuration Example param( [Parameter(Mandatory = $true)] [PSCredential] - $Credscredential + $Credentials ) Import-DscResource -ModuleName Microsoft365DSC @@ -16,8 +16,8 @@ Configuration Example { SCUnifiedAuditLogRetentionPolicy 'Example' { - Credential = $Credscredential; - Ensure = "Absent"; + Credential = $Credentials; + Ensure = "Present"; Name = "Test Policy"; Priority = 1; RetentionDuration = "7Days"; From c8c9985da7d96d3a7b957e1779231ac8dcd85949 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Tue, 10 Sep 2024 09:12:06 -0700 Subject: [PATCH 5/9] Fix readme and settings --- .../MSFT_SCUnifiedAuditLogRetentionPolicy/readme.md | 4 +--- .../MSFT_SCUnifiedAuditLogRetentionPolicy/settings.json | 5 +---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/readme.md index 0c7a7e744d..2a3748febe 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/readme.md @@ -3,6 +3,4 @@ ## Description - -New-UnifiedAuditLogRetentionPolicy [-Name] -Priority -RetentionDuration [-Description ] [-Operations ] [-RecordTypes ] [-UserIds ] [-WhatIf] [-Confirm] [] - +The resource configured the Unified Audit Log Retention Policy in the Security and Compliance. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/settings.json index 846a655d8a..b975389e7d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/settings.json @@ -1,8 +1,5 @@ { "resourceName": "SCUnifiedAuditLogRetentionPolicy", - "description": "This resource configures an -New-UnifiedAuditLogRetentionPolicy [-Name] -Priority -RetentionDuration [-Description ] [-Operations ] [-RecordTypes ] [-UserIds ] [-WhatIf] [-Confirm] [] -.", + "description": "The resource configured the Unified Audit Log Retention Policy in the Security and Compliance.", "permissions":[] - } From e708e0f9c5c8e19dc2956cb4939d8e25f5039df7 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Tue, 10 Sep 2024 11:09:54 -0700 Subject: [PATCH 6/9] Fixes for end-to-end tests --- ...MSFT_SCUnifiedAuditLogRetentionPolicy.psm1 | 29 ++++++++++++++----- ...CUnifiedAuditLogRetentionPolicy.schema.mof | 11 ++++--- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.psm1 index 3f7fed04c2..f7b15aa1e3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.psm1 @@ -12,15 +12,27 @@ function Get-TargetResource [System.String] $Name, - [Parameter(Mandatory = $true)] + [Parameter()] [System.Int32] $Priority, - [Parameter(Mandatory = $true)] + [Parameter()] + [System.String[]] + $RecordTypes, + + [Parameter()] [ValidateSet("SevenDays", "OneMonth", "ThreeMonths", "SixMonths", "NineMonths", "TwelveMonths", "ThreeYears", "FiveYears", "SevenYears", "TenYears")] [System.String] $RetentionDuration, + [Parameter()] + [System.String[]] + $UserIds, + + [Parameter()] + [System.String[]] + $Operations, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -66,13 +78,13 @@ function Get-TargetResource $nullResult.Ensure = 'Absent' try { - $instances = @(Get-UnifiedAuditLogRetentionPolicy -ErrorAction SilentlyContinue) + [array]$instances = @(Get-UnifiedAuditLogRetentionPolicy -ErrorAction SilentlyContinue | Where-Object { $_.Mode -ne 'PendingDeletion' }) if ($null -eq $instances) { return $nullResult } - $instance = $instances | Where-Object { $_.Name -eq $Name -and $_.Priority -eq $Priority -and $_.RetentionDuration -eq $RetentionDuration} | Select-Object -First 1 + $instance = $instances | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 if ($null -eq $instance) { return $nullResult @@ -261,15 +273,15 @@ function Test-TargetResource [System.String[]] $Operations, - [Parameter()] - [System.Int32] + [Parameter(Mandatory = $true)] + [System.UInt32] $Priority, [Parameter()] [System.String[]] $RecordTypes, - [Parameter()] + [Parameter(Mandatory = $true)] [ValidateSet("SevenDays", "OneMonth", "ThreeMonths", "SixMonths", "NineMonths", "TwelveMonths", "ThreeYears", "FiveYears", "SevenYears", "TenYears")] [System.String] $RetentionDuration, @@ -399,7 +411,7 @@ function Export-TargetResource try { - [array]$getValue = Get-UnifiedAuditLogRetentionPolicy -ErrorAction Stop + [array]$getValue = @(Get-UnifiedAuditLogRetentionPolicy -ErrorAction Stop | Where-Object { $_.Mode -ne 'PendingDeletion' }) $i = 1 $dscContent = '' @@ -437,6 +449,7 @@ function Export-TargetResource } $Results = Get-TargetResource @Params + $Results.Remove("Identity") | Out-Null $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` -Results $Results diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.schema.mof index 003d6303a5..51046cdf24 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.schema.mof @@ -1,14 +1,13 @@ [ClassVersion("1.0.0.0"), FriendlyName("SCUnifiedAuditLogRetentionPolicy")] class MSFT_SCUnifiedAuditLogRetentionPolicy : OMI_BaseResource { - [Read, Description("The identity of the policy")] String Identity; [Write, Description("")] String Description; [Key, Description("")] String Name; - [Write, Description("")] String[] Operations; - [Key, Description("")] UInt32 Priority; - [Write, Description("")] String[] RecordTypes; - [Key, Description(""), ValueMap{"SevenDays", "OneMonth", "ThreeMonths", "SixMonths", "NineMonths", "TwelveMonths", "ThreeYears", "FiveYears", "SevenYears", "TenYears"}, Values{"SevenDays", "OneMonth", "ThreeMonths", "SixMonths", "NineMonths", "TwelveMonths", "ThreeYears", "FiveYears", "SevenYears", "TenYears"}] String RetentionDuration; - [Write, Description("")] String[] UserIds; + [Write, Description("")] String Operations[]; + [Write, Description("")] UInt32 Priority; + [Write, Description("")] String RecordTypes[]; + [Write, Description(""), ValueMap{"SevenDays", "OneMonth", "ThreeMonths", "SixMonths", "NineMonths", "TwelveMonths", "ThreeYears", "FiveYears", "SevenYears", "TenYears"}, Values{"SevenDays", "OneMonth", "ThreeMonths", "SixMonths", "NineMonths", "TwelveMonths", "ThreeYears", "FiveYears", "SevenYears", "TenYears"}] String RetentionDuration; + [Write, Description("")] String UserIds[]; [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; From aa88b30d2a224b1135b7b7b96cc6fe55059af9a1 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Tue, 10 Sep 2024 11:12:39 -0700 Subject: [PATCH 7/9] Add unit test for pending deletion policies --- ...SCUnifiedAuditLogRetentionPolicy.Tests.ps1 | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCUnifiedAuditLogRetentionPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCUnifiedAuditLogRetentionPolicy.Tests.ps1 index 3bb7ce1bde..d49c73a33d 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCUnifiedAuditLogRetentionPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCUnifiedAuditLogRetentionPolicy.Tests.ps1 @@ -196,6 +196,31 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $result | Should -Not -BeNullOrEmpty } } + + Context -Name 'Does not return resources that are pending deletion' -Fixture { + BeforeAll { + $testParams = @{ + Name = "Test Policy" + Priority = 42 + RetentionDuration = "SevenDays" + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-UnifiedAuditLogRetentionPolicy -MockWith { + return @{ + Name = "Test Policy" + Priority = 42 + RetentionDuration = "SevenDays" + Mode = "PendingDeletion" + } + } + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + } } } From 60bb860927720aff76c66d8b43d4d578e399a36e Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Tue, 10 Sep 2024 11:17:36 -0700 Subject: [PATCH 8/9] Add missing descriptions to schema --- ...SFT_SCUnifiedAuditLogRetentionPolicy.schema.mof | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.schema.mof index 51046cdf24..f6a6fe902a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCUnifiedAuditLogRetentionPolicy/MSFT_SCUnifiedAuditLogRetentionPolicy.schema.mof @@ -1,13 +1,13 @@ [ClassVersion("1.0.0.0"), FriendlyName("SCUnifiedAuditLogRetentionPolicy")] class MSFT_SCUnifiedAuditLogRetentionPolicy : OMI_BaseResource { - [Write, Description("")] String Description; - [Key, Description("")] String Name; - [Write, Description("")] String Operations[]; - [Write, Description("")] UInt32 Priority; - [Write, Description("")] String RecordTypes[]; - [Write, Description(""), ValueMap{"SevenDays", "OneMonth", "ThreeMonths", "SixMonths", "NineMonths", "TwelveMonths", "ThreeYears", "FiveYears", "SevenYears", "TenYears"}, Values{"SevenDays", "OneMonth", "ThreeMonths", "SixMonths", "NineMonths", "TwelveMonths", "ThreeYears", "FiveYears", "SevenYears", "TenYears"}] String RetentionDuration; - [Write, Description("")] String UserIds[]; + [Write, Description("The description for the audit log retention policy")] String Description; + [Key, Description("Unique name for the audit log retention policy")] String Name; + [Write, Description("Specifies the audit log operations that are retained by the policy")] String Operations[]; + [Write, Description("Priority value for the policy that determines the order of policy processing.")] UInt32 Priority; + [Write, Description("Specifies the audit logs of a specific record type that are retained by the policy.")] String RecordTypes[]; + [Write, Description("How long audit log records are kept"), ValueMap{"SevenDays", "OneMonth", "ThreeMonths", "SixMonths", "NineMonths", "TwelveMonths", "ThreeYears", "FiveYears", "SevenYears", "TenYears"}, Values{"SevenDays", "OneMonth", "ThreeMonths", "SixMonths", "NineMonths", "TwelveMonths", "ThreeYears", "FiveYears", "SevenYears", "TenYears"}] String RetentionDuration; + [Write, Description("Specifies the audit logs that are retained by the policy based on the ID of the user who performed the action")] String UserIds[]; [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; From f7071b2c1833eb4e4b4f0e2bfc9779c7e9f18d9d Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Tue, 10 Sep 2024 12:05:18 -0700 Subject: [PATCH 9/9] Fix example --- .../1-CreateNewUnifiedAuditLogRetentionPolicy.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCUnifiedAuditLogRetentionPolicy/1-CreateNewUnifiedAuditLogRetentionPolicy.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCUnifiedAuditLogRetentionPolicy/1-CreateNewUnifiedAuditLogRetentionPolicy.ps1 index 19b7665df7..ead7b6c305 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SCUnifiedAuditLogRetentionPolicy/1-CreateNewUnifiedAuditLogRetentionPolicy.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SCUnifiedAuditLogRetentionPolicy/1-CreateNewUnifiedAuditLogRetentionPolicy.ps1 @@ -20,7 +20,7 @@ Configuration Example Ensure = "Present"; Name = "Test Policy"; Priority = 1; - RetentionDuration = "7Days"; + RetentionDuration = "SevenDays"; } } }