From 18e8ddf25a509bee94008a23596df6c5d5a1bac6 Mon Sep 17 00:00:00 2001 From: Sandro Lanfranchi Date: Tue, 26 Sep 2023 15:41:09 +0200 Subject: [PATCH 001/465] fix ComplianceRecordingApplications --- .../MSFT_TeamsComplianceRecordingPolicy.psm1 | 57 +++++++++++++++++-- ..._TeamsComplianceRecordingPolicy.schema.mof | 14 ++++- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 index 707422b878..7b8e9393d1 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 @@ -9,7 +9,7 @@ function Get-TargetResource $Identity, [Parameter()] - [System.String[]] + [Microsoft.Management.Infrastructure.CimInstance] $ComplianceRecordingApplications, [Parameter()] @@ -75,10 +75,28 @@ function Get-TargetResource return $nullResult } + if($instance.ComplianceRecordingApplications.Count -gt 0){ + $ComplexComplianceRecordingApplications = @() + foreach($CurrentComplianceRecordingApplications in $instance.ComplianceRecordingApplications){ + $MyComplianceRecordingApplications = @{} + $MyComplianceRecordingApplications.Add('ComplianceRecordingPairedApplications', $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications) + $MyComplianceRecordingApplications.Add('Id', $CurrentComplianceRecordingApplications.Id) + $MyComplianceRecordingApplications.Add('RequiredBeforeMeetingJoin', $CurrentComplianceRecordingApplications.RequiredBeforeMeetingJoin) + $MyComplianceRecordingApplications.Add('RequiredBeforeCallEstablishment', $CurrentComplianceRecordingApplications.RequiredBeforeCallEstablishment) + $MyComplianceRecordingApplications.Add('RequiredDuringMeeting', $CurrentComplianceRecordingApplications.RequiredDuringMeeting) + $MyComplianceRecordingApplications.Add('RequiredDuringCall', $CurrentComplianceRecordingApplications.RequiredDuringCall) + $MyComplianceRecordingApplications.Add('ConcurrentInvitationCount', $CurrentComplianceRecordingApplications.ConcurrentInvitationCount) + + if ($MyComplianceRecordingApplications.values.Where({$null -ne $_}).count -gt 0){ + $ComplexComplianceRecordingApplications += $MyComplianceRecordingApplications + } + } + } + Write-Verbose -Message "Found an instance with Identity {$Identity}" $results = @{ Identity = $instance.Identity - ComplianceRecordingApplications = $instance.ComplianceRecordingApplications + ComplianceRecordingApplications = $ComplexComplianceRecordingApplications Description = $instance.Description DisableComplianceRecordingAudioNotificationForCalls = $instance.DisableComplianceRecordingAudioNotificationForCalls Enabled = $instance.Enabled @@ -113,7 +131,7 @@ function Set-TargetResource $Identity, [Parameter()] - [System.String[]] + [Microsoft.Management.Infrastructure.CimInstance] $ComplianceRecordingApplications, [Parameter()] @@ -236,7 +254,7 @@ function Test-TargetResource $Identity, [Parameter()] - [System.String[]] + [Microsoft.Management.Infrastructure.CimInstance] $ComplianceRecordingApplications, [Parameter()] @@ -406,11 +424,42 @@ function Export-TargetResource $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` -Results $Results + if ($null -ne $Results.ComplianceRecordingApplications) + { + $complexMapping = @( + @{ + Name = 'ComplianceRecordingApplications' + CimInstanceName = 'Microsoft.Teams.Policy.Administration.Cmdlets.Core.ComplianceRecordingApplication' + IsRequired = $False + } + ) + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.ComplianceRecordingApplications ` + -CIMInstanceName 'Microsoft.Teams.Policy.Administration.Cmdlets.Core.ComplianceRecordingApplication' ` + -ComplexTypeMapping $complexMapping + + if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.ComplianceRecordingApplications = $complexTypeStringResult + } + else + { + $Results.Remove('ComplianceRecordingApplications') | Out-Null + } + } + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` -ConnectionMode $ConnectionMode ` -ModulePath $PSScriptRoot ` -Results $Results ` -Credential $Credential + if ($Results.ComplianceRecordingApplications) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ComplianceRecordingApplications' -IsCIMArray:$True + $currentDSCBlock = $currentDSCBlock.Replace('ComplianceRecordingApplications = @("', 'ComplianceRecordingApplications = @(') + $currentDSCBlock = $currentDSCBlock.Replace(" `",`"`r`n", '') + + } $dscContent += $currentDSCBlock Save-M365DSCPartialExport -Content $currentDSCBlock ` -FileName $Global:PartialExportFileName diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof index 25f29236af..4a9e214fd4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof @@ -1,8 +1,20 @@ +[ClassVersion("0.0.96.0"), FriendlyName("TeamsComplianceRecordingApplication)] +class MSFT_Microsoft.Teams.Policy.Administration.Cmdlets.Core.ComplianceRecordingApplication +{ + [Write, Description("")] String Id; + [Write, Description("")] String[] ComplianceRecordingPairedApplications; + [Write, Description("")] Boolean RequiredBeforeMeetingJoin; + [Write, Description("")] Boolean RequiredBeforeCallEstablishment; + [Write, Description("")] Boolean RequiredDuringMeeting; + [Write, Description("")] Boolean RequiredDuringCall; + [Write, Description("")] String ConcurrentInvitationCount; +} + [ClassVersion("1.0.0.0"), FriendlyName("TeamsComplianceRecordingPolicy")] class MSFT_TeamsComplianceRecordingPolicy : OMI_BaseResource { [Key, Description("Unique identifier of the application instance of a policy-based recording application to be retrieved.")] String Identity; - [Write, Description("A list of application instances of policy-based recording applications to assign to this policy. The Id of each of these application instances must be the ObjectId of the application instance as obtained by the Get-CsOnlineApplicationInstance cmdlet.")] String ComplianceRecordingApplications[]; + [Write, Description("A list of application instances of policy-based recording applications to assign to this policy. The Id of each of these application instances must be the ObjectId of the application instance as obtained by the Get-CsOnlineApplicationInstance cmdlet."), EmbeddedInstance("MSFT_Microsoft.Teams.Policy.Administration.Cmdlets.Core.ComplianceRecordingApplication")] String ComplianceRecordingApplications[]; [Write, Description("Enables administrators to provide explanatory text to accompany a Teams recording policy. For example, the Description might include information about the users the policy should be assigned to.")] String Description; [Write, Description("Setting this attribute to true disables recording audio notifications for 1:1 calls that are under compliance recording.")] Boolean DisableComplianceRecordingAudioNotificationForCalls; [Write, Description("Controls whether this Teams recording policy is active or not.")] Boolean Enabled; From 691e5d6fad6b6fedabda99dbfe15012974093e61 Mon Sep 17 00:00:00 2001 From: Sandro Lanfranchi Date: Tue, 26 Sep 2023 16:03:26 +0200 Subject: [PATCH 002/465] wip --- .../MSFT_TeamsComplianceRecordingPolicy.psm1 | 4 ++-- .../MSFT_TeamsComplianceRecordingPolicy.schema.mof | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 index 7b8e9393d1..b834a3a86d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 @@ -429,13 +429,13 @@ function Export-TargetResource $complexMapping = @( @{ Name = 'ComplianceRecordingApplications' - CimInstanceName = 'Microsoft.Teams.Policy.Administration.Cmdlets.Core.ComplianceRecordingApplication' + CimInstanceName = 'TeamsComplianceRecordingApplication' IsRequired = $False } ) $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` -ComplexObject $Results.ComplianceRecordingApplications ` - -CIMInstanceName 'Microsoft.Teams.Policy.Administration.Cmdlets.Core.ComplianceRecordingApplication' ` + -CIMInstanceName 'TeamsComplianceRecordingApplicationn' ` -ComplexTypeMapping $complexMapping if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof index 4a9e214fd4..b14ba1eb62 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof @@ -1,5 +1,5 @@ -[ClassVersion("0.0.96.0"), FriendlyName("TeamsComplianceRecordingApplication)] -class MSFT_Microsoft.Teams.Policy.Administration.Cmdlets.Core.ComplianceRecordingApplication +[ClassVersion("1.0.0"), FriendlyName("TeamsComplianceRecordingApplication)] +class MSFT_TeamsComplianceRecordingApplication { [Write, Description("")] String Id; [Write, Description("")] String[] ComplianceRecordingPairedApplications; @@ -14,7 +14,7 @@ class MSFT_Microsoft.Teams.Policy.Administration.Cmdlets.Core.ComplianceRecordin class MSFT_TeamsComplianceRecordingPolicy : OMI_BaseResource { [Key, Description("Unique identifier of the application instance of a policy-based recording application to be retrieved.")] String Identity; - [Write, Description("A list of application instances of policy-based recording applications to assign to this policy. The Id of each of these application instances must be the ObjectId of the application instance as obtained by the Get-CsOnlineApplicationInstance cmdlet."), EmbeddedInstance("MSFT_Microsoft.Teams.Policy.Administration.Cmdlets.Core.ComplianceRecordingApplication")] String ComplianceRecordingApplications[]; + [Write, Description("A list of application instances of policy-based recording applications to assign to this policy. The Id of each of these application instances must be the ObjectId of the application instance as obtained by the Get-CsOnlineApplicationInstance cmdlet."), EmbeddedInstance("MSFT_TeamsComplianceRecordingApplication")] String ComplianceRecordingApplications[]; [Write, Description("Enables administrators to provide explanatory text to accompany a Teams recording policy. For example, the Description might include information about the users the policy should be assigned to.")] String Description; [Write, Description("Setting this attribute to true disables recording audio notifications for 1:1 calls that are under compliance recording.")] Boolean DisableComplianceRecordingAudioNotificationForCalls; [Write, Description("Controls whether this Teams recording policy is active or not.")] Boolean Enabled; From 1f46e89abc6c9ad2dbacb8a56658e264e6fcf17e Mon Sep 17 00:00:00 2001 From: Sandro Lanfranchi Date: Wed, 4 Oct 2023 18:52:10 +0200 Subject: [PATCH 003/465] Fixes MSFT_TeamsComplianceRecordingPolicy attribute not exported correctly #3712 --- .../MSFT_TeamsComplianceRecordingPolicy.psm1 | 132 ++++++++++++++++-- ..._TeamsComplianceRecordingPolicy.schema.mof | 18 +-- 2 files changed, 132 insertions(+), 18 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 index b834a3a86d..cfe3cbc9b8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 @@ -9,7 +9,7 @@ function Get-TargetResource $Identity, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance] + [Microsoft.Management.Infrastructure.CimInstance[]] $ComplianceRecordingApplications, [Parameter()] @@ -79,7 +79,13 @@ function Get-TargetResource $ComplexComplianceRecordingApplications = @() foreach($CurrentComplianceRecordingApplications in $instance.ComplianceRecordingApplications){ $MyComplianceRecordingApplications = @{} - $MyComplianceRecordingApplications.Add('ComplianceRecordingPairedApplications', $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications) + $ComplianceRecordingPairedApplications = @() + if($CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications.Count -gt 0){ + foreach($CurrentComplianceRecordingPairedApplications in $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications){ + $ComplianceRecordingPairedApplications += $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications.Id + } + } + $MyComplianceRecordingApplications.Add('ComplianceRecordingPairedApplications', $ComplianceRecordingPairedApplications) $MyComplianceRecordingApplications.Add('Id', $CurrentComplianceRecordingApplications.Id) $MyComplianceRecordingApplications.Add('RequiredBeforeMeetingJoin', $CurrentComplianceRecordingApplications.RequiredBeforeMeetingJoin) $MyComplianceRecordingApplications.Add('RequiredBeforeCallEstablishment', $CurrentComplianceRecordingApplications.RequiredBeforeCallEstablishment) @@ -131,7 +137,7 @@ function Set-TargetResource $Identity, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance] + [Microsoft.Management.Infrastructure.CimInstance[]] $ComplianceRecordingApplications, [Parameter()] @@ -215,6 +221,47 @@ function Set-TargetResource } Write-Verbose -Message "Creating {$Identity} with Parameters:`r`n$(Convert-M365DscHashtableToString -Hashtable $CreateParameters)" New-CsTeamsComplianceRecordingPolicy @CreateParameters | Out-Null + + if($ComplianceRecordingApplications.Count -gt 0){ + foreach($CurrentComplianceRecordingApplications in $ComplianceRecordingApplications){ + $Instance = $CurrentComplianceRecordingApplications.Id + $RequiredBeforeMeetingJoin = $CurrentComplianceRecordingApplications.RequiredBeforeMeetingJoin + $RequiredBeforeCallEstablishment = $CurrentComplianceRecordingApplications.RequiredBeforeCallEstablishment + $RequiredDuringMeeting = $CurrentComplianceRecordingApplications.RequiredDuringMeeting + $RequiredDuringCall = $CurrentComplianceRecordingApplications.RequiredDuringCall + $ConcurrentInvitationCount = $CurrentComplianceRecordingApplications.ConcurrentInvitationCount + + $CsTeamsComplianceRecordingApplication = Get-CsTeamsComplianceRecordingApplication -Identity $CsTeamsComplianceRecordingApplicationIdentity -ErrorAction SilentlyContinue + if($null -eq $CsTeamsComplianceRecordingApplication){ + New-CsTeamsComplianceRecordingApplication ` + -RequiredBeforeMeetingJoin $RequiredBeforeMeetingJoin ` + -RequiredBeforeCallEstablishment $RequiredBeforeCallEstablishment ` + -RequiredDuringMeeting $RequiredDuringMeeting ` + -RequiredDuringCall $RequiredDuringCall ` + -ConcurrentInvitationCount $ConcurrentInvitationCount ` + -Parent $Identity -Id $Instance + } + else{ + Set-CsTeamsComplianceRecordingApplication ` + -Identity $CsTeamsComplianceRecordingApplicationIdentity ` + -RequiredBeforeMeetingJoin $RequiredBeforeMeetingJoin ` + -RequiredBeforeCallEstablishment $RequiredBeforeCallEstablishment ` + -RequiredDuringMeeting $RequiredDuringMeeting ` + -RequiredDuringCall $RequiredDuringCall ` + -ConcurrentInvitationCount $ConcurrentInvitationCount + } + + if($CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications.Count -gt 0){ + Set-CsTeamsComplianceRecordingApplication ` + -Identity "$Identity + '/' + $Instance" ` + -ComplianceRecordingPairedApplications @(New-CsTeamsComplianceRecordingPairedApplication ` + -Id $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications) + } + } + $NewCsTeamsComplianceRecordingApplication = Get-CsTeamsComplianceRecordingApplication | Where-Object{$_.Identity -match $Identity} + Set-CsTeamsComplianceRecordingPolicy -Identity $Identity -ComplianceRecordingApplications $NewCsTeamsComplianceRecordingApplication + } + } elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { @@ -235,6 +282,46 @@ function Set-TargetResource } Set-CsTeamsComplianceRecordingPolicy @UpdateParameters | Out-Null + if($ComplianceRecordingApplications.Count -gt 0){ + foreach($CurrentComplianceRecordingApplications in $ComplianceRecordingApplications){ + $Instance = $CurrentComplianceRecordingApplications.Id + $RequiredBeforeMeetingJoin = $CurrentComplianceRecordingApplications.RequiredBeforeMeetingJoin + $RequiredBeforeCallEstablishment = $CurrentComplianceRecordingApplications.RequiredBeforeCallEstablishment + $RequiredDuringMeeting = $CurrentComplianceRecordingApplications.RequiredDuringMeeting + $RequiredDuringCall = $CurrentComplianceRecordingApplications.RequiredDuringCall + $ConcurrentInvitationCount = $CurrentComplianceRecordingApplications.ConcurrentInvitationCount + + $CsTeamsComplianceRecordingApplicationIdentity = $Identity + '/' + $Instance + + $CsTeamsComplianceRecordingApplication = Get-CsTeamsComplianceRecordingApplication -Identity $CsTeamsComplianceRecordingApplicationIdentity -ErrorAction SilentlyContinue + if($null -eq $CsTeamsComplianceRecordingApplication){ + New-CsTeamsComplianceRecordingApplication ` + -RequiredBeforeMeetingJoin $RequiredBeforeMeetingJoin ` + -RequiredBeforeCallEstablishment $RequiredBeforeCallEstablishment ` + -RequiredDuringMeeting $RequiredDuringMeeting ` + -RequiredDuringCall $RequiredDuringCall ` + -ConcurrentInvitationCount $ConcurrentInvitationCount ` + -Parent $Identity -Id $Instance + } + else{ + Set-CsTeamsComplianceRecordingApplication ` + -Identity $CsTeamsComplianceRecordingApplicationIdentity ` + -RequiredBeforeMeetingJoin $RequiredBeforeMeetingJoin ` + -RequiredBeforeCallEstablishment $RequiredBeforeCallEstablishment ` + -RequiredDuringMeeting $RequiredDuringMeeting ` + -RequiredDuringCall $RequiredDuringCall ` + -ConcurrentInvitationCount $ConcurrentInvitationCount + } + + if($CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications.Count -gt 0){ + [string]$CsTeamsComplianceRecordingApplicationIdentity = $Identity + '/' + $Instance + [string]$ComplianceRecordingPairedApplications = $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications + Set-CsTeamsComplianceRecordingApplication -Identity $CsTeamsComplianceRecordingApplicationIdentity -ComplianceRecordingPairedApplications @(New-CsTeamsComplianceRecordingPairedApplication -Id $ComplianceRecordingPairedApplications) + } + } + $NewCsTeamsComplianceRecordingApplication = Get-CsTeamsComplianceRecordingApplication | Where-Object{$_.Identity -match $Identity} + Set-CsTeamsComplianceRecordingPolicy -Identity $Identity -ComplianceRecordingApplications $NewCsTeamsComplianceRecordingApplication + } } elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { @@ -254,7 +341,7 @@ function Test-TargetResource $Identity, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance] + [Microsoft.Management.Infrastructure.CimInstance[]] $ComplianceRecordingApplications, [Parameter()] @@ -318,6 +405,30 @@ function Test-TargetResource Write-Verbose -Message "Test-TargetResource returned $false" return $false } + $testResult = $true + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($source.getType().Name -like '*CimInstance*') + { + $source = Get-M365DSCDRGComplexTypeToHashtable -ComplexObject $source + + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-Not $testResult) + { + $testResult = $false + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" @@ -332,10 +443,13 @@ function Test-TargetResource } } - $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` - -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` - -ValuesToCheck $ValuesToCheck.Keys + if ($testResult) + { + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } Write-Verbose -Message "Test-TargetResource returned $testResult" @@ -435,7 +549,7 @@ function Export-TargetResource ) $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` -ComplexObject $Results.ComplianceRecordingApplications ` - -CIMInstanceName 'TeamsComplianceRecordingApplicationn' ` + -CIMInstanceName 'TeamsComplianceRecordingApplication' ` -ComplexTypeMapping $complexMapping if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof index b14ba1eb62..89c9dab78f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof @@ -1,14 +1,14 @@ -[ClassVersion("1.0.0"), FriendlyName("TeamsComplianceRecordingApplication)] +[ClassVersion("1.0.0")] class MSFT_TeamsComplianceRecordingApplication { - [Write, Description("")] String Id; - [Write, Description("")] String[] ComplianceRecordingPairedApplications; - [Write, Description("")] Boolean RequiredBeforeMeetingJoin; - [Write, Description("")] Boolean RequiredBeforeCallEstablishment; - [Write, Description("")] Boolean RequiredDuringMeeting; - [Write, Description("")] Boolean RequiredDuringCall; - [Write, Description("")] String ConcurrentInvitationCount; -} + [Write, Description("A name that uniquely identifies the application instance of the policy-based recording application.")] String Id; + [Write, Description("Determines the other policy-based recording applications to pair with this application to achieve application resiliency. Can only have one paired application.")] String ComplianceRecordingPairedApplications[]; + [Write, Description("Indicates whether the policy-based recording application must be in the meeting before the user is allowed to join the meeting.")] Boolean RequiredBeforeMeetingJoin; + [Write, Description("Indicates whether the policy-based recording application must be in the call before the call is allowed to establish.")] Boolean RequiredBeforeCallEstablishment; + [Write, Description("Indicates whether the policy-based recording application must be in the meeting while the user is in the meeting.")] Boolean RequiredDuringMeeting; + [Write, Description("Indicates whether the policy-based recording application must be in the call while the call is active.")] Boolean RequiredDuringCall; + [Write, Description("Determines the number of invites to send out to the application instance of the policy-based recording application. Can be set to 1 or 2 only.")] String ConcurrentInvitationCount; +}; [ClassVersion("1.0.0.0"), FriendlyName("TeamsComplianceRecordingPolicy")] class MSFT_TeamsComplianceRecordingPolicy : OMI_BaseResource From 0d08b7d8481807adb839909a0f9c563dcb2fe437 Mon Sep 17 00:00:00 2001 From: Sandro Lanfranchi Date: Wed, 4 Oct 2023 19:39:08 +0200 Subject: [PATCH 004/465] Add Tests --- .../MSFT_TeamsComplianceRecordingPolicy.psm1 | 1 + .../Microsoft365DSC.TeamsComplianceRecordingPolicy.Tests.ps1 | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 index cfe3cbc9b8..0e322f505f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 @@ -214,6 +214,7 @@ function Set-TargetResource { if ($null -ne $CreateParameters.$key -and $CreateParameters.$key.GetType().Name -like '*cimInstance*') { + $keyName = $key.substring(0, 1).ToLower() + $key.substring(1, $key.length - 1) $keyValue = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $CreateParameters.$key $CreateParameters.Remove($key) | Out-Null $CreateParameters.Add($keyName, $keyValue) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.TeamsComplianceRecordingPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.TeamsComplianceRecordingPolicy.Tests.ps1 index 5883bcdf14..9941104d95 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.TeamsComplianceRecordingPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.TeamsComplianceRecordingPolicy.Tests.ps1 @@ -63,7 +63,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Description = 'FakeStringValue' Enabled = $True DisableComplianceRecordingAudioNotificationForCalls = $True - ComplianceRecordingApplications = 'FakeStringValue' Identity = 'FakeStringValue' Ensure = 'Present' Credential = $Credential @@ -166,7 +165,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Description = 'FakeStringValue' Enabled = $True DisableComplianceRecordingAudioNotificationForCalls = $True - ComplianceRecordingApplications = 'FakeStringValue' Identity = 'FakeStringValue' Ensure = 'Present' Credential = $Credential From 5556bfe77933b6f909e90a8c5e4a7222c6cb083a Mon Sep 17 00:00:00 2001 From: Sandro Lanfranchi Date: Wed, 4 Oct 2023 19:42:58 +0200 Subject: [PATCH 005/465] Add Example --- ...TeamsComplianceRecordingPolicy-Example.ps1 | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/TeamsComplianceRecordingPolicy/1-TeamsComplianceRecordingPolicy-Example.ps1 b/Modules/Microsoft365DSC/Examples/Resources/TeamsComplianceRecordingPolicy/1-TeamsComplianceRecordingPolicy-Example.ps1 index 0e67e0222e..cb7abd3b03 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/TeamsComplianceRecordingPolicy/1-TeamsComplianceRecordingPolicy-Example.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/TeamsComplianceRecordingPolicy/1-TeamsComplianceRecordingPolicy-Example.ps1 @@ -14,15 +14,34 @@ Configuration Example node localhost { - TeamsComplianceRecordingPolicy 'Example' + TeamsComplianceRecordingPolicy "TeamsComplianceRecordingPolicy-Tag:MyTeamsComplianceRecordingPolicy" { - ComplianceRecordingApplications = @(); - Credential = $Credscredential; + Credential = $credsCredential; + ComplianceRecordingApplications = @( + MSFT_TeamsComplianceRecordingApplication{ + Id = '00000000-0000-0000-0000-000000000000' + ComplianceRecordingPairedApplications = @('00000000-0000-0000-0000-000000000000') + ConcurrentInvitationCount = 1 + RequiredDuringCall = $True + RequiredBeforeMeetingJoin = $True + RequiredBeforeCallEstablishment = $True + RequiredDuringMeeting = $True + } + MSFT_TeamsComplianceRecordingApplication{ + Id = '12345678-0000-0000-0000-000000000000' + ComplianceRecordingPairedApplications = @('87654321-0000-0000-0000-000000000000') + ConcurrentInvitationCount = 1 + RequiredDuringCall = $True + RequiredBeforeMeetingJoin = $True + RequiredBeforeCallEstablishment = $True + RequiredDuringMeeting = $True + } + ); + Description = "MyTeamsComplianceRecordingPolicy"; DisableComplianceRecordingAudioNotificationForCalls = $False; - Enabled = $False; + Enabled = $True; Ensure = "Present"; - Identity = "Global"; + Identity = "Tag:MyTeamsComplianceRecordingPolicy"; WarnUserOnRemoval = $True; } - } } From 4aedebbb2dbb149f74873ddfc46edb0f3cba2ac5 Mon Sep 17 00:00:00 2001 From: Sandro Lanfranchi Date: Wed, 4 Oct 2023 19:47:02 +0200 Subject: [PATCH 006/465] Add Entry in ChangeLog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b3a79deed..f2d69fdabf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* TeamsComplianceREcordingPolicy + * FIXES [[#3712](https://github.com/microsoft/Microsoft365DSC/issues/3712)] + # 1.23.1004.1 * AADEntitlementManagementAccessPackageAssignmentPolicy From 5f6a23df3e4344031dc03beb4a6c448ef4f46a36 Mon Sep 17 00:00:00 2001 From: Sandro Lanfranchi Date: Wed, 11 Oct 2023 15:10:24 +0200 Subject: [PATCH 007/465] Fix example file --- .../1-TeamsComplianceRecordingPolicy-Example.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/Microsoft365DSC/Examples/Resources/TeamsComplianceRecordingPolicy/1-TeamsComplianceRecordingPolicy-Example.ps1 b/Modules/Microsoft365DSC/Examples/Resources/TeamsComplianceRecordingPolicy/1-TeamsComplianceRecordingPolicy-Example.ps1 index cb7abd3b03..70e5823572 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/TeamsComplianceRecordingPolicy/1-TeamsComplianceRecordingPolicy-Example.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/TeamsComplianceRecordingPolicy/1-TeamsComplianceRecordingPolicy-Example.ps1 @@ -44,4 +44,5 @@ Configuration Example Identity = "Tag:MyTeamsComplianceRecordingPolicy"; WarnUserOnRemoval = $True; } + } } From 8e59d4e34612fdcb57ac875e40c93068b1babffd Mon Sep 17 00:00:00 2001 From: Sandro Lanfranchi Date: Fri, 17 Nov 2023 08:40:21 +0100 Subject: [PATCH 008/465] Correct formatting --- CHANGELOG.md | 4 +- .../MSFT_TeamsComplianceRecordingPolicy.psm1 | 55 ++++++++++++------- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dff0c353f9..164cc2115c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,6 @@ # UNRELEASED -* TeamsComplianceREcordingPolicy - * FIXES [[#3712](https://github.com/microsoft/Microsoft365DSC/issues/3712)] * AADRoleEligibilityScheduleRequest * Added support for groups assignment. FIXES [#3744](https://github.com/microsoft/Microsoft365DSC/issues/3744) @@ -16,6 +14,8 @@ * MISC * M365DSCReport: Also define property dataType, if present, as being primary key on CIM instances. +* TeamsComplianceREcordingPolicy + * FIXES [[#3712](https://github.com/microsoft/Microsoft365DSC/issues/3712)] * TeamsUpgradeConfiguration * Fixes an issue where the SfBMeetingJoinUx property wasn't properly updated. * DEPENDENCIES diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 index 0e322f505f..808cf733cf 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 @@ -75,13 +75,17 @@ function Get-TargetResource return $nullResult } - if($instance.ComplianceRecordingApplications.Count -gt 0){ + if ($instance.ComplianceRecordingApplications.Count -gt 0) + { $ComplexComplianceRecordingApplications = @() - foreach($CurrentComplianceRecordingApplications in $instance.ComplianceRecordingApplications){ + foreach ($CurrentComplianceRecordingApplications in $instance.ComplianceRecordingApplications) + { $MyComplianceRecordingApplications = @{} $ComplianceRecordingPairedApplications = @() - if($CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications.Count -gt 0){ - foreach($CurrentComplianceRecordingPairedApplications in $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications){ + if ($CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications.Count -gt 0) + { + foreach ($CurrentComplianceRecordingPairedApplications in $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications) + { $ComplianceRecordingPairedApplications += $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications.Id } } @@ -93,7 +97,8 @@ function Get-TargetResource $MyComplianceRecordingApplications.Add('RequiredDuringCall', $CurrentComplianceRecordingApplications.RequiredDuringCall) $MyComplianceRecordingApplications.Add('ConcurrentInvitationCount', $CurrentComplianceRecordingApplications.ConcurrentInvitationCount) - if ($MyComplianceRecordingApplications.values.Where({$null -ne $_}).count -gt 0){ + if ($MyComplianceRecordingApplications.values.Where({ $null -ne $_ }).count -gt 0) + { $ComplexComplianceRecordingApplications += $MyComplianceRecordingApplications } } @@ -223,8 +228,10 @@ function Set-TargetResource Write-Verbose -Message "Creating {$Identity} with Parameters:`r`n$(Convert-M365DscHashtableToString -Hashtable $CreateParameters)" New-CsTeamsComplianceRecordingPolicy @CreateParameters | Out-Null - if($ComplianceRecordingApplications.Count -gt 0){ - foreach($CurrentComplianceRecordingApplications in $ComplianceRecordingApplications){ + if ($ComplianceRecordingApplications.Count -gt 0) + { + foreach ($CurrentComplianceRecordingApplications in $ComplianceRecordingApplications) + { $Instance = $CurrentComplianceRecordingApplications.Id $RequiredBeforeMeetingJoin = $CurrentComplianceRecordingApplications.RequiredBeforeMeetingJoin $RequiredBeforeCallEstablishment = $CurrentComplianceRecordingApplications.RequiredBeforeCallEstablishment @@ -233,7 +240,8 @@ function Set-TargetResource $ConcurrentInvitationCount = $CurrentComplianceRecordingApplications.ConcurrentInvitationCount $CsTeamsComplianceRecordingApplication = Get-CsTeamsComplianceRecordingApplication -Identity $CsTeamsComplianceRecordingApplicationIdentity -ErrorAction SilentlyContinue - if($null -eq $CsTeamsComplianceRecordingApplication){ + if ($null -eq $CsTeamsComplianceRecordingApplication) + { New-CsTeamsComplianceRecordingApplication ` -RequiredBeforeMeetingJoin $RequiredBeforeMeetingJoin ` -RequiredBeforeCallEstablishment $RequiredBeforeCallEstablishment ` @@ -242,9 +250,10 @@ function Set-TargetResource -ConcurrentInvitationCount $ConcurrentInvitationCount ` -Parent $Identity -Id $Instance } - else{ + else + { Set-CsTeamsComplianceRecordingApplication ` - -Identity $CsTeamsComplianceRecordingApplicationIdentity ` + -Identity $CsTeamsComplianceRecordingApplicationIdentity ` -RequiredBeforeMeetingJoin $RequiredBeforeMeetingJoin ` -RequiredBeforeCallEstablishment $RequiredBeforeCallEstablishment ` -RequiredDuringMeeting $RequiredDuringMeeting ` @@ -252,14 +261,15 @@ function Set-TargetResource -ConcurrentInvitationCount $ConcurrentInvitationCount } - if($CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications.Count -gt 0){ + if ($CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications.Count -gt 0) + { Set-CsTeamsComplianceRecordingApplication ` -Identity "$Identity + '/' + $Instance" ` -ComplianceRecordingPairedApplications @(New-CsTeamsComplianceRecordingPairedApplication ` - -Id $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications) + -Id $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications) } } - $NewCsTeamsComplianceRecordingApplication = Get-CsTeamsComplianceRecordingApplication | Where-Object{$_.Identity -match $Identity} + $NewCsTeamsComplianceRecordingApplication = Get-CsTeamsComplianceRecordingApplication | Where-Object { $_.Identity -match $Identity } Set-CsTeamsComplianceRecordingPolicy -Identity $Identity -ComplianceRecordingApplications $NewCsTeamsComplianceRecordingApplication } @@ -283,8 +293,10 @@ function Set-TargetResource } Set-CsTeamsComplianceRecordingPolicy @UpdateParameters | Out-Null - if($ComplianceRecordingApplications.Count -gt 0){ - foreach($CurrentComplianceRecordingApplications in $ComplianceRecordingApplications){ + if ($ComplianceRecordingApplications.Count -gt 0) + { + foreach ($CurrentComplianceRecordingApplications in $ComplianceRecordingApplications) + { $Instance = $CurrentComplianceRecordingApplications.Id $RequiredBeforeMeetingJoin = $CurrentComplianceRecordingApplications.RequiredBeforeMeetingJoin $RequiredBeforeCallEstablishment = $CurrentComplianceRecordingApplications.RequiredBeforeCallEstablishment @@ -295,7 +307,8 @@ function Set-TargetResource $CsTeamsComplianceRecordingApplicationIdentity = $Identity + '/' + $Instance $CsTeamsComplianceRecordingApplication = Get-CsTeamsComplianceRecordingApplication -Identity $CsTeamsComplianceRecordingApplicationIdentity -ErrorAction SilentlyContinue - if($null -eq $CsTeamsComplianceRecordingApplication){ + if ($null -eq $CsTeamsComplianceRecordingApplication) + { New-CsTeamsComplianceRecordingApplication ` -RequiredBeforeMeetingJoin $RequiredBeforeMeetingJoin ` -RequiredBeforeCallEstablishment $RequiredBeforeCallEstablishment ` @@ -304,9 +317,10 @@ function Set-TargetResource -ConcurrentInvitationCount $ConcurrentInvitationCount ` -Parent $Identity -Id $Instance } - else{ + else + { Set-CsTeamsComplianceRecordingApplication ` - -Identity $CsTeamsComplianceRecordingApplicationIdentity ` + -Identity $CsTeamsComplianceRecordingApplicationIdentity ` -RequiredBeforeMeetingJoin $RequiredBeforeMeetingJoin ` -RequiredBeforeCallEstablishment $RequiredBeforeCallEstablishment ` -RequiredDuringMeeting $RequiredDuringMeeting ` @@ -314,13 +328,14 @@ function Set-TargetResource -ConcurrentInvitationCount $ConcurrentInvitationCount } - if($CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications.Count -gt 0){ + if ($CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications.Count -gt 0) + { [string]$CsTeamsComplianceRecordingApplicationIdentity = $Identity + '/' + $Instance [string]$ComplianceRecordingPairedApplications = $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications Set-CsTeamsComplianceRecordingApplication -Identity $CsTeamsComplianceRecordingApplicationIdentity -ComplianceRecordingPairedApplications @(New-CsTeamsComplianceRecordingPairedApplication -Id $ComplianceRecordingPairedApplications) } } - $NewCsTeamsComplianceRecordingApplication = Get-CsTeamsComplianceRecordingApplication | Where-Object{$_.Identity -match $Identity} + $NewCsTeamsComplianceRecordingApplication = Get-CsTeamsComplianceRecordingApplication | Where-Object { $_.Identity -match $Identity } Set-CsTeamsComplianceRecordingPolicy -Identity $Identity -ComplianceRecordingApplications $NewCsTeamsComplianceRecordingApplication } } From 24a5053af4b9eff69a5dc17b252387e671f7433d Mon Sep 17 00:00:00 2001 From: Sandro Lanfranchi Date: Fri, 17 Nov 2023 10:28:15 +0100 Subject: [PATCH 009/465] minor typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 164cc2115c..e9aa2b2df5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ * MISC * M365DSCReport: Also define property dataType, if present, as being primary key on CIM instances. -* TeamsComplianceREcordingPolicy +* TeamsComplianceRecordingPolicy * FIXES [[#3712](https://github.com/microsoft/Microsoft365DSC/issues/3712)] * TeamsUpgradeConfiguration * Fixes an issue where the SfBMeetingJoinUx property wasn't properly updated. From 5f4763b76e55dced3df8c675b2c2635a7ca9e6f9 Mon Sep 17 00:00:00 2001 From: Sandro Lanfranchi Date: Mon, 18 Mar 2024 18:31:41 +0100 Subject: [PATCH 010/465] Update tests --- ...C.TeamsComplianceRecordingPolicy.Tests.ps1 | 94 ++++++++++++++----- 1 file changed, 68 insertions(+), 26 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.TeamsComplianceRecordingPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.TeamsComplianceRecordingPolicy.Tests.ps1 index 2d3616280d..280e09f7ef 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.TeamsComplianceRecordingPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.TeamsComplianceRecordingPolicy.Tests.ps1 @@ -94,7 +94,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Description = 'FakeStringValue' Enabled = $True DisableComplianceRecordingAudioNotificationForCalls = $True - ComplianceRecordingApplications = @('123456') Identity = 'FakeStringValue' Ensure = 'Absent' Credential = $Credential @@ -106,14 +105,29 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Description = 'FakeStringValue' Enabled = $True DisableComplianceRecordingAudioNotificationForCalls = $True - ComplianceRecordingApplications = "Microsoft.Teams.Policy.Aministration.Cmdlets.Core.CompianceRecordingApplication" + ComplianceRecordingApplications = @( + @{ + Id = '00000000-0000-0000-0000-000000000000' + ComplianceRecordingPairedApplications = @() + ConcurrentInvitationCount = 1 + RequiredDuringCall = $True + RequiredBeforeMeetingJoin = $True + RequiredBeforeCallEstablishment = $True + RequiredDuringMeeting = $True + } + ) Identity = 'FakeStringValue' } } Mock -CommandName Get-CsTeamsComplianceRecordingApplication -MockWith { return @{ - Identity = 'FakeStringValue/123456' - Id = '123456' + Id = '00000000-0000-0000-0000-000000000000' + ComplianceRecordingPairedApplications = @() + ConcurrentInvitationCount = 1 + RequiredDuringCall = $True + RequiredBeforeMeetingJoin = $True + RequiredBeforeCallEstablishment = $True + RequiredDuringMeeting = $True } } @@ -123,9 +137,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $Result = (Get-TargetResource @testParams) $Result.Ensure | Should -Be 'Present' $Result.ComplianceRecordingApplications.Length | Should -Be 1 - $Result.ComplianceRecordingApplications[0] | Should -Be '123456' Should -Invoke -CommandName Get-CsTeamsComplianceRecordingPolicy -Exactly 1 - Should -Invoke -CommandName Get-CsTeamsComplianceRecordingApplication -ParameterFilter {$Filter -eq 'FakeStringValue/*'} -Exactly 1 } @@ -146,7 +158,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Description = 'FakeStringValue' Enabled = $True DisableComplianceRecordingAudioNotificationForCalls = $True - ComplianceRecordingApplications = @('123456') Identity = 'FakeStringValue' Ensure = 'Present' Credential = $Credential @@ -158,15 +169,29 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Description = 'FakeStringValue' Enabled = $True DisableComplianceRecordingAudioNotificationForCalls = $True - ComplianceRecordingApplications = "Microsoft.Teams.Policy.Aministration.Cmdlets.Core.CompianceRecordingApplication" + ComplianceRecordingApplications = @( + @{ + Id = '00000000-0000-0000-0000-000000000000' + ComplianceRecordingPairedApplications = @() + ConcurrentInvitationCount = 1 + RequiredDuringCall = $True + RequiredBeforeMeetingJoin = $True + RequiredBeforeCallEstablishment = $True + RequiredDuringMeeting = $True + } + ) Identity = 'FakeStringValue' - } } Mock -CommandName Get-CsTeamsComplianceRecordingApplication -MockWith { return @{ - Identity = 'FakeStringValue/123456' - Id = '123456' + Id = '00000000-0000-0000-0000-000000000000' + ComplianceRecordingPairedApplications = @() + ConcurrentInvitationCount = 1 + RequiredDuringCall = $True + RequiredBeforeMeetingJoin = $True + RequiredBeforeCallEstablishment = $True + RequiredDuringMeeting = $True } } } @@ -191,18 +216,33 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-CsTeamsComplianceRecordingPolicy -MockWith { return @{ WarnUserOnRemoval = $False - Description = 'FakeStringValueDrift' #Drift - Enabled = $False - DisableComplianceRecordingAudioNotificationForCalls = $False - ComplianceRecordingApplications = "Microsoft.Teams.Policy.Aministration.Cmdlets.Core.CompianceRecordingApplication" + Description = 'FakeStringValue' + Enabled = $True + DisableComplianceRecordingAudioNotificationForCalls = $True + ComplianceRecordingApplications = @( + @{ + Id = '00000000-0000-0000-0000-000000000000' + ComplianceRecordingPairedApplications = @() + ConcurrentInvitationCount = 1 + RequiredDuringCall = $True + RequiredBeforeMeetingJoin = $True + RequiredBeforeCallEstablishment = $True + RequiredDuringMeeting = $True + } + ) Identity = 'FakeStringValue' } } Mock -CommandName Get-CsTeamsComplianceRecordingApplication -MockWith { return @{ - Identity = 'FakeStringValue/123456Drift' - Id = '123456Drift' #Drift + Id = '00000000-0000-0000-0000-000000000000' + ComplianceRecordingPairedApplications = @() + ConcurrentInvitationCount = 1 + RequiredDuringCall = $True + RequiredBeforeMeetingJoin = $True + RequiredBeforeCallEstablishment = $True + RequiredDuringMeeting = $True } } } @@ -235,18 +275,20 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Description = 'FakeStringValue' Enabled = $True DisableComplianceRecordingAudioNotificationForCalls = $True - ComplianceRecordingApplications = "Microsoft.Teams.Policy.Aministration.Cmdlets.Core.CompianceRecordingApplication" + ComplianceRecordingApplications = @( + @{ + Id = '00000000-0000-0000-0000-000000000000' + ComplianceRecordingPairedApplications = @() + ConcurrentInvitationCount = 1 + RequiredDuringCall = $True + RequiredBeforeMeetingJoin = $True + RequiredBeforeCallEstablishment = $True + RequiredDuringMeeting = $True + } + ) Identity = 'FakeStringValue' - } } - Mock -CommandName Get-CsTeamsComplianceRecordingApplication -MockWith { - return @{ - Identity = 'FakeStringValue/123456' - Id = '123456' - } - } - } It 'Should Reverse Engineer resource from the Export method' { From 6858190f30b7c4a1f1abd01e3579f20ed670aea8 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Mon, 20 May 2024 14:16:55 +0100 Subject: [PATCH 011/465] Change var type --- CHANGELOG.md | 5 +++++ .../MSFT_EXOAntiPhishPolicy.psm1 | 20 +++++++++---------- .../MSFT_EXOAntiPhishPolicy.schema.mof | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 537c3a5134..16e03191c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* EXOAntiPhishPolicy + * Use correct type integer for variable PhishThresholdLevel + # 1.24.515.2 * EXOManagementRoleEntry diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.psm1 index e90d7c6a79..f74ec65cec 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.psm1 @@ -113,9 +113,9 @@ function Get-TargetResource $MakeDefault = $false, [Parameter()] - [ValidateSet('1', '2', '3', '4')] - [System.String] - $PhishThresholdLevel = '1', + [ValidateSet(1, 2, 3, 4)] + [System.Int32] + $PhishThresholdLevel = 1, [Parameter()] [System.String[]] @@ -227,7 +227,7 @@ function Get-TargetResource $PhishThresholdLevelValue = $AntiPhishPolicy.PhishThresholdLevel if ([System.String]::IsNullOrEmpty($PhishThresholdLevelValue)) { - $PhishThresholdLevelValue = '1' + $PhishThresholdLevelValue = 1 } $TargetedUserProtectionActionValue = $AntiPhishPolicy.TargetedUserProtectionAction @@ -419,9 +419,9 @@ function Set-TargetResource $MakeDefault = $false, [Parameter()] - [ValidateSet('1', '2', '3', '4')] - [System.String] - $PhishThresholdLevel = '1', + [ValidateSet(1, 2, 3, 4)] + [System.Int32] + $PhishThresholdLevel = 1, [Parameter()] [System.String[]] @@ -656,9 +656,9 @@ function Test-TargetResource $MakeDefault = $false, [Parameter()] - [ValidateSet('1', '2', '3', '4')] - [System.String] - $PhishThresholdLevel = '1', + [ValidateSet(1, 2, 3, 4)] + [System.Int32] + $PhishThresholdLevel = 1, [Parameter()] [System.String[]] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.schema.mof index 42d4410650..262f724888 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.schema.mof @@ -4,7 +4,7 @@ class MSFT_EXOAntiPhishPolicy : OMI_BaseResource [Key, Description("The Identity parameter specifies the name of the antiphishing policy that you want to modify.")] String Identity; [Write, Description("Specify if this policy should exist or not."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; [Write, Description("The AdminDisplayName parameter specifies a description for the policy.")] String AdminDisplayName; - [Write, Description("The PhishThresholdLevel parameter specifies the tolerance level that's used by machine learning in the handling of phishing messages."), ValueMap{"1","2","3","4"}, Values{"1","2","3","4"}] String PhishThresholdLevel; + [Write, Description("The PhishThresholdLevel parameter specifies the tolerance level that's used by machine learning in the handling of phishing messages."), ValueMap{"1","2","3","4"}, Values{"1","2","3","4"}] UInt32 PhishThresholdLevel; [Write, Description("The AuthenticationFailAction parameter specifies the action to take when the message fails composite authentication."), ValueMap{"MoveToJmf","Quarantine"}, Values{"MoveToJmf","Quarantine"}] String AuthenticationFailAction; [Write, Description("The TargetedUserProtectionAction parameter specifies the action to take on detected user impersonation messages for the users specified by the TargetedUsersToProtect parameter."), ValueMap{"BccMessage","Delete","MoveToJmf","NoAction","Quarantine","Redirect"}, Values{"BccMessage","Delete","MoveToJmf","NoAction","Quarantine","Redirect"}] String TargetedUserProtectionAction; [Write, Description("Specify if this policy should be enabled. Default is $true.")] Boolean Enabled; From 62ac24d16bec53bbb5546f959819198ee81f202c Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Mon, 1 Jul 2024 19:04:53 +0100 Subject: [PATCH 012/465] Recreate policy instead of changing it --- CHANGELOG.md | 9 ++++++++- .../MSFT_EXOAuthenticationPolicy.psm1 | 4 +++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7bc8ff791..8ad9ac561d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* EXOAuthenticationPolicy + * If policy needs changes then recreate it to avoid issue with + `Set-AuthenticationPolicy` cmdlet + FIXES [#4819](https://github.com/microsoft/Microsoft365DSC/issues/4819) + # 1.24.626.1 * AADGroup @@ -19,7 +26,7 @@ * M365DSCUtil * Fixes an issue where the comparison with null-valued desired value throws an error. * DEPENDENCIES - * Updated MSCloudLoginAssistant to version 1.1.18 + * Updated MSCloudLoginAssistant to version 1.1.18 * M365DSCResourceGenerator * Update CimInstance comparison template * MISC diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAuthenticationPolicy/MSFT_EXOAuthenticationPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAuthenticationPolicy/MSFT_EXOAuthenticationPolicy.psm1 index 741cc99558..4d0cf695a3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAuthenticationPolicy/MSFT_EXOAuthenticationPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAuthenticationPolicy/MSFT_EXOAuthenticationPolicy.psm1 @@ -329,10 +329,12 @@ function Set-TargetResource Remove-AuthenticationPolicy -Identity $Identity -Confirm:$false } # CASE: Authentication Policy exists and it should, but has different values than the desired one + # Policy cannot be changed so it must be deleted and re-created again elseif ($Ensure -eq 'Present' -and $currentAuthenticationPolicyConfig.Ensure -eq 'Present') { Write-Verbose -Message "Authentication Policy '$($Identity)' exists. Updating settings." - Set-AuthenticationPolicy -Identity $Identity @NewAuthenticationPolicyParams | Out-Null + Remove-AuthenticationPolicy -Identity $Identity -Confirm:$false + New-AuthenticationPolicy -Name $Identity @NewAuthenticationPolicyParams | Out-Null } } From 8a6b4d8696e6299bba64ed9dd09943f3e87fde27 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Mon, 1 Jul 2024 19:54:29 +0100 Subject: [PATCH 013/465] Fix unit tests --- .../Microsoft365DSC.EXOAuthenticationPolicy.Tests.ps1 | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAuthenticationPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAuthenticationPolicy.Tests.ps1 index e15730e8d0..e0015545ef 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAuthenticationPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAuthenticationPolicy.Tests.ps1 @@ -41,9 +41,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName New-AuthenticationPolicy { } - Mock -CommandName Set-AuthenticationPolicy { - } - Mock -CommandName Remove-AuthenticationPolicy { } @@ -195,7 +192,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the Set method' { Set-TargetResource @testParams - Should -Invoke -CommandName Set-AuthenticationPolicy -Exactly 1 + Should -Invoke -CommandName Remove-AuthenticationPolicy -Exactly 1 + Should -Invoke -CommandName New-AuthenticationPolicy -Exactly 1 } } From e66dc1d1fb24fa3d37f6c40969a1d0a1b940d816 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Mon, 1 Jul 2024 20:21:57 +0100 Subject: [PATCH 014/465] Remove property Ensure --- CHANGELOG.md | 7 ++++++- .../MSFT_EXOMailTips/MSFT_EXOMailTips.psm1 | 21 +------------------ .../MSFT_EXOMailTips.schema.mof | 1 - 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7bc8ff791..026d115c60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* EXOMailTips + * Remove property `Ensure` since this resource is of type `IsSingleInstance` + # 1.24.626.1 * AADGroup @@ -19,7 +24,7 @@ * M365DSCUtil * Fixes an issue where the comparison with null-valued desired value throws an error. * DEPENDENCIES - * Updated MSCloudLoginAssistant to version 1.1.18 + * Updated MSCloudLoginAssistant to version 1.1.18 * M365DSCResourceGenerator * Update CimInstance comparison template * MISC diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailTips/MSFT_EXOMailTips.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailTips/MSFT_EXOMailTips.psm1 index cff7f59a8e..5b87fb95ac 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailTips/MSFT_EXOMailTips.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailTips/MSFT_EXOMailTips.psm1 @@ -29,11 +29,6 @@ function Get-TargetResource [System.Boolean] $MailTipsExternalRecipientsTipsEnabled, - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -93,7 +88,6 @@ function Get-TargetResource #endregion $nullReturn = $PSBoundParameters - $nullReturn.Ensure = 'Absent' try { @@ -112,7 +106,6 @@ function Get-TargetResource MailTipsLargeAudienceThreshold = $OrgConfig.MailTipsLargeAudienceThreshold MailTipsMailboxSourcedTipsEnabled = $OrgConfig.MailTipsMailboxSourcedTipsEnabled MailTipsExternalRecipientsTipsEnabled = $OrgConfig.MailTipsExternalRecipientsTipsEnabled - Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId CertificateThumbprint = $CertificateThumbprint @@ -168,11 +161,6 @@ function Set-TargetResource [System.Boolean] $MailTipsExternalRecipientsTipsEnabled, - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -289,11 +277,6 @@ function Test-TargetResource [System.Boolean] $MailTipsExternalRecipientsTipsEnabled, - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -353,8 +336,7 @@ function Test-TargetResource 'MailTipsGroupMetricsEnabled', 'MailTipsLargeAudienceThreshold', 'MailTipsMailboxSourcedTipsEnabled', - 'MailTipsExternalRecipientsTipsEnabled', - 'Ensure') + 'MailTipsExternalRecipientsTipsEnabled') Write-Verbose -Message "Test-TargetResource returned $TestResult" @@ -462,4 +444,3 @@ function Export-TargetResource } Export-ModuleMember -Function *-TargetResource - diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailTips/MSFT_EXOMailTips.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailTips/MSFT_EXOMailTips.schema.mof index 964dbbfd54..424254b37a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailTips/MSFT_EXOMailTips.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailTips/MSFT_EXOMailTips.schema.mof @@ -8,7 +8,6 @@ class MSFT_EXOMailTips : OMI_BaseResource [Write, Description("Specifies what a large audience is.")] UInt32 MailTipsLargeAudienceThreshold; [Write, Description("Specifies whether MailTips that rely on mailbox data (out-of-office or full mailbox) are enabled.")] Boolean MailTipsMailboxSourcedTipsEnabled; [Write, Description("Specifies whether MailTips for external recipients are enabled.")] Boolean MailTipsExternalRecipientsTipsEnabled; - [Write, Description("Specifies if this MailTip should exist."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; [Write, Description("Credentials of the Exchange Global 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; From f28b76da7b40e415c0d32aa8231808cadefe0053 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Mon, 1 Jul 2024 22:27:27 +0100 Subject: [PATCH 015/465] Fix quality checks --- .../Resources/EXOMailTips/1-Create.ps1 | 30 ------------------- .../Resources/EXOMailTips/2-Update.ps1 | 5 ++-- .../Resources/EXOMailTips/3-Remove.ps1 | 25 ---------------- 3 files changed, 2 insertions(+), 58 deletions(-) delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/1-Create.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/3-Remove.ps1 diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/1-Create.ps1 deleted file mode 100644 index b58921fed5..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/1-Create.ps1 +++ /dev/null @@ -1,30 +0,0 @@ -<# -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 - - $Domain = $Credscredential.Username.Split('@')[1] - node localhost - { - EXOMailTips 'OrgWideMailTips' - { - IsSingleInstance = 'Yes' - MailTipsAllTipsEnabled = $True - MailTipsGroupMetricsEnabled = $True - MailTipsLargeAudienceThreshold = 100 - MailTipsMailboxSourcedTipsEnabled = $True - MailTipsExternalRecipientsTipsEnabled = $True - Ensure = "Present" - Credential = $Credscredential - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/2-Update.ps1 index 95cafdbc6c..67780db1b2 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/2-Update.ps1 @@ -19,11 +19,10 @@ Configuration Example { IsSingleInstance = 'Yes' MailTipsAllTipsEnabled = $True - MailTipsGroupMetricsEnabled = $False # Updated Property - MailTipsLargeAudienceThreshold = 100 + MailTipsGroupMetricsEnabled = $True + MailTipsLargeAudienceThreshold = 13 # Updated Property MailTipsMailboxSourcedTipsEnabled = $True MailTipsExternalRecipientsTipsEnabled = $True - Ensure = "Present" Credential = $Credscredential } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/3-Remove.ps1 deleted file mode 100644 index 3a010d19d9..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/3-Remove.ps1 +++ /dev/null @@ -1,25 +0,0 @@ -<# -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 - - $Domain = $Credscredential.Username.Split('@')[1] - node localhost - { - EXOMailTips 'OrgWideMailTips' - { - IsSingleInstance = 'Yes' - Ensure = "Absent" - Credential = $Credscredential - } - } -} From ea95342fc4527cd871cd466837b47099a5eb7933 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Mon, 1 Jul 2024 23:14:51 +0100 Subject: [PATCH 016/465] Fix unit tests --- .../Microsoft365DSC.EXOMailTips.Tests.ps1 | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailTips.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailTips.Tests.ps1 index b5fe8100f0..e110a243e3 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailTips.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailTips.Tests.ps1 @@ -44,7 +44,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $testParams = @{ IsSingleInstance = 'Yes' MailTipsAllTipsEnabled = $True - Ensure = 'Present' Credential = $Credential } @@ -77,7 +76,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $testParams = @{ IsSingleInstance = 'Yes' MailTipsGroupMetricsEnabled = $True - Ensure = 'Present' Credential = $Credential } @@ -110,7 +108,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $testParams = @{ IsSingleInstance = 'Yes' MailTipsLargeAudienceThreshold = 50 - Ensure = 'Present' Credential = $Credential } @@ -143,7 +140,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $testParams = @{ IsSingleInstance = 'Yes' MailTipsMailboxSourcedTipsEnabled = $True - Ensure = 'Present' Credential = $Credential } @@ -172,7 +168,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $testParams = @{ IsSingleInstance = 'Yes' MailTipsExternalRecipientsTipsEnabled = $True - Ensure = 'Present' Credential = $Credential } @@ -209,7 +204,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { MailTipsMailboxSourcedTipsEnabled = $True MailTipsGroupMetricsEnabled = $True MailTipsExternalRecipientsTipsEnabled = $True - Ensure = 'Present' Credential = $Credential } @@ -225,7 +219,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should return Present from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + (Get-TargetResource @testParams).IsSingleInstance | Should -Be 'Yes' } It 'Should return True from the Test method' { @@ -233,25 +227,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } - Context -Name 'Organization Configuration is null' -Fixture { - BeforeAll { - $testParams = @{ - IsSingleInstance = 'Yes' - MailTipsAllTipsEnabled = $True - Ensure = 'Present' - Credential = $Credential - } - - Mock -CommandName Get-OrganizationConfig -MockWith { - return $null - } - } - - It 'Should return Ensure is Absent from the Get method' { - (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' - } - } - Context -Name 'ReverseDSC Tests' -Fixture { BeforeAll { $Global:CurrentModeIsExport = $true From f42ac6ccc84d77d1c7cadc9cc294249fe8e5bb11 Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Fri, 16 Aug 2024 10:37:32 +0200 Subject: [PATCH 017/465] initial release --- .../MSFT_AADPasswordRuleSettings.psm1 | 483 ++++++++++++++++++ .../MSFT_AADPasswordRuleSettings.schema.mof | 19 + .../MSFT_AADPasswordRuleSettings/Readme.md | 5 + .../settings.json | 45 ++ ...ft365DSC.AADPasswordRuleSettings.Tests.ps1 | 457 +++++++++++++++++ 5 files changed, 1009 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/Readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/settings.json create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPasswordRuleSettings.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.psm1 new file mode 100644 index 0000000000..0e220677eb --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.psm1 @@ -0,0 +1,483 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + [ValidateSet('Yes')] + $IsSingleInstance, + + [Parameter()] + [System.UInt32] + $LockoutThreshold, + + [Parameter()] + [System.UInt32] + $LockoutDurationInSeconds, + + [Parameter()] + [System.Boolean] + $EnableBannedPasswordCheck, + + [Parameter()] + [System.String[]] + $BannedPasswordList, + + [Parameter()] + [System.Boolean] + $EnableBannedPasswordCheckOnPremises, + + [Parameter()] + [validateset('Enforced', 'Audit')] + [System.String] + $BannedPasswordCheckOnPremisesMode, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + Write-Verbose -Message 'Getting configuration of AzureAD Groups Settings' + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -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 + + $nullReturn = $PSBoundParameters + $nullReturn.Ensure = 'Absent' + try + { + $Policy = Get-MgBetaDirectorySetting -All | Where-Object -FilterScript { $_.DisplayName -eq 'Password Rule Settings' } + + if ($null -eq $Policy) + { + return $nullReturn + } + else + { + Write-Verbose -Message 'Found existing AzureAD DirectorySetting for Password Rule Settings' + $valueBannedPasswordCheckOnPremisesMode = $Policy.Values | Where-Object -FilterScript {$_.Name -eq 'BannedPasswordCheckOnPremisesMode'} + $valueEnableBannedPasswordCheckOnPremises = $Policy.Values | Where-Object -FilterScript {$_.Name -eq 'EnableBannedPasswordCheckOnPremises'} + $valueEnableBannedPasswordCheck = $Policy.Values | Where-Object -FilterScript {$_.Name -eq 'EnableBannedPasswordCheck'} + $valueLockoutDurationInSeconds = $Policy.Values | Where-Object -FilterScript {$_.Name -eq 'LockoutDurationInSeconds'} + $valueLockoutThreshold = $Policy.Values | Where-Object -FilterScript {$_.Name -eq 'LockoutThreshold'} + $valueBannedPasswordList = $Policy.Values | Where-Object -FilterScript {$_.Name -eq 'BannedPasswordList'} + + $result = @{ + IsSingleInstance = 'Yes' + BannedPasswordCheckOnPremisesMode = $valueBannedPasswordCheckOnPremisesMode.Value + EnableBannedPasswordCheckOnPremises = [Boolean]::Parse($valueEnableBannedPasswordCheckOnPremises.Value) + EnableBannedPasswordCheck = [Boolean]::Parse($valueEnableBannedPasswordCheck.Value) + LockoutDurationInSeconds = $valueLockoutDurationInSeconds.Value + LockoutThreshold = $valueLockoutThreshold.Value + BannedPasswordList = $valueBannedPasswordList.Value -split "`t" # list is tab-delimited + Ensure = 'Present' + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + Credential = $Credential + Managedidentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + Write-Verbose -Message "Get-TargetResource Result: `n $(Convert-M365DscHashtableToString -Hashtable $result)" + return $result + } + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullReturn + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + [ValidateSet('Yes')] + $IsSingleInstance, + + [Parameter()] + [System.UInt32] + $LockoutThreshold, + + [Parameter()] + [System.UInt32] + $LockoutDurationInSeconds, + + [Parameter()] + [System.Boolean] + $EnableBannedPasswordCheck, + + [Parameter()] + [System.String[]] + $BannedPasswordList, + + [Parameter()] + [System.Boolean] + $EnableBannedPasswordCheckOnPremises, + + [Parameter()] + [validateset('Enforced', 'Audit')] + [System.String] + $BannedPasswordCheckOnPremisesMode, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + Write-Verbose -Message 'Setting configuration of Azure AD Groups Settings' + + #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 + + $currentPolicy = Get-TargetResource @PSBoundParameters + + # Policy should exist but it doesn't + $needToUpdate = $false + if ($Ensure -eq 'Present' -and $currentPolicy.Ensure -eq 'Absent') + { + $template = Get-MgBetaDirectorySettingTemplate -All | Where-Object -FilterScript {$_.Displayname -eq 'Password Rule Settings'} + $Policy = New-MgBetaDirectorySetting -TemplateId $template.Id | Out-Null + $needToUpdate = $true + } + + $Policy = Get-MgBetaDirectorySetting -All | Where-Object -FilterScript { $_.DisplayName -eq 'Password Rule Settings' } + + if (($Ensure -eq 'Present' -and $currentPolicy.Ensure -eq 'Present') -or $needToUpdate) + { + $index = 0 + foreach ($property in $Policy.Values) + { + if ($property.Name -eq 'LockoutThreshold') + { + $entry = $Policy.Values | Where-Object -FilterScript {$_.Name -eq $property.Name} + $entry.Value = $LockoutThreshold + } + elseif ($property.Name -eq 'LockoutDurationInSeconds') + { + $entry = $Policy.Values | Where-Object -FilterScript {$_.Name -eq $property.Name} + $entry.Value = $LockoutDurationInSeconds + } + elseif ($property.Value -eq 'EnableBannedPasswordCheck') + { + $entry = $Policy.Values | Where-Object -FilterScript {$_.Name -eq $property.Name} + $entry.Value = [System.Boolean]$EnableBannedPasswordCheck + } + elseif ($property.Value -eq 'BannedPasswordList') + { + $entry = $Policy.Values | Where-Object -FilterScript {$_.Name -eq $property.Name} + $entry.Value = $BannedPasswordList -join "`t" + } + elseif ($property.Value -eq 'EnableBannedPasswordCheckOnPremises') + { + $entry = $Policy.Values | Where-Object -FilterScript {$_.Name -eq $property.Name} + $entry.Value = [System.Boolean]$EnableBannedPasswordCheckOnPremises + } + elseif ($property.Value -eq 'BannedPasswordCheckOnPremisesMode') + { + $entry = $Policy.Values | Where-Object -FilterScript {$_.Name -eq $property.Name} + $entry.Value = $BannedPasswordCheckOnPremisesMode + } + $index++ + } + + Write-Verbose -Message "Updating Policy's Values with $($Policy.Values | Out-String)" + Update-MgBetaDirectorySetting -DirectorySettingId $Policy.id -Values $Policy.Values | Out-Null + } + elseif ($Ensure -eq 'Absent' -and $currentPolicy.Ensure -eq 'Present') + { + Write-Verbose -Message "An existing Directory Setting entry exists, and we don't allow to have it removed." + throw 'The AADPasswordRuleSettings resource cannot delete existing Directory Setting entries. Please specify Present.' + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + [ValidateSet('Yes')] + $IsSingleInstance, + + [Parameter()] + [System.UInt32] + $LockoutThreshold, + + [Parameter()] + [System.UInt32] + $LockoutDurationInSeconds, + + [Parameter()] + [System.Boolean] + $EnableBannedPasswordCheck, + + [Parameter()] + [System.String[]] + $BannedPasswordList, + + [Parameter()] + [System.Boolean] + $EnableBannedPasswordCheckOnPremises, + + [Parameter()] + [validateset('Enforced', 'Audit')] + [System.String] + $BannedPasswordCheckOnPremisesMode, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + + #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 AzureAD Password Rule Settings' + + $CurrentValues = Get-TargetResource @PSBoundParameters + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + $ValuesToCheck = $PSBoundParameters + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -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 + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $Params = @{ + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + IsSingleInstance = 'Yes' + ApplicationSecret = $ApplicationSecret + Credential = $Credential + Managedidentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + $dscContent = '' + $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 + 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_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.schema.mof new file mode 100644 index 0000000000..7fd52a97e9 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.schema.mof @@ -0,0 +1,19 @@ +[ClassVersion("1.0.0.0"), FriendlyName("AADPasswordRuleSettings")] +class MSFT_AADPasswordRuleSettings : OMI_BaseResource +{ + [Key, Description("Only valid value is 'Yes'."), ValueMap{"Yes"}, Values{"Yes"}] String IsSingleInstance; + [Write, Description("The number of failed login attempts before the first lockout period begins.")] UInt32 LockoutThreshold; + [Write, Description("The duration in seconds of the initial lockout period.")] UInt32 LockoutDurationInSeconds; + [Write, Description("Boolean indicating if the banned password check for tenant specific banned password list is turned on or not.")] Boolean EnableBannedPasswordCheck; + [Write, Description("A list of banned words in passwords.")] String[] BannedPasswordList; + [Write, Description("How should we enforce password policy check in on-premises system.")] Boolean BannedPasswordCheckOnPremisesMode; + [Write, Description("Boolean indicating if the banned password check is turned on or not for on-premises system.")] Boolean EnableBannedPasswordCheckOnPremises; + [Write, Description("Specify if the Azure AD Password Rule Settings should exist or not."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Write, Description("Credentials for the Microsoft Graph delegated permissions."), 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("Secret of the Azure Active Directory application to authenticate with."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/Readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/Readme.md new file mode 100644 index 0000000000..94efd9bcd6 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/Readme.md @@ -0,0 +1,5 @@ +# AADPasswordRuleSettings + +## Description + +This resource configures the Azure Active Directory Password Rule Settings. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/settings.json new file mode 100644 index 0000000000..f2fcba1008 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/settings.json @@ -0,0 +1,45 @@ +{ + "resourceName": "AADGroupsSettings", + "description": "This resource configures the Azure Active Directory Password Rule Settings.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [ + { + "name": "Directory.Read.All" + }, + { + "name": "Group.Read.All" + } + ], + "update": [ + { + "name": "Directory.Read.All" + }, + { + "name": "Directory.ReadWrite.All" + } + ] + }, + "application": { + "read": [ + { + "name": "Directory.Read.All" + } + ], + "update": [ + { + "name": "Directory.Read.All" + }, + { + "name": "Directory.ReadWrite.All" + } + ] + } + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPasswordRuleSettings.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPasswordRuleSettings.Tests.ps1 new file mode 100644 index 0000000000..14f15f107b --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPasswordRuleSettings.Tests.ps1 @@ -0,0 +1,457 @@ +[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 'AADGroupsSettings' -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 Update-MgBetaDirectorySetting -MockWith { + } + + Mock -CommandName Remove-MgBetaDirectorySetting -MockWith { + } + + Mock -CommandName New-MgBetaDirectorySetting -MockWith { + } + Mock -CommandName Get-MgBetaDirectorySettingTemplate -MockWith { + return @{ + DisplayName = 'Password Rule Settings' + Id = '123456-1234-1234-1234-123456789012' + TemplateId = '5cf42378-d67d-4f36-ba46-e8b86229381d' + Values = @( + @{ + Name = 'BannedPasswordCheckOnPremisesMode' + DefaultValue = 'Audit' + }, + @{ + Name = 'EnableBannedPasswordCheckOnPremises' + DefaultValue = $true + }, + @{ + Name = 'EnableBannedPasswordCheck' + DefaultValue = $true + }, + @{ + Name = 'LockoutDurationInSeconds' + DefaultValue = 60 + }, + @{ + Name = 'LockoutThreshold' + DefaultValue = 10 + }, + @{ + Name = 'BannedPasswordList' + DefaultValue = $null + } + ) + } + } + + + # 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 Policy should exist but it DOES NOT' -Fixture { + BeforeAll { + $Script:calledOnceAlready = $false + $testParams = @{ + BannedPasswordCheckOnPremisesMode = 'Audit' + EnableBannedPasswordCheckOnPremises = $false + EnableBannedPasswordCheck = $false + LockoutDurationInSeconds = 30 + LockoutThreshold = 6 + Ensure = 'Present' + Credential = $Credential + IsSingleInstance = 'Yes' + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return 'Credentials' + } + } + + BeforeEach { + Mock -CommandName Get-MgBetaDirectorySetting -MockWith { + if (-not $Script:calledOnceAlready) + { + $Script:calledOnceAlready = $true + return $null + } + else + { + return @{ + DisplayName = 'Password Rule Settings' + Id = '123456-1234-1234-1234-123456789012' + TemplateId = '5cf42378-d67d-4f36-ba46-e8b86229381d' + Values = @( + @{ + Name = 'BannedPasswordCheckOnPremisesMode' + Value = 'Audit' + }, + @{ + Name = 'EnableBannedPasswordCheckOnPremises' + Value = $true + }, + @{ + Name = 'EnableBannedPasswordCheck' + Value = $true + }, + @{ + Name = 'LockoutDurationInSeconds' + Value = 60 + }, + @{ + Name = 'LockoutThreshold' + Value = 10 + }, + @{ + Name = 'BannedPasswordList' + Value = $null + } + ) + } + } + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + Should -Invoke -CommandName 'Get-MgBetaDirectorySetting' -Exactly 1 + } + + It 'Should return true from the Test method' { + $Script:calledOnceAlready = $false + Test-TargetResource @testParams | Should -Be $false + } + BeforeEach { + Mock -CommandName Get-MgBetaDirectorySetting -MockWith { + if (-not $Script:calledOnceAlready) + { + $Script:calledOnceAlready = $true + return $null + } + else + { + return @{ + DisplayName = 'Password Rule Settings' + Id = '123456-1234-1234-1234-123456789012' + TemplateId = '5cf42378-d67d-4f36-ba46-e8b86229381d' + Values = @( + @{ + Name = 'BannedPasswordCheckOnPremisesMode' + Value = 'Audit' + }, + @{ + Name = 'EnableBannedPasswordCheckOnPremises' + Value = $true + }, + @{ + Name = 'EnableBannedPasswordCheck' + Value = $true + }, + @{ + Name = 'LockoutDurationInSeconds' + Value = 60 + }, + @{ + Name = 'LockoutThreshold' + Value = 10 + }, + @{ + Name = 'BannedPasswordList' + Value = $null + } + ) + } + } + } + } + It 'Should create and set the settings in the Set method' { + $Script:calledOnceAlready = $false + Set-TargetResource @testParams + Should -Invoke -CommandName 'New-MgBetaDirectorySetting' -Exactly 1 + Should -Invoke -CommandName 'Update-MgBetaDirectorySetting' -Exactly 1 + } + } + + Context -Name 'The Policy exists but it SHOULD NOT' -Fixture { + BeforeAll { + $testParams = @{ + IsSingleInstance = 'Yes' + Ensure = 'Absent' + Credential = $Credential + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return 'Credentials' + } + + Mock -CommandName Get-MgBetaDirectorySetting -MockWith { + return @{ + DisplayName = 'Password Rule Settings' + Id = '123456-1234-1234-1234-123456789012' + TemplateId = '5cf42378-d67d-4f36-ba46-e8b86229381d' + Values = @( + @{ + Name = 'BannedPasswordCheckOnPremisesMode' + Value = 'Audit' + }, + @{ + Name = 'EnableBannedPasswordCheckOnPremises' + Value = $true + }, + @{ + Name = 'EnableBannedPasswordCheck' + Value = $true + }, + @{ + Name = 'LockoutDurationInSeconds' + Value = 60 + }, + @{ + Name = 'LockoutThreshold' + Value = 10 + }, + @{ + Name = 'BannedPasswordList' + Value = $null + } + ) + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + Should -Invoke -CommandName 'Get-MgBetaDirectorySetting' -Exactly 1 + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should Prevent Remove the Policy from the Set method' { + { Set-TargetResource @testParams } | Should -Throw 'The AADPasswordRuleSettings resource cannot delete existing Directory Setting entries. Please specify Present.' + } + } + Context -Name 'The Policy Exists and Values are already in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + BannedPasswordCheckOnPremisesMode = 'Audit' + EnableBannedPasswordCheckOnPremises = $false + EnableBannedPasswordCheck = $false + LockoutDurationInSeconds = 30 + LockoutThreshold = 6 + BannedPasswordList = $null + Ensure = 'Present' + Credential = $Credential + IsSingleInstance = 'Yes' + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return 'Credentials' + } + + Mock -CommandName Get-MgBetaDirectorySetting -MockWith { + return @{ + DisplayName = 'Password Rule Settings' + Id = '123456-1234-1234-1234-123456789012' + TemplateId = '5cf42378-d67d-4f36-ba46-e8b86229381d' + Values = @( + @{ + Name = 'BannedPasswordCheckOnPremisesMode' + Value = 'Audit' + }, + @{ + Name = 'EnableBannedPasswordCheckOnPremises' + Value = $false + }, + @{ + Name = 'EnableBannedPasswordCheck' + Value = $false + }, + @{ + Name = 'LockoutDurationInSeconds' + Value = 30 + }, + @{ + Name = 'LockoutThreshold' + Value = 6 + }, + @{ + Name = 'BannedPasswordList' + Value = $null + } + ) + } + } + + } + + It 'Should return Values from the Get method' { + Get-TargetResource @testParams + Should -Invoke -CommandName 'Get-MgBetaDirectorySetting' -Exactly 1 + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name 'Values are NOT in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + BannedPasswordCheckOnPremisesMode = 'Audit' + EnableBannedPasswordCheckOnPremises = $false + EnableBannedPasswordCheck = $false + LockoutDurationInSeconds = 30 + LockoutThreshold = 6 + BannedPasswordList = $null + Ensure = 'Present' + Credential = $Credential + IsSingleInstance = 'Yes' + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return 'Credentials' + } + + Mock -CommandName Get-MgBetaDirectorySetting -MockWith { + return @{ + DisplayName = 'Password Rule Settings' + Id = '123456-1234-1234-1234-123456789012' + TemplateId = '5cf42378-d67d-4f36-ba46-e8b86229381d' + Values = @( + @{ + Name = 'BannedPasswordCheckOnPremisesMode' + Value = 'Enforced' + }, + @{ + Name = 'EnableBannedPasswordCheckOnPremises' + Value = $true + }, + @{ + Name = 'EnableBannedPasswordCheck' + Value = $true + }, + @{ + Name = 'LockoutDurationInSeconds' + Value = 60 + }, + @{ + Name = 'LockoutThreshold' + Value = 10 + }, + @{ + Name = 'BannedPasswordList' + Value = $null + } + ) + } + } + } + } + + It 'Should return Values from the Get method' { + Get-TargetResource @testParams + Should -Invoke -CommandName 'Get-MgBetaDirectorySetting' -Exactly 1 + } + + 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 'Update-MgBetaDirectorySetting' -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDirectorySetting -MockWith { + return @{ + DisplayName = 'Password Rule Settings' + Id = '123456-1234-1234-1234-123456789012' + TemplateId = '5cf42378-d67d-4f36-ba46-e8b86229381d' + Values = @( + @{ + Name = 'BannedPasswordCheckOnPremisesMode' + Value = 'Audit' + }, + @{ + Name = 'EnableBannedPasswordCheckOnPremises' + Value = $false + }, + @{ + Name = 'EnableBannedPasswordCheck' + Value = $false + }, + @{ + Name = 'LockoutDurationInSeconds' + Value = 30 + }, + @{ + Name = 'LockoutThreshold' + Value = 6 + }, + @{ + Name = 'BannedPasswordList' + Value = $null + } + ) + } + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return 'Credentials' + } + } + + 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 161fb05c9ea058fc533e06223c2cdc4134c2d87d Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Fri, 16 Aug 2024 10:57:22 +0200 Subject: [PATCH 018/465] fixed mof --- .../MSFT_AADPasswordRuleSettings.schema.mof | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.schema.mof index 7fd52a97e9..353e64c585 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.schema.mof @@ -5,7 +5,7 @@ class MSFT_AADPasswordRuleSettings : OMI_BaseResource [Write, Description("The number of failed login attempts before the first lockout period begins.")] UInt32 LockoutThreshold; [Write, Description("The duration in seconds of the initial lockout period.")] UInt32 LockoutDurationInSeconds; [Write, Description("Boolean indicating if the banned password check for tenant specific banned password list is turned on or not.")] Boolean EnableBannedPasswordCheck; - [Write, Description("A list of banned words in passwords.")] String[] BannedPasswordList; + [Write, Description("A list of banned words in passwords.")] String BannedPasswordList[]; [Write, Description("How should we enforce password policy check in on-premises system.")] Boolean BannedPasswordCheckOnPremisesMode; [Write, Description("Boolean indicating if the banned password check is turned on or not for on-premises system.")] Boolean EnableBannedPasswordCheckOnPremises; [Write, Description("Specify if the Azure AD Password Rule Settings should exist or not."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; From 36b8c5d61652984da6df41ea5c293600cba300cf Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Fri, 16 Aug 2024 12:33:51 +0200 Subject: [PATCH 019/465] fixed unittest --- .../Microsoft365DSC.AADPasswordRuleSettings.Tests.ps1 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPasswordRuleSettings.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPasswordRuleSettings.Tests.ps1 index 14f15f107b..33bf15a0d1 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPasswordRuleSettings.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPasswordRuleSettings.Tests.ps1 @@ -15,7 +15,7 @@ Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` -Resolve) $Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` - -DscResource 'AADGroupsSettings' -GenericStubModule $GenericStubPath + -DscResource 'AADPasswordRuleSettings' -GenericStubModule $GenericStubPath Describe -Name $Global:DscHelper.DescribeHeader -Fixture { InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope @@ -380,7 +380,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } ) } - } } } From a6f1da1ab245add344d4bce61bcbd2ec57b70a56 Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Fri, 16 Aug 2024 12:59:56 +0200 Subject: [PATCH 020/465] added example --- .../AADPasswordRulesSettings/1-Update.ps1 | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADPasswordRulesSettings/1-Update.ps1 diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADPasswordRulesSettings/1-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADPasswordRulesSettings/1-Update.ps1 new file mode 100644 index 0000000000..dcb58a5fa6 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADPasswordRulesSettings/1-Update.ps1 @@ -0,0 +1,40 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADPasswordRuleSettings 'GeneralPasswordRuleSettings' + { + IsSingleInstance = "Yes" + LockoutThreshold = 6 + LockoutDurationInSeconds = 30 + BannedPasswordCheckOnPremisesMode = 'Audit' + EnableBannedPasswordCheckOnPremises = $false + EnableBannedPasswordCheck = $false + BannedPasswordList = $null + Ensure = "Present" + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} From 1cd8a1d3f1e1ccedfd578e056218a9a70d079d74 Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Fri, 16 Aug 2024 13:05:00 +0200 Subject: [PATCH 021/465] fixed misspelled foldername for example --- .../AADPasswordRuleSettings/1-Update.ps1 | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADPasswordRuleSettings/1-Update.ps1 diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADPasswordRuleSettings/1-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADPasswordRuleSettings/1-Update.ps1 new file mode 100644 index 0000000000..dcb58a5fa6 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADPasswordRuleSettings/1-Update.ps1 @@ -0,0 +1,40 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADPasswordRuleSettings 'GeneralPasswordRuleSettings' + { + IsSingleInstance = "Yes" + LockoutThreshold = 6 + LockoutDurationInSeconds = 30 + BannedPasswordCheckOnPremisesMode = 'Audit' + EnableBannedPasswordCheckOnPremises = $false + EnableBannedPasswordCheck = $false + BannedPasswordList = $null + Ensure = "Present" + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} From e6668e73fa26c55cc421c3c8cc3c424ab6d2ccdf Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Fri, 16 Aug 2024 13:05:46 +0200 Subject: [PATCH 022/465] remove misspelled example-folder --- .../AADPasswordRulesSettings/1-Update.ps1 | 40 ------------------- 1 file changed, 40 deletions(-) delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADPasswordRulesSettings/1-Update.ps1 diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADPasswordRulesSettings/1-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADPasswordRulesSettings/1-Update.ps1 deleted file mode 100644 index dcb58a5fa6..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/AADPasswordRulesSettings/1-Update.ps1 +++ /dev/null @@ -1,40 +0,0 @@ -<# -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()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - Import-DscResource -ModuleName Microsoft365DSC - - node localhost - { - AADPasswordRuleSettings 'GeneralPasswordRuleSettings' - { - IsSingleInstance = "Yes" - LockoutThreshold = 6 - LockoutDurationInSeconds = 30 - BannedPasswordCheckOnPremisesMode = 'Audit' - EnableBannedPasswordCheckOnPremises = $false - EnableBannedPasswordCheck = $false - BannedPasswordList = $null - Ensure = "Present" - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - } - } -} From 15c84dc643a0d238f19898ca12ee998207aa1c9e Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Fri, 16 Aug 2024 13:21:45 +0200 Subject: [PATCH 023/465] fixed mof for parameter BannedPasswordCheckOnPremisesMode --- .../MSFT_AADPasswordRuleSettings.schema.mof | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.schema.mof index 353e64c585..1356eee844 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.schema.mof @@ -6,7 +6,7 @@ class MSFT_AADPasswordRuleSettings : OMI_BaseResource [Write, Description("The duration in seconds of the initial lockout period.")] UInt32 LockoutDurationInSeconds; [Write, Description("Boolean indicating if the banned password check for tenant specific banned password list is turned on or not.")] Boolean EnableBannedPasswordCheck; [Write, Description("A list of banned words in passwords.")] String BannedPasswordList[]; - [Write, Description("How should we enforce password policy check in on-premises system.")] Boolean BannedPasswordCheckOnPremisesMode; + [Write, Description("How should we enforce password policy check in on-premises system.")] String BannedPasswordCheckOnPremisesMode; [Write, Description("Boolean indicating if the banned password check is turned on or not for on-premises system.")] Boolean EnableBannedPasswordCheckOnPremises; [Write, Description("Specify if the Azure AD Password Rule Settings should exist or not."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; [Write, Description("Credentials for the Microsoft Graph delegated permissions."), EmbeddedInstance("MSFT_Credential")] string Credential; From 9500772f5da702ab84dbc501fcc889ed8e8fc260 Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Fri, 16 Aug 2024 13:58:49 +0200 Subject: [PATCH 024/465] removed usage of Get-MgBetaDirectorySettingTemplate --- .../MSFT_AADPasswordRuleSettings.psm1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.psm1 index 0e220677eb..2f293f01f6 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.psm1 @@ -227,8 +227,8 @@ function Set-TargetResource $needToUpdate = $false if ($Ensure -eq 'Present' -and $currentPolicy.Ensure -eq 'Absent') { - $template = Get-MgBetaDirectorySettingTemplate -All | Where-Object -FilterScript {$_.Displayname -eq 'Password Rule Settings'} - $Policy = New-MgBetaDirectorySetting -TemplateId $template.Id | Out-Null + #$template = Get-MgBetaDirectorySettingTemplate -All | Where-Object -FilterScript {$_.Displayname -eq 'Password Rule Settings'} + $Policy = New-MgBetaDirectorySetting -TemplateId '5cf42378-d67d-4f36-ba46-e8b86229381d' | Out-Null $needToUpdate = $true } From 18d022f8b154b9a42d8add393600d5a722bd3702 Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Fri, 16 Aug 2024 14:34:16 +0200 Subject: [PATCH 025/465] also removed cmdlet Get-MgBetaDirectorySettingTemplate from unittest --- ...ft365DSC.AADPasswordRuleSettings.Tests.ps1 | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPasswordRuleSettings.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPasswordRuleSettings.Tests.ps1 index 33bf15a0d1..28d5984aa9 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPasswordRuleSettings.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPasswordRuleSettings.Tests.ps1 @@ -41,40 +41,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName New-MgBetaDirectorySetting -MockWith { } - Mock -CommandName Get-MgBetaDirectorySettingTemplate -MockWith { - return @{ - DisplayName = 'Password Rule Settings' - Id = '123456-1234-1234-1234-123456789012' - TemplateId = '5cf42378-d67d-4f36-ba46-e8b86229381d' - Values = @( - @{ - Name = 'BannedPasswordCheckOnPremisesMode' - DefaultValue = 'Audit' - }, - @{ - Name = 'EnableBannedPasswordCheckOnPremises' - DefaultValue = $true - }, - @{ - Name = 'EnableBannedPasswordCheck' - DefaultValue = $true - }, - @{ - Name = 'LockoutDurationInSeconds' - DefaultValue = 60 - }, - @{ - Name = 'LockoutThreshold' - DefaultValue = 10 - }, - @{ - Name = 'BannedPasswordList' - DefaultValue = $null - } - ) - } - } - # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { From 152f9875816d64bd5caa1a86f43ad0d7644c7ba7 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Sat, 31 Aug 2024 19:40:01 +0530 Subject: [PATCH 026/465] Added MailboxCalendarConfiguration --- .../MSFT_EXOMailboxCalendarConfiguration.psm1 | 879 ++++++++++++++++++ ...EXOMailboxCalendarConfiguration.schema.mof | 56 ++ .../readme.md | 6 + .../settings.json | 34 + 4 files changed, 975 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/settings.json diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 new file mode 100644 index 0000000000..00481e3274 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 @@ -0,0 +1,879 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.Boolean] + $AgendaMailIntroductionEnabled, + + [Parameter()] + [System.Boolean] + $AutoDeclineWhenBusy, + + [Parameter()] + [System.String] + $CalendarFeedsPreferredLanguage, + + [Parameter()] + [System.String] + $CalendarFeedsPreferredRegion, + + [Parameter()] + [System.String] + $CalendarFeedsRootPageId, + + [Parameter()] + [System.Boolean] + $ConversationalSchedulingEnabled, + + [Parameter()] + [System.Boolean] + $CreateEventsFromEmailAsPrivate, + + [Parameter()] + [System.Int32] + $DefaultMinutesToReduceLongEventsBy, + + [Parameter()] + [System.Int32] + $DefaultMinutesToReduceShortEventsBy, + + [Parameter()] + [System.Object] + $DefaultOnlineMeetingProvider, + + [Parameter()] + [System.TimeSpan] + $DefaultReminderTime, + + [Parameter()] + [System.Boolean] + $DeleteMeetingRequestOnRespond, + + [Parameter()] + [System.Boolean] + $DiningEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $EntertainmentEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $EventsFromEmailEnabled, + + [Parameter()] + [System.Object] + $FirstWeekOfYear, + + [Parameter()] + [System.Boolean] + $FlightEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $HotelEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $InvoiceEventsFromEmailEnabled, + + [Parameter()] + [System.Object] + $LocationDetailsInFreeBusy, + + [Parameter()] + [System.Object] + $MailboxLocation, + + [Parameter()] + [System.Object] + $OnlineMeetingsByDefaultEnabled, + + [Parameter()] + [System.Boolean] + $PackageDeliveryEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $PreserveDeclinedMeetings, + + [Parameter()] + [System.Boolean] + $RemindersEnabled, + + [Parameter()] + [System.Boolean] + $ReminderSoundEnabled, + + [Parameter()] + [System.Boolean] + $RentalCarEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $ServiceAppointmentEventsFromEmailEnabled, + + [Parameter()] + [System.Object] + $ShortenEventScopeDefault, + + [Parameter()] + [System.Boolean] + $ShowWeekNumbers, + + [Parameter()] + [System.Object] + $TimeIncrement, + + [Parameter()] + [System.Boolean] + $UseBrightCalendarColorThemeInOwa, + + [Parameter()] + [System.Object] + $WeatherEnabled, + + [Parameter()] + [System.Int32] + $WeatherLocationBookmark, + + [Parameter()] + [System.Object] + $WeatherLocations, + + [Parameter()] + [System.Object] + $WeatherUnit, + + [Parameter()] + [System.Object] + $WeekStartDay, + + [Parameter()] + [System.Object] + $WorkDays, + + [Parameter()] + [System.TimeSpan] + $WorkingHoursEndTime, + + [Parameter()] + [System.TimeSpan] + $WorkingHoursStartTime, + + [Parameter()] + [System.Object] + $WorkingHoursTimeZone, + + [Parameter()] + [System.Object] + $WorkspaceUserEnabled, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Identity -eq $Identity} + } + else + { + $instance = Get-MailboxCalendarConfiguration -Identity $Identity -ErrorAction Stop + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + Ensure = 'Present' + Identity = $Identity + AgendaMailIntroductionEnabled = $AgendaMailIntroductionEnabled + AutoDeclineWhenBusy = $AutoDeclineWhenBusy + CalendarFeedsPreferredLanguage = $CalendarFeedsPreferredLanguage + CalendarFeedsPreferredRegion = $CalendarFeedsPreferredRegion + CalendarFeedsRootPageId = $CalendarFeedsRootPageId + ConversationalSchedulingEnabled = $ConversationalSchedulingEnabled + CreateEventsFromEmailAsPrivate = $CreateEventsFromEmailAsPrivate + DefaultMinutesToReduceLongEventsBy = $DefaultMinutesToReduceLongEventsBy + DefaultMinutesToReduceShortEventsBy = $DefaultMinutesToReduceShortEventsBy + DefaultOnlineMeetingProvider = $DefaultOnlineMeetingProvider + DefaultReminderTime = $DefaultReminderTime + DeleteMeetingRequestOnRespond = $DeleteMeetingRequestOnRespond + DiningEventsFromEmailEnabled = $DiningEventsFromEmailEnabled + EntertainmentEventsFromEmailEnabled = $EntertainmentEventsFromEmailEnabled + EventsFromEmailEnabled = $EventsFromEmailEnabled + FirstWeekOfYear = $FirstWeekOfYear + FlightEventsFromEmailEnabled = $FlightEventsFromEmailEnabled + HotelEventsFromEmailEnabled = $HotelEventsFromEmailEnabled + InvoiceEventsFromEmailEnabled = $InvoiceEventsFromEmailEnabled + LocationDetailsInFreeBusy = $LocationDetailsInFreeBusy + MailboxLocation = $MailboxLocation + OnlineMeetingsByDefaultEnabled = $OnlineMeetingsByDefaultEnabled + PackageDeliveryEventsFromEmailEnabled = $PackageDeliveryEventsFromEmailEnabled + PreserveDeclinedMeetings = $PreserveDeclinedMeetings + RemindersEnabled = $RemindersEnabled + ReminderSoundEnabled = $ReminderSoundEnabled + RentalCarEventsFromEmailEnabled = $RentalCarEventsFromEmailEnabled + ServiceAppointmentEventsFromEmailEnabled = $ServiceAppointmentEventsFromEmailEnabled + ShortenEventScopeDefault = $ShortenEventScopeDefault + ShowWeekNumbers = $ShowWeekNumbers + TimeIncrement = $TimeIncrement + UseBrightCalendarColorThemeInOwa = $UseBrightCalendarColorThemeInOwa + WeatherEnabled = $WeatherEnabled + WeatherLocationBookmark = $WeatherLocationBookmark + WeatherLocations = $WeatherLocations + WeatherUnit = $WeatherUnit + WeekStartDay = $WeekStartDay + WorkDays = $WorkDays + WorkingHoursEndTime = $WorkingHoursEndTime + WorkingHoursStartTime = $WorkingHoursStartTime + WorkingHoursTimeZone = $WorkingHoursTimeZone + WorkspaceUserEnabled = $WorkspaceUserEnabled + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + 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(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.Boolean] + $AgendaMailIntroductionEnabled, + + [Parameter()] + [System.Boolean] + $AutoDeclineWhenBusy, + + [Parameter()] + [System.String] + $CalendarFeedsPreferredLanguage, + + [Parameter()] + [System.String] + $CalendarFeedsPreferredRegion, + + [Parameter()] + [System.String] + $CalendarFeedsRootPageId, + + [Parameter()] + [System.Boolean] + $ConversationalSchedulingEnabled, + + [Parameter()] + [System.Boolean] + $CreateEventsFromEmailAsPrivate, + + [Parameter()] + [System.Int32] + $DefaultMinutesToReduceLongEventsBy, + + [Parameter()] + [System.Int32] + $DefaultMinutesToReduceShortEventsBy, + + [Parameter()] + [System.Object] + $DefaultOnlineMeetingProvider, + + [Parameter()] + [System.TimeSpan] + $DefaultReminderTime, + + [Parameter()] + [System.Boolean] + $DeleteMeetingRequestOnRespond, + + [Parameter()] + [System.Boolean] + $DiningEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $EntertainmentEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $EventsFromEmailEnabled, + + [Parameter()] + [System.Object] + $FirstWeekOfYear, + + [Parameter()] + [System.Boolean] + $FlightEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $HotelEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $InvoiceEventsFromEmailEnabled, + + [Parameter()] + [System.Object] + $LocationDetailsInFreeBusy, + + [Parameter()] + [System.Object] + $MailboxLocation, + + [Parameter()] + [System.Object] + $OnlineMeetingsByDefaultEnabled, + + [Parameter()] + [System.Boolean] + $PackageDeliveryEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $PreserveDeclinedMeetings, + + [Parameter()] + [System.Boolean] + $RemindersEnabled, + + [Parameter()] + [System.Boolean] + $ReminderSoundEnabled, + + [Parameter()] + [System.Boolean] + $RentalCarEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $ServiceAppointmentEventsFromEmailEnabled, + + [Parameter()] + [System.Object] + $ShortenEventScopeDefault, + + [Parameter()] + [System.Boolean] + $ShowWeekNumbers, + + [Parameter()] + [System.Object] + $TimeIncrement, + + [Parameter()] + [System.Boolean] + $UseBrightCalendarColorThemeInOwa, + + [Parameter()] + [System.Object] + $WeatherEnabled, + + [Parameter()] + [System.Int32] + $WeatherLocationBookmark, + + [Parameter()] + [System.Object] + $WeatherLocations, + + [Parameter()] + [System.Object] + $WeatherUnit, + + [Parameter()] + [System.Object] + $WeekStartDay, + + [Parameter()] + [System.Object] + $WorkDays, + + [Parameter()] + [System.TimeSpan] + $WorkingHoursEndTime, + + [Parameter()] + [System.TimeSpan] + $WorkingHoursStartTime, + + [Parameter()] + [System.Object] + $WorkingHoursTimeZone, + + [Parameter()] + [System.Object] + $WorkspaceUserEnabled, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + Set-MailboxCalendarConfiguration @SetParameters +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.Boolean] + $AgendaMailIntroductionEnabled, + + [Parameter()] + [System.Boolean] + $AutoDeclineWhenBusy, + + [Parameter()] + [System.String] + $CalendarFeedsPreferredLanguage, + + [Parameter()] + [System.String] + $CalendarFeedsPreferredRegion, + + [Parameter()] + [System.String] + $CalendarFeedsRootPageId, + + [Parameter()] + [System.Boolean] + $ConversationalSchedulingEnabled, + + [Parameter()] + [System.Boolean] + $CreateEventsFromEmailAsPrivate, + + [Parameter()] + [System.Int32] + $DefaultMinutesToReduceLongEventsBy, + + [Parameter()] + [System.Int32] + $DefaultMinutesToReduceShortEventsBy, + + [Parameter()] + [System.Object] + $DefaultOnlineMeetingProvider, + + [Parameter()] + [System.TimeSpan] + $DefaultReminderTime, + + [Parameter()] + [System.Boolean] + $DeleteMeetingRequestOnRespond, + + [Parameter()] + [System.Boolean] + $DiningEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $EntertainmentEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $EventsFromEmailEnabled, + + [Parameter()] + [System.Object] + $FirstWeekOfYear, + + [Parameter()] + [System.Boolean] + $FlightEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $HotelEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $InvoiceEventsFromEmailEnabled, + + [Parameter()] + [System.Object] + $LocationDetailsInFreeBusy, + + [Parameter()] + [System.Object] + $MailboxLocation, + + [Parameter()] + [System.Object] + $OnlineMeetingsByDefaultEnabled, + + [Parameter()] + [System.Boolean] + $PackageDeliveryEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $PreserveDeclinedMeetings, + + [Parameter()] + [System.Boolean] + $RemindersEnabled, + + [Parameter()] + [System.Boolean] + $ReminderSoundEnabled, + + [Parameter()] + [System.Boolean] + $RentalCarEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $ServiceAppointmentEventsFromEmailEnabled, + + [Parameter()] + [System.Object] + $ShortenEventScopeDefault, + + [Parameter()] + [System.Boolean] + $ShowWeekNumbers, + + [Parameter()] + [System.Object] + $TimeIncrement, + + [Parameter()] + [System.Boolean] + $UseBrightCalendarColorThemeInOwa, + + [Parameter()] + [System.Object] + $WeatherEnabled, + + [Parameter()] + [System.Int32] + $WeatherLocationBookmark, + + [Parameter()] + [System.Object] + $WeatherLocations, + + [Parameter()] + [System.Object] + $WeatherUnit, + + [Parameter()] + [System.Object] + $WeekStartDay, + + [Parameter()] + [System.Object] + $WorkDays, + + [Parameter()] + [System.TimeSpan] + $WorkingHoursEndTime, + + [Parameter()] + [System.TimeSpan] + $WorkingHoursStartTime, + + [Parameter()] + [System.Object] + $WorkingHoursTimeZone, + + [Parameter()] + [System.Object] + $WorkspaceUserEnabled, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-Mailbox -ResultSize 'Unlimited' -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.UserPrincipalName + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Identity = $config.UserPrincipalName + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.schema.mof new file mode 100644 index 0000000000..dc4a73f6a9 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.schema.mof @@ -0,0 +1,56 @@ +[ClassVersion("1.0.0.0"), FriendlyName("EXOMailboxCalendarConfiguration")] +class MSFT_EXOMailboxCalendarConfiguration: OMI_BaseResource +{ + + [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; + + [Key, Description("Specifies the mailbox identity.")] String Identity; + [Write, Description("Enables or disables agenda mail introduction.")] Boolean AgendaMailIntroductionEnabled; + [Write, Description("Automatically declines meeting requests when the user is busy.")] Boolean AutoDeclineWhenBusy; + [Write, Description("Preferred language for calendar feeds.")] String CalendarFeedsPreferredLanguage; + [Write, Description("Preferred region for calendar feeds.")] String CalendarFeedsPreferredRegion; + [Write, Description("Root page ID for calendar feeds.")] String CalendarFeedsRootPageId; + [Write, Description("Enables or disables conversational scheduling.")] Boolean ConversationalSchedulingEnabled; + [Write, Description("Creates events from email as private.")] Boolean CreateEventsFromEmailAsPrivate; + [Write, Description("Default minutes to reduce long events by.")] Int32 DefaultMinutesToReduceLongEventsBy; + [Write, Description("Default minutes to reduce short events by.")] Int32 DefaultMinutesToReduceShortEventsBy; + [Write, Description("Default online meeting provider.")] Object DefaultOnlineMeetingProvider; + [Write, Description("Default reminder time.")] TimeSpan DefaultReminderTime; + [Write, Description("Deletes meeting request on respond.")] Boolean DeleteMeetingRequestOnRespond; + [Write, Description("Enables or disables dining events from email.")] Boolean DiningEventsFromEmailEnabled; + [Write, Description("Enables or disables entertainment events from email.")] Boolean EntertainmentEventsFromEmailEnabled; + [Write, Description("Enables or disables events from email.")] Boolean EventsFromEmailEnabled; + [Write, Description("Specifies the first week of the year.")] Object FirstWeekOfYear; + [Write, Description("Enables or disables flight events from email.")] Boolean FlightEventsFromEmailEnabled; + [Write, Description("Enables or disables hotel events from email.")] Boolean HotelEventsFromEmailEnabled; + [Write, Description("Enables or disables invoice events from email.")] Boolean InvoiceEventsFromEmailEnabled; + [Write, Description("Specifies location details in free/busy information.")] Object LocationDetailsInFreeBusy; + [Write, Description("Specifies the mailbox location.")] Object MailboxLocation; + [Write, Description("Enables or disables online meetings by default.")] Boolean OnlineMeetingsByDefaultEnabled; + [Write, Description("Enables or disables package delivery events from email.")] Boolean PackageDeliveryEventsFromEmailEnabled; + [Write, Description("Preserves declined meetings.")] Boolean PreserveDeclinedMeetings; + [Write, Description("Enables or disables reminders.")] Boolean RemindersEnabled; + [Write, Description("Enables or disables reminder sound.")] Boolean ReminderSoundEnabled; + [Write, Description("Enables or disables rental car events from email.")] Boolean RentalCarEventsFromEmailEnabled; + [Write, Description("Enables or disables service appointment events from email.")] Boolean ServiceAppointmentEventsFromEmailEnabled; + [Write, Description("Specifies the default scope for shortening events.")] Object ShortenEventScopeDefault; + [Write, Description("Shows or hides week numbers.")] Boolean ShowWeekNumbers; + [Write, Description("Specifies the time increment for calendar events.")] Object TimeIncrement; + [Write, Description("Uses a bright calendar color theme in Outlook on the web.")] Boolean UseBrightCalendarColorThemeInOwa; + [Write, Description("Enables or disables weather information.")] Object WeatherEnabled; + [Write, Description("Specifies the weather location bookmark.")] Int32 WeatherLocationBookmark; + [Write, Description("Specifies the weather locations.")] Object WeatherLocations; + [Write, Description("Specifies the weather unit.")] Object WeatherUnit; + [Write, Description("Specifies the start day of the week.")] Object WeekStartDay; + [Write, Description("Specifies the work days.")] Object WorkDays; + [Write, Description("Specifies the end time of working hours.")] TimeSpan WorkingHoursEndTime; + [Write, Description("Specifies the start time of working hours.")] TimeSpan WorkingHoursStartTime; + [Write, Description("Specifies the time zone for working hours.")] Object WorkingHoursTimeZone; + [Write, Description("Enables or disables workspace user.")] Object WorkspaceUserEnabled; + [Write, Description("Ensures the presence or absence of the configuration.")] String Ensure; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/readme.md new file mode 100644 index 0000000000..6e9db5a7b0 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/readme.md @@ -0,0 +1,6 @@ + +# EXOMailboxCalendarConfiguration + +## Description + +##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/settings.json new file mode 100644 index 0000000000..c656ab4211 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/settings.json @@ -0,0 +1,34 @@ +{ + "resourceName": "EXOMailboxCalendarFolder", + "description": "", + "roles": { + "read": [ + "Global Reader" + ], + "update": [ + "Exchange Administrator" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + }, + "exchange": { + "requiredroles": [ + "Organization Management", + "Recipient Management" + ], + "requiredrolegroups": [ + "Organization Management", + "Help Desk" + ] + } + } +} From 875b2f0e05a4c0bcaf30f859c240cb495db98c68 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Sat, 31 Aug 2024 21:19:28 +0530 Subject: [PATCH 027/465] minor changes --- .../MSFT_EXOMailboxCalendarConfiguration.psm1 | 181 ++++++++---------- ...EXOMailboxCalendarConfiguration.schema.mof | 38 ++-- .../settings.json | 2 +- 3 files changed, 105 insertions(+), 116 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 index 00481e3274..bba78ee2d0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 @@ -45,7 +45,7 @@ function Get-TargetResource $DefaultMinutesToReduceShortEventsBy, [Parameter()] - [System.Object] + [System.String] $DefaultOnlineMeetingProvider, [Parameter()] @@ -69,7 +69,7 @@ function Get-TargetResource $EventsFromEmailEnabled, [Parameter()] - [System.Object] + [System.String] $FirstWeekOfYear, [Parameter()] @@ -85,15 +85,15 @@ function Get-TargetResource $InvoiceEventsFromEmailEnabled, [Parameter()] - [System.Object] + [System.String] $LocationDetailsInFreeBusy, [Parameter()] - [System.Object] + [System.String] $MailboxLocation, [Parameter()] - [System.Object] + [System.Boolean] $OnlineMeetingsByDefaultEnabled, [Parameter()] @@ -121,7 +121,7 @@ function Get-TargetResource $ServiceAppointmentEventsFromEmailEnabled, [Parameter()] - [System.Object] + [System.String] $ShortenEventScopeDefault, [Parameter()] @@ -129,7 +129,7 @@ function Get-TargetResource $ShowWeekNumbers, [Parameter()] - [System.Object] + [System.String] $TimeIncrement, [Parameter()] @@ -137,7 +137,7 @@ function Get-TargetResource $UseBrightCalendarColorThemeInOwa, [Parameter()] - [System.Object] + [System.String] $WeatherEnabled, [Parameter()] @@ -145,19 +145,19 @@ function Get-TargetResource $WeatherLocationBookmark, [Parameter()] - [System.Object] + [System.String[]] $WeatherLocations, [Parameter()] - [System.Object] + [System.String] $WeatherUnit, [Parameter()] - [System.Object] + [System.String] $WeekStartDay, [Parameter()] - [System.Object] + [System.String] $WorkDays, [Parameter()] @@ -169,11 +169,11 @@ function Get-TargetResource $WorkingHoursStartTime, [Parameter()] - [System.Object] + [System.String] $WorkingHoursTimeZone, [Parameter()] - [System.Object] + [System.Boolean] $WorkspaceUserEnabled, [Parameter()] @@ -225,64 +225,53 @@ function Get-TargetResource $nullResult.Ensure = 'Absent' try { - if ($null -ne $Script:exportedInstances -and $Script:ExportMode) - { - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Identity -eq $Identity} - } - else - { - $instance = Get-MailboxCalendarConfiguration -Identity $Identity -ErrorAction Stop - } - if ($null -eq $instance) - { - return $nullResult - } + $config = Get-MailboxCalendarConfiguration -Identity $Identity -ErrorAction Stop $results = @{ Ensure = 'Present' Identity = $Identity - AgendaMailIntroductionEnabled = $AgendaMailIntroductionEnabled - AutoDeclineWhenBusy = $AutoDeclineWhenBusy - CalendarFeedsPreferredLanguage = $CalendarFeedsPreferredLanguage - CalendarFeedsPreferredRegion = $CalendarFeedsPreferredRegion - CalendarFeedsRootPageId = $CalendarFeedsRootPageId - ConversationalSchedulingEnabled = $ConversationalSchedulingEnabled - CreateEventsFromEmailAsPrivate = $CreateEventsFromEmailAsPrivate - DefaultMinutesToReduceLongEventsBy = $DefaultMinutesToReduceLongEventsBy - DefaultMinutesToReduceShortEventsBy = $DefaultMinutesToReduceShortEventsBy - DefaultOnlineMeetingProvider = $DefaultOnlineMeetingProvider - DefaultReminderTime = $DefaultReminderTime - DeleteMeetingRequestOnRespond = $DeleteMeetingRequestOnRespond - DiningEventsFromEmailEnabled = $DiningEventsFromEmailEnabled - EntertainmentEventsFromEmailEnabled = $EntertainmentEventsFromEmailEnabled - EventsFromEmailEnabled = $EventsFromEmailEnabled - FirstWeekOfYear = $FirstWeekOfYear - FlightEventsFromEmailEnabled = $FlightEventsFromEmailEnabled - HotelEventsFromEmailEnabled = $HotelEventsFromEmailEnabled - InvoiceEventsFromEmailEnabled = $InvoiceEventsFromEmailEnabled - LocationDetailsInFreeBusy = $LocationDetailsInFreeBusy - MailboxLocation = $MailboxLocation - OnlineMeetingsByDefaultEnabled = $OnlineMeetingsByDefaultEnabled - PackageDeliveryEventsFromEmailEnabled = $PackageDeliveryEventsFromEmailEnabled - PreserveDeclinedMeetings = $PreserveDeclinedMeetings - RemindersEnabled = $RemindersEnabled - ReminderSoundEnabled = $ReminderSoundEnabled - RentalCarEventsFromEmailEnabled = $RentalCarEventsFromEmailEnabled - ServiceAppointmentEventsFromEmailEnabled = $ServiceAppointmentEventsFromEmailEnabled - ShortenEventScopeDefault = $ShortenEventScopeDefault - ShowWeekNumbers = $ShowWeekNumbers - TimeIncrement = $TimeIncrement - UseBrightCalendarColorThemeInOwa = $UseBrightCalendarColorThemeInOwa - WeatherEnabled = $WeatherEnabled - WeatherLocationBookmark = $WeatherLocationBookmark - WeatherLocations = $WeatherLocations - WeatherUnit = $WeatherUnit - WeekStartDay = $WeekStartDay - WorkDays = $WorkDays - WorkingHoursEndTime = $WorkingHoursEndTime - WorkingHoursStartTime = $WorkingHoursStartTime - WorkingHoursTimeZone = $WorkingHoursTimeZone - WorkspaceUserEnabled = $WorkspaceUserEnabled + AgendaMailIntroductionEnabled = $config.AgendaMailIntroductionEnabled + AutoDeclineWhenBusy = $config.AutoDeclineWhenBusy + CalendarFeedsPreferredLanguage = $config.CalendarFeedsPreferredLanguage + CalendarFeedsPreferredRegion = $config.CalendarFeedsPreferredRegion + CalendarFeedsRootPageId = $config.CalendarFeedsRootPageId + ConversationalSchedulingEnabled = $config.ConversationalSchedulingEnabled + CreateEventsFromEmailAsPrivate = $config.CreateEventsFromEmailAsPrivate + DefaultMinutesToReduceLongEventsBy = $config.DefaultMinutesToReduceLongEventsBy + DefaultMinutesToReduceShortEventsBy = $config.DefaultMinutesToReduceShortEventsBy + DefaultOnlineMeetingProvider = $config.DefaultOnlineMeetingProvider + DefaultReminderTime = $config.DefaultReminderTime + DeleteMeetingRequestOnRespond = $config.DeleteMeetingRequestOnRespond + DiningEventsFromEmailEnabled = $config.DiningEventsFromEmailEnabled + EntertainmentEventsFromEmailEnabled = $config.EntertainmentEventsFromEmailEnabled + EventsFromEmailEnabled = $config.EventsFromEmailEnabled + FirstWeekOfYear = $config.FirstWeekOfYear + FlightEventsFromEmailEnabled = $config.FlightEventsFromEmailEnabled + HotelEventsFromEmailEnabled = $config.HotelEventsFromEmailEnabled + InvoiceEventsFromEmailEnabled = $config.InvoiceEventsFromEmailEnabled + LocationDetailsInFreeBusy = $config.LocationDetailsInFreeBusy + MailboxLocation = $config.MailboxLocation + OnlineMeetingsByDefaultEnabled = $config.OnlineMeetingsByDefaultEnabled + PackageDeliveryEventsFromEmailEnabled = $config.PackageDeliveryEventsFromEmailEnabled + PreserveDeclinedMeetings = $config.PreserveDeclinedMeetings + RemindersEnabled = $config.RemindersEnabled + ReminderSoundEnabled = $config.ReminderSoundEnabled + RentalCarEventsFromEmailEnabled = $config.RentalCarEventsFromEmailEnabled + ServiceAppointmentEventsFromEmailEnabled = $config.ServiceAppointmentEventsFromEmailEnabled + ShortenEventScopeDefault = $config.ShortenEventScopeDefault + ShowWeekNumbers = $config.ShowWeekNumbers + TimeIncrement = $config.TimeIncrement + UseBrightCalendarColorThemeInOwa = $config.UseBrightCalendarColorThemeInOwa + WeatherEnabled = $config.WeatherEnabled + WeatherLocationBookmark = $config.WeatherLocationBookmark + WeatherLocations = $config.WeatherLocations + WeatherUnit = $config.WeatherUnit + WeekStartDay = $config.WeekStartDay + WorkDays = $config.WorkDays + WorkingHoursEndTime = $config.WorkingHoursEndTime + WorkingHoursStartTime = $config.WorkingHoursStartTime + WorkingHoursTimeZone = $config.WorkingHoursTimeZone + WorkspaceUserEnabled = $config.WorkspaceUserEnabled Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId @@ -350,7 +339,7 @@ function Set-TargetResource $DefaultMinutesToReduceShortEventsBy, [Parameter()] - [System.Object] + [System.String] $DefaultOnlineMeetingProvider, [Parameter()] @@ -374,7 +363,7 @@ function Set-TargetResource $EventsFromEmailEnabled, [Parameter()] - [System.Object] + [System.String] $FirstWeekOfYear, [Parameter()] @@ -390,15 +379,15 @@ function Set-TargetResource $InvoiceEventsFromEmailEnabled, [Parameter()] - [System.Object] + [System.String] $LocationDetailsInFreeBusy, [Parameter()] - [System.Object] + [System.String] $MailboxLocation, [Parameter()] - [System.Object] + [System.Boolean] $OnlineMeetingsByDefaultEnabled, [Parameter()] @@ -426,7 +415,7 @@ function Set-TargetResource $ServiceAppointmentEventsFromEmailEnabled, [Parameter()] - [System.Object] + [System.String] $ShortenEventScopeDefault, [Parameter()] @@ -434,7 +423,7 @@ function Set-TargetResource $ShowWeekNumbers, [Parameter()] - [System.Object] + [System.String] $TimeIncrement, [Parameter()] @@ -442,7 +431,7 @@ function Set-TargetResource $UseBrightCalendarColorThemeInOwa, [Parameter()] - [System.Object] + [System.String] $WeatherEnabled, [Parameter()] @@ -450,19 +439,19 @@ function Set-TargetResource $WeatherLocationBookmark, [Parameter()] - [System.Object] + [System.String[]] $WeatherLocations, [Parameter()] - [System.Object] + [System.String] $WeatherUnit, [Parameter()] - [System.Object] + [System.String] $WeekStartDay, [Parameter()] - [System.Object] + [System.String] $WorkDays, [Parameter()] @@ -474,11 +463,11 @@ function Set-TargetResource $WorkingHoursStartTime, [Parameter()] - [System.Object] + [System.String] $WorkingHoursTimeZone, [Parameter()] - [System.Object] + [System.Boolean] $WorkspaceUserEnabled, [Parameter()] @@ -577,7 +566,7 @@ function Test-TargetResource $DefaultMinutesToReduceShortEventsBy, [Parameter()] - [System.Object] + [System.String] $DefaultOnlineMeetingProvider, [Parameter()] @@ -601,7 +590,7 @@ function Test-TargetResource $EventsFromEmailEnabled, [Parameter()] - [System.Object] + [System.String] $FirstWeekOfYear, [Parameter()] @@ -617,15 +606,15 @@ function Test-TargetResource $InvoiceEventsFromEmailEnabled, [Parameter()] - [System.Object] + [System.String] $LocationDetailsInFreeBusy, [Parameter()] - [System.Object] + [System.String] $MailboxLocation, [Parameter()] - [System.Object] + [System.Boolean] $OnlineMeetingsByDefaultEnabled, [Parameter()] @@ -653,7 +642,7 @@ function Test-TargetResource $ServiceAppointmentEventsFromEmailEnabled, [Parameter()] - [System.Object] + [System.String] $ShortenEventScopeDefault, [Parameter()] @@ -661,7 +650,7 @@ function Test-TargetResource $ShowWeekNumbers, [Parameter()] - [System.Object] + [System.String] $TimeIncrement, [Parameter()] @@ -669,7 +658,7 @@ function Test-TargetResource $UseBrightCalendarColorThemeInOwa, [Parameter()] - [System.Object] + [System.String] $WeatherEnabled, [Parameter()] @@ -677,19 +666,19 @@ function Test-TargetResource $WeatherLocationBookmark, [Parameter()] - [System.Object] + [System.String[]] $WeatherLocations, [Parameter()] - [System.Object] + [System.String] $WeatherUnit, [Parameter()] - [System.Object] + [System.String] $WeekStartDay, [Parameter()] - [System.Object] + [System.String] $WorkDays, [Parameter()] @@ -701,11 +690,11 @@ function Test-TargetResource $WorkingHoursStartTime, [Parameter()] - [System.Object] + [System.String] $WorkingHoursTimeZone, [Parameter()] - [System.Object] + [System.Boolean] $WorkspaceUserEnabled, [Parameter()] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.schema.mof index dc4a73f6a9..3a0c7f94d8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.schema.mof @@ -17,20 +17,20 @@ class MSFT_EXOMailboxCalendarConfiguration: OMI_BaseResource [Write, Description("Root page ID for calendar feeds.")] String CalendarFeedsRootPageId; [Write, Description("Enables or disables conversational scheduling.")] Boolean ConversationalSchedulingEnabled; [Write, Description("Creates events from email as private.")] Boolean CreateEventsFromEmailAsPrivate; - [Write, Description("Default minutes to reduce long events by.")] Int32 DefaultMinutesToReduceLongEventsBy; - [Write, Description("Default minutes to reduce short events by.")] Int32 DefaultMinutesToReduceShortEventsBy; - [Write, Description("Default online meeting provider.")] Object DefaultOnlineMeetingProvider; - [Write, Description("Default reminder time.")] TimeSpan DefaultReminderTime; + [Write, Description("Default minutes to reduce long events by.")] UInt32 DefaultMinutesToReduceLongEventsBy; + [Write, Description("Default minutes to reduce short events by.")] UInt32 DefaultMinutesToReduceShortEventsBy; + [Write, Description("Default online meeting provider.")] String DefaultOnlineMeetingProvider; + [Write, Description("Default reminder time.")] String DefaultReminderTime; [Write, Description("Deletes meeting request on respond.")] Boolean DeleteMeetingRequestOnRespond; [Write, Description("Enables or disables dining events from email.")] Boolean DiningEventsFromEmailEnabled; [Write, Description("Enables or disables entertainment events from email.")] Boolean EntertainmentEventsFromEmailEnabled; [Write, Description("Enables or disables events from email.")] Boolean EventsFromEmailEnabled; - [Write, Description("Specifies the first week of the year.")] Object FirstWeekOfYear; + [Write, Description("Specifies the first week of the year.")] String FirstWeekOfYear; [Write, Description("Enables or disables flight events from email.")] Boolean FlightEventsFromEmailEnabled; [Write, Description("Enables or disables hotel events from email.")] Boolean HotelEventsFromEmailEnabled; [Write, Description("Enables or disables invoice events from email.")] Boolean InvoiceEventsFromEmailEnabled; - [Write, Description("Specifies location details in free/busy information.")] Object LocationDetailsInFreeBusy; - [Write, Description("Specifies the mailbox location.")] Object MailboxLocation; + [Write, Description("Specifies location details in free/busy information.")] String LocationDetailsInFreeBusy; + [Write, Description("Specifies the mailbox location.")] String MailboxLocation; [Write, Description("Enables or disables online meetings by default.")] Boolean OnlineMeetingsByDefaultEnabled; [Write, Description("Enables or disables package delivery events from email.")] Boolean PackageDeliveryEventsFromEmailEnabled; [Write, Description("Preserves declined meetings.")] Boolean PreserveDeclinedMeetings; @@ -38,19 +38,19 @@ class MSFT_EXOMailboxCalendarConfiguration: OMI_BaseResource [Write, Description("Enables or disables reminder sound.")] Boolean ReminderSoundEnabled; [Write, Description("Enables or disables rental car events from email.")] Boolean RentalCarEventsFromEmailEnabled; [Write, Description("Enables or disables service appointment events from email.")] Boolean ServiceAppointmentEventsFromEmailEnabled; - [Write, Description("Specifies the default scope for shortening events.")] Object ShortenEventScopeDefault; + [Write, Description("Specifies the default scope for shortening events.")] String ShortenEventScopeDefault; [Write, Description("Shows or hides week numbers.")] Boolean ShowWeekNumbers; - [Write, Description("Specifies the time increment for calendar events.")] Object TimeIncrement; + [Write, Description("Specifies the time increment for calendar events.")] String TimeIncrement; [Write, Description("Uses a bright calendar color theme in Outlook on the web.")] Boolean UseBrightCalendarColorThemeInOwa; - [Write, Description("Enables or disables weather information.")] Object WeatherEnabled; - [Write, Description("Specifies the weather location bookmark.")] Int32 WeatherLocationBookmark; - [Write, Description("Specifies the weather locations.")] Object WeatherLocations; - [Write, Description("Specifies the weather unit.")] Object WeatherUnit; - [Write, Description("Specifies the start day of the week.")] Object WeekStartDay; - [Write, Description("Specifies the work days.")] Object WorkDays; - [Write, Description("Specifies the end time of working hours.")] TimeSpan WorkingHoursEndTime; - [Write, Description("Specifies the start time of working hours.")] TimeSpan WorkingHoursStartTime; - [Write, Description("Specifies the time zone for working hours.")] Object WorkingHoursTimeZone; - [Write, Description("Enables or disables workspace user.")] Object WorkspaceUserEnabled; + [Write, Description("Enables or disables weather information.")] String WeatherEnabled; + [Write, Description("Specifies the weather location bookmark.")] UInt32 WeatherLocationBookmark; + [Write, Description("Specifies the weather locations.")] String WeatherLocations[]; + [Write, Description("Specifies the weather unit.")] String WeatherUnit; + [Write, Description("Specifies the start day of the week.")] String WeekStartDay; + [Write, Description("Specifies the work days.")] String WorkDays; + [Write, Description("Specifies the end time of working hours.")] String WorkingHoursEndTime; + [Write, Description("Specifies the start time of working hours.")] String WorkingHoursStartTime; + [Write, Description("Specifies the time zone for working hours.")] String WorkingHoursTimeZone; + [Write, Description("Enables or disables workspace user.")] Boolean WorkspaceUserEnabled; [Write, Description("Ensures the presence or absence of the configuration.")] String Ensure; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/settings.json index c656ab4211..f9832ee223 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/settings.json @@ -1,5 +1,5 @@ { - "resourceName": "EXOMailboxCalendarFolder", + "resourceName": "EXOMailboxCalendarConfiguration", "description": "", "roles": { "read": [ From d3b76f8b220d62bcd050381bbfa512809db584ea Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Sat, 31 Aug 2024 21:34:36 +0530 Subject: [PATCH 028/465] minor fix --- .../MSFT_EXOMailboxCalendarConfiguration.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 index bba78ee2d0..80dfb4db3c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 @@ -264,7 +264,7 @@ function Get-TargetResource UseBrightCalendarColorThemeInOwa = $config.UseBrightCalendarColorThemeInOwa WeatherEnabled = $config.WeatherEnabled WeatherLocationBookmark = $config.WeatherLocationBookmark - WeatherLocations = $config.WeatherLocations + WeatherLocations = [Array]$config.WeatherLocations WeatherUnit = $config.WeatherUnit WeekStartDay = $config.WeekStartDay WorkDays = $config.WorkDays From 61abb0f1f958274141588cddf84467e3b60b361c Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Sun, 1 Sep 2024 17:45:30 +0530 Subject: [PATCH 029/465] Added Unit Tests --- ....EXOMailboxCalendarConfiguration.Tests.ps1 | 394 ++++++++++++++++++ 1 file changed, 394 insertions(+) create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxCalendarConfiguration.Tests.ps1 diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxCalendarConfiguration.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxCalendarConfiguration.Tests.ps1 new file mode 100644 index 0000000000..66062756d8 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxCalendarConfiguration.Tests.ps1 @@ -0,0 +1,394 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Set-MailboxCalendarConfiguration -MockWith { + return $null + } + + + Mock -CommandName Get-Mailbox -MockWith { + return @{ + Id = '12345-12345-12345-12345-12345' + UserPrincipalName = "admin@contoso.com" + } + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + + Context -Name 'Settings are not in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + AgendaMailIntroductionEnabled = $True; + AutoDeclineWhenBusy = $False; + ConversationalSchedulingEnabled = $True; + CreateEventsFromEmailAsPrivate = $True; + Credential = $Credscredential; + DefaultMinutesToReduceLongEventsBy = 10; + DefaultMinutesToReduceShortEventsBy = 5; + DefaultOnlineMeetingProvider = "TeamsForBusiness"; + DefaultReminderTime = "00:15:00"; + DeleteMeetingRequestOnRespond = $True; + DiningEventsFromEmailEnabled = $True; + Ensure = "Present"; + EntertainmentEventsFromEmailEnabled = $True; + EventsFromEmailEnabled = $True; + FirstWeekOfYear = "FirstDay"; + FlightEventsFromEmailEnabled = $True; + HotelEventsFromEmailEnabled = $True; + Identity = "admin@contoso.com"; + InvoiceEventsFromEmailEnabled = $True; + LocationDetailsInFreeBusy = "Desk"; + PackageDeliveryEventsFromEmailEnabled = $False; + PreserveDeclinedMeetings = $False; + RemindersEnabled = $True; + ReminderSoundEnabled = $True; + RentalCarEventsFromEmailEnabled = $True; + ServiceAppointmentEventsFromEmailEnabled = $True; + ShortenEventScopeDefault = "None"; + ShowWeekNumbers = $False; + TimeIncrement = "ThirtyMinutes"; + UseBrightCalendarColorThemeInOwa = $False; + WeatherEnabled = "FirstRun"; + WeatherLocationBookmark = 0; + WeatherLocations = @(); + WeatherUnit = "Default"; + WeekStartDay = "Sunday"; + WorkDays = "Monday, Tuesday"; + WorkingHoursEndTime = "17:00:00"; + WorkingHoursStartTime = "08:00:00"; + WorkingHoursTimeZone = "Pacific Standard Time"; + WorkspaceUserEnabled = $False; + } + + Mock -CommandName Get-MailboxCalendarConfiguration -MockWith { + return @{ + AgendaMailIntroductionEnabled = $True; + AutoDeclineWhenBusy = $False; + ConversationalSchedulingEnabled = $True; + CreateEventsFromEmailAsPrivate = $True; + Credential = $Credscredential; + DefaultMinutesToReduceLongEventsBy = 10; + DefaultMinutesToReduceShortEventsBy = 6; #drift + DefaultOnlineMeetingProvider = "TeamsForBusiness"; + DefaultReminderTime = "00:15:00"; + DeleteMeetingRequestOnRespond = $True; + DiningEventsFromEmailEnabled = $True; + Ensure = "Present"; + EntertainmentEventsFromEmailEnabled = $True; + EventsFromEmailEnabled = $True; + FirstWeekOfYear = "FirstDay"; + FlightEventsFromEmailEnabled = $True; + HotelEventsFromEmailEnabled = $True; + Identity = "admin@contoso.com"; + InvoiceEventsFromEmailEnabled = $True; + LocationDetailsInFreeBusy = "Desk"; + PackageDeliveryEventsFromEmailEnabled = $False; + PreserveDeclinedMeetings = $False; + RemindersEnabled = $True; + ReminderSoundEnabled = $True; + RentalCarEventsFromEmailEnabled = $True; + ServiceAppointmentEventsFromEmailEnabled = $True; + ShortenEventScopeDefault = "None"; + ShowWeekNumbers = $False; + TimeIncrement = "ThirtyMinutes"; + UseBrightCalendarColorThemeInOwa = $False; + WeatherEnabled = "FirstRun"; + WeatherLocationBookmark = 0; + WeatherLocations = @(); + WeatherUnit = "Default"; + WeekStartDay = "Sunday"; + WorkDays = "Monday, Tuesday"; + WorkingHoursEndTime = "17:00:00"; + WorkingHoursStartTime = "08:00:00"; + WorkingHoursTimeZone = "Pacific Standard Time"; + WorkspaceUserEnabled = $False; + + } + } + } + + 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-MailboxCalendarConfiguration -Exactly 1 + } + + It 'Should return Present from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + } + + Context -Name 'Settings are already in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + AgendaMailIntroductionEnabled = $True; + AutoDeclineWhenBusy = $False; + ConversationalSchedulingEnabled = $True; + CreateEventsFromEmailAsPrivate = $True; + Credential = $Credscredential; + DefaultMinutesToReduceLongEventsBy = 10; + DefaultMinutesToReduceShortEventsBy = 5; + DefaultOnlineMeetingProvider = "TeamsForBusiness"; + DefaultReminderTime = "00:15:00"; + DeleteMeetingRequestOnRespond = $True; + DiningEventsFromEmailEnabled = $True; + Ensure = "Present"; + EntertainmentEventsFromEmailEnabled = $True; + EventsFromEmailEnabled = $True; + FirstWeekOfYear = "FirstDay"; + FlightEventsFromEmailEnabled = $True; + HotelEventsFromEmailEnabled = $True; + Identity = "admin@contoso.com"; + InvoiceEventsFromEmailEnabled = $True; + LocationDetailsInFreeBusy = "Desk"; + PackageDeliveryEventsFromEmailEnabled = $False; + PreserveDeclinedMeetings = $False; + RemindersEnabled = $True; + ReminderSoundEnabled = $True; + RentalCarEventsFromEmailEnabled = $True; + ServiceAppointmentEventsFromEmailEnabled = $True; + ShortenEventScopeDefault = "None"; + ShowWeekNumbers = $False; + TimeIncrement = "ThirtyMinutes"; + UseBrightCalendarColorThemeInOwa = $False; + WeatherEnabled = "FirstRun"; + WeatherLocationBookmark = 0; + WeatherLocations = @(); + WeatherUnit = "Default"; + WeekStartDay = "Sunday"; + WorkDays = "Monday, Tuesday"; + WorkingHoursEndTime = "17:00:00"; + WorkingHoursStartTime = "08:00:00"; + WorkingHoursTimeZone = "Pacific Standard Time"; + WorkspaceUserEnabled = $False; + } + + Mock -CommandName Get-MailboxCalendarConfiguration -MockWith { + return @{ + AgendaMailIntroductionEnabled = $True; + AutoDeclineWhenBusy = $False; + ConversationalSchedulingEnabled = $True; + CreateEventsFromEmailAsPrivate = $True; + Credential = $Credscredential; + DefaultMinutesToReduceLongEventsBy = 10; + DefaultMinutesToReduceShortEventsBy = 5; + DefaultOnlineMeetingProvider = "TeamsForBusiness"; + DefaultReminderTime = "00:15:00"; + DeleteMeetingRequestOnRespond = $True; + DiningEventsFromEmailEnabled = $True; + Ensure = "Present"; + EntertainmentEventsFromEmailEnabled = $True; + EventsFromEmailEnabled = $True; + FirstWeekOfYear = "FirstDay"; + FlightEventsFromEmailEnabled = $True; + HotelEventsFromEmailEnabled = $True; + Identity = "admin@contoso.com"; + InvoiceEventsFromEmailEnabled = $True; + LocationDetailsInFreeBusy = "Desk"; + PackageDeliveryEventsFromEmailEnabled = $False; + PreserveDeclinedMeetings = $False; + RemindersEnabled = $True; + ReminderSoundEnabled = $True; + RentalCarEventsFromEmailEnabled = $True; + ServiceAppointmentEventsFromEmailEnabled = $True; + ShortenEventScopeDefault = "None"; + ShowWeekNumbers = $False; + TimeIncrement = "ThirtyMinutes"; + UseBrightCalendarColorThemeInOwa = $False; + WeatherEnabled = "FirstRun"; + WeatherLocationBookmark = 0; + WeatherLocations = @(); + WeatherUnit = "Default"; + WeekStartDay = "Sunday"; + WorkDays = "Monday, Tuesday"; + WorkingHoursEndTime = "17:00:00"; + WorkingHoursStartTime = "08:00:00"; + WorkingHoursTimeZone = "Pacific Standard Time"; + WorkspaceUserEnabled = $False; + } + } + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + + It 'Should return Present from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + } + + Context -Name "User doesn't exist" -Fixture { + BeforeAll { + $testParams = @{ + AgendaMailIntroductionEnabled = $True; + AutoDeclineWhenBusy = $False; + ConversationalSchedulingEnabled = $True; + CreateEventsFromEmailAsPrivate = $True; + Credential = $Credscredential; + DefaultMinutesToReduceLongEventsBy = 10; + DefaultMinutesToReduceShortEventsBy = 5; + DefaultOnlineMeetingProvider = "TeamsForBusiness"; + DefaultReminderTime = "00:15:00"; + DeleteMeetingRequestOnRespond = $True; + DiningEventsFromEmailEnabled = $True; + Ensure = "Present"; + EntertainmentEventsFromEmailEnabled = $True; + EventsFromEmailEnabled = $True; + FirstWeekOfYear = "FirstDay"; + FlightEventsFromEmailEnabled = $True; + HotelEventsFromEmailEnabled = $True; + Identity = "admin@contoso.com"; + InvoiceEventsFromEmailEnabled = $True; + LocationDetailsInFreeBusy = "Desk"; + PackageDeliveryEventsFromEmailEnabled = $False; + PreserveDeclinedMeetings = $False; + RemindersEnabled = $True; + ReminderSoundEnabled = $True; + RentalCarEventsFromEmailEnabled = $True; + ServiceAppointmentEventsFromEmailEnabled = $True; + ShortenEventScopeDefault = "None"; + ShowWeekNumbers = $False; + TimeIncrement = "ThirtyMinutes"; + UseBrightCalendarColorThemeInOwa = $False; + WeatherEnabled = "FirstRun"; + WeatherLocationBookmark = 0; + WeatherLocations = @(); + WeatherUnit = "Default"; + WeekStartDay = "Sunday"; + WorkDays = "Monday, Tuesday"; + WorkingHoursEndTime = "17:00:00"; + WorkingHoursStartTime = "08:00:00"; + WorkingHoursTimeZone = "Pacific Standard Time"; + WorkspaceUserEnabled = $False; + } + + Mock -CommandName Get-MailboxCalendarConfiguration -MockWith { + return $null + } + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should return Absent from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + } + + + + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-Mailbox -MockWith { + return @{ + Id = '12345-12345-12345-12345-12345' + UserPrincipalName = "admin@contoso.com" + } + } + + Mock -CommandName Get-MailboxCalendarConfiguration -MockWith { + return @{ + AgendaMailIntroductionEnabled = $True; + AutoDeclineWhenBusy = $False; + ConversationalSchedulingEnabled = $True; + CreateEventsFromEmailAsPrivate = $True; + Credential = $Credscredential; + DefaultMinutesToReduceLongEventsBy = 10; + DefaultMinutesToReduceShortEventsBy = 5; + DefaultOnlineMeetingProvider = "TeamsForBusiness"; + DefaultReminderTime = "00:15:00"; + DeleteMeetingRequestOnRespond = $True; + DiningEventsFromEmailEnabled = $True; + Ensure = "Present"; + EntertainmentEventsFromEmailEnabled = $True; + EventsFromEmailEnabled = $True; + FirstWeekOfYear = "FirstDay"; + FlightEventsFromEmailEnabled = $True; + HotelEventsFromEmailEnabled = $True; + Identity = "admin@contoso.com"; + InvoiceEventsFromEmailEnabled = $True; + LocationDetailsInFreeBusy = "Desk"; + PackageDeliveryEventsFromEmailEnabled = $False; + PreserveDeclinedMeetings = $False; + RemindersEnabled = $True; + ReminderSoundEnabled = $True; + RentalCarEventsFromEmailEnabled = $True; + ServiceAppointmentEventsFromEmailEnabled = $True; + ShortenEventScopeDefault = "None"; + ShowWeekNumbers = $False; + TimeIncrement = "ThirtyMinutes"; + UseBrightCalendarColorThemeInOwa = $False; + WeatherEnabled = "FirstRun"; + WeatherLocationBookmark = 0; + WeatherLocations = @(); + WeatherUnit = "Default"; + WeekStartDay = "Sunday"; + WorkDays = "Monday, Tuesday"; + WorkingHoursEndTime = "17:00:00"; + WorkingHoursStartTime = "08:00:00"; + WorkingHoursTimeZone = "Pacific Standard Time"; + WorkspaceUserEnabled = $False; + } + } + } + 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 70ff7783ba6f1ae1f3723c83fa5ad1a0bf07f930 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Sun, 1 Sep 2024 18:40:10 +0530 Subject: [PATCH 030/465] Added examples --- .../readme.md | 2 +- .../2-Update.ps1 | 70 +++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarConfiguration/2-Update.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/readme.md index 6e9db5a7b0..5f4846dd1e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/readme.md @@ -3,4 +3,4 @@ ## Description -##TODO - Provide a short description of what the resource is set to configure. +This resource allows users to manage mailbox calendar settings. diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarConfiguration/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarConfiguration/2-Update.ps1 new file mode 100644 index 0000000000..da4080f99f --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarConfiguration/2-Update.ps1 @@ -0,0 +1,70 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOMailboxCalendarConfiguration "EXOMailboxCalendarConfiguration-Test" + { + AgendaMailIntroductionEnabled = $True; + AutoDeclineWhenBusy = $False; + ConversationalSchedulingEnabled = $True; + CreateEventsFromEmailAsPrivate = $True; + DefaultMinutesToReduceLongEventsBy = 10; + DefaultMinutesToReduceShortEventsBy = 6; # Updated Property + DefaultOnlineMeetingProvider = "TeamsForBusiness"; + DefaultReminderTime = "00:15:00"; + DeleteMeetingRequestOnRespond = $True; + DiningEventsFromEmailEnabled = $True; + Ensure = "Present"; + EntertainmentEventsFromEmailEnabled = $True; + EventsFromEmailEnabled = $True; + FirstWeekOfYear = "FirstDay"; + FlightEventsFromEmailEnabled = $True; + HotelEventsFromEmailEnabled = $True; + Identity = "admin@$TenantId"; + InvoiceEventsFromEmailEnabled = $True; + LocationDetailsInFreeBusy = "Desk"; + PackageDeliveryEventsFromEmailEnabled = $False; + PreserveDeclinedMeetings = $False; + RemindersEnabled = $True; + ReminderSoundEnabled = $True; + RentalCarEventsFromEmailEnabled = $True; + ServiceAppointmentEventsFromEmailEnabled = $True; + ShortenEventScopeDefault = "None"; + ShowWeekNumbers = $False; + TimeIncrement = "ThirtyMinutes"; + UseBrightCalendarColorThemeInOwa = $False; + WeatherEnabled = "FirstRun"; + WeatherLocationBookmark = 0; + WeatherLocations = @(); + WeatherUnit = "Default"; + WeekStartDay = "Sunday"; + WorkDays = "Monday, Tuesday"; + WorkingHoursEndTime = "17:00:00"; + WorkingHoursStartTime = "08:00:00"; + WorkingHoursTimeZone = "Pacific Standard Time"; + WorkspaceUserEnabled = $False; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} From 5f779768618cd051f454d62ae1cae3864276aac5 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Sun, 1 Sep 2024 19:22:41 +0530 Subject: [PATCH 031/465] fixing UTs --- .../MSFT_EXOMailboxCalendarConfiguration.psm1 | 5 + Tests/Unit/Stubs/Microsoft365.psm1 | 216 ++++++++++++++++++ 2 files changed, 221 insertions(+) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 index 80dfb4db3c..4e64667fca 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxCalendarConfiguration/MSFT_EXOMailboxCalendarConfiguration.psm1 @@ -227,6 +227,11 @@ function Get-TargetResource { $config = Get-MailboxCalendarConfiguration -Identity $Identity -ErrorAction Stop + if ($null -eq $config) + { + return $nullResult + } + $results = @{ Ensure = 'Present' Identity = $Identity diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index d8d8db6694..5ddc086f57 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -1,4 +1,220 @@ # region ExchangeOnlineManagement +function Get-MailboxCalendarConfiguration +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $MailboxLocation, + + [Parameter()] + [System.Object] + $Identity + ) +} + +function Set-MailboxCalendarConfiguration +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Int32] + $WeatherLocationBookmark, + + [Parameter()] + [System.Object] + $WorkspaceUserEnabled, + + [Parameter()] + [System.Boolean] + $ConversationalSchedulingEnabled, + + [Parameter()] + [System.Boolean] + $HotelEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $SkipAgendaMailOnFreeDays, + + [Parameter()] + [System.Boolean] + $DiningEventsFromEmailEnabled, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Boolean] + $CreateEventsFromEmailAsPrivate, + + [Parameter()] + [System.String] + $CalendarFeedsPreferredLanguage, + + [Parameter()] + [System.Boolean] + $PackageDeliveryEventsFromEmailEnabled, + + [Parameter()] + [System.Object] + $WorkingHoursTimeZone, + + [Parameter()] + [System.Object] + $WeatherLocations, + + [Parameter()] + [System.Boolean] + $FlightEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $RentalCarEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $DeleteMeetingRequestOnRespond, + + [Parameter()] + [System.Int32] + $DefaultMeetingDuration, + + [Parameter()] + [System.Boolean] + $ReminderSoundEnabled, + + [Parameter()] + [System.TimeSpan] + $WorkingHoursEndTime, + + [Parameter()] + [System.Object] + $ShortenEventScopeDefault, + + [Parameter()] + [System.Boolean] + $InvoiceEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $UseBrightCalendarColorThemeInOwa, + + [Parameter()] + [System.TimeSpan] + $DefaultReminderTime, + + [Parameter()] + [System.Object] + $LocationDetailsInFreeBusy, + + [Parameter()] + [System.Object] + $WeatherEnabled, + + [Parameter()] + [System.String] + $CalendarFeedsPreferredRegion, + + [Parameter()] + [System.Boolean] + $ServiceAppointmentEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $ShowWeekNumbers, + + [Parameter()] + [System.Boolean] + $RemindersEnabled, + + [Parameter()] + [System.Object] + $WeekStartDay, + + [Parameter()] + [System.Object] + $FirstWeekOfYear, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Boolean] + $AgendaMailIntroductionEnabled, + + [Parameter()] + [System.TimeSpan] + $WorkingHoursStartTime, + + [Parameter()] + [System.String] + $CalendarFeedsRootPageId, + + [Parameter()] + [System.Object] + $DailyAgendaMailSchedule, + + [Parameter()] + [System.Int32] + $DefaultMinutesToReduceLongEventsBy, + + [Parameter()] + [System.Int32] + $DefaultMinutesToReduceShortEventsBy, + + [Parameter()] + [System.Boolean] + $AutoDeclineWhenBusy, + + [Parameter()] + [System.Object] + $OnlineMeetingsByDefaultEnabled, + + [Parameter()] + [System.Boolean] + $PreserveDeclinedMeetings, + + [Parameter()] + [System.Object] + $TimeIncrement, + + [Parameter()] + [System.Object] + $WorkDays, + + [Parameter()] + [System.Boolean] + $EntertainmentEventsFromEmailEnabled, + + [Parameter()] + [System.Boolean] + $EventsFromEmailEnabled, + + [Parameter()] + [System.Object] + $WeatherUnit, + + [Parameter()] + [System.Object] + $DefaultOnlineMeetingProvider, + + [Parameter()] + [System.Object] + $MailboxLocation, + + [Parameter()] + [System.Boolean] + $AgendaMailEnabled, + + [Parameter()] + [System.Boolean] + $AgendaPaneEnabled + ) +} + function Get-SweepRule { [CmdletBinding()] From 539f3755f9ed2786de2e1547f5913e0b5fb537fb Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Mon, 2 Sep 2024 17:05:49 +0530 Subject: [PATCH 032/465] EXOMangementScope Initial Release --- CHANGELOG.md | 2 + .../MSFT_EXOManagementScope.psm1 | 416 ++++++++++++++++++ .../MSFT_EXOManagementScope.schema.mof | 16 + .../MSFT_EXOManagementScope/readme.md | 6 + .../MSFT_EXOManagementScope/settings.json | 33 ++ .../Resources/EXOManagementScope/1-Create.ps1 | 26 ++ .../Resources/EXOManagementScope/2-Update.ps1 | 34 ++ .../Resources/EXOManagementScope/3-Remove.ps1 | 35 ++ ...crosoft365DSC.EXOManagementScope.Tests.ps1 | 210 +++++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 96 ++++ 10 files changed, 874 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/MSFT_EXOManagementScope.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/MSFT_EXOManagementScope.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOManagementScope.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 24b85d6bd6..6d0b75b9cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* EXOManagementScope + * Initial Release. * EXOSweepRule * Initial Release. * M365DSCDRGUtil diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/MSFT_EXOManagementScope.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/MSFT_EXOManagementScope.psm1 new file mode 100644 index 0000000000..33a84bd0b3 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/MSFT_EXOManagementScope.psm1 @@ -0,0 +1,416 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $RecipientRestrictionFilter, + + [Parameter()] + [System.String] + $RecipientRoot, + + [Parameter()] + [System.Boolean] + $Exclusive, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace the workload by the one associated to your resource + New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + ##TODO - Replace the PrimaryKey in the Filter by the one for the resource + $ManagementScope = $Script:exportedInstances | Where-Object -FilterScript {$_.Identity -eq $Identity} + } + else + { + ##TODO - Replace the cmdlet by the one to retrieve a specific instance. + $ManagementScope = Get-ManagementScope -Identity $Identity -ErrorAction Stop + } + if ($null -eq $ManagementScope) + { + return $nullResult + } + + $results = @{ + ##TODO - Add the list of parameters to be returned + Identity = $Identity + Name = $ManagementScope.Name + RecipientRestrictionFilter = $ManagementScope.RecipientFilter + RecipientRoot = $ManagementScope.RecipientRoot + Exclusive = $ManagementScope.Exclusive + Ensure = "Present" + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + 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(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $RecipientRestrictionFilter, + + [Parameter()] + [System.String] + $RecipientRoot, + + [Parameter()] + [System.Boolean] + $Exclusive, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + if ($setParameters.ContainsKey('Identity')) + { + $setParameters.Remove('Identity') | Out-Null + } + New-ManagementScope @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + if ($setParameters.ContainsKey('Exclusive')) + { + $setParameters.Remove('Exclusive') | Out-Null + } + Set-ManagementScope @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + ## should I just send identity to the remove cmdlet? + Remove-ManagementScope -Identity $Identity + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $RecipientRestrictionFilter, + + [Parameter()] + [System.String] + $RecipientRoot, + + [Parameter()] + [System.Boolean] + $Exclusive, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace workload + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + { + $Script:ExportMode = $true + ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances + [array] $Script:exportedInstances = Get-ManagementScope -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + ##TODO - Specify the Primary Key + #PrimaryKey = $config.PrimaryKey + Identity = $config.Identity + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_EXOManagementScope/MSFT_EXOManagementScope.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/MSFT_EXOManagementScope.schema.mof new file mode 100644 index 0000000000..9c6726ec14 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/MSFT_EXOManagementScope.schema.mof @@ -0,0 +1,16 @@ +[ClassVersion("1.0.0.0"), FriendlyName("EXOManagementScope")] +class MSFT_EXOManagementScope : OMI_BaseResource +{ + [Key, Description("The Identity parameter specifies the name of the management scope to modify.")] String Identity; + [Write, Description("The Name parameter specifies the name of the management scope.")] String Name; + [Write, Description("The RecipientRestrictionFilter parameter uses OPATH filter syntax to specify the recipients that are included in the scope.")] String RecipientRestrictionFilter; + [Write, Description("The RecipientRoot parameter specifies the organizational unit (OU) under which the filter specified with the RecipientRestrictionFilter parameter should be applied.")] String RecipientRoot; + [Write, Description("The Exclusive switch specifies that the role should be an exclusive scope.")] Boolean Exclusive; + [Write, Description("")] 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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; \ No newline at end of file diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/readme.md new file mode 100644 index 0000000000..2a43485a5b --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/readme.md @@ -0,0 +1,6 @@ + +# EXOManagementScope + +## Description + +Use this resource to create ManagementScopes. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/settings.json new file mode 100644 index 0000000000..09c305555c --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/settings.json @@ -0,0 +1,33 @@ +{ + "resourceName": "EXOManagementScope", + "description": "Use this resource to create Management Scope.", + "roles": { + "read": [ + "Global Reader" + ], + "update": [ + "Exchange Administrator" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + }, + "exchange": { + "requiredroles": [ + "Hygiene Management", + "Compliance Management", + "Organization Management", + "View-Only Organization Management" + ], + "requiredrolegroups": "Organization Management" + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/1-Create.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/1-Create.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/2-Update.ps1 new file mode 100644 index 0000000000..64528717e8 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/2-Update.ps1 @@ -0,0 +1,34 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOManagementScope "EXOManagementScope-Test New DGs" + { + Credential = $Credscredential; + Ensure = "Present"; + Exclusive = $False; + Identity = "Test New DGs"; + Name = "Test New DGs"; + RecipientRestrictionFilter = "Name -like 'NewTest*'"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/3-Remove.ps1 new file mode 100644 index 0000000000..3524dc103d --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/3-Remove.ps1 @@ -0,0 +1,35 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOManagementScope "EXOManagementScope-Test New DGs" + { + Credential = $Credscredential; + Ensure = "Absent"; + Exclusive = $False; + Identity = "Test New DGs"; + Name = "Test New DGs"; + RecipientRestrictionFilter = "Name -like 'NewTest*'"; + } + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOManagementScope.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOManagementScope.Tests.ps1 new file mode 100644 index 0000000000..dde34a4529 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOManagementScope.Tests.ps1 @@ -0,0 +1,210 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + Mock -CommandName New-ManagementScope -MockWith { + } + + Mock -CommandName Set-ManagementScope -MockWith { + } + + Mock -CommandName Remove-ManagementScope -MockWith { + } + + Mock -CommandName Get-ManagementScope -MockWith { + } + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Credential = $Credscredential; + Ensure = "Present"; + Exclusive = $False; + Identity = "Nik DGs"; + Name = "Nik DGs"; + RecipientRestrictionFilter = "Name -like 'Nik*'"; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-ManagementScope -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 a new instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-ManagementScope -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Credential = $Credscredential; + Ensure = "Absent"; + Exclusive = $False; + Identity = "Nik DGs"; + Name = "Nik DGs"; + RecipientRestrictionFilter = "Name -like 'Nik*'"; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-ManagementScope -MockWith { + return @{ + Exclusive = $False; + Identity = "Nik DGs"; + Name = "Nik DGs"; + RecipientFilter = "Name -like 'Nik*'"; + } + } + } + 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 remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-ManagementScope -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Credential = $Credscredential; + Ensure = "Present"; + Exclusive = $False; + Identity = "Nik DGs"; + Name = "Nik DGs"; + RecipientRestrictionFilter = "Name -like 'Nik*'"; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-ManagementScope -MockWith { + return @{ + Exclusive = $False; + Identity = "Nik DGs"; + Name = "Nik DGs"; + RecipientFilter = "Name -like 'Nik*'"; + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource -Verbose @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Credential = $Credscredential; + Ensure = "Present"; + Exclusive = $False; + Identity = "Nik DGs"; + Name = "Nik DGs"; + RecipientRestrictionFilter = "Name -like 'Nik*'"; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-ManagementScope -MockWith { + return @{ + Exclusive = $False; + Identity = "Nik DGs"; + Name = "Nik DGs Drift"; + RecipientFilter = "Name -like 'Nik*'"; + } + } + } + + 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-ManagementScope -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-ManagementScope -MockWith { + return @{ + Exclusive = $False; + Identity = "Nik DGs"; + Name = "Nik DGs"; + RecipientFilter = "Name -like 'Nik*'"; + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index d8d8db6694..9278ceb5e8 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -1,4 +1,100 @@ # region ExchangeOnlineManagement +function Get-ManagementScope +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Boolean] + $Exclusive, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Orphan + ) +} + +function New-ManagementScope +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Exclusive, + + [Parameter()] + [System.Object] + $RecipientRoot, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $RecipientRestrictionFilter, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force + ) +} + +function Set-ManagementScope +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $RecipientRoot, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $RecipientRestrictionFilter, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force + ) +} + +function Remove-ManagementScope +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force + ) +} + function Get-SweepRule { [CmdletBinding()] From 475ac5c8147ee5686e3bd90656cdd01dea61107b Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Mon, 2 Sep 2024 17:11:14 +0530 Subject: [PATCH 033/465] added create example --- .../Resources/EXOManagementScope/1-Create.ps1 | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/1-Create.ps1 index b516274848..ba630d844a 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementScope/1-Create.ps1 @@ -18,9 +18,19 @@ Configuration Example [System.String] $CertificateThumbprint ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost { - + EXOManagementScope "EXOManagementScope-Test New DGs" + { + Credential = $Credscredential; + Ensure = "Present"; + Exclusive = $False; + Identity = "Test New DGs"; + Name = "Test New DGs"; + RecipientRestrictionFilter = "Name -like 'Test*'"; + } } } From 8fe090a650f9d653c1089588d76b0d0f10466d61 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 2 Sep 2024 17:48:03 +0530 Subject: [PATCH 034/465] Added Focused Inbox --- .../MSFT_EXOFocusedInbox.psm1 | 354 ++++++++++++++++++ .../MSFT_EXOFocusedInbox.schema.mof | 13 + .../MSFT_EXOFocusedInbox/readme.md | 5 + .../MSFT_EXOFocusedInbox/settings.json | 34 ++ 4 files changed, 406 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/MSFT_EXOFocusedInbox.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/MSFT_EXOFocusedInbox.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/settings.json diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/MSFT_EXOFocusedInbox.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/MSFT_EXOFocusedInbox.psm1 new file mode 100644 index 0000000000..7229731dc3 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/MSFT_EXOFocusedInbox.psm1 @@ -0,0 +1,354 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.DateTime] + $FocusedInboxOnLastUpdateTime + + [Parameter()] + [System.Boolean] + $FocusedInboxOn, + + [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()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + { + $instance = Get-FocusedInbox -Identity $Identity -ErrorAction Stop + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + Identity = $Identity + FocusedInboxOn = [Boolean]$instance.FocusedInboxOn + UseCustomRouting = [Boolean]$instance.UseCustomRouting + FocusedInboxOnLastUpdateTime = $instance.FocusedInboxOnLastUpdateTime + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + 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(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.DateTime] + $FocusedInboxOnLastUpdateTime + + [Parameter()] + [System.Boolean] + $FocusedInboxOn, + + [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()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + SetParameters.Remove("FocusedInboxOnLastUpdateTime") | Out-Null + Set-FocusedInbox @SetParameters +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.DateTime] + $FocusedInboxOnLastUpdateTime + + [Parameter()] + [System.Boolean] + $FocusedInboxOn, + + [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()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-Mailbox -ResultSize Unlimited -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.UserPrincipalName + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Identity = $displayedKey + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_EXOFocusedInbox/MSFT_EXOFocusedInbox.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/MSFT_EXOFocusedInbox.schema.mof new file mode 100644 index 0000000000..25265b3151 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/MSFT_EXOFocusedInbox.schema.mof @@ -0,0 +1,13 @@ +[ClassVersion("1.0.0.0"), FriendlyName("EXOFocusedInbox")] +class MSFT_EXOFocusedInbox : OMI_BaseResource +{ + [Key, Description("The Identity parameter specifies the mailbox that you want to modify.")] String Identity; + [Write, Description("The FocusedInboxOn parameter enables or disables Focused Inbox for the mailbox.")] Boolean FocusedInboxOn; + [Write, Description("Gets the last updated time on focused inbox")] String FocusedInboxOnLastUpdateTime; + [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/readme.md new file mode 100644 index 0000000000..0212dc7bb0 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/readme.md @@ -0,0 +1,5 @@ + +# EXOFocusedInbox + +## Description +Manage the Focused Inbox configuration for mailboxes in your organization. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/settings.json new file mode 100644 index 0000000000..5421220128 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/settings.json @@ -0,0 +1,34 @@ +{ + "resourceName": "EXOFocusedInbox", + "description": "", + "roles": { + "read": [ + "Global Reader" + ], + "update": [ + "Exchange Administrator" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + }, + "exchange": { + "requiredroles": [ + "Organization Management", + "Recipient Management" + ], + "requiredrolegroups": [ + "Organization Management", + "Help Desk" + ] + } + } +} From cab09e60c7dd9f924481e4d8b5a11cfbb040bf74 Mon Sep 17 00:00:00 2001 From: Sai Sistla Date: Mon, 2 Sep 2024 19:10:32 +0530 Subject: [PATCH 035/465] Added changes for EmailTenantSettings --- .../MSFT_EXOEmailTenantSettings.psm1 | 450 ++++++++++++++++++ .../MSFT_EXOEmailTenantSettings.schema.mof | 19 + .../MSFT_EXOEmailTenantSettings/readme.md | 5 + .../MSFT_EXOEmailTenantSettings/settings.json | 34 ++ .../EXOEmailTenantSettings/2-Update.ps1 | 37 ++ ...oft365DSC.EXOEmailTenantSettings.Tests.ps1 | 136 ++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 18 + 7 files changed, 699 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOEmailTenantSettings.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 new file mode 100644 index 0000000000..89d50d48a3 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 @@ -0,0 +1,450 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + [ValidateSet('Yes')] + $IsSingleInstance, + + [Parameter()] + [System.Boolean] + $EnablePriorityAccountProtection, + + [Parameter()] + [System.Boolean] + $IsValid, + + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $ObjectState, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + Write-Verbose -Message 'Getting EXO Email Tenant Settings' + + if ($Global:CurrentModeIsExport) + { + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters ` + -SkipModuleReload $true + } + else + { + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + + $nullReturn = $PSBoundParameters + $nullReturn.Ensure = 'Absent' + + try + { + $EmailTenantSettings = Get-EmailTenantSettings -ErrorAction Stop + + $result = @{ + IsSingleInstance = 'Yes' + Identity = $EmailTenantSettings.Identity + EnablePriorityAccountProtection = $EmailTenantSettings.EnablePriorityAccountProtection + Name = $EmailTenantSettings.Name + IsValid = $EmailTenantSettings.IsValid + ObjectState = $EmailTenantSettings.ObjectState + Credential = $Credential + Ensure = 'Present' + ApplicationId = $ApplicationId + CertificateThumbprint = $CertificateThumbprint + CertificatePath = $CertificatePath + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + TenantId = $TenantId + AccessTokens = $AccessTokens + } + + Write-Verbose -Message 'Found Email Tenant Settings config ' + Write-Verbose -Message "Get-TargetResource Result: `n $(Convert-M365DscHashtableToString -Hashtable $result)" + return $result + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullReturn + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + [ValidateSet('Yes')] + $IsSingleInstance, + + [Parameter()] + [System.Boolean] + $EnablePriorityAccountProtection, + + [Parameter()] + [System.Boolean] + $IsValid, + + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $ObjectState, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + #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 'Setting configuration of Email tenant setings' + + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters + + $EmailTenantSettingsParams = [System.Collections.Hashtable]($PSBoundParameters) + $EmailTenantSettingsParams.Remove('Ensure') | Out-Null + $EmailTenantSettingsParams.Remove('Credential') | Out-Null + $EmailTenantSettingsParams.Remove('ApplicationId') | Out-Null + $EmailTenantSettingsParams.Remove('TenantId') | Out-Null + $EmailTenantSettingsParams.Remove('CertificateThumbprint') | Out-Null + $EmailTenantSettingsParams.Remove('CertificatePath') | Out-Null + $EmailTenantSettingsParams.Remove('CertificatePassword') | Out-Null + $EmailTenantSettingsParams.Remove('ManagedIdentity') | Out-Null + $EmailTenantSettingsParams.Remove('IsSingleInstance') | Out-Null + $EmailTenantSettingsParams.Remove('AccessTokens') | Out-Null + + #removing params that cannot be set. + $EmailTenantSettingsParams.Remove('Name') | Out-Null + $EmailTenantSettingsParams.Remove('IsValid') | Out-Null + $EmailTenantSettingsParams.Remove('ObjectState') | Out-Null + + if (('Present' -eq $Ensure ) -and ($Null -ne $EmailTenantSettingsParams)) + { + Write-Verbose -Message "Setting Email tenant settings with values: $(Convert-M365DscHashtableToString -Hashtable $EmailTenantSettingsParams)" + Set-EmailTenantSettings @EmailTenantSettingsParams + + Write-Verbose -Message 'Email tenant settings updated successfully' + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + [ValidateSet('Yes')] + $IsSingleInstance, + + [Parameter()] + [System.Boolean] + $EnablePriorityAccountProtection, + + [Parameter()] + [System.Boolean] + $IsValid, + + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $ObjectState, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + #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 Email tenant settings' + + $CurrentValues = Get-TargetResource @PSBoundParameters + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + $ValuesToCheck = $PSBoundParameters + $ValuesToCheck.Remove('Ensure') | Out-Null + + $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.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' -InboundParameters $PSBoundParameters -SkipModuleReload $true + + #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 + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $EmailTenantSettings = Get-EmailTenantSettings -ErrorAction Stop + $dscContent = '' + Write-Host "`r`n" -NoNewline + + Write-Host " |---[1/1] $($EmailTenantSettings.Identity)" -NoNewline + + $Params = @{ + IsSingleInstance = 'Yes' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + CertificatePath = $CertificatePath + AccessTokens = $AccessTokens + } + + $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 + 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_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.schema.mof new file mode 100644 index 0000000000..722a76bcd3 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.schema.mof @@ -0,0 +1,19 @@ +[ClassVersion("1.0.0.0"), FriendlyName("EXOEmailTenantSettings")] +class MSFT_EXOEmailTenantSettings : OMI_BaseResource +{ + [Key, Description("Only valid value is 'Yes'."), ValueMap{"Yes"}, Values{"Yes"}] String IsSingleInstance; + [Write, Description("Identity which indicates the organization name.")] String Identity; + [Write, Description("Specifies whether priority account protection is enabled.")] Boolean EnablePriorityAccountProtection; + [Write, Description("Specifies whether the migration configuration is valid.")] Boolean IsValid; + [Write, Description("Specifies the state of the object.")] String ObjectState; + [Write, Description("Specifies the name of the object.")] String Name; + [Write, Description("Specifies if this EmailTenantSettings should exist."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Write, Description("Credentials of the Exchange Global 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("Path to certificate used in service principal usually a PFX file.")] String CertificatePath; + [Write, Description("Username can be made up to anything but password will be used for CertificatePassword"), EmbeddedInstance("MSFT_Credential")] String CertificatePassword; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/readme.md new file mode 100644 index 0000000000..b07d58c77b --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/readme.md @@ -0,0 +1,5 @@ +EXOEmailTenantSettings + +## Description + +This resource allows users to manage email tenant settings. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/settings.json new file mode 100644 index 0000000000..a3fb9d4fcf --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/settings.json @@ -0,0 +1,34 @@ +{ + "resourceName": "EXOEmailTenantSettings", + "description": "", + "roles": { + "read": [ + "Global Reader" + ], + "update": [ + "Exchange Administrator" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + }, + "exchange": { + "requiredroles": [ + "Organization Management", + "Security Reader" + ], + "requiredrolegroups": [ + "Organization Management", + "Security Administrator" + ] + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 new file mode 100644 index 0000000000..c94feac8ee --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 @@ -0,0 +1,37 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOEmailTenantSettings "EXOEmailTenantSettings-Test" + { + EnablePriorityAccountProtection = $True; + Identity = $TenantId; + IsValid = $True; + ObjectState = "Unchanged" + Ensure = "Present"; + Name = "Default" + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationId = $ApplicationId + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOEmailTenantSettings.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOEmailTenantSettings.Tests.ps1 new file mode 100644 index 0000000000..43cf5d4ba9 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOEmailTenantSettings.Tests.ps1 @@ -0,0 +1,136 @@ +[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 'EXOEmailTenantSettings' -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 New-M365DSCConnection -MockWith { + return 'Credentials' + } + + Mock -CommandName Get-PSSession -MockWith { + } + + Mock -CommandName Remove-PSSession -MockWith { + } + + Mock -CommandName Set-EmailTenantSettings -MockWith { + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + + # Test contexts + Context -Name 'Configuration needs updating' -Fixture { + BeforeAll { + $testParams = @{ + IsSingleInstance = 'Yes' + EnablePriorityAccountProtection = $True; + Identity = "sotmcpoc.onmicrosoft.com\Default"; + IsValid = $True; + ObjectState = "New" + Credential = $Credential + Name = "Default" + Ensure = "Present" + } + + Mock -CommandName Get-EmailTenantSettings -MockWith { + return @{ + EnablePriorityAccountProtection = $False; + IsValid = $True; + ObjectState = "New" + } + } + } + + 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-EmailTenantSettings -Exactly 1 + } + } + + Context -Name 'Update not required.' -Fixture { + BeforeAll { + $testParams = @{ + IsSingleInstance = 'Yes' + EnablePriorityAccountProtection = $True; + Identity = "sotmcpoc.onmicrosoft.com\Default"; + IsValid = $True; + ObjectState = "New" + Credential = $Credential + Name = "Default" + Ensure = "Present" + } + + Mock -CommandName Get-EmailTenantSettings -MockWith { + return @{ + EnablePriorityAccountProtection = $True; + IsValid = $True; + ObjectState = "New" + Identity = "sotmcpoc.onmicrosoft.com\Default" + Name = "Default" + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-EmailTenantSettings -MockWith { + return @{ + EnablePriorityAccountProtection = $False; + IsValid = $True; + ObjectState = "New" + } + } + } + + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index d8d8db6694..09ef698c93 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -1,4 +1,22 @@ # region ExchangeOnlineManagement +function Get-EmailTenantSettings +{ + [CmdletBinding()] + param( + ) +} + +function Set-EmailTenantSettings +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Boolean] + $EnablePriorityAccountProtection + ) +} + + function Get-SweepRule { [CmdletBinding()] From 428431d7c705b9d9cee0cea5c5052ad38e7bfa4a Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 2 Sep 2024 19:51:10 +0530 Subject: [PATCH 036/465] Added UTs and bug fixes --- .../MSFT_EXOFocusedInbox.psm1 | 13 +- .../MSFT_EXOFocusedInbox.schema.mof | 3 +- .../Microsoft365DSC.EXOFocusedInbox.Tests.ps1 | 173 ++++++++++++++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 32 ++++ 4 files changed, 213 insertions(+), 8 deletions(-) create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOFocusedInbox.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/MSFT_EXOFocusedInbox.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/MSFT_EXOFocusedInbox.psm1 index 7229731dc3..c424b4364e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/MSFT_EXOFocusedInbox.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/MSFT_EXOFocusedInbox.psm1 @@ -10,7 +10,7 @@ function Get-TargetResource [Parameter()] [System.DateTime] - $FocusedInboxOnLastUpdateTime + $FocusedInboxOnLastUpdateTime, [Parameter()] [System.Boolean] @@ -65,7 +65,7 @@ function Get-TargetResource $nullResult.Ensure = 'Absent' try { - $instance = Get-FocusedInbox -Identity $Identity -ErrorAction Stop + $instance = Get-FocusedInbox -Identity $Identity if ($null -eq $instance) { return $nullResult @@ -74,8 +74,7 @@ function Get-TargetResource $results = @{ Identity = $Identity FocusedInboxOn = [Boolean]$instance.FocusedInboxOn - UseCustomRouting = [Boolean]$instance.UseCustomRouting - FocusedInboxOnLastUpdateTime = $instance.FocusedInboxOnLastUpdateTime + FocusedInboxOnLastUpdateTime = [DateTime]$instance.FocusedInboxOnLastUpdateTime Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -109,7 +108,7 @@ function Set-TargetResource [Parameter()] [System.DateTime] - $FocusedInboxOnLastUpdateTime + $FocusedInboxOnLastUpdateTime, [Parameter()] [System.Boolean] @@ -161,7 +160,7 @@ function Set-TargetResource $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters - SetParameters.Remove("FocusedInboxOnLastUpdateTime") | Out-Null + $SetParameters.Remove("FocusedInboxOnLastUpdateTime") | Out-Null Set-FocusedInbox @SetParameters } @@ -177,7 +176,7 @@ function Test-TargetResource [Parameter()] [System.DateTime] - $FocusedInboxOnLastUpdateTime + $FocusedInboxOnLastUpdateTime, [Parameter()] [System.Boolean] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/MSFT_EXOFocusedInbox.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/MSFT_EXOFocusedInbox.schema.mof index 25265b3151..8b3cdaffa9 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/MSFT_EXOFocusedInbox.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOFocusedInbox/MSFT_EXOFocusedInbox.schema.mof @@ -3,7 +3,8 @@ class MSFT_EXOFocusedInbox : OMI_BaseResource { [Key, Description("The Identity parameter specifies the mailbox that you want to modify.")] String Identity; [Write, Description("The FocusedInboxOn parameter enables or disables Focused Inbox for the mailbox.")] Boolean FocusedInboxOn; - [Write, Description("Gets the last updated time on focused inbox")] String FocusedInboxOnLastUpdateTime; + [Write, Description("Gets the last updated time on focused inbox")] DateTime FocusedInboxOnLastUpdateTime; + [Write, Description("Specify if the AcceptedDomain should exist or not."), ValueMap{"Present"}, Values{"Present"}] 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; diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOFocusedInbox.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOFocusedInbox.Tests.ps1 new file mode 100644 index 0000000000..029fd0ad34 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOFocusedInbox.Tests.ps1 @@ -0,0 +1,173 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Set-FocusedInbox -MockWith { + return $null + } + + Mock -CommandName Get-Mailbox -MockWith { + return @{ + Id = "12345-12345-12345-12345-12345" + UserPrincipalName = "admin@contoso.com" + } + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + + Context -Name 'Settings are not in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + Ensure = "Present"; + FocusedInboxOn = $True; + FocusedInboxOnLastUpdateTime = "1/1/0001 12:00:00 AM"; + Identity = "admin@contoso.com"; + } + + Mock -CommandName Get-FocusedInbox -MockWith { + return @{ + FocusedInboxOn = $False; + FocusedInboxOnLastUpdateTime = "1/1/0001 12:00:00 AM"; + Identity = "admin@contoso.com"; + } + } + } + + 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-FocusedInbox -Exactly 1 + } + + It 'Should return Present from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + } + + Context -Name 'Settings are already in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + Ensure = "Present"; + FocusedInboxOn = $True; + FocusedInboxOnLastUpdateTime = "1/1/0001 12:00:00 AM"; + Identity = "admin@contoso.com"; + } + + Mock -CommandName Get-FocusedInbox -MockWith { + return @{ + FocusedInboxOn = $True; + FocusedInboxOnLastUpdateTime = "1/1/0001 12:00:00 AM"; + Identity = "admin@contoso.com"; + } + } + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + + It 'Should return Present from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + } + + Context -Name "User doesn't exist" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = "Present"; + FocusedInboxOn = $True; + FocusedInboxOnLastUpdateTime = "1/1/0001 12:00:00 AM"; + Identity = "admin@contoso.com"; + } + + Mock -CommandName Get-FocusedInbox -MockWith { + return $null + } + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should return Absent from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + } + + + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-Mailbox -MockWith { + return @{ + Id = "12345-12345-12345-12345-12345" + UserPrincipalName = "admin@contoso.com" + } + } + Mock -CommandName Get-FocusedInbox -MockWith { + return @{ + Ensure = "Present"; + FocusedInboxOn = $True; + FocusedInboxOnLastUpdateTime = "1/1/0001 12:00:00 AM"; + Identity = "admin@contoso.com"; + + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index d8d8db6694..0a51020dfa 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -1,4 +1,36 @@ # region ExchangeOnlineManagement +function Get-FocusedInbox +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $UseCustomRouting, + + [Parameter()] + [System.Object] + $Identity + ) +} + +function Set-FocusedInbox +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $UseCustomRouting, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $FocusedInboxOn + ) +} + function Get-SweepRule { [CmdletBinding()] From 01c8730226f865e6014768cde3661e5d9af82260 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 2 Sep 2024 19:55:00 +0530 Subject: [PATCH 037/465] Adding Example --- .../Resources/EXOFocusedInbox/2-Update.ps1 | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOFocusedInbox/2-Update.ps1 diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOFocusedInbox/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOFocusedInbox/2-Update.ps1 new file mode 100644 index 0000000000..5505182c87 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOFocusedInbox/2-Update.ps1 @@ -0,0 +1,36 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOFocusedInbox "EXOFocusedInbox-Test" + { + Ensure = "Present"; + FocusedInboxOn = $False; # Updated Property + FocusedInboxOnLastUpdateTime = "1/1/0001 12:00:00 AM"; + Identity = "admin@$TenantId"; + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + + } +} From da415dbaf8614b1b0584dfeee532b2667911f630 Mon Sep 17 00:00:00 2001 From: ritikmit Date: Tue, 3 Sep 2024 11:29:32 +0530 Subject: [PATCH 038/465] Added EXOPhishSimOverrideRule resource --- .../MSFT_EXOPhishSimOverrideRule.psm1 | 422 ++++++++++++++++++ .../MSFT_EXOPhishSimOverrideRule.schema.mof | 16 + .../MSFT_EXOPhishSimOverrideRule/readme.md | 7 + .../settings.json | 34 ++ .../EXOPhishSimOverrideRule/1-Create.ps1 | 37 ++ .../EXOPhishSimOverrideRule/2-Update.ps1 | 35 ++ .../EXOPhishSimOverrideRule/3-Remove.ps1 | 35 ++ ...ft365DSC.EXOPhishSimOverrideRule.Tests.ps1 | 214 +++++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 96 ++++ 9 files changed, 896 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOPhishSimOverrideRule.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 new file mode 100644 index 0000000000..f0f6917106 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 @@ -0,0 +1,422 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.String[]] + $Domains, + + [Parameter()] + [System.String[]] + $SenderIpRanges, + + [Parameter()] + [System.String] + $Comment, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Identity -eq $Identity} + } + else + { + $instance = Get-EXOPhishSimOverrideRule -Identity $Identity + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + Identity = $instance.Identity + SenderIpRanges = $instance.SenderIpRanges + Domains = $instance.Domains + Comment = $instance.Comment + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +# Function to compare and modify properties +function ModifyPropertiesForSetCmdlet { + param ( + [Hashtable]$setParameters, + [Hashtable]$currentInstance, + [string]$propertyName + ) + + # Get the arrays + $setArray = $setParameters[$propertyName] + $currentArray = $currentInstance[$propertyName] + + # Compare arrays + $addArray = $setArray | Where-Object { $_ -notin $currentArray } + $removeArray = $currentArray | Where-Object { $_ -notin $setArray } + + # Modify $setParameters + if ($addArray.Count -gt 0) { + $setParameters.Add("Add$propertyName", $addArray) + } + if ($removeArray.Count -gt 0) { + $setParameters.Add("Remove$propertyName", $removeArray) + } + + # Remove the original property + $setParameters.Remove($propertyName) +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.String[]] + $Domains, + + [Parameter()] + [System.String[]] + $SenderIpRanges, + + [Parameter()] + [System.String] + $Comment, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + $ruleIdentity = $setParameters['Identity'] + $setParameters.Add("Name", $ruleIdentity) + $setParameters.Remove("Identity") + + New-EXOPhishSimOverrideRule @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + # Modify Domains and SenderIpRanges parameters as Set cmdlet for this resource has different parameter names + ModifyPropertiesForSetCmdlet -setParameters $setParameters -currentInstance $currentInstance -propertyName "Domains" + ModifyPropertiesForSetCmdlet -setParameters $setParameters -currentInstance $currentInstance -propertyName "SenderIpRanges" + + Set-EXOPhishSimOverrideRule @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Remove-EXOPhishSimOverrideRule -Identity $setParameters['Identity'] + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.String[]] + $Domains, + + [Parameter()] + [System.String[]] + $SenderIpRanges, + + [Parameter()] + [System.String] + $Comment, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-EXOPhishSimOverrideRule + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Identity = $config.Identity + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.schema.mof new file mode 100644 index 0000000000..539215c4e6 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.schema.mof @@ -0,0 +1,16 @@ +[ClassVersion("1.0.0.0"), FriendlyName("EXOPhishSimOverrideRule")] +class MSFT_EXOPhishSimOverrideRule : OMI_BaseResource +{ +[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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; + + [Key, Description("The unique identifier (GUID or name) of the override rule. This parameter is mandatory.")] String Identity; + [Write, Description("The domains for the override rule.")] String Domains[]; + [Write, Description("The IP ranges for the override rule.")] String SenderIpRanges[]; + [Write, Description("An optional comment for the override rule.")] String Comment; + [Write, Description("Ensures the presence or absence of the configuration.")] String Ensure; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/readme.md new file mode 100644 index 0000000000..b80529a2c8 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/readme.md @@ -0,0 +1,7 @@ + +# EXOPhishSimOverrideRule + +## Description + +This resource allows users to manage resource to modify third-party phishing +simulation override rules to bypass Exchange Online Protection filtering. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json new file mode 100644 index 0000000000..745b156e7b --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json @@ -0,0 +1,34 @@ +{ + "resourceName": "EXOPhishSimOverrideRule", + "description": "", + "roles": { + "read": [ + "Global Reader" + ], + "update": [ + "Exchange Administrator" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + }, + "exchange": { + "requiredroles": [ + "Organization Management", + "Recipient Management" + ], + "requiredrolegroups": [ + "Organization Management", + "Help Desk" + ] + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/1-Create.ps1 new file mode 100644 index 0000000000..c47de1b845 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/1-Create.ps1 @@ -0,0 +1,37 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOPhishSimOverrideRule "EXOPhishSimOverrideRule-_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b" + { + Comment = "Comment note"; + Credential = $Credscredential; + Domains = @("fabrikam.com","wingtiptoys.com"); + Ensure = "Present"; + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + SenderIpRanges = @("192.168.1.55"); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/2-Update.ps1 new file mode 100644 index 0000000000..12b382f5fa --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/2-Update.ps1 @@ -0,0 +1,35 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOPhishSimOverrideRule "EXOPhishSimOverrideRule-_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b" + { + Comment = "New Comment note"; + Credential = $Credscredential; + Ensure = "Present"; + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/3-Remove.ps1 new file mode 100644 index 0000000000..176420b33e --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/3-Remove.ps1 @@ -0,0 +1,35 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOPhishSimOverrideRule "EXOPhishSimOverrideRule-_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b" + { + Credential = $Credscredential; + Ensure = "Absent"; + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOPhishSimOverrideRule.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOPhishSimOverrideRule.Tests.ps1 new file mode 100644 index 0000000000..b7ac8ca276 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOPhishSimOverrideRule.Tests.ps1 @@ -0,0 +1,214 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Set-EXOPhishSimOverrideRule -MockWith { + return $null + } + + Mock -CommandName Remove-EXOPhishSimOverrideRule -MockWith { + return $null + } + + Mock -CommandName New-EXOPhishSimOverrideRule -MockWith { + return $null + } + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present' + Credential = $Credential; + Comment = "Comment note"; + Domains = @("fabrikam.com","wingtiptoys.com"); + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + SenderIpRanges = @("192.168.1.55"); + } + + Mock -CommandName Get-EXOPhishSimOverrideRule -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 a new instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-EXOPhishSimOverrideRule -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Absent' + Credential = $Credential; + Comment = "Comment note"; + Domains = @("fabrikam.com","wingtiptoys.com"); + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + SenderIpRanges = @("192.168.1.55"); + } + + Mock -CommandName Get-EXOPhishSimOverrideRule -MockWith { + return @{ + Ensure = 'Present' + Credential = $Credential; + Comment = "Comment note"; + Domains = @("fabrikam.com","wingtiptoys.com"); + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + SenderIpRanges = @("192.168.1.55"); + } + } + } + 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 remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-EXOPhishSimOverrideRule -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present' + Credential = $Credential; + Comment = "Comment note"; + Domains = @("fabrikam.com","wingtiptoys.com"); + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + SenderIpRanges = @("192.168.1.55"); + } + + Mock -CommandName Get-EXOPhishSimOverrideRule -MockWith { + return @{ + Ensure = 'Present' + Credential = $Credential; + Comment = "Comment note"; + Domains = @("fabrikam.com","wingtiptoys.com"); + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + SenderIpRanges = @("192.168.1.55"); + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + Comment = "Comment note"; + Domains = @("fabrikam.com","wingtiptoys.com"); + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + SenderIpRanges = @("192.168.1.55"); + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-EXOPhishSimOverrideRule -MockWith { + return @{ + Ensure = 'Present' + Credential = $Credential; + Comment = "Comment note"; + Domains = @("fabrikam.com","wingtiptoys.com", "newdomain.com"); + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + SenderIpRanges = @("192.168.1.56"); + } + } + } + + 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-EXOPhishSimOverrideRule -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-EXOPhishSimOverrideRule -MockWith { + return @{ + Ensure = 'Present' + Credential = $Credential; + Comment = "Comment note"; + Domains = @("fabrikam.com","wingtiptoys.com"); + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + SenderIpRanges = @("192.168.1.55"); + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index d8d8db6694..ffc3d9f7c9 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -149,6 +149,102 @@ function Set-SweepRule ) } +function Get-ExoPhishSimOverrideRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $Policy + ) +} + +function New-ExoPhishSimOverrideRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Object] + $SenderIpRanges, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $Domains, + + [Parameter()] + [System.String] + $Comment, + + [Parameter()] + [System.Object] + $Policy + ) +} + +function Remove-ExoPhishSimOverrideRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $Identity + ) +} + +function Set-ExoPhishSimOverrideRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $AddDomains, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $Comment, + + [Parameter()] + [System.Object] + $AddSenderIpRanges, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $RemoveDomains, + + [Parameter()] + [System.Object] + $RemoveSenderIpRanges + ) +} + function Get-DefaultTenantBriefingConfig { [CmdletBinding()] From 6517b257d7a17472006136220b2f179686a87423 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Tue, 3 Sep 2024 11:39:18 +0530 Subject: [PATCH 039/465] EXOMailboxIRMAccess Initial release --- ...rosoft365DSC.EXOMailboxIRMAccess.Tests.ps1 | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxIRMAccess.Tests.ps1 diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxIRMAccess.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxIRMAccess.Tests.ps1 new file mode 100644 index 0000000000..dd15e92933 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxIRMAccess.Tests.ps1 @@ -0,0 +1,167 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Get-MailboxIRMAccess -MockWith { + } + + Mock -CommandName Set-MailboxIRMAccess -MockWith { + } + + Mock -CommandName Remove-MailboxIRMAccess -MockWith { + } + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + AccessLevel = "Block"; + Identity = "qwe@test.org"; + User = "admin@test.org"; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MailboxIRMAccess -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 a new instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Set-MailboxIRMAccess -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + AccessLevel = "Block"; + Identity = "qwe@test.org"; + User = "admin@test.org"; + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-MailboxIRMAccess -MockWith { + return @{ + AccessLevel = "Block"; + Identity = "qwe@test.org"; + User = "admin@test.org"; + } + } + } + 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 remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MailboxIRMAccess -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + AccessLevel = "Block"; + Identity = "qwe@test.org"; + User = "admin@test.org"; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MailboxIRMAccess -MockWith { + return @{ + AccessLevel = "Block"; + Identity = "qwe@test.org"; + User = "admin@test.org"; + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-MailboxIRMAccess -MockWith { + return @{ + Identity = "john.smith@contoso.com"; + AccessLevel = "Block"; + User = "admin@contoso.com"; + } + } + + Mock -CommandName Get-Mailbox -MockWith { + return @{ + UserPrincipalName = "john.smith@contoso.com"; + } + } + } + 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 9dcd333e62f7ee47f4134aa354be047a8ea751c3 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Tue, 3 Sep 2024 11:48:12 +0530 Subject: [PATCH 040/465] EXOMailboxIRMAccess incremental --- CHANGELOG.md | 2 + .../MSFT_EXOMailboxIRMAccess.psm1 | 392 ++++++++++++++++++ .../MSFT_EXOMailboxIRMAccess.schema.mof | 14 + .../MSFT_EXOMailboxIRMAccess/readme.md | 6 + .../MSFT_EXOMailboxIRMAccess/settings.json | 32 ++ .../EXOMailboxIRMAccess/1-Create.ps1 | 33 ++ .../EXOMailboxIRMAccess/2-Update.ps1 | 26 ++ Tests/Unit/Stubs/Microsoft365.psm1 | 46 ++ 8 files changed, 551 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/MSFT_EXOMailboxIRMAccess.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/MSFT_EXOMailboxIRMAccess.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/2-Update.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 24b85d6bd6..dcc7f18b46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* EXOMailboxIRMAccess + * Initial Release. * EXOSweepRule * Initial Release. * M365DSCDRGUtil diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/MSFT_EXOMailboxIRMAccess.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/MSFT_EXOMailboxIRMAccess.psm1 new file mode 100644 index 0000000000..13c1f4be94 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/MSFT_EXOMailboxIRMAccess.psm1 @@ -0,0 +1,392 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter(Mandatory = $true)] + [System.String] + $User, + + [Parameter()] + [ValidateSet('Block')] + [System.String] + $AccessLevel, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Identity -eq $Identity -and $_.User -eq $User} + } + else + { + $instance = Get-MailboxIRMAccess -Identity $Identity -User $User + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + Identity = $Identity + User = $User + AccessLevel = $instance.AccessLevel + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + 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(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter(Mandatory = $true)] + [System.String] + $User, + + [Parameter()] + [ValidateSet('Block')] + [System.String] + $AccessLevel, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Set-MailboxIRMAccess @setParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + $setParameters.Remove('AccessLevel') | Out-Null + Remove-MailboxIRMAccess @SetParameters + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter(Mandatory = $true)] + [System.String] + $User, + + [Parameter()] + [ValidateSet('Block')] + [System.String] + $AccessLevel, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace workload + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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]$mailboxes = Get-Mailbox -ResultSize 'Unlimited' -ErrorAction Stop + + if ($mailboxes.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + $dscContent = '' + $i = 1 + foreach ($mailbox in $mailboxes) + { + Write-Host " |---[$i/$($mailboxes.Count)] $($mailbox.UserPrincipalName)" -NoNewline + + [Array]$irmAccesses = Get-MailboxIRMAccess -Identity $mailbox.UserPrincipalName + + $j = 1 + Write-Host "`r`n" -NoNewline + foreach ($irmAccess in $irmAccesses) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + Write-Host " |---[$j/$($irmAccesses.Count)] $($irmAccess.User)" -NoNewline + Write-Host "`r`n" -NoNewline + $dscIRMAccess = @{ + Identity = $mailbox.UserPrincipalName + User = $irmAccess.User + AccessLevel = $irmAccess.AccessLevel + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + CertificatePath = $CertificatePath + AccessTokens = $AccessTokens + } + + $Result = $dscIRMAccess + $Result = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Result + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Result ` + -Credential $Credential + $dscContent += $currentDSCBlock + + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $j++ + } + + $i++ + } + 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_EXOMailboxIRMAccess/MSFT_EXOMailboxIRMAccess.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/MSFT_EXOMailboxIRMAccess.schema.mof new file mode 100644 index 0000000000..8dc3e7f108 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/MSFT_EXOMailboxIRMAccess.schema.mof @@ -0,0 +1,14 @@ +[ClassVersion("1.0.0.0"), FriendlyName("EXOMailboxIRMAccess")] +class MSFT_EXOMailboxIRMAccess : OMI_BaseResource +{ + [Key, Description("The Identity parameter specifies the mailbox that you want to modify")] String Identity; + [Key, Description("The User parameter specifies the delegate who is blocked from reading IRM-protected messages in the mailbox.")] String User; + [Write, Description("The AccessLevel parameter specifies what delegates can do to IRM-protected messages in the mailbox that's specified by the Identity parameter."), ValueMap{"Block"}, Values{"Block"}] string AccessLevel; + [Write, Description("Present ensures the resource 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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/readme.md new file mode 100644 index 0000000000..afc0ca3907 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/readme.md @@ -0,0 +1,6 @@ + +# EXOMailboxIRMAccess + +## Description + +Use this resource to set MailboxIRMAccess settings diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/settings.json new file mode 100644 index 0000000000..d622035579 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "EXOMailboxIRMAccess", + "description": "Description of what the resource is about.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/1-Create.ps1 new file mode 100644 index 0000000000..f47d2d2105 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/1-Create.ps1 @@ -0,0 +1,33 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOMailboxIRMAccess "EXOMailboxIRMAccess-qwe@testorg.onmicrosoft.com" + { + AccessLevel = "Block"; + Credential = $Credscredential; + Ensure = "Present"; + Identity = "qwe@$OrganizationName"; + User = "admin@$OrganizationName"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxIRMAccess/2-Update.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index d8d8db6694..f504c14a0a 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -1,4 +1,50 @@ # region ExchangeOnlineManagement +function Get-MailboxIRMAccess +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $User, + + [Parameter()] + [System.Object] + $Identity + ) +} + +function Set-MailboxIRMAccess +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $User, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $AccessLevel + ) +} + +function Remove-MailboxIRMAccess +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $User, + + [Parameter()] + [System.Object] + $Identity + ) +} + function Get-SweepRule { [CmdletBinding()] From 55081bef12d58aec2129f09aa777a33ceac84440 Mon Sep 17 00:00:00 2001 From: ritikmit Date: Wed, 4 Sep 2024 10:42:53 +0530 Subject: [PATCH 041/465] Fixed permissions --- .../MSFT_EXOPhishSimOverrideRule/settings.json | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json index 745b156e7b..c009359f55 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json @@ -1,12 +1,12 @@ { - "resourceName": "EXOPhishSimOverrideRule", - "description": "", + "resourceName": "EXOSweepRule", + "description": "Use this resource to manage phish sim override rules.", "roles": { "read": [ - "Global Reader" + "Exchange Admin" ], "update": [ - "Exchange Administrator" + "Exchange Admin" ] }, "permissions": { @@ -19,16 +19,6 @@ "read": [], "update": [] } - }, - "exchange": { - "requiredroles": [ - "Organization Management", - "Recipient Management" - ], - "requiredrolegroups": [ - "Organization Management", - "Help Desk" - ] } } } From 4b1ac8928767942db4b7b0116b235f358f9143f1 Mon Sep 17 00:00:00 2001 From: ritikmit Date: Wed, 4 Sep 2024 11:13:25 +0530 Subject: [PATCH 042/465] Added EXOSecOpsOverrideRule Resource --- .../MSFT_EXOSecOpsOverrideRule.psm1 | 350 ++++++++++++++++++ .../MSFT_EXOSecOpsOverrideRule.schema.mof | 13 + .../MSFT_EXOSecOpsOverrideRule/readme.md | 6 + .../MSFT_EXOSecOpsOverrideRule/settings.json | 32 ++ .../Resources/ResourceName/1-Create.ps1 | 26 ++ .../Resources/ResourceName/2-Update.ps1 | 26 ++ .../Resources/ResourceName/3-Remove.ps1 | 26 ++ .../Microsoft365DSC.ResourceName.Tests.ps1 | 176 +++++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 71 ++++ 9 files changed, 726 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 new file mode 100644 index 0000000000..7d42466c4c --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 @@ -0,0 +1,350 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace the workload by the one associated to your resource + New-M365DSCConnection -Workload 'Workload' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + ##TODO - Replace the PrimaryKey in the Filter by the one for the resource + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.PrimaryKey -eq $PrimaryKey} + } + else + { + ##TODO - Replace the cmdlet by the one to retrieve a specific instance. + $instance = Get-cmdlet -PrimaryKey $PrimaryKey -ErrorAction Stop + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + ##TODO - Add the list of parameters to be returned + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + 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 + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + ##TODO - Replace by the New cmdlet for the resource + New-Cmdlet @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Update/Set cmdlet for the resource + Set-cmdlet @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Remove cmdlet for the resource + Remove-cmdlet @SetParameters + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace workload + $ConnectionMode = New-M365DSCConnection -Workload 'Workload' ` + -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 + { + $Script:ExportMode = $true + ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances + [array] $Script:exportedInstances = Get-Cmdlet -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + ##TODO - Specify the Primary Key + #PrimaryKey = $config.PrimaryKey + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof new file mode 100644 index 0000000000..6fa43ce435 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof @@ -0,0 +1,13 @@ +[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] +class MSFT_ResourceName : OMI_BaseResource +{ + [Key, Description("")] String PrimaryKey; + [Write, Description("")] String OtherProperties; + + [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; \ No newline at end of file diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/readme.md new file mode 100644 index 0000000000..32e0e7fb27 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/readme.md @@ -0,0 +1,6 @@ + +# ResourceName + +## Description + +##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/settings.json new file mode 100644 index 0000000000..edf14b05e4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "ResourceName", + "description": "Description of what the resource is about.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 new file mode 100644 index 0000000000..20857e0393 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 @@ -0,0 +1,176 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -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 a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 remove the instance from the Set method' { + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + 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 + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index d8d8db6694..6925634ba0 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -149,6 +149,8 @@ function Set-SweepRule ) } + + function Get-DefaultTenantBriefingConfig { [CmdletBinding()] @@ -302,6 +304,75 @@ function Add-RecipientPermission $Trustee ) } +function Get-ExoSecOpsOverrideRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $Policy + ) +} + +function New-ExoSecOpsOverrideRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Object] + $Policy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $Comment + ) +} +function Remove-ExoSecOpsOverrideRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $Identity + ) +} +function Set-ExoSecOpsOverrideRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $Comment, + + [Parameter()] + [System.Object] + $Identity + ) +} function Disable-JournalRule { [CmdletBinding()] From 68ae07aae4ec20567825b9f22a7177ff5b6f9203 Mon Sep 17 00:00:00 2001 From: ritikmit Date: Wed, 4 Sep 2024 12:32:46 +0530 Subject: [PATCH 043/465] Added Policy param --- .../MSFT_EXOPhishSimOverrideRule.psm1 | 24 +++++++++++++++---- .../MSFT_EXOPhishSimOverrideRule.schema.mof | 1 + .../EXOPhishSimOverrideRule/1-Create.ps1 | 1 + Tests/Unit/Stubs/Microsoft365.psm1 | 4 ++-- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 index f0f6917106..a4740deb97 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 @@ -20,6 +20,10 @@ function Get-TargetResource [System.String] $Comment, + [Parameter()] + [System.String] + $Policy, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -83,10 +87,11 @@ function Get-TargetResource } $results = @{ - Identity = $instance.Identity - SenderIpRanges = $instance.SenderIpRanges - Domains = $instance.Domains - Comment = $instance.Comment + Identity = $instance.Identity + SenderIpRanges = $instance.SenderIpRanges + Domains = $instance.Domains + Comment = $instance.Comment + Policy = $instance.Policy Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -158,6 +163,10 @@ function Set-TargetResource [System.String] $Comment, + [Parameter()] + [System.String] + $Policy, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -251,6 +260,10 @@ function Test-TargetResource [System.String] $Comment, + [Parameter()] + [System.String] + $Policy, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -418,5 +431,6 @@ function Export-TargetResource return '' } } - +$Credential = Get-Credential +Test-TargetResource -Identity "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b" -Policy "fc55717b-28bb-4cf3-98ee-9ba57903c978" -Domains @("fabrikam.com","wingtiptoys.com") -SenderIpRanges @("192.168.1.55") -Comment "abc" -Ensure "Present" -Credential $Credential Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.schema.mof index 539215c4e6..ddc28bdfd4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.schema.mof @@ -12,5 +12,6 @@ class MSFT_EXOPhishSimOverrideRule : OMI_BaseResource [Write, Description("The domains for the override rule.")] String Domains[]; [Write, Description("The IP ranges for the override rule.")] String SenderIpRanges[]; [Write, Description("An optional comment for the override rule.")] String Comment; + [Write, Description("The phishing simulation override policy that's associated with the rule.")] String Policy; [Write, Description("Ensures the presence or absence of the configuration.")] String Ensure; }; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/1-Create.ps1 index c47de1b845..7556c1cd1d 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/1-Create.ps1 @@ -28,6 +28,7 @@ Configuration Example Domains = @("fabrikam.com","wingtiptoys.com"); Ensure = "Present"; Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + Policy = "fc55717b-28bb-4cf3-98ee-9ba57903c978"; SenderIpRanges = @("192.168.1.55"); ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index ffc3d9f7c9..a3e7b9b348 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -162,7 +162,7 @@ function Get-ExoPhishSimOverrideRule $Identity, [Parameter()] - [System.Object] + [System.String] $Policy ) } @@ -192,7 +192,7 @@ function New-ExoPhishSimOverrideRule $Comment, [Parameter()] - [System.Object] + [System.String] $Policy ) } From d46ed7264a26c83c072f32dbfee1977e9112af00 Mon Sep 17 00:00:00 2001 From: ritikmit Date: Wed, 4 Sep 2024 12:40:37 +0530 Subject: [PATCH 044/465] Removed unrequired code --- .../MSFT_EXOPhishSimOverrideRule.psm1 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 index a4740deb97..445b4c496f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 @@ -431,6 +431,5 @@ function Export-TargetResource return '' } } -$Credential = Get-Credential -Test-TargetResource -Identity "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b" -Policy "fc55717b-28bb-4cf3-98ee-9ba57903c978" -Domains @("fabrikam.com","wingtiptoys.com") -SenderIpRanges @("192.168.1.55") -Comment "abc" -Ensure "Present" -Credential $Credential + Export-ModuleMember -Function *-TargetResource From 4c40415e0b05b0282100f615d587dcf771aa83b8 Mon Sep 17 00:00:00 2001 From: ritikmit Date: Wed, 4 Sep 2024 14:22:37 +0530 Subject: [PATCH 045/465] Fix permissions file --- .../DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json index c009359f55..73353fa2e3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json @@ -1,5 +1,5 @@ { - "resourceName": "EXOSweepRule", + "resourceName": "EXOPhishSimOverrideRule", "description": "Use this resource to manage phish sim override rules.", "roles": { "read": [ From 123d683d3d3cba76e97ca14892a1d6697981a622 Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Wed, 4 Sep 2024 14:29:42 +0530 Subject: [PATCH 046/465] Fix json encoding --- .../DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json index 73353fa2e3..2c02172d8e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/settings.json @@ -1,4 +1,4 @@ -{ +{ "resourceName": "EXOPhishSimOverrideRule", "description": "Use this resource to manage phish sim override rules.", "roles": { From 691128fb9f6ef9f8d766060260d9b37b9f55ec03 Mon Sep 17 00:00:00 2001 From: ritikmit Date: Wed, 4 Sep 2024 14:50:10 +0530 Subject: [PATCH 047/465] More changes --- .../MSFT_EXOSecOpsOverrideRule.psm1 | 83 +++++++++++++------ .../MSFT_EXOSecOpsOverrideRule.schema.mof | 12 +-- .../MSFT_EXOSecOpsOverrideRule/readme.md | 5 +- .../MSFT_EXOSecOpsOverrideRule/settings.json | 20 ++--- 4 files changed, 72 insertions(+), 48 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 index 7d42466c4c..7f3dc4c1f7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 @@ -4,12 +4,22 @@ function Get-TargetResource [OutputType([System.Collections.Hashtable])] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $Identity, - ##TODO - Add the list of Parameters + [Parameter()] + [System.String] + $Comment, + + [Parameter()] + [System.String] + $Policy, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', [Parameter()] [System.Management.Automation.PSCredential] @@ -36,8 +46,7 @@ function Get-TargetResource $AccessTokens ) - ##TODO - Replace the workload by the one associated to your resource - New-M365DSCConnection -Workload 'Workload' ` + New-M365DSCConnection -Workload 'ExchangeOnline' ` -InboundParameters $PSBoundParameters | Out-Null #Ensure the proper dependencies are installed in the current environment. @@ -58,13 +67,11 @@ function Get-TargetResource { if ($null -ne $Script:exportedInstances -and $Script:ExportMode) { - ##TODO - Replace the PrimaryKey in the Filter by the one for the resource - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.PrimaryKey -eq $PrimaryKey} + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Identity -eq $Identity} } else { - ##TODO - Replace the cmdlet by the one to retrieve a specific instance. - $instance = Get-cmdlet -PrimaryKey $PrimaryKey -ErrorAction Stop + $instance = Get-EXOSecOpsOverrideRule -PrimaryKey $PrimaryKey -ErrorAction Stop } if ($null -eq $instance) { @@ -72,7 +79,9 @@ function Get-TargetResource } $results = @{ - ##TODO - Add the list of parameters to be returned + Identity = $instance.Identity + Comment = $instance.Comment + Policy = $instance.Policy Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -100,12 +109,22 @@ function Set-TargetResource [CmdletBinding()] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $Identity, + + [Parameter()] + [System.String] + $Comment, + + [Parameter()] + [System.String] + $Policy, - ##TODO - Add the list of Parameters + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', [Parameter()] [System.Management.Automation.PSCredential] @@ -151,20 +170,20 @@ function Set-TargetResource # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - ##TODO - Replace by the New cmdlet for the resource - New-Cmdlet @SetParameters + $ruleIdentity = $setParameters['Identity'] + $setParameters.Add("Name", $ruleIdentity) + $setParameters.Remove("Identity") + New-EXOSecOpsOverrideRule @SetParameters } # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - ##TODO - Replace by the Update/Set cmdlet for the resource - Set-cmdlet @SetParameters + Set-EXOSecOpsOverrideRule @SetParameters } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - ##TODO - Replace by the Remove cmdlet for the resource - Remove-cmdlet @SetParameters + Remove-EXOSecOpsOverrideRule @SetParameters } } @@ -174,12 +193,22 @@ function Test-TargetResource [OutputType([System.Boolean])] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $Identity, + + [Parameter()] + [System.String] + $Comment, + + [Parameter()] + [System.String] + $Policy, - ##TODO - Add the list of Parameters + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', [Parameter()] [System.Management.Automation.PSCredential] @@ -270,7 +299,7 @@ function Export-TargetResource ) ##TODO - Replace workload - $ConnectionMode = New-M365DSCConnection -Workload 'Workload' ` + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` -InboundParameters $PSBoundParameters #Ensure the proper dependencies are installed in the current environment. @@ -288,8 +317,7 @@ function Export-TargetResource try { $Script:ExportMode = $true - ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances - [array] $Script:exportedInstances = Get-Cmdlet -ErrorAction Stop + [array] $Script:exportedInstances = Get-EXOSecOpsOverrideRule $i = 1 $dscContent = '' @@ -306,8 +334,9 @@ function Export-TargetResource $displayedKey = $config.Id Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline $params = @{ - ##TODO - Specify the Primary Key - #PrimaryKey = $config.PrimaryKey + Identity = $instance.Identity + Comment = $instance.Comment + Policy = $instance.Policy Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof index 6fa43ce435..384770fdc2 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof @@ -1,13 +1,15 @@ [ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] class MSFT_ResourceName : OMI_BaseResource { - [Key, Description("")] String PrimaryKey; - [Write, Description("")] String OtherProperties; - - [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Identity; [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; [Write, Description("Access token used for authentication.")] String AccessTokens[]; -}; \ No newline at end of file + + [Key, Description("The unique identifier (GUID or name) of the override rule. This parameter is mandatory.")] String PrimaryKey; + [Write, Description("An optional comment for the override rule.")] String Comment; + [Write, Description("The SecOps simulation override policy that's associated with the rule.")] String Policy; + [Write, Description("Ensures the presence or absence of the configuration.")] String Ensure; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/readme.md index 32e0e7fb27..bf657c2c98 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/readme.md @@ -1,6 +1,7 @@ -# ResourceName +# EXOSecOpsOverrideRule ## Description -##TODO - Provide a short description of what the resource is set to configure. +This resource allows users to manage resource to modify SecOps +override rules to bypass Exchange Online Protection filtering. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/settings.json index edf14b05e4..4a5626d5d0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/settings.json @@ -1,12 +1,12 @@ { - "resourceName": "ResourceName", - "description": "Description of what the resource is about.", + "resourceName": "EXOSecOpsOverrideRule", + "description": "Use this resource to manage phish sim override rules.", "roles": { "read": [ - "Role" + "Exchange Admin" ], "update": [ - "Role" + "Exchange Admin" ] }, "permissions": { @@ -16,16 +16,8 @@ "update": [] }, "application": { - "read": [ - { - "name": "Permission for Monitoring and Export" - } - ], - "update": [ - { - "name": "Permission for deploying" - } - ] + "read": [], + "update": [] } } } From 1291d76a0e1b6ce0d321d97f7b35f7858a91d3f9 Mon Sep 17 00:00:00 2001 From: ritikmit Date: Wed, 4 Sep 2024 17:44:52 +0530 Subject: [PATCH 048/465] Small fixes --- .../MSFT_EXOSecOpsOverrideRule.psm1 | 8 ++-- .../MSFT_EXOSecOpsOverrideRule.schema.mof | 8 ++-- .../1-Create.ps1 | 9 ++++- .../EXOSecOpsOverrideRule/2-Update.ps1 | 38 +++++++++++++++++++ .../3-Remove.ps1 | 7 +++- .../Resources/ResourceName/2-Update.ps1 | 26 ------------- 6 files changed, 60 insertions(+), 36 deletions(-) rename Modules/Microsoft365DSC/Examples/Resources/{ResourceName => EXOSecOpsOverrideRule}/1-Create.ps1 (52%) create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/2-Update.ps1 rename Modules/Microsoft365DSC/Examples/Resources/{ResourceName => EXOSecOpsOverrideRule}/3-Remove.ps1 (60%) delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 index 7f3dc4c1f7..81ccc875a8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 @@ -71,7 +71,7 @@ function Get-TargetResource } else { - $instance = Get-EXOSecOpsOverrideRule -PrimaryKey $PrimaryKey -ErrorAction Stop + $instance = Get-EXOSecOpsOverrideRule -Identity $Identity } if ($null -eq $instance) { @@ -334,9 +334,9 @@ function Export-TargetResource $displayedKey = $config.Id Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline $params = @{ - Identity = $instance.Identity - Comment = $instance.Comment - Policy = $instance.Policy + Identity = $config.Identity + Comment = $config.Comment + Policy = $config.Policy Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof index 384770fdc2..dc359367af 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof @@ -1,14 +1,14 @@ -[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] -class MSFT_ResourceName : OMI_BaseResource +[ClassVersion("1.0.0.0"), FriendlyName("EXOSecOpsOverrideRule")] +class MSFT_EXOSecOpsOverrideRule : OMI_BaseResource { - [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Identity; + [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; [Write, Description("Access token used for authentication.")] String AccessTokens[]; - [Key, Description("The unique identifier (GUID or name) of the override rule. This parameter is mandatory.")] String PrimaryKey; + [Key, Description("The unique identifier (GUID or name) of the override rule. This parameter is mandatory.")] String Identity; [Write, Description("An optional comment for the override rule.")] String Comment; [Write, Description("The SecOps simulation override policy that's associated with the rule.")] String Policy; [Write, Description("Ensures the presence or absence of the configuration.")] String Ensure; diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/1-Create.ps1 similarity index 52% rename from Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 rename to Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/1-Create.ps1 index b516274848..30bf69e8a9 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/1-Create.ps1 @@ -21,6 +21,13 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + EXOSecOpsOverrideRule "EXOSecOpsOverrideRule-_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245" + { + Comment = "TestComment"; + Credential = $Credscredential; + Ensure = "Present"; + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/2-Update.ps1 new file mode 100644 index 0000000000..1af8f7628f --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/2-Update.ps1 @@ -0,0 +1,38 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOSecOpsOverrideRule "EXOSecOpsOverrideRule-_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245" + { + Comment = "TestComment"; + Credential = $Credscredential; + Ensure = "Present"; + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; + Credential = $Credscredential; + Domains = @("fabrikam.com","wingtiptoys.com"); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/3-Remove.ps1 similarity index 60% rename from Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 rename to Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/3-Remove.ps1 index b516274848..f2cfff7388 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/3-Remove.ps1 @@ -21,6 +21,11 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + EXOSecOpsOverrideRule "EXOSecOpsOverrideRule-_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245" + { + Credential = $Credscredential; + Ensure = "Present"; + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 deleted file mode 100644 index b516274848..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -<# -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()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - - } -} From 41d9cdba66a8523739c1340087a319488c327e32 Mon Sep 17 00:00:00 2001 From: ritikmit Date: Wed, 4 Sep 2024 17:52:16 +0530 Subject: [PATCH 049/465] Added UTs --- ...oft365DSC.EXOSecOpsOverrideRule.Tests.ps1} | 68 ++++++++++++++----- 1 file changed, 50 insertions(+), 18 deletions(-) rename Tests/Unit/Microsoft365DSC/{Microsoft365DSC.ResourceName.Tests.ps1 => Microsoft365DSC.EXOSecOpsOverrideRule.Tests.ps1} (63%) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOSecOpsOverrideRule.Tests.ps1 similarity index 63% rename from Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 rename to Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOSecOpsOverrideRule.Tests.ps1 index 20857e0393..1e6b3407b0 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOSecOpsOverrideRule.Tests.ps1 @@ -35,7 +35,17 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets + Mock -CommandName Set-EXOSecOpsOverrideRule -MockWith { + return $null + } + + Mock -CommandName Remove-EXOSecOpsOverrideRule -MockWith { + return $null + } + + Mock -CommandName New-EXOSecOpsOverrideRule -MockWith { + return $null + } # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { @@ -47,13 +57,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + Comment = "TestComment"; + Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; Ensure = 'Present' Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-EXOSecOpsOverrideRule -MockWith { return $null } } @@ -65,23 +76,29 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should create a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one - Should -Invoke -CommandName New-Cmdlet -Exactly 1 + Set-TargetResource @testParams + Should -Invoke -CommandName New-EXOSecOpsOverrideRule -Exactly 1 } } Context -Name "The instance exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Absent' + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + Comment = "TestComment"; + Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; + Ensure = 'Absent'; Credential = $Credential; } ##TODO - Mock the Get-Cmdlet to return an instance Mock -CommandName Get-Cmdlet -MockWith { return @{ - + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + Comment = "TestComment"; + Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; + Ensure = 'Present'; + Credential = $Credential; } } } @@ -93,15 +110,17 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should remove the instance from the Set method' { - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-EXOSecOpsOverrideRule -Exactly 1 } } Context -Name "The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + Comment = "TestComment"; + Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; Ensure = 'Present' Credential = $Credential; } @@ -109,7 +128,11 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ##TODO - Mock the Get-Cmdlet to return the desired values Mock -CommandName Get-Cmdlet -MockWith { return @{ - + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + Comment = "TestComment"; + Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; + Ensure = 'Present'; + Credential = $Credential; } } } @@ -122,7 +145,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + Comment = "TestComment"; + Policy = "40528418-717d-4368-a1ae-7912918f8a1g"; Ensure = 'Present' Credential = $Credential; } @@ -130,7 +155,11 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ##TODO - Mock the Get-Cmdlet to return a drift Mock -CommandName Get-Cmdlet -MockWith { return @{ - + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + Comment = "TestComment"; + Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; + Ensure = 'Present'; + Credential = $Credential; } } } @@ -145,8 +174,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the Set method' { Set-TargetResource @testParams - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + Should -Invoke -CommandName Update-EXOSecOpsOverrideRule -Exactly 1 } } @@ -161,7 +189,11 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ##TODO - Mock the Get-Cmdlet to return an instance Mock -CommandName Get-Cmdlet -MockWith { return @{ - + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + Comment = "TestComment"; + Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; + Ensure = 'Present'; + Credential = $Credential; } } } From 67f90dab10ad5ccfdaec40b1adcce34d8d3e7bcd Mon Sep 17 00:00:00 2001 From: ritikmit Date: Wed, 4 Sep 2024 18:20:34 +0530 Subject: [PATCH 050/465] Fixed UTs --- .../MSFT_EXOSecOpsOverrideRule.psm1 | 3 ++- ...icrosoft365DSC.EXOSecOpsOverrideRule.Tests.ps1 | 14 +++++--------- Tests/Unit/Stubs/Microsoft365.psm1 | 15 --------------- 3 files changed, 7 insertions(+), 25 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 index 81ccc875a8..7c378d2fdf 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 @@ -178,12 +178,13 @@ function Set-TargetResource # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { + $setParameters.Remove("Policy") Set-EXOSecOpsOverrideRule @SetParameters } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - Remove-EXOSecOpsOverrideRule @SetParameters + Remove-EXOSecOpsOverrideRule -Identity $Identity } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOSecOpsOverrideRule.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOSecOpsOverrideRule.Tests.ps1 index 1e6b3407b0..9195f5b3fc 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOSecOpsOverrideRule.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOSecOpsOverrideRule.Tests.ps1 @@ -91,8 +91,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-EXOSecOpsOverrideRule -MockWith { return @{ Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; Comment = "TestComment"; @@ -125,8 +124,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-EXOSecOpsOverrideRule -MockWith { return @{ Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; Comment = "TestComment"; @@ -152,8 +150,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-EXOSecOpsOverrideRule -MockWith { return @{ Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; Comment = "TestComment"; @@ -174,7 +171,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the Set method' { Set-TargetResource @testParams - Should -Invoke -CommandName Update-EXOSecOpsOverrideRule -Exactly 1 + Should -Invoke -CommandName Set-EXOSecOpsOverrideRule -Exactly 1 } } @@ -186,8 +183,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-EXOSecOpsOverrideRule -MockWith { return @{ Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; Comment = "TestComment"; diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 6925634ba0..d71f902eb2 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -308,10 +308,6 @@ function Get-ExoSecOpsOverrideRule { [CmdletBinding()] param( - [Parameter()] - [System.Management.Automation.SwitchParameter] - $Confirm, - [Parameter()] [System.Object] $Identity, @@ -334,10 +330,6 @@ function New-ExoSecOpsOverrideRule [System.Object] $Policy, - [Parameter()] - [System.Management.Automation.SwitchParameter] - $Confirm, - [Parameter()] [System.String] $Comment @@ -347,9 +339,6 @@ function Remove-ExoSecOpsOverrideRule { [CmdletBinding()] param( - [Parameter()] - [System.Management.Automation.SwitchParameter] - $Confirm, [Parameter()] [System.Object] @@ -360,10 +349,6 @@ function Set-ExoSecOpsOverrideRule { [CmdletBinding()] param( - [Parameter()] - [System.Management.Automation.SwitchParameter] - $Confirm, - [Parameter()] [System.String] $Comment, From 7b81f9e6c61a19ebbee54b792e46da9a01d3550a Mon Sep 17 00:00:00 2001 From: ritikmit Date: Wed, 4 Sep 2024 18:22:35 +0530 Subject: [PATCH 051/465] Fixed json encoding --- .../DSCResources/MSFT_EXOSecOpsOverrideRule/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/settings.json index 4a5626d5d0..9c0ed5b836 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/settings.json @@ -1,4 +1,4 @@ -{ +{ "resourceName": "EXOSecOpsOverrideRule", "description": "Use this resource to manage phish sim override rules.", "roles": { From 342132849be46aff4f7b4477f45e315ef4c97b22 Mon Sep 17 00:00:00 2001 From: ritikmit Date: Thu, 5 Sep 2024 10:51:25 +0530 Subject: [PATCH 052/465] Fixed example --- .../Examples/Resources/EXOSecOpsOverrideRule/2-Update.ps1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/2-Update.ps1 index 1af8f7628f..0f617f9dde 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/2-Update.ps1 @@ -24,12 +24,10 @@ Configuration Example EXOSecOpsOverrideRule "EXOSecOpsOverrideRule-_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245" { Comment = "TestComment"; - Credential = $Credscredential; Ensure = "Present"; Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; Credential = $Credscredential; - Domains = @("fabrikam.com","wingtiptoys.com"); ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint From 03ba58028e500f099ac9ab1692485f327d2f257f Mon Sep 17 00:00:00 2001 From: namrataguptams <91058803+namrataguptams@users.noreply.github.com> Date: Thu, 5 Sep 2024 16:02:13 +0530 Subject: [PATCH 053/465] working fully --- .../MSFT_EXOArcConfig/MSFT_EXOArcConfig.psm1 | 415 ++++++++++++++++++ .../MSFT_EXOArcConfig.schema.mof | 15 + .../DSCResources/MSFT_EXOArcConfig/readme.md | 6 + .../MSFT_EXOArcConfig/settings.json | 34 ++ .../Resources/EXOArcConfig/2-Update.ps1 | 33 ++ .../Microsoft365DSC.EXOArcConfig.Tests.ps1 | 123 ++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 20 + 7 files changed, 646 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/MSFT_EXOArcConfig.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/MSFT_EXOArcConfig.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOArcConfig/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOArcConfig.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/MSFT_EXOArcConfig.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/MSFT_EXOArcConfig.psm1 new file mode 100644 index 0000000000..960cb08373 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/MSFT_EXOArcConfig.psm1 @@ -0,0 +1,415 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + [ValidateSet('Yes')] + $IsSingleInstance, + + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.String[]] + $ArcTrustedSealers, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + Write-Verbose -Message 'Getting EXO Arc Settings' + + if ($Global:CurrentModeIsExport) + { + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters ` + -SkipModuleReload $true + } + else + { + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + try + { + $ArcConfigSettings = Get-ArcConfig -ErrorAction Stop + + $result = @{ + IsSingleInstance = 'Yes' + ArcTrustedSealers = $ArcConfigSettings.ArcTrustedSealers + Credential = $Credential + Ensure = 'Present' + ApplicationId = $ApplicationId + CertificateThumbprint = $CertificateThumbprint + CertificatePath = $CertificatePath + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + TenantId = $TenantId + AccessTokens = $AccessTokens + } + + Write-Verbose -Message 'Found Arc config settings' + Write-Verbose -Message "Get-TargetResource Result: `n $(Convert-M365DscHashtableToString -Hashtable $result)" + return $result + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + [ValidateSet('Yes')] + $IsSingleInstance, + + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.String[]] + $ArcTrustedSealers, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 'Setting configuration of Arc Config' + + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters + + $ArcConfigParams = [System.Collections.Hashtable]($PSBoundParameters) + $ArcConfigParams.Remove('Ensure') | Out-Null + $ArcConfigParams.Remove('Credential') | Out-Null + $ArcConfigParams.Remove('ApplicationId') | Out-Null + $ArcConfigParams.Remove('TenantId') | Out-Null + $ArcConfigParams.Remove('CertificateThumbprint') | Out-Null + $ArcConfigParams.Remove('CertificatePath') | Out-Null + $ArcConfigParams.Remove('CertificatePassword') | Out-Null + $ArcConfigParams.Remove('ManagedIdentity') | Out-Null + $ArcConfigParams.Remove('IsSingleInstance') | Out-Null + $ArcConfigParams.Remove('AccessTokens') | Out-Null + + if (('Present' -eq $Ensure ) -and ($Null -ne $ArcConfigParams)) + { + Write-Verbose -Message "Setting Arc Config with values: $(Convert-M365DscHashtableToString -Hashtable $ArcConfigParams)" + Set-ArcConfig @ArcConfigParams + + Write-Verbose -Message 'Arc Config updated successfully' + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + [ValidateSet('Yes')] + $IsSingleInstance, + + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.String[]] + $ArcTrustedSealers, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 Arc Config settings' + + $CurrentValues = Get-TargetResource @PSBoundParameters + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + $ValuesToCheck = $PSBoundParameters + $ValuesToCheck.Remove('Ensure') | Out-Null + + # Need to remove Identity as Get-ArcConfig doesn't return Identity + $ValuesToCheck.Remove('Identity') | Out-Null + + $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()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' -InboundParameters $PSBoundParameters -SkipModuleReload $true + + #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 + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $ArcConfigSettings = Get-ArcConfig -ErrorAction Stop + $dscContent = '' + Write-Host "`r`n" -NoNewline + + Write-Host " |---[1/1]" -NoNewline + + $Params = @{ + IsSingleInstance = 'Yes' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + CertificatePath = $CertificatePath + AccessTokens = $AccessTokens + } + + $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 + 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_EXOArcConfig/MSFT_EXOArcConfig.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/MSFT_EXOArcConfig.schema.mof new file mode 100644 index 0000000000..8c1261e915 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/MSFT_EXOArcConfig.schema.mof @@ -0,0 +1,15 @@ +[ClassVersion("1.0.0.0"), FriendlyName("EXOArcConfig")] +class MSFT_EXOArcConfig : OMI_BaseResource +{ + [Key, Description("Only valid value is 'Yes'."), ValueMap{"Yes"}, Values{"Yes"}] String IsSingleInstance; + [Write, Description("Identity which indicates the organization.")] String Identity; + [Write, Description("The domain names of the ARC sealers.")] String ArcTrustedSealers[]; + [Write, Description("Specifies if this EmailTenantSettings should exist."), 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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; \ No newline at end of file diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/readme.md new file mode 100644 index 0000000000..c1d7d37c14 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/readme.md @@ -0,0 +1,6 @@ + +# EXOArcConfig + +## Description + +This resource manages the list of trusted Authenticated Received Chain (ARC) sealers that are configured in the organization. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/settings.json new file mode 100644 index 0000000000..3e8c121cd5 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/settings.json @@ -0,0 +1,34 @@ +{ + "resourceName": "EXOArcConfig", + "description": "This resource manages the list of trusted Authenticated Received Chain (ARC) sealers that are configured in the organization.", + "roles": { + "read": [ + "Global Reader" + ], + "update": [ + "Exchange Administrator" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + }, + "exchange": { + "requiredroles": [ + "Security Admin", + "Security Reader", + "Tenant AllowBlockList Manager", + "Transport Hygiene", + "View-Only Configuration" + ], + "requiredrolegroups": "Organization Management" + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOArcConfig/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOArcConfig/2-Update.ps1 new file mode 100644 index 0000000000..216c944862 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOArcConfig/2-Update.ps1 @@ -0,0 +1,33 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOArcConfig "EXOArcConfig-Test" + { + ArcTrustedSealers = "contoso.com"; + Ensure = "Present"; + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationId = $ApplicationId + } + } +} \ No newline at end of file diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOArcConfig.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOArcConfig.Tests.ps1 new file mode 100644 index 0000000000..7907b4f4aa --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOArcConfig.Tests.ps1 @@ -0,0 +1,123 @@ +[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 'EXOArcConfig' -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 New-M365DSCConnection -MockWith { + return 'Credentials' + } + + Mock -CommandName Get-PSSession -MockWith { + } + + Mock -CommandName Remove-PSSession -MockWith { + } + + Mock -CommandName Set-ArcConfig -MockWith { + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + + # Test contexts + Context -Name 'Configuration needs updating' -Fixture { + BeforeAll { + $testParams = @{ + IsSingleInstance = 'Yes' + ArcTrustedSealers = "cohovineyard.com,tailspintoys.com"; + Identity = "Default"; + Credential = $Credential + Ensure = "Present" + } + + Mock -CommandName Get-ArcConfig -MockWith { + return @{ + ArcTrustedSealers = "abc.com,cohovineyard.com,tailspintoys.com"; + } + } + + } + + 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-ArcConfig -Exactly 1 + } + } + + Context -Name 'Update not required.' -Fixture { + BeforeAll { + $testParams = @{ + IsSingleInstance = 'Yes' + ArcTrustedSealers = "abc.com,cohovineyard.com,tailspintoys.com"; + Identity = "Default"; + Credential = $Credential + Ensure = "Present" + } + + Mock -CommandName Get-ArcConfig -MockWith { + return @{ + ArcTrustedSealers = "abc.com,cohovineyard.com,tailspintoys.com"; + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-ArcConfig -MockWith { + return @{ + ArcTrustedSealers = "abc.com,cohovineyard.com,tailspintoys.com"; + } + } + } + + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope \ No newline at end of file diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index d8d8db6694..e2e1f26fa8 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -1,4 +1,24 @@ # region ExchangeOnlineManagement +function Get-ArcConfig +{ + [CmdletBinding()] + param() +} + +function Set-ArcConfig +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $ArcTrustedSealers, + + [Parameter()] + [System.Object] + $Identity + ) +} + function Get-SweepRule { [CmdletBinding()] From f4902f325db5889c974c1a561a65fac9cac2be13 Mon Sep 17 00:00:00 2001 From: namrataguptams <91058803+namrataguptams@users.noreply.github.com> Date: Thu, 5 Sep 2024 19:08:25 +0530 Subject: [PATCH 054/465] chnged changeLog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24b85d6bd6..a165525ef2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Change log for Microsoft365DSC # UNRELEASED - +* EXOArcConfig + * Initial Release. * EXOSweepRule * Initial Release. * M365DSCDRGUtil From f39e646b41a9817c7dd627b25934358665229ff1 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 6 Sep 2024 11:31:17 -0400 Subject: [PATCH 055/465] SPOAccessControlSettings added property EnableRestrictedAccessControl --- .../MSFT_SPOAccessControlSettings.psm1 | 59 ++++++++++++------- .../MSFT_SPOAccessControlSettings.schema.mof | 1 + .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 2 +- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SPOAccessControlSettings/MSFT_SPOAccessControlSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SPOAccessControlSettings/MSFT_SPOAccessControlSettings.psm1 index ea35a596ee..1a29f5f30b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SPOAccessControlSettings/MSFT_SPOAccessControlSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SPOAccessControlSettings/MSFT_SPOAccessControlSettings.psm1 @@ -45,6 +45,10 @@ function Get-TargetResource [System.UInt32] $EmailAttestationReAuthDays, + [Parameter()] + [System.Boolean] + $EnableRestrictedAccessControl, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -117,27 +121,28 @@ function Get-TargetResource $SPOAccessControlSettings = Get-PnPTenant -ErrorAction Stop return @{ - IsSingleInstance = 'Yes' - DisplayStartASiteOption = $SPOAccessControlSettings.DisplayStartASiteOption - StartASiteFormUrl = $SPOAccessControlSettings.StartASiteFormUrl - IPAddressEnforcement = $SPOAccessControlSettings.IPAddressEnforcement - IPAddressAllowList = $SPOAccessControlSettings.IPAddressAllowList - IPAddressWACTokenLifetime = $SPOAccessControlSettings.IPAddressWACTokenLifetime - DisallowInfectedFileDownload = $SPOAccessControlSettings.DisallowInfectedFileDownload - ExternalServicesEnabled = $SPOAccessControlSettings.ExternalServicesEnabled - EmailAttestationRequired = $SPOAccessControlSettings.EmailAttestationRequired - EmailAttestationReAuthDays = $SPOAccessControlSettings.EmailAttestationReAuthDays - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - ApplicationSecret = $ApplicationSecret - CertificatePassword = $CertificatePassword - CertificatePath = $CertificatePath - CertificateThumbprint = $CertificateThumbprint - Managedidentity = $ManagedIdentity.IsPresent - Ensure = 'Present' - ConditionalAccessPolicy = $SPOAccessControlSettings.ConditionalAccessPolicy - AccessTokens = $AccessTokens + IsSingleInstance = 'Yes' + DisplayStartASiteOption = $SPOAccessControlSettings.DisplayStartASiteOption + StartASiteFormUrl = $SPOAccessControlSettings.StartASiteFormUrl + IPAddressEnforcement = $SPOAccessControlSettings.IPAddressEnforcement + IPAddressAllowList = $SPOAccessControlSettings.IPAddressAllowList + IPAddressWACTokenLifetime = $SPOAccessControlSettings.IPAddressWACTokenLifetime + DisallowInfectedFileDownload = $SPOAccessControlSettings.DisallowInfectedFileDownload + ExternalServicesEnabled = $SPOAccessControlSettings.ExternalServicesEnabled + EmailAttestationRequired = $SPOAccessControlSettings.EmailAttestationRequired + EmailAttestationReAuthDays = $SPOAccessControlSettings.EmailAttestationReAuthDays + EnableRestrictedAccessControl = $SPOAccessControlSettings.RestrictedAccessControl + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificatePassword = $CertificatePassword + CertificatePath = $CertificatePath + CertificateThumbprint = $CertificateThumbprint + Managedidentity = $ManagedIdentity.IsPresent + Ensure = 'Present' + ConditionalAccessPolicy = $SPOAccessControlSettings.ConditionalAccessPolicy + AccessTokens = $AccessTokens } } catch @@ -203,6 +208,10 @@ function Set-TargetResource [System.UInt32] $EmailAttestationReAuthDays, + [Parameter()] + [System.Boolean] + $EnableRestrictedAccessControl, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -286,6 +295,7 @@ function Set-TargetResource $CurrentParameters.Remove('IPAddressEnforcement') $CurrentParameters.Remove('IPAddressAllowList') } + $tenant = Set-PnPTenant @CurrentParameters } @@ -336,6 +346,10 @@ function Test-TargetResource [System.UInt32] $EmailAttestationReAuthDays, + [Parameter()] + [System.Boolean] + $EnableRestrictedAccessControl, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -414,7 +428,8 @@ function Test-TargetResource 'ExternalServicesEnabled', ` 'EmailAttestationRequired', ` 'EmailAttestationReAuthDays', - 'ConditionalAccessPolicy') + 'ConditionalAccessPolicy', ` + 'EnableRestrictedAccessControl') Write-Verbose -Message "Test-TargetResource returned $TestResult" diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SPOAccessControlSettings/MSFT_SPOAccessControlSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SPOAccessControlSettings/MSFT_SPOAccessControlSettings.schema.mof index c3ca2476c9..f999384424 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SPOAccessControlSettings/MSFT_SPOAccessControlSettings.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SPOAccessControlSettings/MSFT_SPOAccessControlSettings.schema.mof @@ -11,6 +11,7 @@ class MSFT_SPOAccessControlSettings : OMI_BaseResource [Write, Description("Enables external services for a tenant. External services are defined as services that are not in the Office 365 datacenters.")] boolean ExternalServicesEnabled; [Write, Description("Sets email attestation to required")] boolean EmailAttestationRequired; [Write, Description("Sets email attestation re-auth days")] uint32 EmailAttestationReAuthDays; + [Write, Description("Enables or disables the restricted access control.")] boolean EnableRestrictedAccessControl; [Write, Description("Only value accepted is 'Present'"), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; [Write, Description("Credentials of the account to authenticate with."), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 5dec239d62..97782f27e6 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1710,7 +1710,7 @@ function New-M365DSCConnection [Parameter(Mandatory = $true)] [ValidateSet('AzureDevOPS', 'ExchangeOnline', 'Fabric', 'Intune', ` 'SecurityComplianceCenter', 'PnP', 'PowerPlatforms', ` - 'MicrosoftTeams', 'MicrosoftGraph', 'Tasks')] + 'MicrosoftTeams', 'MicrosoftGraph', 'SharePointOnlineREST', 'Tasks')] [System.String] $Workload, From 64d697b22209df9ed11c91ad226c181b3f24acb8 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 6 Sep 2024 14:18:41 -0400 Subject: [PATCH 056/465] Updates --- CHANGELOG.md | 5 ++++ .../MSFT_SPOAccessControlSettings.psm1 | 25 ++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c2ad6918c..bccd8aa9c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* SPOAccessControlSettings + * Added support for property EnableRestrictedAccessControl. + # 1.24.904.1 * EXOOwaMailboxPolicy diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SPOAccessControlSettings/MSFT_SPOAccessControlSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SPOAccessControlSettings/MSFT_SPOAccessControlSettings.psm1 index 1a29f5f30b..687543a436 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SPOAccessControlSettings/MSFT_SPOAccessControlSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SPOAccessControlSettings/MSFT_SPOAccessControlSettings.psm1 @@ -296,7 +296,30 @@ function Set-TargetResource $CurrentParameters.Remove('IPAddressAllowList') } - $tenant = Set-PnPTenant @CurrentParameters + $EnableRestrictedAccessControlValue = $null + if ($null -ne $EnableRestrictedAccessControl) + { + $EnableRestrictedAccessControlValue = $EnableRestrictedAccessControl + $CurrentParameters.Remove('EnableRestrictedAccessControl') | Out-Null + } + + Set-PnPTenant @CurrentParameters | Out-Null + + try + { + Set-PnPTenant -EnableRestrictedAccessControl $EnableRestrictedAccessControlValue -ErrorAction Stop | Out-Null + } + catch + { + if ($_.ErrorDetails.Message.Contains("This operation can't be performed as the tenant doesn't have the required license")) + { + Write-Warning -Message "The tenant doesn't have the required license to configure Restrcited Access Control." + } + else + { + Write-Error $_.ErrorDetails.Message + } + } } function Test-TargetResource From b80e5acb9104b8268aa51dee78d3ac3d7646ef49 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 6 Sep 2024 18:34:39 +0000 Subject: [PATCH 057/465] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/sharepoint/SPOAccessControlSettings.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/resources/sharepoint/SPOAccessControlSettings.md b/docs/docs/resources/sharepoint/SPOAccessControlSettings.md index cc24a9a375..bcfe8f4ad9 100644 --- a/docs/docs/resources/sharepoint/SPOAccessControlSettings.md +++ b/docs/docs/resources/sharepoint/SPOAccessControlSettings.md @@ -14,6 +14,7 @@ | **ExternalServicesEnabled** | Write | Boolean | Enables external services for a tenant. External services are defined as services that are not in the Office 365 datacenters. | | | **EmailAttestationRequired** | Write | Boolean | Sets email attestation to required | | | **EmailAttestationReAuthDays** | Write | UInt32 | Sets email attestation re-auth days | | +| **EnableRestrictedAccessControl** | Write | Boolean | Enables or disables the restricted access control. | | | **Ensure** | Write | String | Only value accepted is 'Present' | `Present`, `Absent` | | **Credential** | Write | PSCredential | Credentials of the account to authenticate with. | | | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | From 008dc64b5ac65a081039be17afd572907979e64a Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 6 Sep 2024 18:36:48 +0000 Subject: [PATCH 058/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index ff560fdb1f..c093f98711 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -39042,6 +39042,11 @@ "Name": "EmailAttestationReAuthDays", "Option": "Write" }, + { + "CIMType": "boolean", + "Name": "EnableRestrictedAccessControl", + "Option": "Write" + }, { "CIMType": "String", "Name": "Ensure", From 1e92c12703b05aeb6feaaec31a8846784c6d21dc Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Sun, 8 Sep 2024 12:18:45 +0200 Subject: [PATCH 059/465] Fix invalid parameter definition --- CHANGELOG.md | 3 +++ ...IntuneAntivirusPolicyWindows10SettingCatalog.psm1 | 12 ++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bccd8aa9c8..c01d2ac4f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ # UNRELEASED +* IntuneAntivirusPolicyWindows10SettingCatalog + * Fixes an issue with invalid parameter definition. + FIXES [#5015](https://github.com/microsoft/Microsoft365DSC/issues/5015) * SPOAccessControlSettings * Added support for property EnableRestrictedAccessControl. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.psm1 index ee80cfb92b..79cd8949f8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.psm1 @@ -90,11 +90,11 @@ function Get-TargetResource [System.int32] $avgcpuloadfactor, - [Parameter] + [Parameter()] [System.Int32] $archivemaxdepth, - [Parameter] + [Parameter()] [System.Int32] $archivemaxsize, @@ -601,11 +601,11 @@ function Set-TargetResource [System.int32] $avgcpuloadfactor, - [Parameter] + [Parameter()] [System.Int32] $archivemaxdepth, - [Parameter] + [Parameter()] [System.Int32] $archivemaxsize, @@ -1095,11 +1095,11 @@ function Test-TargetResource [System.int32] $avgcpuloadfactor, - [Parameter] + [Parameter()] [System.Int32] $archivemaxdepth, - [Parameter] + [Parameter()] [System.Int32] $archivemaxsize, From e431c5e6c4c97a5269764b883ed3abc65b64af61 Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Mon, 9 Sep 2024 10:31:21 +0200 Subject: [PATCH 060/465] updated changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bccd8aa9c8..cc7285ea30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* AADPasswordRuleSettings + * Initial release * SPOAccessControlSettings * Added support for property EnableRestrictedAccessControl. From a6ffb794512d7ab4f61e99c471922b88a7b999fd Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Mon, 9 Sep 2024 14:55:18 +0200 Subject: [PATCH 061/465] fixed verbose messages --- .../MSFT_AADPasswordRuleSettings.psm1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.psm1 index 2f293f01f6..4c4d286efe 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPasswordRuleSettings/MSFT_AADPasswordRuleSettings.psm1 @@ -68,7 +68,7 @@ function Get-TargetResource $AccessTokens ) - Write-Verbose -Message 'Getting configuration of AzureAD Groups Settings' + Write-Verbose -Message 'Getting configuration of AzureAD Password Rule Settings' $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` -InboundParameters $PSBoundParameters @@ -207,7 +207,7 @@ function Set-TargetResource $AccessTokens ) - Write-Verbose -Message 'Setting configuration of Azure AD Groups Settings' + Write-Verbose -Message 'Setting configuration of Azure AD Password Rule Settings' #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies From 5144525384dbfbfa407e679829ac05c0127c0e55 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 9 Sep 2024 18:37:09 +0530 Subject: [PATCH 062/465] AI generated commit --- .../MSFT_EXORetentionPolicy.psm1 | 411 ++++++++++++++++++ .../MSFT_EXORetentionPolicy.schema.mof | 18 + .../MSFT_EXORetentionPolicy/readme.md | 5 + .../MSFT_EXORetentionPolicy/settings.json | 34 ++ 4 files changed, 468 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/MSFT_EXORetentionPolicy.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/MSFT_EXORetentionPolicy.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/settings.json diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/MSFT_EXORetentionPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/MSFT_EXORetentionPolicy.psm1 new file mode 100644 index 0000000000..c53c4c4322 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/MSFT_EXORetentionPolicy.psm1 @@ -0,0 +1,411 @@ + +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.Boolean] + $Force, + + [Parameter()] + [System.Boolean] + $IsDefault, + + [Parameter()] + [System.Boolean] + $IsDefaultArbitrationMailbox, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Guid] + $RetentionId, + + [Parameter()] + [System.String[]] + $RetentionPolicyTagLinks, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters | Out-Null + + 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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Identity -eq $Identity} + } + else + { + $instance = Get-RetentionPolicy -Identity $Identity -ErrorAction Stop + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + Ensure = 'Present' + Identity = [System.String]$Identity + Force = [System.Boolean]$Force + IsDefault = [System.Boolean]$IsDefault + IsDefaultArbitrationMailbox = [System.Boolean]$IsDefaultArbitrationMailbox + Name = [System.String]$Name + RetentionId = [System.Guid]$RetentionId + RetentionPolicyTagLinks = [System.String[]]$RetentionPolicyTagLinks + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + 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(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.Boolean] + $Force, + + [Parameter()] + [System.Boolean] + $IsDefault, + + [Parameter()] + [System.Boolean] + $IsDefaultArbitrationMailbox, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Guid] + $RetentionId, + + [Parameter()] + [System.String[]] + $RetentionPolicyTagLinks, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + $setParameters.Remove("Force") + New-RetentionPolicy @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Set-RetentionPolicy @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Remove-RetentionPolicy -Identity $Identity + } +} + + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.Boolean] + $Force, + + [Parameter()] + [System.Boolean] + $IsDefault, + + [Parameter()] + [System.Boolean] + $IsDefaultArbitrationMailbox, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Guid] + $RetentionId, + + [Parameter()] + [System.String[]] + $RetentionPolicyTagLinks, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters + + 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 + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-RetentionPolicy -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Identity + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Identity = $config.Identity + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_EXORetentionPolicy/MSFT_EXORetentionPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/MSFT_EXORetentionPolicy.schema.mof new file mode 100644 index 0000000000..a887a0973c --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/MSFT_EXORetentionPolicy.schema.mof @@ -0,0 +1,18 @@ +[ClassVersion("1.0.0.0"), FriendlyName("EXORetentionPolicy")] +class MSFT_EXORetentionPolicy : OMI_BaseResource +{ + [Key, Description("The Identity parameter specifies the name, distinguished name (DN), or GUID of the retention policy.")] String Identity; + [Write, Description("The Force switch hides warning or confirmation messages. You don't need to specify a value with this switch.")] Boolean Force; + [Write, Description("The IsDefault switch specifies that this retention policy is the default retention policy. You don't need to specify a value with this switch.")] Boolean IsDefault; + [Write, Description("The IsDefaultArbitrationMailbox switch configures this policy as the default retention policy for arbitration mailboxes in your Exchange Online organization. You don't need to specify a value with this switch.")] Boolean IsDefaultArbitrationMailbox; + [Write, Description("The Name parameter specifies a unique name for the retention policy.")] String Name; + [Write, Description("The RetentionId parameter specifies the identity of the retention policy to make sure mailboxes moved between two Exchange organizations continue to have the same retention policy applied to them.")] String RetentionId; + [Write, Description("The RetentionPolicyTagLinks parameter specifies the identity of retention policy tags to associate with the retention policy. Mailboxes that get a retention policy applied have retention tags linked with that retention policy.")] String RetentionPolicyTagLinks[]; + + [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/readme.md new file mode 100644 index 0000000000..08cbda5846 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/readme.md @@ -0,0 +1,5 @@ +# EXORetentionPolicy + +## Description + +Use the New-RetentionPolicy cmdlet to create a retention policy and the Set-RetentionPolicy cmdlet to change the properties of an existing retention policy. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/settings.json new file mode 100644 index 0000000000..f9832ee223 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/settings.json @@ -0,0 +1,34 @@ +{ + "resourceName": "EXOMailboxCalendarConfiguration", + "description": "", + "roles": { + "read": [ + "Global Reader" + ], + "update": [ + "Exchange Administrator" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + }, + "exchange": { + "requiredroles": [ + "Organization Management", + "Recipient Management" + ], + "requiredrolegroups": [ + "Organization Management", + "Help Desk" + ] + } + } +} From 66442b6123fe426d23e3657111dce9b6ea7a4232 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 9 Sep 2024 13:14:39 +0000 Subject: [PATCH 063/465] Updated Resources and Cmdlet documentation pages --- .../azure-ad/AADPasswordRuleSettings.md | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 docs/docs/resources/azure-ad/AADPasswordRuleSettings.md diff --git a/docs/docs/resources/azure-ad/AADPasswordRuleSettings.md b/docs/docs/resources/azure-ad/AADPasswordRuleSettings.md new file mode 100644 index 0000000000..66ff3a0bfb --- /dev/null +++ b/docs/docs/resources/azure-ad/AADPasswordRuleSettings.md @@ -0,0 +1,97 @@ +# AADPasswordRuleSettings + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **IsSingleInstance** | Key | String | Only valid value is 'Yes'. | `Yes` | +| **LockoutThreshold** | Write | UInt32 | The number of failed login attempts before the first lockout period begins. | | +| **LockoutDurationInSeconds** | Write | UInt32 | The duration in seconds of the initial lockout period. | | +| **EnableBannedPasswordCheck** | Write | Boolean | Boolean indicating if the banned password check for tenant specific banned password list is turned on or not. | | +| **BannedPasswordList** | Write | StringArray[] | A list of banned words in passwords. | | +| **BannedPasswordCheckOnPremisesMode** | Write | String | How should we enforce password policy check in on-premises system. | | +| **EnableBannedPasswordCheckOnPremises** | Write | Boolean | Boolean indicating if the banned password check is turned on or not for on-premises system. | | +| **Ensure** | Write | String | Specify if the Azure AD Password Rule Settings should exist or not. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials for the Microsoft Graph delegated permissions. | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory application to authenticate with. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +## Description + +This resource configures the Azure Active Directory Password Rule Settings. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - Directory.Read.All, Group.Read.All + +- **Update** + + - Directory.Read.All, Directory.ReadWrite.All + +#### Application permissions + +- **Read** + + - Directory.Read.All + +- **Update** + + - Directory.Read.All, Directory.ReadWrite.All + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADPasswordRuleSettings 'GeneralPasswordRuleSettings' + { + IsSingleInstance = "Yes" + LockoutThreshold = 6 + LockoutDurationInSeconds = 30 + BannedPasswordCheckOnPremisesMode = 'Audit' + EnableBannedPasswordCheckOnPremises = $false + EnableBannedPasswordCheck = $false + BannedPasswordList = $null + Ensure = "Present" + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + From ebf2730d8b966945c0f70e3735130684dbb456a1 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 9 Sep 2024 13:16:46 +0000 Subject: [PATCH 064/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index c093f98711..39576dcab5 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -3919,6 +3919,86 @@ } ] }, + { + "ClassName": "MSFT_AADPasswordRuleSettings", + "Parameters": [ + { + "CIMType": "String", + "Name": "IsSingleInstance", + "Option": "Key" + }, + { + "CIMType": "UInt32", + "Name": "LockoutThreshold", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "LockoutDurationInSeconds", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EnableBannedPasswordCheck", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "BannedPasswordList", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "BannedPasswordCheckOnPremisesMode", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EnableBannedPasswordCheckOnPremises", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AADRoleDefinition", "Parameters": [ From 2a92d72971a9a5cd2881d82ad73e07f43e14b317 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 9 Sep 2024 09:55:28 -0400 Subject: [PATCH 065/465] SCInsiderRiskEntityList - Initial Release --- CHANGELOG.md | 4 + .../MSFT_SCInsiderRiskEntityList.psm1 | 350 ++++++++++++++++++ .../MSFT_SCInsiderRiskEntityList.schema.mof | 13 + .../MSFT_SCInsiderRiskEntityList/readme.md | 6 + .../settings.json | 32 ++ .../Dependencies/Manifest.psd1 | 36 +- .../SCInsiderRiskEntityList/1-Create.ps1 | 26 ++ .../SCInsiderRiskEntityList/2-Update.ps1 | 26 ++ .../SCInsiderRiskEntityList/3-Remove.ps1 | 26 ++ ...ft365DSC.SCInsiderRiskEntityList.Tests.ps1 | 176 +++++++++ 10 files changed, 677 insertions(+), 18 deletions(-) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskEntityList.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index cc7285ea30..1ee23c0323 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,12 @@ * AADPasswordRuleSettings * Initial release +* SCInsiderRiskEntityList + * Initial release. * SPOAccessControlSettings * Added support for property EnableRestrictedAccessControl. +* DEPENDENCIES + * Updated Microsoft.Graph to version 2.23.0. # 1.24.904.1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 new file mode 100644 index 0000000000..7d42466c4c --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 @@ -0,0 +1,350 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace the workload by the one associated to your resource + New-M365DSCConnection -Workload 'Workload' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + ##TODO - Replace the PrimaryKey in the Filter by the one for the resource + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.PrimaryKey -eq $PrimaryKey} + } + else + { + ##TODO - Replace the cmdlet by the one to retrieve a specific instance. + $instance = Get-cmdlet -PrimaryKey $PrimaryKey -ErrorAction Stop + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + ##TODO - Add the list of parameters to be returned + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + 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 + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + ##TODO - Replace by the New cmdlet for the resource + New-Cmdlet @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Update/Set cmdlet for the resource + Set-cmdlet @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Remove cmdlet for the resource + Remove-cmdlet @SetParameters + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace workload + $ConnectionMode = New-M365DSCConnection -Workload 'Workload' ` + -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 + { + $Script:ExportMode = $true + ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances + [array] $Script:exportedInstances = Get-Cmdlet -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + ##TODO - Specify the Primary Key + #PrimaryKey = $config.PrimaryKey + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof new file mode 100644 index 0000000000..07accdc886 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof @@ -0,0 +1,13 @@ +[ClassVersion("1.0.0.0"), FriendlyName("SCInsiderRiskEntityList")] +class MSFT_SCInsiderRiskEntityList : OMI_BaseResource +{ + [Key, Description("")] String PrimaryKey; + [Write, Description("")] String OtherProperties; + + [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/readme.md new file mode 100644 index 0000000000..1a24877790 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/readme.md @@ -0,0 +1,6 @@ + +# SCInsiderRiskEntityList + +## Description + +##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/settings.json new file mode 100644 index 0000000000..c44468a9df --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "SCInsiderRiskEntityList", + "description": "Description of what the resource is about.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 717197df8f..1c36e81530 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -10,75 +10,75 @@ }, @{ ModuleName = 'Microsoft.Graph.Applications' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Authentication' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.DeviceManagement' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Devices.CorporateManagement' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.DeviceManagement.Administration' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.DeviceManagement.Enrollment' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Identity.DirectoryManagement' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Identity.Governance' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Identity.SignIns' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Reports' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Teams' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.DeviceManagement.Administration' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.DirectoryObjects' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Groups' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Planner' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Sites' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Users' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Users.Actions' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.PowerApps.Administration.PowerShell' diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/1-Create.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/1-Create.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/2-Update.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/3-Remove.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/3-Remove.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskEntityList.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskEntityList.Tests.ps1 new file mode 100644 index 0000000000..20857e0393 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskEntityList.Tests.ps1 @@ -0,0 +1,176 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -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 a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 remove the instance from the Set method' { + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + 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 + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 fdfb2228e005a6dade706f8a98a5006f98ec5465 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 9 Sep 2024 23:29:44 +0530 Subject: [PATCH 066/465] Extra fixes --- .../MSFT_EXORetentionPolicy.psm1 | 101 +++++++++--------- .../MSFT_EXORetentionPolicy.schema.mof | 3 +- 2 files changed, 54 insertions(+), 50 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/MSFT_EXORetentionPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/MSFT_EXORetentionPolicy.psm1 index c53c4c4322..fbd6d16c3a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/MSFT_EXORetentionPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/MSFT_EXORetentionPolicy.psm1 @@ -9,10 +9,6 @@ function Get-TargetResource [System.String] $Identity, - [Parameter()] - [System.Boolean] - $Force, - [Parameter()] [System.Boolean] $IsDefault, @@ -36,6 +32,11 @@ function Get-TargetResource [Parameter()] [System.Management.Automation.PSCredential] $Credential, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', [Parameter()] [System.String] @@ -58,7 +59,7 @@ function Get-TargetResource $AccessTokens ) - New-M365DSCConnection -Workload 'ExchangeOnline' ` + New-M365DSCConnection -Workload 'ExchangeOnline' ` -InboundParameters $PSBoundParameters | Out-Null Confirm-M365DSCDependencies @@ -66,8 +67,8 @@ function Get-TargetResource #region Telemetry $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` -Parameters $PSBoundParameters Add-M365DSCTelemetryEvent -Data $data #endregion @@ -91,13 +92,12 @@ function Get-TargetResource $results = @{ Ensure = 'Present' - Identity = [System.String]$Identity - Force = [System.Boolean]$Force - IsDefault = [System.Boolean]$IsDefault - IsDefaultArbitrationMailbox = [System.Boolean]$IsDefaultArbitrationMailbox - Name = [System.String]$Name - RetentionId = [System.Guid]$RetentionId - RetentionPolicyTagLinks = [System.String[]]$RetentionPolicyTagLinks + Identity = [System.String]$instance.Identity + IsDefault = [System.Boolean]$instance.IsDefault + IsDefaultArbitrationMailbox = [System.Boolean]$instance.IsDefaultArbitrationMailbox + Name = [System.String]$instance.Name + RetentionId = [System.Guid]$instance.RetentionId + RetentionPolicyTagLinks = [System.String[]]$instance.RetentionPolicyTagLinks Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId @@ -109,10 +109,10 @@ function Get-TargetResource } catch { - New-M365DSCLogEntry -Message 'Error retrieving data:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` -Credential $Credential return $nullResult @@ -129,10 +129,6 @@ function Set-TargetResource [System.String] $Identity, - [Parameter()] - [System.Boolean] - $Force, - [Parameter()] [System.Boolean] $IsDefault, @@ -152,6 +148,12 @@ function Set-TargetResource [Parameter()] [System.String[]] $RetentionPolicyTagLinks, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + [Parameter()] [System.Management.Automation.PSCredential] @@ -184,8 +186,8 @@ function Set-TargetResource #region Telemetry $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` -Parameters $PSBoundParameters Add-M365DSCTelemetryEvent -Data $data #endregion @@ -197,18 +199,18 @@ function Set-TargetResource # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - $setParameters.Remove("Force") + $setParameters.Remove("Identity") New-RetentionPolicy @SetParameters } # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - Set-RetentionPolicy @SetParameters + Set-RetentionPolicy @SetParameters -Force } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - Remove-RetentionPolicy -Identity $Identity + Remove-RetentionPolicy -Identity $Identity -Force } } @@ -223,10 +225,6 @@ function Test-TargetResource [System.String] $Identity, - [Parameter()] - [System.Boolean] - $Force, - [Parameter()] [System.Boolean] $IsDefault, @@ -246,6 +244,11 @@ function Test-TargetResource [Parameter()] [System.String[]] $RetentionPolicyTagLinks, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', [Parameter()] [System.Management.Automation.PSCredential] @@ -278,8 +281,8 @@ function Test-TargetResource #region Telemetry $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` -Parameters $PSBoundParameters Add-M365DSCTelemetryEvent -Data $data #endregion @@ -290,9 +293,9 @@ function Test-TargetResource Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" - $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` - -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` -ValuesToCheck $ValuesToCheck.Keys Write-Verbose -Message "Test-TargetResource returned $testResult" @@ -335,7 +338,7 @@ function Export-TargetResource $AccessTokens ) - $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` -InboundParameters $PSBoundParameters Confirm-M365DSCDependencies @@ -343,8 +346,8 @@ function Export-TargetResource #region Telemetry $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') $CommandName = $MyInvocation.MyCommand - $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` - -CommandName $CommandName ` + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` -Parameters $PSBoundParameters Add-M365DSCTelemetryEvent -Data $data #endregion @@ -379,16 +382,16 @@ function Export-TargetResource } $Results = Get-TargetResource @Params - $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` -Results $Results - $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` - -ConnectionMode $ConnectionMode ` - -ModulePath $PSScriptRoot ` - -Results $Results ` + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` -Credential $Credential $dscContent += $currentDSCBlock - Save-M365DSCPartialExport -Content $currentDSCBlock ` + Save-M365DSCPartialExport -Content $currentDSCBlock ` -FileName $Global:PartialExportFileName $i++ Write-Host $Global:M365DSCEmojiGreenCheckMark @@ -399,10 +402,10 @@ function Export-TargetResource { Write-Host $Global:M365DSCEmojiRedX - New-M365DSCLogEntry -Message 'Error during Export:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` -Credential $Credential return '' diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/MSFT_EXORetentionPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/MSFT_EXORetentionPolicy.schema.mof index a887a0973c..06fc8d548a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/MSFT_EXORetentionPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORetentionPolicy/MSFT_EXORetentionPolicy.schema.mof @@ -2,13 +2,14 @@ class MSFT_EXORetentionPolicy : OMI_BaseResource { [Key, Description("The Identity parameter specifies the name, distinguished name (DN), or GUID of the retention policy.")] String Identity; - [Write, Description("The Force switch hides warning or confirmation messages. You don't need to specify a value with this switch.")] Boolean Force; [Write, Description("The IsDefault switch specifies that this retention policy is the default retention policy. You don't need to specify a value with this switch.")] Boolean IsDefault; [Write, Description("The IsDefaultArbitrationMailbox switch configures this policy as the default retention policy for arbitration mailboxes in your Exchange Online organization. You don't need to specify a value with this switch.")] Boolean IsDefaultArbitrationMailbox; [Write, Description("The Name parameter specifies a unique name for the retention policy.")] String Name; [Write, Description("The RetentionId parameter specifies the identity of the retention policy to make sure mailboxes moved between two Exchange organizations continue to have the same retention policy applied to them.")] String RetentionId; [Write, Description("The RetentionPolicyTagLinks parameter specifies the identity of retention policy tags to associate with the retention policy. Mailboxes that get a retention policy applied have retention tags linked with that retention policy.")] String RetentionPolicyTagLinks[]; + + [Write, Description("Specifies if this report submission rule should exist."), 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; From 647f42858956dbfdf0fea58734b2e038692f5761 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Mon, 9 Sep 2024 16:20:20 -0700 Subject: [PATCH 067/465] 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 068/465] 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 c19bed2f18ddc3904f837200da3df003afcce5a3 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Tue, 10 Sep 2024 09:59:53 +0530 Subject: [PATCH 069/465] first commit --- .../MSFT_EXOMailboxFolderPermission.psm1 | 423 ++++++++++++++++++ ...MSFT_EXOMailboxFolderPermission.schema.mof | 18 + .../MSFT_EXOMailboxFolderPermission/readme.md | 6 + .../settings.json | 24 + .../Resources/ResourceName/1-Create.ps1 | 26 ++ .../Resources/ResourceName/2-Update.ps1 | 26 ++ .../Resources/ResourceName/3-Remove.ps1 | 26 ++ .../Microsoft365DSC.ResourceName.Tests.ps1 | 176 ++++++++ 8 files changed, 725 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 new file mode 100644 index 0000000000..52c04f2ae6 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 @@ -0,0 +1,423 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter(Mandatory = $true)] + [System.String[]] + $AccessRights, + + [Parameter(Mandatory = $true)] + [System.String] + [ValidateSet("None", "Delegate", "CanViewPrivateItems")] + $SharingPermissionFlags, + + [Parameter(Mandatory = $true)] + [System.String] + $User, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace the workload by the one associated to your resource + New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Identity -eq $Identity -and $_.User -eq $User} + } + else + { + $instance = Get-MailboxFolderPermission -Identity $Identity -User $User -ErrorAction Stop + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + Identity = $Identity + User = $User + AccessRights = $instance.AccessRights + SharingPermissionFlags = $instance.SharingPermissionFlags + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + 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(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter(Mandatory = $true)] + [System.String[]] + $AccessRights, + + [Parameter(Mandatory = $true)] + [System.String] + [ValidateSet("None", "Delegate", "CanViewPrivateItems")] + $SharingPermissionFlags, + + [Parameter(Mandatory = $true)] + [System.String] + $User, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Add-MailboxFolderPermission @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Set-MailboxFolderPermission @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + $instanceParams.Remove('AccessTokens') | Out-Null + $instanceParams.Remove('SharingPermissionFlags') | Out-Null + Remove-MailboxFolderPermission @SetParameters -Confirm:$false + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter(Mandatory = $true)] + [System.String[]] + $AccessRights, + + [Parameter(Mandatory = $true)] + [System.String] + [ValidateSet("None", "Delegate", "CanViewPrivateItems")] + $SharingPermissionFlags, + + [Parameter(Mandatory = $true)] + [System.String] + $User, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace workload + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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]$mailboxes = Get-Mailbox -ResultSize 'Unlimited' -ErrorAction Stop + + if ($mailboxes.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + $dscContent = '' + $i = 1 + foreach ($mailbox in $mailboxes) + { + Write-Host " |---[$i/$($mailboxes.Count)] $($mailbox.UserPrincipalName)" -NoNewline + + [Array]$mailboxFolders = Get-MailboxFolder -Identity $mailbox.UserPrincipalName -Recurse + + $j = 1 + Write-Host "`r`n" -NoNewline + foreach ($mailboxFolder in $mailboxFolders) + { + [Array]$mailboxFolderPermissions = Get-MailboxFolderPermission -Identity $mailboxFolder.Identity + + Write-Host " |---[$j/$($mailboxFolders.count)] $($mailboxFolder.Identity)" -NoNewline + Write-Host "`r`n" -NoNewline + + foreach ($permission in $mailboxFolderPermissions) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + Write-Host " |---[$j/$($mailboxFolderPermissions.Count)] $($permission.User)" -NoNewline + Write-Host "`r`n" -NoNewline + + $dscIRMAccess = @{ + Identity = $permission.Identity + User = $permission.User + AccessRights = $permission.AccessRights + SharingPermissionFlags = $permission.SharingPermissionFlags + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + CertificatePath = $CertificatePath + AccessTokens = $AccessTokens + } + + $Result = $dscIRMAccess + $Result = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Result + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Result ` + -Credential $Credential + $dscContent += $currentDSCBlock + + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + + } + $j++ + } + + $i++ + } + 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_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.schema.mof new file mode 100644 index 0000000000..5a396e560c --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.schema.mof @@ -0,0 +1,18 @@ +[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] +class MSFT_ResourceName : OMI_BaseResource +{ + [Key, Description("The Identity parameter specifies the target mailbox and folder. The syntax is MailboxID:\ParentFolder[\SubFolder]. For the MailboxID you can use any value that uniquely identifies the mailbox.")] String Identity; + [Required, Description("The AccessRights parameter specifies the permissions that you want to add for the user on the mailbox folder.")] String AccessRights[]; + [Key, Description("The User parameter specifies who gets the permissions on the mailbox folder.")] String User; + [Key, Description("The SharingPermissionFlags parameter assigns calendar delegate permissions. This parameter only applies to calendar folders and can only be used when the AccessRights parameter value is Editor. Valid values are: None, Delegate, CanViewPrivateItems"), ValueMap{"None", "Delegate", "CanViewPrivateItems"}, Values{"None", "Delegate", "CanViewPrivateItems"}] String SharingPermissionFlags; + + [Write, Description("Determines wheter or not the permission should exist on the mailbox."), ValueMap{"Present"}, Values{"Present"}] String Ensure; + [Write, Description("Credentials of the Exchange Global 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("Username can be made up to anything but password will be used for CertificatePassword"), EmbeddedInstance("MSFT_Credential")] String CertificatePassword; + [Write, Description("Path to certificate used in service principal usually a PFX file.")] String CertificatePath; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/readme.md new file mode 100644 index 0000000000..6c2b64a330 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/readme.md @@ -0,0 +1,6 @@ + +# EXOMailboxFolderPermission + +## Description + +Use this resource to add/set/remove mailbox folder permissions for users in your tenant. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/settings.json new file mode 100644 index 0000000000..585ca11f72 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/settings.json @@ -0,0 +1,24 @@ +{ + "resourceName": "EXOMailboxFolderPermission", + "description": "Use this resource to add/set/remove mailbox folder permissions for users in your tenant.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 new file mode 100644 index 0000000000..20857e0393 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 @@ -0,0 +1,176 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -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 a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 remove the instance from the Set method' { + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + 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 + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 bdb2b7e5da235d7f06c93f87b707c69ee5431b21 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Tue, 10 Sep 2024 10:06:28 +0530 Subject: [PATCH 070/465] resolving comments --- .../MSFT_EXOManagementScope.psm1 | 11 +---------- .../MSFT_EXOManagementScope.schema.mof | 4 ++-- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/MSFT_EXOManagementScope.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/MSFT_EXOManagementScope.psm1 index 33a84bd0b3..bd19cc11f4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/MSFT_EXOManagementScope.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/MSFT_EXOManagementScope.psm1 @@ -54,7 +54,6 @@ function Get-TargetResource $AccessTokens ) - ##TODO - Replace the workload by the one associated to your resource New-M365DSCConnection -Workload 'ExchangeOnline' ` -InboundParameters $PSBoundParameters | Out-Null @@ -76,12 +75,10 @@ function Get-TargetResource { if ($null -ne $Script:exportedInstances -and $Script:ExportMode) { - ##TODO - Replace the PrimaryKey in the Filter by the one for the resource $ManagementScope = $Script:exportedInstances | Where-Object -FilterScript {$_.Identity -eq $Identity} } else { - ##TODO - Replace the cmdlet by the one to retrieve a specific instance. $ManagementScope = Get-ManagementScope -Identity $Identity -ErrorAction Stop } if ($null -eq $ManagementScope) @@ -90,7 +87,6 @@ function Get-TargetResource } $results = @{ - ##TODO - Add the list of parameters to be returned Identity = $Identity Name = $ManagementScope.Name RecipientRestrictionFilter = $ManagementScope.RecipientFilter @@ -210,7 +206,6 @@ function Set-TargetResource # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - ## should I just send identity to the remove cmdlet? Remove-ManagementScope -Identity $Identity } } @@ -334,7 +329,6 @@ function Export-TargetResource $AccessTokens ) - ##TODO - Replace workload $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` -InboundParameters $PSBoundParameters @@ -353,7 +347,6 @@ function Export-TargetResource try { $Script:ExportMode = $true - ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances [array] $Script:exportedInstances = Get-ManagementScope -ErrorAction Stop $i = 1 @@ -368,11 +361,9 @@ function Export-TargetResource } foreach ($config in $Script:exportedInstances) { - $displayedKey = $config.Id + $displayedKey = $config.Identity Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline $params = @{ - ##TODO - Specify the Primary Key - #PrimaryKey = $config.PrimaryKey Identity = $config.Identity Credential = $Credential ApplicationId = $ApplicationId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/MSFT_EXOManagementScope.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/MSFT_EXOManagementScope.schema.mof index 9c6726ec14..4fbc6b845d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/MSFT_EXOManagementScope.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOManagementScope/MSFT_EXOManagementScope.schema.mof @@ -6,11 +6,11 @@ class MSFT_EXOManagementScope : OMI_BaseResource [Write, Description("The RecipientRestrictionFilter parameter uses OPATH filter syntax to specify the recipients that are included in the scope.")] String RecipientRestrictionFilter; [Write, Description("The RecipientRoot parameter specifies the organizational unit (OU) under which the filter specified with the RecipientRestrictionFilter parameter should be applied.")] String RecipientRoot; [Write, Description("The Exclusive switch specifies that the role should be an exclusive scope.")] Boolean Exclusive; - [Write, Description("")] String Ensure; + [Write, Description("Specifies if this Outbound connector should exist."), 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("Managed ID being used for authentication.")] Boolean ManagedIdentity; [Write, Description("Access token used for authentication.")] String AccessTokens[]; -}; \ No newline at end of file +}; From a8080c1988ecf6e7417db127bdf0403ba2634e65 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Tue, 10 Sep 2024 15:58:04 +0530 Subject: [PATCH 071/465] Added UTs --- .../Resources/EXORetentionPolicy/1-Create.ps1 | 39 +++ .../Resources/EXORetentionPolicy/2-Update.ps1 | 40 ++++ .../Resources/EXORetentionPolicy/3-Remove.ps1 | 41 ++++ ...crosoft365DSC.EXORetentionPolicy.Tests.ps1 | 225 ++++++++++++++++++ 4 files changed, 345 insertions(+) create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXORetentionPolicy/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXORetentionPolicy/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXORetentionPolicy/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORetentionPolicy.Tests.ps1 diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXORetentionPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXORetentionPolicy/1-Create.ps1 new file mode 100644 index 0000000000..60526cc374 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXORetentionPolicy/1-Create.ps1 @@ -0,0 +1,39 @@ + +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXORetentionPolicy "EXORetentionPolicy-Test" + { + Name = "Test Retention Policy"; + Identity = "Test Retention Policy"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + RetentionPolicyTagLinks = @("6 Month Delete","Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); + Ensure = "Present"; + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXORetentionPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXORetentionPolicy/2-Update.ps1 new file mode 100644 index 0000000000..327596b942 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXORetentionPolicy/2-Update.ps1 @@ -0,0 +1,40 @@ + + +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXORetentionPolicy "EXORetentionPolicy-Test" + { + Name = "Test Retention Policy"; + Identity = "Test Retention Policy"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + RetentionPolicyTagLinks = @("Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); # drifted property + Ensure = "Present"; + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXORetentionPolicy/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXORetentionPolicy/3-Remove.ps1 new file mode 100644 index 0000000000..6793de2f80 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXORetentionPolicy/3-Remove.ps1 @@ -0,0 +1,41 @@ + + + +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXORetentionPolicy "EXORetentionPolicy-Test" + { + Name = "Test Retention Policy"; + Identity = "Test Retention Policy"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + RetentionPolicyTagLinks = @("6 Month Delete","Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); + Ensure = "Absent"; + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORetentionPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORetentionPolicy.Tests.ps1 new file mode 100644 index 0000000000..f2a75a1328 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORetentionPolicy.Tests.ps1 @@ -0,0 +1,225 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + + Mock -CommandName New-RetentionPolicy -MockWith { + return $null + } + + Mock -CommandName Remove-RetentionPolicy -MockWith { + return $null + } + + Mock -CommandName Set-RetentionPolicy -MockWith { + return $null + } + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present'; + Credential = $Credential; + Identity = "Ritik"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + Name = "Ritik"; + RetentionId = "559f68de-1e58-4dcc-9d40-ba5ff0e4253e"; + RetentionPolicyTagLinks = @("6 Month Delete","Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); + } + + Mock -CommandName Get-RetentionPolicy -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 a new instance from the Set method' { + Should -Invoke -CommandName New-RetentionPolicy -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Absent'; + Credential = $Credential; + Identity = "Ritik"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + Name = "Ritik"; + RetentionId = "559f68de-1e58-4dcc-9d40-ba5ff0e4253e"; + RetentionPolicyTagLinks = @("6 Month Delete","Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); + } + + Mock -CommandName Get-RetentionPolicy -MockWith { + return @{ + Identity = "Ritik"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + Name = "Ritik"; + RetentionId = "559f68de-1e58-4dcc-9d40-ba5ff0e4253e"; + RetentionPolicyTagLinks = @("6 Month Delete","Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); + + } + } + } + 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 remove the instance from the Set method' { + Should -Invoke -CommandName Remove-RetentionPolicy -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present'; + Credential = $Credential; + Identity = "Ritik"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + Name = "Ritik"; + RetentionId = "559f68de-1e58-4dcc-9d40-ba5ff0e4253e"; + RetentionPolicyTagLinks = @("6 Month Delete","Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); + + } + + Mock -CommandName Get-RetentionPolicy -MockWith { + return @{ + Identity = "Ritik"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + Name = "Ritik"; + RetentionId = "559f68de-1e58-4dcc-9d40-ba5ff0e4253e"; + RetentionPolicyTagLinks = @("6 Month Delete","Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present'; + Credential = $Credential; + Identity = "Ritik"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + Name = "Ritik"; + RetentionId = "559f68de-1e58-4dcc-9d40-ba5ff0e4253e"; + RetentionPolicyTagLinks = @("6 Month Delete","Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); + + } + + Mock -CommandName Get-RetentionPolicy -MockWith { + return @{ + Identity = "Ritik"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $True; # drift + Name = "Ritik"; + RetentionId = "559f68de-1e58-4dcc-9d40-ba5ff0e4253e"; + RetentionPolicyTagLinks = @("6 Month Delete","Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); + + + } + } + } + + 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-RetentionPolicy -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-RetentionPolicy -MockWith { + return @{ + Identity = "Ritik"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + Name = "Ritik"; + RetentionId = "559f68de-1e58-4dcc-9d40-ba5ff0e4253e"; + RetentionPolicyTagLinks = @("6 Month Delete","Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); + } + } + } + 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 4720060812fb0dc24ace530a1263dc8b3570e323 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Tue, 10 Sep 2024 16:29:31 +0530 Subject: [PATCH 072/465] resolving comments --- .../MSFT_EXOMailboxIRMAccess/settings.json | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/settings.json index d622035579..df17329583 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxIRMAccess/settings.json @@ -1,12 +1,12 @@ { "resourceName": "EXOMailboxIRMAccess", - "description": "Description of what the resource is about.", + "description": "Use this resource to create block Mailbox IRM access for delegates.", "roles": { "read": [ - "Role" + "Global Reader" ], "update": [ - "Role" + "Exchange Administrator" ] }, "permissions": { @@ -16,17 +16,18 @@ "update": [] }, "application": { - "read": [ - { - "name": "Permission for Monitoring and Export" - } - ], - "update": [ - { - "name": "Permission for deploying" - } - ] + "read": [], + "update": [] } + }, + "exchange": { + "requiredroles": [ + "Hygiene Management", + "Compliance Management", + "Organization Management", + "View-Only Organization Management" + ], + "requiredrolegroups": "Organization Management" } } } From 46474a1f678ec4b2089c925a47e6dea148b9cbd6 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 10 Sep 2024 13:00:10 +0000 Subject: [PATCH 073/465] Updated Resources and Cmdlet documentation pages --- .../resources/exchange/EXOManagementScope.md | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 docs/docs/resources/exchange/EXOManagementScope.md diff --git a/docs/docs/resources/exchange/EXOManagementScope.md b/docs/docs/resources/exchange/EXOManagementScope.md new file mode 100644 index 0000000000..873248793d --- /dev/null +++ b/docs/docs/resources/exchange/EXOManagementScope.md @@ -0,0 +1,154 @@ +# EXOManagementScope + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Identity** | Key | String | The Identity parameter specifies the name of the management scope to modify. | | +| **Name** | Write | String | The Name parameter specifies the name of the management scope. | | +| **RecipientRestrictionFilter** | Write | String | The RecipientRestrictionFilter parameter uses OPATH filter syntax to specify the recipients that are included in the scope. | | +| **RecipientRoot** | Write | String | The RecipientRoot parameter specifies the organizational unit (OU) under which the filter specified with the RecipientRestrictionFilter parameter should be applied. | | +| **Exclusive** | Write | Boolean | The Exclusive switch specifies that the role should be an exclusive scope. | | +| **Ensure** | Write | String | Specifies if this Outbound connector should exist. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Use this resource to create ManagementScopes. + +## Permissions + +### Exchange + +To authenticate with Microsoft Exchange, this resource required the following permissions: + +#### Roles + +- Hygiene Management, Compliance Management, Organization Management, View-Only Organization Management + +#### Role Groups + +- Organization Management + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + EXOManagementScope "EXOManagementScope-Test New DGs" + { + Credential = $Credscredential; + Ensure = "Present"; + Exclusive = $False; + Identity = "Test New DGs"; + Name = "Test New DGs"; + RecipientRestrictionFilter = "Name -like 'Test*'"; + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOManagementScope "EXOManagementScope-Test New DGs" + { + Credential = $Credscredential; + Ensure = "Present"; + Exclusive = $False; + Identity = "Test New DGs"; + Name = "Test New DGs"; + RecipientRestrictionFilter = "Name -like 'NewTest*'"; + } + } +} +``` + +### Example 3 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOManagementScope "EXOManagementScope-Test New DGs" + { + Credential = $Credscredential; + Ensure = "Absent"; + Exclusive = $False; + Identity = "Test New DGs"; + Name = "Test New DGs"; + RecipientRestrictionFilter = "Name -like 'NewTest*'"; + } + + } +} +``` + From 2783b3d24155eea70c2ddfcbb5e91016a6046a9b Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 10 Sep 2024 13:03:03 +0000 Subject: [PATCH 074/465] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index f8f29f2774..dbdfbb1fd7 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -467,6 +467,15 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOManagementScope 'EXOManagementScope-Test New DGs' + { + Credential = $Credscredential; + Ensure = "Present"; + Exclusive = $False; + Identity = "Test New DGs"; + Name = "Test New DGs"; + RecipientRestrictionFilter = "Name -like 'Test*'"; + } EXOMessageClassification 'ConfigureMessageClassification' { Identity = "Contoso Message Classification" From 2b313849ef1ef97e12b35acbb3c155c89b0c8c62 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 10 Sep 2024 13:03:24 +0000 Subject: [PATCH 075/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 39576dcab5..90e653682a 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -10544,6 +10544,71 @@ } ] }, + { + "ClassName": "MSFT_EXOManagementScope", + "Parameters": [ + { + "CIMType": "String", + "Name": "Identity", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Name", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "RecipientRestrictionFilter", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "RecipientRoot", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "Exclusive", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOMessageClassification", "Parameters": [ From 12212d3c0d36ad0ae6c3599dc3083fe4af7dac04 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 10 Sep 2024 13:03:27 +0000 Subject: [PATCH 076/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index fb92ed7632..1187fe3ade 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -705,6 +705,15 @@ Identity = "Information Rights Management\Get-BookingMailbox" Parameters = @("ANR","RecipientTypeDetails", "ResultSize") } + EXOManagementScope 'EXOManagementScope-Test New DGs' + { + Credential = $Credscredential; + Ensure = "Present"; + Exclusive = $False; + Identity = "Test New DGs"; + Name = "Test New DGs"; + RecipientRestrictionFilter = "Name -like 'NewTest*'"; + } EXOMessageClassification 'ConfigureMessageClassification' { Identity = "Contoso Message Classification" From 1b3319d06ede378bc0a68cecfe9574be214c5891 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 10 Sep 2024 13:03:46 +0000 Subject: [PATCH 077/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Remove.Tests.ps1 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 index e192eb32a3..915a099176 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 @@ -330,6 +330,15 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOManagementScope 'EXOManagementScope-Test New DGs' + { + Credential = $Credscredential; + Ensure = "Absent"; + Exclusive = $False; + Identity = "Test New DGs"; + Name = "Test New DGs"; + RecipientRestrictionFilter = "Name -like 'NewTest*'"; + } EXOMessageClassification 'ConfigureMessageClassification' { Identity = "Contoso Message Classification" From b67079d3aef1fcf3d0c4471bf85d86c1851a2bbd Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Tue, 10 Sep 2024 18:49:04 +0530 Subject: [PATCH 078/465] Added Stubs --- Tests/Unit/Stubs/Microsoft365.psm1 | 100 +++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index d8d8db6694..ba770943c9 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -1,4 +1,104 @@ # region ExchangeOnlineManagement + + +function Get-RetentionPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $Identity + ) +} + +function New-RetentionPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Object[]] + $RetentionPolicyTagLinks, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsDefaultArbitrationMailbox, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsDefault, + + [Parameter()] + [System.Guid] + $RetentionId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} + + +function Remove-RetentionPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force + ) +} + + +function Set-RetentionPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Object[]] + $RetentionPolicyTagLinks, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsDefault, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Guid] + $RetentionId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsDefaultArbitrationMailbox, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force + ) +} + function Get-SweepRule { [CmdletBinding()] From b1a6280554103659b64ae9f667d6a2b47ab14b69 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Tue, 10 Sep 2024 08:23:37 -0700 Subject: [PATCH 079/465] 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 080/465] 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 081/465] 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 e44834c7a39f7517b12cad8d83225a3588486e1d Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 10 Sep 2024 12:30:51 -0400 Subject: [PATCH 082/465] SentinelSetting - Initial Release --- CHANGELOG.md | 5 + .../MSFT_SentinelSetting.psm1 | 477 ++++++++++++++++++ .../MSFT_SentinelSetting.schema.mof | 17 + .../MSFT_SentinelSetting/readme.md | 6 + .../MSFT_SentinelSetting/settings.json | 20 + .../Dependencies/Manifest.psd1 | 46 +- .../Resources/SentinelSetting/2-Update.ps1 | 26 + .../Modules/M365DSCReverse.psm1 | 2 +- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 9 +- .../Microsoft365DSC.SentinelSetting.Tests.ps1 | 130 +++++ Tests/Unit/Stubs/Microsoft365.psm1 | 54 +- .../MSFT_ResourceName/MSFT_ResourceName.psm1 | 1 + 12 files changed, 771 insertions(+), 22 deletions(-) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/MSFT_SentinelSetting.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/MSFT_SentinelSetting.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SentinelSetting/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelSetting.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index c48faf0849..f545d61404 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,13 @@ * IntuneAntivirusPolicyWindows10SettingCatalog * Fixes an issue with invalid parameter definition. FIXES [#5015](https://github.com/microsoft/Microsoft365DSC/issues/5015) +* SentinelSetting + * Initial release. * SPOAccessControlSettings * Added support for property EnableRestrictedAccessControl. +* DEPENDENCIES + * Added dependencies on Az.Accounts and Az.SecurityInsights + * Updated MSCloudLoginAssistant to version 1.1.21. # 1.24.904.1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/MSFT_SentinelSetting.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/MSFT_SentinelSetting.psm1 new file mode 100644 index 0000000000..7939a6a80c --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/MSFT_SentinelSetting.psm1 @@ -0,0 +1,477 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $ResourceGroupName, + + [Parameter(Mandatory = $true)] + [System.String] + $WorkspaceName, + + [Parameter()] + [System.String] + $SubscriptionId, + + [Parameter()] + [System.Boolean] + $AnomaliesIsEnabled, + + [Parameter()] + [System.Boolean] + $EntityAnalyticsIsEnabled, + + [Parameter()] + [System.Boolean] + $EyesOnIsEnabled, + + [Parameter()] + [System.String[]] + $UebaDataSource, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'Azure' ` + -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 + try + { + $ResourceGroupNameValue = $ResourceGroupName + $WorkspaceNameValue = $WorkspaceName + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $entry = $Script:exportedInstances | Where-Object -FilterScript {$_.Name -eq $WorkspaceName} + $instance = Get-AzSentinelSetting -ResourceGroupName $entry.ResourceGroupName -WorkspaceName $entry.Name -ErrorAction SilentlyContinue + $ResourceGroupNameValue = $entry.ResourceGroupName + $WorkspaceNameValue = $entry.Name + } + else + { + Write-Verbose -Message "Retrieving Sentinel Settings for {$WorkspaceName}" + $instance = Get-AzSentinelSetting -ResourceGroupName $ResourceGroupName -WorkspaceName $WorkspaceName -ErrorAction SilentlyContinue + } + if ($null -eq $instance) + { + throw "Could not find Sentinel Workspace {$WorkspaceName} in Resource Group {$ResourceGroupName}" + } + + Write-Verbose -Message "Found an instance of Sentinel Workspace {$Workspace}" + $Anomalies = $instance | Where-Object -FilterScript {$_.Name -eq 'Anomalies'} + $AnomaliesIsEnabledValue = $false + if ($null -ne $Anomalies) + { + Write-Verbose -Message "Anomalies instance found." + $AnomaliesIsEnabledValue = $Anomalies.IsEnabled + } + + $EntityAnalytics = $instance | Where-Object -FilterScript {$_.Name -eq 'EntityAnalytics'} + $EntityAnalyticsIsEnabledValue = $false + if ($null -ne $EntityAnalytics) + { + Write-Verbose -Message "EntityAnalytics instance found." + $EntityAnalyticsIsEnabledValue = $EntityAnalytics.IsEnabled + } + + $EyesOn = $instance | Where-Object -FilterScript {$_.Name -eq 'EyesOn'} + $EyesOnIsEnabledValue = $false + if ($null -ne $EyesOn) + { + Write-Verbose -Message "EyesOn instance found." + $EyesOnIsEnabledValue = $EyesOn.IsEnabled + } + + $Ueba = $instance | Where-Object -FilterScript {$_.Name -eq 'Ueba'} + $UebaDataSourceValue = $null + if ($null -ne $Ueba) + { + Write-Verbose -Message "UEBA Data source instance found." + $UebaDataSourceValue = $Ueba.DataSource + } + + $results = @{ + AnomaliesIsEnabled = [Boolean]$AnomaliesIsEnabledValue + EntityAnalyticsIsEnabled = [Boolean]$EntityAnalyticsIsEnabledValue + EyesOnIsEnabled = [Boolean]$EyesOnIsEnabledValue + UebaDataSource = $UebaDataSourceValue + ResourceGroupName = $ResourceGroupNameValue + WorkspaceName = $WorkspaceNameValue + SubscriptionId = $SubscriptionId + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $ResourceGroupName, + + [Parameter(Mandatory = $true)] + [System.String] + $WorkspaceName, + + [Parameter()] + [System.String] + $SubscriptionId, + + [Parameter()] + [System.Boolean] + $AnomaliesIsEnabled, + + [Parameter()] + [System.Boolean] + $EntityAnalyticsIsEnabled, + + [Parameter()] + [System.Boolean] + $EyesOnIsEnabled, + + [Parameter()] + [System.String[]] + $UebaDataSource, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + if ($PSBoundParameters.ContainsKey('AnomaliesIsEnabled')) + { + Write-Verbose -Message "Updating Anomalies IsEnabled value to {$AnomaliesIsEnabled}" + Update-AzSentinelSetting -ResourceGroupName $ResourceGroupName ` + -WorkspaceName $WorkspaceName ` + -SettingsName "Anomalies" ` + -Enabled $AnomaliesIsEnabled | Out-Null + } + if ($PSBoundParameters.ContainsKey('EntityAnalyticsIsEnabled')) + { + Write-Verbose -Message "Updating Entity Analytics IsEnabled value to {$EntityAnalyticsIsEnabled}" + Update-AzSentinelSetting -ResourceGroupName $ResourceGroupName ` + -WorkspaceName $WorkspaceName ` + -SettingsName "EntityAnalytics" ` + -Enabled $EntityAnalyticsIsEnabled | Out-Null + } + if ($PSBoundParameters.ContainsKey('EyesOnIsEnabled')) + { + Write-Verbose -Message "Updating Eyes On IsEnabled value to {$EyesOnIsEnabled}" + Update-AzSentinelSetting -ResourceGroupName $ResourceGroupName ` + -WorkspaceName $WorkspaceName ` + -SettingsName "EyesOn" ` + -Enabled $EyesOnIsEnabled | Out-Null + } + if ($PSBoundParameters.ContainsKey('UebaDataSource')) + { + Write-Verbose -Message "Updating UEBA Data Source value to {$UebaDataSource}" + Update-AzSentinelSetting -ResourceGroupName $ResourceGroupName ` + -WorkspaceName $WorkspaceName ` + -SettingsName "Ueba" ` + -DataSource $UebaDataSource | Out-Null + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $ResourceGroupName, + + [Parameter(Mandatory = $true)] + [System.String] + $WorkspaceName, + + [Parameter()] + [System.String] + $SubscriptionId, + + [Parameter()] + [System.Boolean] + $AnomaliesIsEnabled, + + [Parameter()] + [System.Boolean] + $EntityAnalyticsIsEnabled, + + [Parameter()] + [System.Boolean] + $EyesOnIsEnabled, + + [Parameter()] + [System.String[]] + $UebaDataSource, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'Azure' ` + -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 + { + $Script:ExportMode = $true + + [array] $Script:exportedInstances = Get-AzResource -ResourceType 'Microsoft.OperationalInsights/workspaces' + + $dscContent = '' + $i = 1 + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + $displayedKey = $config.Name + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + ResourceGroupName = $config.ResourceGroupName + WorkspaceName = $config.Name + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_SentinelSetting/MSFT_SentinelSetting.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/MSFT_SentinelSetting.schema.mof new file mode 100644 index 0000000000..495b1e4330 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/MSFT_SentinelSetting.schema.mof @@ -0,0 +1,17 @@ +[ClassVersion("1.0.0.0"), FriendlyName("SentinelSetting")] +class MSFT_SentinelSetting : OMI_BaseResource +{ + [Key, Description("The Resource Group Name")] String ResourceGroupName; + [Required, Description("The name of the workspace.")] String WorkspaceName; + [Write, Description("Gets subscription credentials which uniquely identify Microsoft Azure subscription. The subscription ID forms part of the URI for every service call.")] String SubscriptionId; + [Write, Description("Specififies if Anomaly detection should be enabled or not.")] Boolean AnomaliesIsEnabled; + [Write, Description("Specififies if Entity Analyticsshould be enabled or not.")] Boolean EntityAnalyticsIsEnabled; + [Write, Description("Specififies if Auditing and Health Monitoring should be enabled or not.")] Boolean EyesOnIsEnabled; + [Write, Description("The list of Data sources associated with the UEBA.")] String UebaDataSource[]; + [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/readme.md new file mode 100644 index 0000000000..3886ec78ee --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/readme.md @@ -0,0 +1,6 @@ + +# SentinelSetting + +## Description + +Configures settings for a Sentinel instance. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/settings.json new file mode 100644 index 0000000000..eea41c3e86 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/settings.json @@ -0,0 +1,20 @@ +{ + "resourceName": "SentinelSetting", + "description": "Configures settings for a Sentinel instance.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 717197df8f..2743394cbf 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -1,5 +1,13 @@ @{ Dependencies = @( + @{ + ModuleName = 'Az.Accounts' + RequiredVersion = '3.0.2' + }, + @{ + ModuleName = 'Az.SecurityInsights' + RequiredVersion = '3.1.2' + }, @{ ModuleName = 'DSCParser' RequiredVersion = '2.0.0.8' @@ -10,75 +18,75 @@ }, @{ ModuleName = 'Microsoft.Graph.Applications' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Authentication' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.DeviceManagement' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Devices.CorporateManagement' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.DeviceManagement.Administration' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.DeviceManagement.Enrollment' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Identity.DirectoryManagement' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Identity.Governance' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Identity.SignIns' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Reports' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Teams' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.DeviceManagement.Administration' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.DirectoryObjects' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Groups' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Planner' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Sites' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Users' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.Graph.Users.Actions' - RequiredVersion = '2.20.0' + RequiredVersion = '2.23.0' }, @{ ModuleName = 'Microsoft.PowerApps.Administration.PowerShell' @@ -90,7 +98,7 @@ }, @{ ModuleName = "MSCloudLoginAssistant" - RequiredVersion = "1.1.20" + RequiredVersion = "1.1.21" }, @{ ModuleName = 'PnP.PowerShell' diff --git a/Modules/Microsoft365DSC/Examples/Resources/SentinelSetting/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SentinelSetting/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SentinelSetting/2-Update.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 index 61ed490d9b..2b124e6da7 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 @@ -41,7 +41,7 @@ function Start-M365DSCConfigurationExtract $MaxProcesses = 16, [Parameter()] - [ValidateSet('AAD', 'FABRIC', 'SPO', 'EXO', 'INTUNE', 'SC', 'OD', 'O365', 'TEAMS', 'PP', 'PLANNER')] + [ValidateSet('AAD', 'FABRIC', 'SPO', 'EXO', 'INTUNE', 'SC', 'SENTINEL', 'OD', 'O365', 'TEAMS', 'PP', 'PLANNER')] [System.String[]] $Workloads, diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 97782f27e6..9397159c76 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1708,7 +1708,7 @@ function New-M365DSCConnection param ( [Parameter(Mandatory = $true)] - [ValidateSet('AzureDevOPS', 'ExchangeOnline', 'Fabric', 'Intune', ` + [ValidateSet('Azure', 'AzureDevOPS', 'ExchangeOnline', 'Fabric', 'Intune', ` 'SecurityComplianceCenter', 'PnP', 'PowerPlatforms', ` 'MicrosoftTeams', 'MicrosoftGraph', 'SharePointOnlineREST', 'Tasks')] [System.String] @@ -1771,6 +1771,7 @@ function New-M365DSCConnection [System.Boolean] $SkipModuleReload = $false ) + $verbosepreference = 'Continue' $Global:MaximumFunctionCount = 32767 if ($Workload -eq 'MicrosoftTeams') { @@ -2193,12 +2194,14 @@ function New-M365DSCConnection { $Global:M365DSCTelemetryConnectionToGraphParams.Add('CertificateThumbprint', $InboundParameters.CertificateThumbprint) } + Write-Verbose -Message "Calling into Connect-M365Tenant" Connect-M365Tenant -Workload $Workload ` -ApplicationId $InboundParameters.ApplicationId ` -TenantId $InboundParameters.TenantId ` -CertificateThumbprint $InboundParameters.CertificateThumbprint ` -SkipModuleReload $Global:CurrentModeIsExport ` -Url $Url + Write-Verbose -Message "Connection initiated." if (-not $Script:M365ConnectedToWorkloads -contains "$Workload-ServicePrincipalWithThumbprint") { $data.Add('ConnectionMode', 'ServicePrincipalWithThumbprint') @@ -3690,6 +3693,10 @@ function Get-M365DSCExportContentForResource { $primaryKey = $Results.CDNType } + elseif ($Keys.Contains('WorkspaceName')) + { + $primaryKey = $Results.WorkspaceName + } if ([String]::IsNullOrEmpty($primaryKey) -and ` -not $Keys.Contains('IsSingleInstance')) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelSetting.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelSetting.Tests.ps1 new file mode 100644 index 0000000000..54e5f57ef4 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelSetting.Tests.ps1 @@ -0,0 +1,130 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Update-AzSentinelSetting -MockWith { + } + + Mock -CommandName Get-AzResource -MockWith { + return @{ + ResourceGroupName = "MyResourceGroup" + Name = 'MySentinelWorkspace' + } + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ResourceGroupName = 'MyResourceGroup' + WorkspaceName = 'MySentinelWorkspace' + AnomaliesIsEnabled = $true + Credential = $Credential; + } + + Mock -CommandName Get-AzSentinelSetting -MockWith { + return @{ + Name = 'Anomalies' + IsEnabled = $true + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ResourceGroupName = 'MyResourceGroup' + WorkspaceName = 'MySentinelWorkspace' + AnomaliesIsEnabled = $true + Credential = $Credential; + } + + Mock -CommandName Get-AzSentinelSetting -MockWith { + return @{ + Name = 'Anomalies' + IsEnabled = $false #drift + } + } + } + + 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 Update-AzSentinelSetting -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + BeforeAll { + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-AzSentinelSetting -MockWith { + return @{ + Name = 'Anomalies' + IsEnabled = $true + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index d8d8db6694..17668db78c 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -1,3 +1,56 @@ +#region Azure +function Get-AzSentinel +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $ResourceGroupName, + + [Parameter()] + [System.String] + $WorkspaceName + + ) +} + +function Update-AzSentinel +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $ResourceGroupName, + + [Parameter()] + [System.String] + $WorkspaceName, + + [Parameter()] + [System.Boolean] + $Enabled, + + [Parameter()] + [System.String] + $SettingsName, + + [Parameter()] + [System.String] + $DataSource + ) +} + +function Get-AzResource +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $ResourceType + ) +} +#endregion + # region ExchangeOnlineManagement function Get-SweepRule { @@ -28,7 +81,6 @@ function Get-SweepRule $ResultSize ) } - function New-SweepRule { [CmdletBinding()] diff --git a/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.psm1 b/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.psm1 index 7d42466c4c..c6f63d3927 100644 --- a/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.psm1 +++ b/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.psm1 @@ -85,6 +85,7 @@ function Get-TargetResource } catch { + Write-Verbose -Message $_ New-M365DSCLogEntry -Message 'Error retrieving data:' ` -Exception $_ ` -Source $($MyInvocation.MyCommand.Source) ` From dca6f4fbe6f51cc47fe019e19b2ad471f7ee8777 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 10 Sep 2024 13:59:42 -0400 Subject: [PATCH 083/465] Fixes to the auth --- CHANGELOG.md | 4 ++-- .../MSFT_SentinelSetting.psm1 | 15 ++++++++------- .../Microsoft365DSC/Dependencies/Manifest.psd1 | 6 +++++- Tests/Unit/Stubs/Microsoft365.psm1 | 4 ++-- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f545d61404..5fcba5cd30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,8 @@ * SPOAccessControlSettings * Added support for property EnableRestrictedAccessControl. * DEPENDENCIES - * Added dependencies on Az.Accounts and Az.SecurityInsights - * Updated MSCloudLoginAssistant to version 1.1.21. + * Added dependencies on Az.Accounts, Az.Resources and Az.SecurityInsights + * Updated MSCloudLoginAssistant to version 1.1.22. # 1.24.904.1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/MSFT_SentinelSetting.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/MSFT_SentinelSetting.psm1 index 7939a6a80c..21c39097df 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/MSFT_SentinelSetting.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/MSFT_SentinelSetting.psm1 @@ -85,14 +85,20 @@ function Get-TargetResource if ($null -ne $Script:exportedInstances -and $Script:ExportMode) { $entry = $Script:exportedInstances | Where-Object -FilterScript {$_.Name -eq $WorkspaceName} - $instance = Get-AzSentinelSetting -ResourceGroupName $entry.ResourceGroupName -WorkspaceName $entry.Name -ErrorAction SilentlyContinue + $instance = Get-AzSentinelSetting -ResourceGroupName $entry.ResourceGroupName ` + -WorkspaceName $entry.Name ` + -SubscriptionId $SubscriptionId ` + -ErrorAction SilentlyContinue $ResourceGroupNameValue = $entry.ResourceGroupName $WorkspaceNameValue = $entry.Name } else { Write-Verbose -Message "Retrieving Sentinel Settings for {$WorkspaceName}" - $instance = Get-AzSentinelSetting -ResourceGroupName $ResourceGroupName -WorkspaceName $WorkspaceName -ErrorAction SilentlyContinue + $instance = Get-AzSentinelSetting -ResourceGroupName $ResourceGroupName ` + -WorkspaceName $WorkspaceName ` + -ErrorAction SilentlyContinue ` + -SubscriptionId $SubscriptionId } if ($null -eq $instance) { @@ -195,11 +201,6 @@ function Set-TargetResource [System.String[]] $UebaDataSource, - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - [Parameter()] [System.Management.Automation.PSCredential] $Credential, diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 2743394cbf..54b3565d09 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -4,6 +4,10 @@ ModuleName = 'Az.Accounts' RequiredVersion = '3.0.2' }, + @{ + ModuleName = 'Az.Resources' + RequiredVersion = '7.2.0' + }, @{ ModuleName = 'Az.SecurityInsights' RequiredVersion = '3.1.2' @@ -98,7 +102,7 @@ }, @{ ModuleName = "MSCloudLoginAssistant" - RequiredVersion = "1.1.21" + RequiredVersion = "1.1.22" }, @{ ModuleName = 'PnP.PowerShell' diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 17668db78c..67bd3f160f 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -1,5 +1,5 @@ #region Azure -function Get-AzSentinel +function Get-AzSentinelSetting { [CmdletBinding()] param( @@ -14,7 +14,7 @@ function Get-AzSentinel ) } -function Update-AzSentinel +function Update-AzSentinelSetting { [CmdletBinding()] param( From e708e0f9c5c8e19dc2956cb4939d8e25f5039df7 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Tue, 10 Sep 2024 11:09:54 -0700 Subject: [PATCH 084/465] 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 085/465] 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 086/465] 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 9a7253ed6f7055f66183e2a670640e70a0af5f20 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 10 Sep 2024 14:53:04 -0400 Subject: [PATCH 087/465] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 67bd3f160f..d9daa50d7f 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -9,8 +9,11 @@ function Get-AzSentinelSetting [Parameter()] [System.String] - $WorkspaceName + $WorkspaceName, + [Parameter()] + [System.String] + $SubscriptionId ) } From f7071b2c1833eb4e4b4f0e2bfc9779c7e9f18d9d Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Tue, 10 Sep 2024 12:05:18 -0700 Subject: [PATCH 088/465] 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"; } } } From 1c0e3df8cdb6743a8c7c9f47b020bcc1aef1c709 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 10 Sep 2024 19:14:28 +0000 Subject: [PATCH 089/465] Updated Resources and Cmdlet documentation pages --- .../security-compliance/SentinelSetting.md | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 docs/docs/resources/security-compliance/SentinelSetting.md diff --git a/docs/docs/resources/security-compliance/SentinelSetting.md b/docs/docs/resources/security-compliance/SentinelSetting.md new file mode 100644 index 0000000000..d2ee71451a --- /dev/null +++ b/docs/docs/resources/security-compliance/SentinelSetting.md @@ -0,0 +1,82 @@ +# SentinelSetting + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **ResourceGroupName** | Key | String | The Resource Group Name | | +| **WorkspaceName** | Required | String | The name of the workspace. | | +| **SubscriptionId** | Write | String | Gets subscription credentials which uniquely identify Microsoft Azure subscription. The subscription ID forms part of the URI for every service call. | | +| **AnomaliesIsEnabled** | Write | Boolean | Specififies if Anomaly detection should be enabled or not. | | +| **EntityAnalyticsIsEnabled** | Write | Boolean | Specififies if Entity Analyticsshould be enabled or not. | | +| **EyesOnIsEnabled** | Write | Boolean | Specififies if Auditing and Health Monitoring should be enabled or not. | | +| **UebaDataSource** | Write | StringArray[] | The list of Data sources associated with the UEBA. | | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Configures settings for a Sentinel instance. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} +``` + From d34b49df36aab550e9a873d9b5883538bb0a0d55 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 10 Sep 2024 19:16:57 +0000 Subject: [PATCH 090/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 90e653682a..922b858773 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -39134,6 +39134,76 @@ } ] }, + { + "ClassName": "MSFT_SentinelSetting", + "Parameters": [ + { + "CIMType": "String", + "Name": "ResourceGroupName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "WorkspaceName", + "Option": "Required" + }, + { + "CIMType": "String", + "Name": "SubscriptionId", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AnomaliesIsEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EntityAnalyticsIsEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EyesOnIsEnabled", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "UebaDataSource", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_SPOAccessControlSettings", "Parameters": [ From 16bb7a22fba67be692c8171eb79ce4f7467da81b Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Wed, 11 Sep 2024 11:26:27 +0530 Subject: [PATCH 091/465] Added Change Logs --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e533f00634..38ede660c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* EXOFocusedInbox + * Initial Release. * EXOManagementScope * Initial Release. * AADPasswordRuleSettings From cd9758bcb5df52fd2c5da6dd8eb0929fc21d12e9 Mon Sep 17 00:00:00 2001 From: ritikmit <88980817+ritikmit@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:38:27 +0530 Subject: [PATCH 092/465] Update MSFT_EXOPhishSimOverrideRule.schema.mof --- .../MSFT_EXOPhishSimOverrideRule.schema.mof | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.schema.mof index ddc28bdfd4..d6b5aa4a56 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.schema.mof @@ -13,5 +13,5 @@ class MSFT_EXOPhishSimOverrideRule : OMI_BaseResource [Write, Description("The IP ranges for the override rule.")] String SenderIpRanges[]; [Write, Description("An optional comment for the override rule.")] String Comment; [Write, Description("The phishing simulation override policy that's associated with the rule.")] String Policy; - [Write, Description("Ensures the presence or absence of the configuration.")] String Ensure; + [Write, Description("Ensures the presence or absence of the configuration."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; }; From 90b82916841b4e8164994211c0cdb0db0e860b18 Mon Sep 17 00:00:00 2001 From: ritikmit <88980817+ritikmit@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:42:15 +0530 Subject: [PATCH 093/465] Update MSFT_EXOPhishSimOverrideRule.psm1 --- .../MSFT_EXOPhishSimOverrideRule.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 index 445b4c496f..ee3dc48fbe 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPhishSimOverrideRule/MSFT_EXOPhishSimOverrideRule.psm1 @@ -389,7 +389,7 @@ function Export-TargetResource } foreach ($config in $Script:exportedInstances) { - $displayedKey = $config.Id + $displayedKey = $config.Identity Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline $params = @{ Identity = $config.Identity From fa6fe5595568e0bf031e2747cad90c4c5592fdf3 Mon Sep 17 00:00:00 2001 From: ritikmit <88980817+ritikmit@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:43:27 +0530 Subject: [PATCH 094/465] Update 1-Create.ps1 --- .../Examples/Resources/EXOPhishSimOverrideRule/1-Create.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/1-Create.ps1 index 7556c1cd1d..937fe41382 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/1-Create.ps1 @@ -24,7 +24,6 @@ Configuration Example EXOPhishSimOverrideRule "EXOPhishSimOverrideRule-_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b" { Comment = "Comment note"; - Credential = $Credscredential; Domains = @("fabrikam.com","wingtiptoys.com"); Ensure = "Present"; Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; From 67eb1b36bed8bd00177fe6b0e7365370bbbb2afe Mon Sep 17 00:00:00 2001 From: ritikmit <88980817+ritikmit@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:43:38 +0530 Subject: [PATCH 095/465] Update 2-Update.ps1 --- .../Examples/Resources/EXOPhishSimOverrideRule/2-Update.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/2-Update.ps1 index 12b382f5fa..b55b0c65d3 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/2-Update.ps1 @@ -24,7 +24,6 @@ Configuration Example EXOPhishSimOverrideRule "EXOPhishSimOverrideRule-_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b" { Comment = "New Comment note"; - Credential = $Credscredential; Ensure = "Present"; Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; ApplicationId = $ApplicationId From 2760f9578c4610effa4702f007558b61b0158982 Mon Sep 17 00:00:00 2001 From: ritikmit <88980817+ritikmit@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:43:48 +0530 Subject: [PATCH 096/465] Update 3-Remove.ps1 --- .../Examples/Resources/EXOPhishSimOverrideRule/3-Remove.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/3-Remove.ps1 index 176420b33e..5cef0b2b2f 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPhishSimOverrideRule/3-Remove.ps1 @@ -24,7 +24,6 @@ Configuration Example { EXOPhishSimOverrideRule "EXOPhishSimOverrideRule-_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b" { - Credential = $Credscredential; Ensure = "Absent"; Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; ApplicationId = $ApplicationId From 7d72bf80ba385dae69e08e41e5b7ac470a0fd7e8 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 06:14:01 +0000 Subject: [PATCH 097/465] Updated Resources and Cmdlet documentation pages --- .../resources/exchange/EXOFocusedInbox.md | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 docs/docs/resources/exchange/EXOFocusedInbox.md diff --git a/docs/docs/resources/exchange/EXOFocusedInbox.md b/docs/docs/resources/exchange/EXOFocusedInbox.md new file mode 100644 index 0000000000..1bc5b11848 --- /dev/null +++ b/docs/docs/resources/exchange/EXOFocusedInbox.md @@ -0,0 +1,78 @@ +# EXOFocusedInbox + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Identity** | Key | String | The Identity parameter specifies the mailbox that you want to modify. | | +| **FocusedInboxOn** | Write | Boolean | The FocusedInboxOn parameter enables or disables Focused Inbox for the mailbox. | | +| **FocusedInboxOnLastUpdateTime** | Write | DateTime | Gets the last updated time on focused inbox | | +| **Ensure** | Write | String | Specify if the AcceptedDomain should exist or not. | `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +# EXOFocusedInbox + +## Description +Manage the Focused Inbox configuration for mailboxes in your organization. + +## Permissions + +### Exchange + +To authenticate with Microsoft Exchange, this resource required the following permissions: + +#### Roles + +- Organization Management, Recipient Management + +#### Role Groups + +- Organization Management, Help Desk + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOFocusedInbox "EXOFocusedInbox-Test" + { + Ensure = "Present"; + FocusedInboxOn = $False; # Updated Property + FocusedInboxOnLastUpdateTime = "1/1/0001 12:00:00 AM"; + Identity = "admin@$TenantId"; + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + + } +} +``` + From f38d46b081499be7daee4a1ffd90e1a067fde638 Mon Sep 17 00:00:00 2001 From: ritikmit <88980817+ritikmit@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:45:04 +0530 Subject: [PATCH 098/465] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e533f00634..9b67060b70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* EXOPhishSimOverrideRule + * Initial Release. * EXOManagementScope * Initial Release. * AADPasswordRuleSettings From ccd1000dbcfea309c19bd1f92464b8cb45bd5148 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 06:16:32 +0000 Subject: [PATCH 099/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 922b858773..de3c102c49 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -7714,6 +7714,61 @@ } ] }, + { + "ClassName": "MSFT_EXOFocusedInbox", + "Parameters": [ + { + "CIMType": "String", + "Name": "Identity", + "Option": "Key" + }, + { + "CIMType": "Boolean", + "Name": "FocusedInboxOn", + "Option": "Write" + }, + { + "CIMType": "DateTime", + "Name": "FocusedInboxOnLastUpdateTime", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOGlobalAddressList", "Parameters": [ From 1741c5b1627ec117eedf418df3b1cf1083110262 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 06:17:28 +0000 Subject: [PATCH 100/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index 1187fe3ade..cd26da09ce 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -348,6 +348,16 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOFocusedInbox 'EXOFocusedInbox-Test' + { + Ensure = "Present"; + FocusedInboxOn = $False; # Updated Property + FocusedInboxOnLastUpdateTime = "1/1/0001 12:00:00 AM"; + Identity = "admin@$TenantId"; + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } EXOGlobalAddressList 'ConfigureGlobalAddressList' { Name = "Contoso Human Resources in Washington" From 96528f74532c3b1f2c5c28feb0a704ce2a4a856a Mon Sep 17 00:00:00 2001 From: ritikmit <88980817+ritikmit@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:51:10 +0530 Subject: [PATCH 101/465] Update MSFT_EXOSecOpsOverrideRule.schema.mof --- .../MSFT_EXOSecOpsOverrideRule.schema.mof | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof index dc359367af..e3212f2c4b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.schema.mof @@ -11,5 +11,5 @@ class MSFT_EXOSecOpsOverrideRule : OMI_BaseResource [Key, Description("The unique identifier (GUID or name) of the override rule. This parameter is mandatory.")] String Identity; [Write, Description("An optional comment for the override rule.")] String Comment; [Write, Description("The SecOps simulation override policy that's associated with the rule.")] String Policy; - [Write, Description("Ensures the presence or absence of the configuration.")] String Ensure; + [Write, Description("Ensures the presence or absence of the configuration."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; }; From d0c4d6bca790ec8bfb4f9d1b81b8fd00d202767f Mon Sep 17 00:00:00 2001 From: ritikmit <88980817+ritikmit@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:51:25 +0530 Subject: [PATCH 102/465] Update MSFT_EXOSecOpsOverrideRule.psm1 --- .../MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 index 7c378d2fdf..a804064c90 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSecOpsOverrideRule/MSFT_EXOSecOpsOverrideRule.psm1 @@ -332,7 +332,7 @@ function Export-TargetResource } foreach ($config in $Script:exportedInstances) { - $displayedKey = $config.Id + $displayedKey = $config.Identity Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline $params = @{ Identity = $config.Identity From bc164a4bca8f9e6fc761d357cd5077441f049510 Mon Sep 17 00:00:00 2001 From: ritikmit <88980817+ritikmit@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:51:53 +0530 Subject: [PATCH 103/465] Update 1-Create.ps1 --- .../Examples/Resources/EXOSecOpsOverrideRule/1-Create.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/1-Create.ps1 index 30bf69e8a9..b46fb3fead 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/1-Create.ps1 @@ -24,7 +24,6 @@ Configuration Example EXOSecOpsOverrideRule "EXOSecOpsOverrideRule-_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245" { Comment = "TestComment"; - Credential = $Credscredential; Ensure = "Present"; Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; From 97d11fe9ce6c12ba734539618300b43896eab2c1 Mon Sep 17 00:00:00 2001 From: ritikmit <88980817+ritikmit@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:52:09 +0530 Subject: [PATCH 104/465] Update 2-Update.ps1 --- .../Examples/Resources/EXOSecOpsOverrideRule/2-Update.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/2-Update.ps1 index 0f617f9dde..6382526e63 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/2-Update.ps1 @@ -27,7 +27,6 @@ Configuration Example Ensure = "Present"; Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; - Credential = $Credscredential; ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint From 2d100f1531541b83512c0d8c213b2bbfeffc2d39 Mon Sep 17 00:00:00 2001 From: ritikmit <88980817+ritikmit@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:52:22 +0530 Subject: [PATCH 105/465] Update 3-Remove.ps1 --- .../Examples/Resources/EXOSecOpsOverrideRule/3-Remove.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/3-Remove.ps1 index f2cfff7388..363364de58 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/3-Remove.ps1 @@ -23,7 +23,6 @@ Configuration Example { EXOSecOpsOverrideRule "EXOSecOpsOverrideRule-_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245" { - Credential = $Credscredential; Ensure = "Present"; Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; } From aa6c1b0b43e16f23f7f536adb8f0dbc119b16431 Mon Sep 17 00:00:00 2001 From: ritikmit <88980817+ritikmit@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:52:40 +0530 Subject: [PATCH 106/465] Update 3-Remove.ps1 --- .../Examples/Resources/EXOSecOpsOverrideRule/3-Remove.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/3-Remove.ps1 index 363364de58..bfb8dd091d 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSecOpsOverrideRule/3-Remove.ps1 @@ -23,7 +23,7 @@ Configuration Example { EXOSecOpsOverrideRule "EXOSecOpsOverrideRule-_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245" { - Ensure = "Present"; + Ensure = "Absent"; Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; } } From 2a20d04cca99f748a0d76ef013d03c398de0e69d Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Wed, 11 Sep 2024 11:53:00 +0530 Subject: [PATCH 107/465] Added Change Logs --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38ede660c2..5a0a4944c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ * EXOFocusedInbox * Initial Release. +* EXOMailboxCalendarConfiguration + * Initial Release. * EXOManagementScope * Initial Release. * AADPasswordRuleSettings From a0ac2c249f5774d2775ec6b7ff116df2e0627490 Mon Sep 17 00:00:00 2001 From: ritikmit <88980817+ritikmit@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:53:24 +0530 Subject: [PATCH 108/465] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38ede660c2..fe00b7d3d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ * Initial Release. * EXOManagementScope * Initial Release. +* EXOManagementScope + * Initial Release. * AADPasswordRuleSettings * Initial release * IntuneAntivirusPolicyWindows10SettingCatalog From 2e6ecf87bf11b6f0287ec7d31d7d66c3acaba2f3 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 06:30:28 +0000 Subject: [PATCH 109/465] Updated Resources and Cmdlet documentation pages --- .../exchange/EXOPhishSimOverrideRule.md | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 docs/docs/resources/exchange/EXOPhishSimOverrideRule.md diff --git a/docs/docs/resources/exchange/EXOPhishSimOverrideRule.md b/docs/docs/resources/exchange/EXOPhishSimOverrideRule.md new file mode 100644 index 0000000000..366c5c5045 --- /dev/null +++ b/docs/docs/resources/exchange/EXOPhishSimOverrideRule.md @@ -0,0 +1,167 @@ +# EXOPhishSimOverrideRule + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | +| **Identity** | Key | String | The unique identifier (GUID or name) of the override rule. This parameter is mandatory. | | +| **Domains** | Write | StringArray[] | The domains for the override rule. | | +| **SenderIpRanges** | Write | StringArray[] | The IP ranges for the override rule. | | +| **Comment** | Write | String | An optional comment for the override rule. | | +| **Policy** | Write | String | The phishing simulation override policy that's associated with the rule. | | +| **Ensure** | Write | String | Ensures the presence or absence of the configuration. | `Present`, `Absent` | + + +## Description + +This resource allows users to manage resource to modify third-party phishing +simulation override rules to bypass Exchange Online Protection filtering. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOPhishSimOverrideRule "EXOPhishSimOverrideRule-_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b" + { + Comment = "Comment note"; + Domains = @("fabrikam.com","wingtiptoys.com"); + Ensure = "Present"; + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + Policy = "fc55717b-28bb-4cf3-98ee-9ba57903c978"; + SenderIpRanges = @("192.168.1.55"); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOPhishSimOverrideRule "EXOPhishSimOverrideRule-_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b" + { + Comment = "New Comment note"; + Ensure = "Present"; + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + +### Example 3 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOPhishSimOverrideRule "EXOPhishSimOverrideRule-_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b" + { + Ensure = "Absent"; + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + From e2ee525de80f78d204421dd92bf04e3096f4cdfb Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 06:33:17 +0000 Subject: [PATCH 110/465] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index dbdfbb1fd7..cd98b3df94 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -725,6 +725,18 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOPhishSimOverrideRule 'EXOPhishSimOverrideRule-_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b' + { + Comment = "Comment note"; + Domains = @("fabrikam.com","wingtiptoys.com"); + Ensure = "Present"; + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + Policy = "fc55717b-28bb-4cf3-98ee-9ba57903c978"; + SenderIpRanges = @("192.168.1.55"); + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } EXOPlace 'TestPlace' { AudioDeviceName = "MyAudioDevice"; From 5da4e0d4a1f630b644ffcc53e2e0e7fce26a2c28 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 06:33:42 +0000 Subject: [PATCH 111/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index cd26da09ce..a2d1bc8262 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -1048,6 +1048,15 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOPhishSimOverrideRule 'EXOPhishSimOverrideRule-_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b' + { + Comment = "New Comment note"; + Ensure = "Present"; + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } EXOPlace 'TestPlace' { AudioDeviceName = "MyAudioDevice"; From 9e6bca2f9d3d928e4c2ac5ba4074037986a41a9b Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 06:34:01 +0000 Subject: [PATCH 112/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Remove.Tests.ps1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 index 915a099176..d295e0f589 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 @@ -418,6 +418,14 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOPhishSimOverrideRule 'EXOPhishSimOverrideRule-_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b' + { + Ensure = "Absent"; + Identity = "_Exe:PhishSimOverr:d779965e-ab14-4dd8-b3f5-0876a99f988b"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } EXOPlace 'TestPlace' { AudioDeviceName = "MyAudioDevice"; From bd9455bd1082646241e13cd62df0d67c19b2e995 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 06:36:34 +0000 Subject: [PATCH 113/465] Updated Resources and Cmdlet documentation pages --- .../EXOMailboxCalendarConfiguration.md | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 docs/docs/resources/exchange/EXOMailboxCalendarConfiguration.md diff --git a/docs/docs/resources/exchange/EXOMailboxCalendarConfiguration.md b/docs/docs/resources/exchange/EXOMailboxCalendarConfiguration.md new file mode 100644 index 0000000000..686a881e9d --- /dev/null +++ b/docs/docs/resources/exchange/EXOMailboxCalendarConfiguration.md @@ -0,0 +1,151 @@ +# EXOMailboxCalendarConfiguration + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | +| **Identity** | Key | String | Specifies the mailbox identity. | | +| **AgendaMailIntroductionEnabled** | Write | Boolean | Enables or disables agenda mail introduction. | | +| **AutoDeclineWhenBusy** | Write | Boolean | Automatically declines meeting requests when the user is busy. | | +| **CalendarFeedsPreferredLanguage** | Write | String | Preferred language for calendar feeds. | | +| **CalendarFeedsPreferredRegion** | Write | String | Preferred region for calendar feeds. | | +| **CalendarFeedsRootPageId** | Write | String | Root page ID for calendar feeds. | | +| **ConversationalSchedulingEnabled** | Write | Boolean | Enables or disables conversational scheduling. | | +| **CreateEventsFromEmailAsPrivate** | Write | Boolean | Creates events from email as private. | | +| **DefaultMinutesToReduceLongEventsBy** | Write | UInt32 | Default minutes to reduce long events by. | | +| **DefaultMinutesToReduceShortEventsBy** | Write | UInt32 | Default minutes to reduce short events by. | | +| **DefaultOnlineMeetingProvider** | Write | String | Default online meeting provider. | | +| **DefaultReminderTime** | Write | String | Default reminder time. | | +| **DeleteMeetingRequestOnRespond** | Write | Boolean | Deletes meeting request on respond. | | +| **DiningEventsFromEmailEnabled** | Write | Boolean | Enables or disables dining events from email. | | +| **EntertainmentEventsFromEmailEnabled** | Write | Boolean | Enables or disables entertainment events from email. | | +| **EventsFromEmailEnabled** | Write | Boolean | Enables or disables events from email. | | +| **FirstWeekOfYear** | Write | String | Specifies the first week of the year. | | +| **FlightEventsFromEmailEnabled** | Write | Boolean | Enables or disables flight events from email. | | +| **HotelEventsFromEmailEnabled** | Write | Boolean | Enables or disables hotel events from email. | | +| **InvoiceEventsFromEmailEnabled** | Write | Boolean | Enables or disables invoice events from email. | | +| **LocationDetailsInFreeBusy** | Write | String | Specifies location details in free/busy information. | | +| **MailboxLocation** | Write | String | Specifies the mailbox location. | | +| **OnlineMeetingsByDefaultEnabled** | Write | Boolean | Enables or disables online meetings by default. | | +| **PackageDeliveryEventsFromEmailEnabled** | Write | Boolean | Enables or disables package delivery events from email. | | +| **PreserveDeclinedMeetings** | Write | Boolean | Preserves declined meetings. | | +| **RemindersEnabled** | Write | Boolean | Enables or disables reminders. | | +| **ReminderSoundEnabled** | Write | Boolean | Enables or disables reminder sound. | | +| **RentalCarEventsFromEmailEnabled** | Write | Boolean | Enables or disables rental car events from email. | | +| **ServiceAppointmentEventsFromEmailEnabled** | Write | Boolean | Enables or disables service appointment events from email. | | +| **ShortenEventScopeDefault** | Write | String | Specifies the default scope for shortening events. | | +| **ShowWeekNumbers** | Write | Boolean | Shows or hides week numbers. | | +| **TimeIncrement** | Write | String | Specifies the time increment for calendar events. | | +| **UseBrightCalendarColorThemeInOwa** | Write | Boolean | Uses a bright calendar color theme in Outlook on the web. | | +| **WeatherEnabled** | Write | String | Enables or disables weather information. | | +| **WeatherLocationBookmark** | Write | UInt32 | Specifies the weather location bookmark. | | +| **WeatherLocations** | Write | StringArray[] | Specifies the weather locations. | | +| **WeatherUnit** | Write | String | Specifies the weather unit. | | +| **WeekStartDay** | Write | String | Specifies the start day of the week. | | +| **WorkDays** | Write | String | Specifies the work days. | | +| **WorkingHoursEndTime** | Write | String | Specifies the end time of working hours. | | +| **WorkingHoursStartTime** | Write | String | Specifies the start time of working hours. | | +| **WorkingHoursTimeZone** | Write | String | Specifies the time zone for working hours. | | +| **WorkspaceUserEnabled** | Write | Boolean | Enables or disables workspace user. | | +| **Ensure** | Write | String | Ensures the presence or absence of the configuration. | | + + +## Description + +This resource allows users to manage mailbox calendar settings. + +## Permissions + +### Exchange + +To authenticate with Microsoft Exchange, this resource required the following permissions: + +#### Roles + +- Organization Management, Recipient Management + +#### Role Groups + +- Organization Management, Help Desk + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOMailboxCalendarConfiguration "EXOMailboxCalendarConfiguration-Test" + { + AgendaMailIntroductionEnabled = $True; + AutoDeclineWhenBusy = $False; + ConversationalSchedulingEnabled = $True; + CreateEventsFromEmailAsPrivate = $True; + DefaultMinutesToReduceLongEventsBy = 10; + DefaultMinutesToReduceShortEventsBy = 6; # Updated Property + DefaultOnlineMeetingProvider = "TeamsForBusiness"; + DefaultReminderTime = "00:15:00"; + DeleteMeetingRequestOnRespond = $True; + DiningEventsFromEmailEnabled = $True; + Ensure = "Present"; + EntertainmentEventsFromEmailEnabled = $True; + EventsFromEmailEnabled = $True; + FirstWeekOfYear = "FirstDay"; + FlightEventsFromEmailEnabled = $True; + HotelEventsFromEmailEnabled = $True; + Identity = "admin@$TenantId"; + InvoiceEventsFromEmailEnabled = $True; + LocationDetailsInFreeBusy = "Desk"; + PackageDeliveryEventsFromEmailEnabled = $False; + PreserveDeclinedMeetings = $False; + RemindersEnabled = $True; + ReminderSoundEnabled = $True; + RentalCarEventsFromEmailEnabled = $True; + ServiceAppointmentEventsFromEmailEnabled = $True; + ShortenEventScopeDefault = "None"; + ShowWeekNumbers = $False; + TimeIncrement = "ThirtyMinutes"; + UseBrightCalendarColorThemeInOwa = $False; + WeatherEnabled = "FirstRun"; + WeatherLocationBookmark = 0; + WeatherLocations = @(); + WeatherUnit = "Default"; + WeekStartDay = "Sunday"; + WorkDays = "Monday, Tuesday"; + WorkingHoursEndTime = "17:00:00"; + WorkingHoursStartTime = "08:00:00"; + WorkingHoursTimeZone = "Pacific Standard Time"; + WorkspaceUserEnabled = $False; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + From 0430e20f5c74b7edc7a20c5de8cc4a6ce27c971b Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 06:38:10 +0000 Subject: [PATCH 114/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 320 ++++++++++++++++++ 1 file changed, 320 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index de3c102c49..bea8332ade 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -9479,6 +9479,261 @@ } ] }, + { + "ClassName": "MSFT_EXOMailboxCalendarConfiguration", + "Parameters": [ + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Identity", + "Option": "Key" + }, + { + "CIMType": "Boolean", + "Name": "AgendaMailIntroductionEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AutoDeclineWhenBusy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CalendarFeedsPreferredLanguage", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CalendarFeedsPreferredRegion", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CalendarFeedsRootPageId", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ConversationalSchedulingEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "CreateEventsFromEmailAsPrivate", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "DefaultMinutesToReduceLongEventsBy", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "DefaultMinutesToReduceShortEventsBy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DefaultOnlineMeetingProvider", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DefaultReminderTime", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "DeleteMeetingRequestOnRespond", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "DiningEventsFromEmailEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EntertainmentEventsFromEmailEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EventsFromEmailEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "FirstWeekOfYear", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "FlightEventsFromEmailEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "HotelEventsFromEmailEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "InvoiceEventsFromEmailEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "LocationDetailsInFreeBusy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MailboxLocation", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "OnlineMeetingsByDefaultEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PackageDeliveryEventsFromEmailEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PreserveDeclinedMeetings", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "RemindersEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ReminderSoundEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "RentalCarEventsFromEmailEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ServiceAppointmentEventsFromEmailEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ShortenEventScopeDefault", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ShowWeekNumbers", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TimeIncrement", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "UseBrightCalendarColorThemeInOwa", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "WeatherEnabled", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "WeatherLocationBookmark", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "WeatherLocations", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "WeatherUnit", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "WeekStartDay", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "WorkDays", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "WorkingHoursEndTime", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "WorkingHoursStartTime", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "WorkingHoursTimeZone", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "WorkspaceUserEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Ensure", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOMailboxCalendarFolder", "Parameters": [ @@ -12849,6 +13104,71 @@ } ] }, + { + "ClassName": "MSFT_EXOPhishSimOverrideRule", + "Parameters": [ + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Identity", + "Option": "Key" + }, + { + "CIMType": "String[]", + "Name": "Domains", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "SenderIpRanges", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Comment", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Policy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Ensure", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOPlace", "Parameters": [ From 6ef7beb07fb4231245041863ce8114b6c9407dbc Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 06:39:21 +0000 Subject: [PATCH 115/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index a2d1bc8262..3e67a55a83 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -575,6 +575,51 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOMailboxCalendarConfiguration 'EXOMailboxCalendarConfiguration-Test' + { + AgendaMailIntroductionEnabled = $True; + AutoDeclineWhenBusy = $False; + ConversationalSchedulingEnabled = $True; + CreateEventsFromEmailAsPrivate = $True; + DefaultMinutesToReduceLongEventsBy = 10; + DefaultMinutesToReduceShortEventsBy = 6; # Updated Property + DefaultOnlineMeetingProvider = "TeamsForBusiness"; + DefaultReminderTime = "00:15:00"; + DeleteMeetingRequestOnRespond = $True; + DiningEventsFromEmailEnabled = $True; + Ensure = "Present"; + EntertainmentEventsFromEmailEnabled = $True; + EventsFromEmailEnabled = $True; + FirstWeekOfYear = "FirstDay"; + FlightEventsFromEmailEnabled = $True; + HotelEventsFromEmailEnabled = $True; + Identity = "admin@$TenantId"; + InvoiceEventsFromEmailEnabled = $True; + LocationDetailsInFreeBusy = "Desk"; + PackageDeliveryEventsFromEmailEnabled = $False; + PreserveDeclinedMeetings = $False; + RemindersEnabled = $True; + ReminderSoundEnabled = $True; + RentalCarEventsFromEmailEnabled = $True; + ServiceAppointmentEventsFromEmailEnabled = $True; + ShortenEventScopeDefault = "None"; + ShowWeekNumbers = $False; + TimeIncrement = "ThirtyMinutes"; + UseBrightCalendarColorThemeInOwa = $False; + WeatherEnabled = "FirstRun"; + WeatherLocationBookmark = 0; + WeatherLocations = @(); + WeatherUnit = "Default"; + WeekStartDay = "Sunday"; + WorkDays = "Monday, Tuesday"; + WorkingHoursEndTime = "17:00:00"; + WorkingHoursStartTime = "08:00:00"; + WorkingHoursTimeZone = "Pacific Standard Time"; + WorkspaceUserEnabled = $False; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } EXOMailboxCalendarFolder 'JohnCalendarFolder' { DetailLevel = "AvailabilityOnly"; From 98f495af7f5dcc686fdbe935891287d73e18a63e Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 07:03:52 +0000 Subject: [PATCH 116/465] Updated Resources and Cmdlet documentation pages --- .../exchange/EXOSecOpsOverrideRule.md | 157 ++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 docs/docs/resources/exchange/EXOSecOpsOverrideRule.md diff --git a/docs/docs/resources/exchange/EXOSecOpsOverrideRule.md b/docs/docs/resources/exchange/EXOSecOpsOverrideRule.md new file mode 100644 index 0000000000..e012da3f3a --- /dev/null +++ b/docs/docs/resources/exchange/EXOSecOpsOverrideRule.md @@ -0,0 +1,157 @@ +# EXOSecOpsOverrideRule + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | +| **Identity** | Key | String | The unique identifier (GUID or name) of the override rule. This parameter is mandatory. | | +| **Comment** | Write | String | An optional comment for the override rule. | | +| **Policy** | Write | String | The SecOps simulation override policy that's associated with the rule. | | +| **Ensure** | Write | String | Ensures the presence or absence of the configuration. | `Present`, `Absent` | + + +## Description + +This resource allows users to manage resource to modify SecOps +override rules to bypass Exchange Online Protection filtering. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOSecOpsOverrideRule "EXOSecOpsOverrideRule-_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245" + { + Comment = "TestComment"; + Ensure = "Present"; + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOSecOpsOverrideRule "EXOSecOpsOverrideRule-_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245" + { + Comment = "TestComment"; + Ensure = "Present"; + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + +### Example 3 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOSecOpsOverrideRule "EXOSecOpsOverrideRule-_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245" + { + Ensure = "Absent"; + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + } + } +} +``` + From 377a5bf15c3502b9549c77dd871d7d6e79219645 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 07:05:49 +0000 Subject: [PATCH 117/465] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index cd98b3df94..e9e92113e8 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -884,6 +884,13 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOSecOpsOverrideRule 'EXOSecOpsOverrideRule-_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245' + { + Comment = "TestComment"; + Ensure = "Present"; + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; + } EXOSharedMailbox 'SharedMailbox' { DisplayName = "Integration" From 0248a95b93844c70a5287ba0b29804fce30ed17f Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 07:06:13 +0000 Subject: [PATCH 118/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index 3e67a55a83..0137945fd7 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -1278,6 +1278,16 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOSecOpsOverrideRule 'EXOSecOpsOverrideRule-_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245' + { + Comment = "TestComment"; + Ensure = "Present"; + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + Policy = "40528418-717d-4368-a1ae-7912918f8a1f"; + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } EXOSharedMailbox 'SharedMailbox' { DisplayName = "Integration" From 28e8d4f70fee8d50bf1c7cc4b27195ae8dbe5e35 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 07:06:33 +0000 Subject: [PATCH 119/465] Updated {Update} EXO Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 index d295e0f589..8552b683e1 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 @@ -531,6 +531,11 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOSecOpsOverrideRule 'EXOSecOpsOverrideRule-_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245' + { + Ensure = "Absent"; + Identity = "_Exe:SecOpsOverrid:ca3c51ac-925c-49f4-af42-43e26b874245"; + } EXOSharedMailbox 'SharedMailbox' { DisplayName = "Integration" From ed2141c15311584f4f17e65b6ead9d863bcb499d Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Wed, 11 Sep 2024 13:02:22 +0530 Subject: [PATCH 120/465] Added Change Logs and fixed UTs --- CHANGELOG.md | 6 ++++-- .../Microsoft365DSC.EXORetentionPolicy.Tests.ps1 | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1607d6bb76..c1470328d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* AADPasswordRuleSettings + * Initial release * EXOFocusedInbox * Initial Release. * EXOMailboxCalendarConfiguration @@ -10,8 +12,8 @@ * Initial Release. * EXOManagementScope * Initial Release. -* AADPasswordRuleSettings - * Initial release +* EXORetenionPolicy + * Initial Release. * EXOPhishSimOverrideRule * Initial Release. * IntuneAntivirusPolicyWindows10SettingCatalog diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORetentionPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORetentionPolicy.Tests.ps1 index f2a75a1328..b3b827c6d9 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORetentionPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORetentionPolicy.Tests.ps1 @@ -58,7 +58,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ - Ensure = 'Present'; + Ensure = "Present"; Credential = $Credential; Identity = "Ritik"; IsDefault = $False; @@ -80,6 +80,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should create a new instance from the Set method' { + Set-TargetResource @testParams Should -Invoke -CommandName New-RetentionPolicy -Exactly 1 } } @@ -117,6 +118,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should remove the instance from the Set method' { + Set-TargetResource @testParams Should -Invoke -CommandName Remove-RetentionPolicy -Exactly 1 } } From 878cb363985bd4b5d95dd42d3d49a701821f3917 Mon Sep 17 00:00:00 2001 From: namratagupta2024 Date: Wed, 11 Sep 2024 13:31:32 +0530 Subject: [PATCH 121/465] removed Ensure --- CHANGELOG.md | 2 ++ .../MSFT_EXOArcConfig/MSFT_EXOArcConfig.psm1 | 35 +++---------------- .../MSFT_EXOArcConfig.schema.mof | 1 - .../Resources/EXOArcConfig/2-Update.ps1 | 2 +- .../Microsoft365DSC.EXOArcConfig.Tests.ps1 | 2 -- 5 files changed, 7 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ca837185a..daa712f0be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ # UNRELEASED * EXOArcConfig * Initial Release. +* EXOFocusedInbox + * Initial Release. * EXOMailboxCalendarConfiguration * Initial Release. * EXOManagementScope diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/MSFT_EXOArcConfig.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/MSFT_EXOArcConfig.psm1 index 960cb08373..3da9fdc728 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/MSFT_EXOArcConfig.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/MSFT_EXOArcConfig.psm1 @@ -17,11 +17,6 @@ function Get-TargetResource [System.String[]] $ArcTrustedSealers, - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -38,7 +33,7 @@ function Get-TargetResource [System.String] $CertificateThumbprint, - [Parameter()] + [Parameter()] [System.String] $CertificatePath, @@ -82,7 +77,6 @@ function Get-TargetResource #endregion $nullResult = $PSBoundParameters - $nullResult.Ensure = 'Absent' try { $ArcConfigSettings = Get-ArcConfig -ErrorAction Stop @@ -91,7 +85,6 @@ function Get-TargetResource IsSingleInstance = 'Yes' ArcTrustedSealers = $ArcConfigSettings.ArcTrustedSealers Credential = $Credential - Ensure = 'Present' ApplicationId = $ApplicationId CertificateThumbprint = $CertificateThumbprint CertificatePath = $CertificatePath @@ -135,11 +128,6 @@ function Set-TargetResource [System.String[]] $ArcTrustedSealers, - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -189,22 +177,13 @@ function Set-TargetResource $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` -InboundParameters $PSBoundParameters - $ArcConfigParams = [System.Collections.Hashtable]($PSBoundParameters) - $ArcConfigParams.Remove('Ensure') | Out-Null - $ArcConfigParams.Remove('Credential') | Out-Null - $ArcConfigParams.Remove('ApplicationId') | Out-Null - $ArcConfigParams.Remove('TenantId') | Out-Null - $ArcConfigParams.Remove('CertificateThumbprint') | Out-Null - $ArcConfigParams.Remove('CertificatePath') | Out-Null - $ArcConfigParams.Remove('CertificatePassword') | Out-Null - $ArcConfigParams.Remove('ManagedIdentity') | Out-Null + $ArcConfigParams = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters $ArcConfigParams.Remove('IsSingleInstance') | Out-Null - $ArcConfigParams.Remove('AccessTokens') | Out-Null - if (('Present' -eq $Ensure ) -and ($Null -ne $ArcConfigParams)) + if ($Null -ne $ArcConfigParams) { Write-Verbose -Message "Setting Arc Config with values: $(Convert-M365DscHashtableToString -Hashtable $ArcConfigParams)" - Set-ArcConfig @ArcConfigParams + Set-ArcConfig -Identity Default @ArcConfigParams Write-Verbose -Message 'Arc Config updated successfully' } @@ -229,11 +208,6 @@ function Test-TargetResource [System.String[]] $ArcTrustedSealers, - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -287,7 +261,6 @@ function Test-TargetResource Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" $ValuesToCheck = $PSBoundParameters - $ValuesToCheck.Remove('Ensure') | Out-Null # Need to remove Identity as Get-ArcConfig doesn't return Identity $ValuesToCheck.Remove('Identity') | Out-Null diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/MSFT_EXOArcConfig.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/MSFT_EXOArcConfig.schema.mof index 8c1261e915..e773a36adf 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/MSFT_EXOArcConfig.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOArcConfig/MSFT_EXOArcConfig.schema.mof @@ -4,7 +4,6 @@ class MSFT_EXOArcConfig : OMI_BaseResource [Key, Description("Only valid value is 'Yes'."), ValueMap{"Yes"}, Values{"Yes"}] String IsSingleInstance; [Write, Description("Identity which indicates the organization.")] String Identity; [Write, Description("The domain names of the ARC sealers.")] String ArcTrustedSealers[]; - [Write, Description("Specifies if this EmailTenantSettings should exist."), 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; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOArcConfig/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOArcConfig/2-Update.ps1 index 216c944862..0ac8f73520 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOArcConfig/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOArcConfig/2-Update.ps1 @@ -24,7 +24,7 @@ Configuration Example EXOArcConfig "EXOArcConfig-Test" { ArcTrustedSealers = "contoso.com"; - Ensure = "Present"; + IsSingleInstance = "Yes" TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint ApplicationId = $ApplicationId diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOArcConfig.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOArcConfig.Tests.ps1 index 7907b4f4aa..a0154cb4d4 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOArcConfig.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOArcConfig.Tests.ps1 @@ -54,7 +54,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ArcTrustedSealers = "cohovineyard.com,tailspintoys.com"; Identity = "Default"; Credential = $Credential - Ensure = "Present" } Mock -CommandName Get-ArcConfig -MockWith { @@ -82,7 +81,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ArcTrustedSealers = "abc.com,cohovineyard.com,tailspintoys.com"; Identity = "Default"; Credential = $Credential - Ensure = "Present" } Mock -CommandName Get-ArcConfig -MockWith { From 3b81c19feb059fa24f1c1d5b7c61b04a3f813933 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 09:55:57 +0000 Subject: [PATCH 122/465] Updated Resources and Cmdlet documentation pages --- .../resources/exchange/EXORetentionPolicy.md | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 docs/docs/resources/exchange/EXORetentionPolicy.md diff --git a/docs/docs/resources/exchange/EXORetentionPolicy.md b/docs/docs/resources/exchange/EXORetentionPolicy.md new file mode 100644 index 0000000000..b5ee023a0d --- /dev/null +++ b/docs/docs/resources/exchange/EXORetentionPolicy.md @@ -0,0 +1,165 @@ +# EXORetentionPolicy + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Identity** | Key | String | The Identity parameter specifies the name, distinguished name (DN), or GUID of the retention policy. | | +| **IsDefault** | Write | Boolean | The IsDefault switch specifies that this retention policy is the default retention policy. You don't need to specify a value with this switch. | | +| **IsDefaultArbitrationMailbox** | Write | Boolean | The IsDefaultArbitrationMailbox switch configures this policy as the default retention policy for arbitration mailboxes in your Exchange Online organization. You don't need to specify a value with this switch. | | +| **Name** | Write | String | The Name parameter specifies a unique name for the retention policy. | | +| **RetentionId** | Write | String | The RetentionId parameter specifies the identity of the retention policy to make sure mailboxes moved between two Exchange organizations continue to have the same retention policy applied to them. | | +| **RetentionPolicyTagLinks** | Write | StringArray[] | The RetentionPolicyTagLinks parameter specifies the identity of retention policy tags to associate with the retention policy. Mailboxes that get a retention policy applied have retention tags linked with that retention policy. | | +| **Ensure** | Write | String | Specifies if this report submission rule should exist. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +# EXORetentionPolicy + +## Description + +Use the New-RetentionPolicy cmdlet to create a retention policy and the Set-RetentionPolicy cmdlet to change the properties of an existing retention policy. + +## Permissions + +### Exchange + +To authenticate with Microsoft Exchange, this resource required the following permissions: + +#### Roles + +- Organization Management, Recipient Management + +#### Role Groups + +- Organization Management, Help Desk + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXORetentionPolicy "EXORetentionPolicy-Test" + { + Name = "Test Retention Policy"; + Identity = "Test Retention Policy"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + RetentionPolicyTagLinks = @("6 Month Delete","Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); + Ensure = "Present"; + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXORetentionPolicy "EXORetentionPolicy-Test" + { + Name = "Test Retention Policy"; + Identity = "Test Retention Policy"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + RetentionPolicyTagLinks = @("Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); # drifted property + Ensure = "Present"; + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + + } +} +``` + +### Example 3 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXORetentionPolicy "EXORetentionPolicy-Test" + { + Name = "Test Retention Policy"; + Identity = "Test Retention Policy"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + RetentionPolicyTagLinks = @("6 Month Delete","Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); + Ensure = "Absent"; + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + + } +} +``` + From cc223e369f5f2baf288e16f63fc95e34e7bc7d63 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 09:57:51 +0000 Subject: [PATCH 123/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index bea8332ade..efc3299287 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -14044,6 +14044,76 @@ } ] }, + { + "ClassName": "MSFT_EXORetentionPolicy", + "Parameters": [ + { + "CIMType": "String", + "Name": "Identity", + "Option": "Key" + }, + { + "CIMType": "Boolean", + "Name": "IsDefault", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsDefaultArbitrationMailbox", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Name", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "RetentionId", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "RetentionPolicyTagLinks", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXORoleAssignmentPolicy", "Parameters": [ @@ -14609,6 +14679,61 @@ } ] }, + { + "ClassName": "MSFT_EXOSecOpsOverrideRule", + "Parameters": [ + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Identity", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Comment", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Policy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Ensure", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOSharedMailbox", "Parameters": [ From 35e405c167a4521009bbd561caa67eae9543813c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 09:58:59 +0000 Subject: [PATCH 124/465] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index e9e92113e8..09ec18abf2 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -811,6 +811,18 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXORetentionPolicy 'EXORetentionPolicy-Test' + { + Name = "Test Retention Policy"; + Identity = "Test Retention Policy"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + RetentionPolicyTagLinks = @("6 Month Delete","Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); + Ensure = "Present"; + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } EXORoleAssignmentPolicy 'ConfigureRoleAssignmentPolicy' { Name = "Integration Policy" From db246594a96f603f7c31fdc41931b0f6014b5bf5 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 09:59:26 +0000 Subject: [PATCH 125/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index 0137945fd7..5770180b09 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -1205,6 +1205,18 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXORetentionPolicy 'EXORetentionPolicy-Test' + { + Name = "Test Retention Policy"; + Identity = "Test Retention Policy"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + RetentionPolicyTagLinks = @("Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); # drifted property + Ensure = "Present"; + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } EXORoleAssignmentPolicy 'ConfigureRoleAssignmentPolicy' { Name = "Integration Policy" From 5224df7a35dcdd9b5abc634608eec39a69db4ff6 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 09:59:45 +0000 Subject: [PATCH 126/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Remove.Tests.ps1 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 index 8552b683e1..9561195d84 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 @@ -471,6 +471,18 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXORetentionPolicy 'EXORetentionPolicy-Test' + { + Name = "Test Retention Policy"; + Identity = "Test Retention Policy"; + IsDefault = $False; + IsDefaultArbitrationMailbox = $False; + RetentionPolicyTagLinks = @("6 Month Delete","Personal 5 year move to archive","1 Month Delete","1 Week Delete","Personal never move to archive","Personal 1 year move to archive","Default 2 year move to archive","Deleted Items","Junk Email","Recoverable Items 14 days move to archive","Never Delete"); + Ensure = "Absent"; + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } EXORoleAssignmentPolicy 'ConfigureRoleAssignmentPolicy' { Name = "Integration Policy" From ad71ad3665d939d6de2bac73a98c31d3dd176e56 Mon Sep 17 00:00:00 2001 From: Alex Floca Date: Wed, 11 Sep 2024 12:31:31 +0200 Subject: [PATCH 127/465] Fix ressource --- .../MSFT_SCRoleGroup/MSFT_SCRoleGroup.psm1 | 25 ++++++++++++++++++- .../MSFT_SCRoleGroup.schema.mof | 1 + 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.psm1 index 5533d71d2f..14c3e57243 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.psm1 @@ -9,6 +9,10 @@ function Get-TargetResource [System.String] $Name, + [Parameter()] + [System.String] + $DisplayName, + [Parameter()] [System.String] $Description, @@ -95,8 +99,9 @@ function Get-TargetResource { $result = @{ Name = $RoleGroup.Name + DisplayName = $RoleGroup.DisplayName Description = $RoleGroup.Description - Roles = $RoleGroup.Roles + Roles = $RoleGroup.Roles -replace "^.*\/(?=[^\/]*$)" Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -134,6 +139,11 @@ function Set-TargetResource [System.String] $Name, + [Parameter()] + [ValidateLength(1, 256)] + [System.String] + $DisplayName, + [Parameter()] [System.String] $Description, @@ -205,6 +215,14 @@ function Set-TargetResource Roles = $Roles Confirm = $false } + # Add DisplayName Parameter equals Name if null or Empty as creation with no value will lead to a corrupted state of the created RoleGroup + if ([System.String]::IsNullOrEmpty($DisplayName)) + { + $NewRoleGroupParams.Add('DisplayName', $Name) + } + else { + $NewRoleGroupParams.Add('DisplayName', $DisplayName) + } # Remove Description Parameter if null or Empty as the creation fails with $null parameter if ([System.String]::IsNullOrEmpty($Description)) { @@ -240,6 +258,11 @@ function Test-TargetResource [System.String] $Name, + [Parameter()] + [ValidateLength(1, 256)] + [System.String] + $DisplayName, + [Parameter()] [System.String] $Description, diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.schema.mof index 9348360605..f4c0b669a4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.schema.mof @@ -2,6 +2,7 @@ class MSFT_SCRoleGroup : OMI_BaseResource { [Key, Description("The Name parameter specifies the name of the role. The maximum length of the name is 64 characters.")] String Name; + [Write, Description("The DisplayName parameter specifies the name of the role. The maximum length of the name is 256 characters.")] String DisplayName; [Write, Description("The Description parameter specifies the description that's displayed when the role group is viewed using the Get-RoleGroup cmdlet. Enclose the description in quotation marks")] String Description; [Write, Description("The Roles parameter specifies the management roles to assign to the role group when it's created. If a role name contains spaces, enclose the name in quotation marks. If you want to assign more that one role, separate the role names with commas.")] String Roles[]; [Write, Description("Specify if the Role Group should exist or not."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; From afbdae231e11a3cfa25c93cb09deee1fda9bed35 Mon Sep 17 00:00:00 2001 From: namratagupta2024 Date: Wed, 11 Sep 2024 16:16:20 +0530 Subject: [PATCH 128/465] fixed test --- .../Examples/Resources/EXOArcConfig/2-Update.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOArcConfig/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOArcConfig/2-Update.ps1 index 0ac8f73520..7f1e257061 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOArcConfig/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOArcConfig/2-Update.ps1 @@ -24,10 +24,10 @@ Configuration Example EXOArcConfig "EXOArcConfig-Test" { ArcTrustedSealers = "contoso.com"; - IsSingleInstance = "Yes" - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ApplicationId = $ApplicationId + IsSingleInstance = "Yes"; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + ApplicationId = $ApplicationId; } } } \ No newline at end of file From 8f89de7d6972d853d752ae33aad07050c43bc414 Mon Sep 17 00:00:00 2001 From: Alex Floca Date: Wed, 11 Sep 2024 13:29:20 +0200 Subject: [PATCH 129/465] link Issue&update release notes --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1470328d7..af66f76b24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,10 @@ * IntuneAntivirusPolicyWindows10SettingCatalog * Fixes an issue with invalid parameter definition. FIXES [#5015](https://github.com/microsoft/Microsoft365DSC/issues/5015) +* SCRoleGroup + * Fixes an issue with creation without specifying Displayname + * Fixes an issue with Drifts because of returned Role format + FIXES [#5036](https://github.com/microsoft/Microsoft365DSC/issues/5036) * SentinelSetting * Initial release. * SPOAccessControlSettings From 22c3569cd167b0c8c26bbba09e3738fae4212ddc Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 11 Sep 2024 07:32:32 -0400 Subject: [PATCH 130/465] Updated --- .../MSFT_SCInsiderRiskEntityList.psm1 | 61 ++++++++++++++----- .../Dependencies/Manifest.psd1 | 2 +- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 index 7d42466c4c..c477dc7fc2 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 @@ -4,12 +4,21 @@ function Get-TargetResource [OutputType([System.Collections.Hashtable])] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $Name, - ##TODO - Add the list of Parameters + [Parameter(Mandatory = $true)] + [System.String] + $ListType, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DisplayName, [Parameter()] [System.Management.Automation.PSCredential] @@ -37,7 +46,7 @@ function Get-TargetResource ) ##TODO - Replace the workload by the one associated to your resource - New-M365DSCConnection -Workload 'Workload' ` + New-M365DSCConnection -Workload 'SecurityComplianceCenter' ` -InboundParameters $PSBoundParameters | Out-Null #Ensure the proper dependencies are installed in the current environment. @@ -58,13 +67,18 @@ function Get-TargetResource { if ($null -ne $Script:exportedInstances -and $Script:ExportMode) { - ##TODO - Replace the PrimaryKey in the Filter by the one for the resource - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.PrimaryKey -eq $PrimaryKey} + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.ListType -eq $ListType -and $_.DisplayName -eq $DisplayName} + } + else + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.ListType -eq $ListType -and $_.Name -eq $Name} + } } else { - ##TODO - Replace the cmdlet by the one to retrieve a specific instance. - $instance = Get-cmdlet -PrimaryKey $PrimaryKey -ErrorAction Stop + $instance = Get-InsiderRiskEntityList -Type $ListType -ErrorAction Stop } if ($null -eq $instance) { @@ -72,7 +86,10 @@ function Get-TargetResource } $results = @{ - ##TODO - Add the list of parameters to be returned + DisplayName = $instance.DisplayName + Name = $instance.Name + Description = $instance.Description + ListType = $instance.ListType Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -269,8 +286,7 @@ function Export-TargetResource $AccessTokens ) - ##TODO - Replace workload - $ConnectionMode = New-M365DSCConnection -Workload 'Workload' ` + $ConnectionMode = New-M365DSCConnection -Workload 'SecurityComplianceCenter' ` -InboundParameters $PSBoundParameters #Ensure the proper dependencies are installed in the current environment. @@ -288,8 +304,16 @@ function Export-TargetResource try { $Script:ExportMode = $true - ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances - [array] $Script:exportedInstances = Get-Cmdlet -ErrorAction Stop + [array] $Script:exportedInstances = @() + $availableTypes = @('HveLists', 'DomainLists', 'CriticalAssetLists', 'WindowsFilePathRegexLists', 'SensitiveTypeLists', 'SiteLists', 'KeywordLists', ` + 'CustomDomainLists', 'CustomSiteLists', 'CustomKeywordLists', 'CustomFileTypeLists', 'CustomFilePathRegexLists', ` + 'CustomSensitiveInformationTypeLists', 'CustomMLClassifierTypeLists', 'GlobalExclusionSGMapping', 'DlpPolicyLists') + + # Retrieve entries for each type + foreach ($listType in $availableTypes) + { + $Script:exportedInstances += Get-InsiderRiskEntityList -Type $listType -ErrorAction Stop + } $i = 1 $dscContent = '' @@ -303,11 +327,16 @@ function Export-TargetResource } foreach ($config in $Script:exportedInstances) { - $displayedKey = $config.Id + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + $displayedKey = $config.ListType + ' - ' + $config.Name Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline $params = @{ - ##TODO - Specify the Primary Key - #PrimaryKey = $config.PrimaryKey + DisplayName = $config.DisplayName + Name = $config.Name + ListType = $config.ListType Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 1c36e81530..04f716b118 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -90,7 +90,7 @@ }, @{ ModuleName = "MSCloudLoginAssistant" - RequiredVersion = "1.1.20" + RequiredVersion = "1.1.22" }, @{ ModuleName = 'PnP.PowerShell' From b93d7062f85330335e00cafe592c28e365592785 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 11:38:56 +0000 Subject: [PATCH 131/465] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/exchange/EXOArcConfig.md | 73 ++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 docs/docs/resources/exchange/EXOArcConfig.md diff --git a/docs/docs/resources/exchange/EXOArcConfig.md b/docs/docs/resources/exchange/EXOArcConfig.md new file mode 100644 index 0000000000..f2e949c0fe --- /dev/null +++ b/docs/docs/resources/exchange/EXOArcConfig.md @@ -0,0 +1,73 @@ +# EXOArcConfig + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **IsSingleInstance** | Key | String | Only valid value is 'Yes'. | `Yes` | +| **Identity** | Write | String | Identity which indicates the organization. | | +| **ArcTrustedSealers** | Write | StringArray[] | The domain names of the ARC sealers. | | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +This resource manages the list of trusted Authenticated Received Chain (ARC) sealers that are configured in the organization. + +## Permissions + +### Exchange + +To authenticate with Microsoft Exchange, this resource required the following permissions: + +#### Roles + +- Security Admin, Security Reader, Tenant AllowBlockList Manager, Transport Hygiene, View-Only Configuration + +#### Role Groups + +- Organization Management + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOArcConfig "EXOArcConfig-Test" + { + ArcTrustedSealers = "contoso.com"; + IsSingleInstance = "Yes"; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + ApplicationId = $ApplicationId; + } + } +} +``` + From 42a7976295efb0e9b874e88f3ea7b965338a34cc Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 11:41:08 +0000 Subject: [PATCH 132/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index efc3299287..44a4eb2643 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -5929,6 +5929,56 @@ } ] }, + { + "ClassName": "MSFT_EXOArcConfig", + "Parameters": [ + { + "CIMType": "String", + "Name": "IsSingleInstance", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Identity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ArcTrustedSealers", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOAtpPolicyForO365", "Parameters": [ From e3479569774bc419d339b726c822b5cbf78aaed9 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 11:42:10 +0000 Subject: [PATCH 133/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index 5770180b09..e3fd8c95b0 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -130,6 +130,14 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOArcConfig 'EXOArcConfig-Test' + { + ArcTrustedSealers = "contoso.com"; + IsSingleInstance = "Yes"; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + ApplicationId = $ApplicationId; + } EXOAtpPolicyForO365 'ConfigureAntiPhishPolicy' { IsSingleInstance = "Yes" From 982d8500309fa34397916e0b4e66a0312b54039c Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 11 Sep 2024 07:52:12 -0400 Subject: [PATCH 134/465] Update MSFT_SCInsiderRiskEntityList.schema.mof --- .../MSFT_SCInsiderRiskEntityList.schema.mof | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof index 07accdc886..0343b1604a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof @@ -1,8 +1,10 @@ [ClassVersion("1.0.0.0"), FriendlyName("SCInsiderRiskEntityList")] class MSFT_SCInsiderRiskEntityList : OMI_BaseResource { - [Key, Description("")] String PrimaryKey; - [Write, Description("")] String OtherProperties; + [Key, Description("")] String Name; + [Required, Description("")] String ListType; + [Write, Description("")] String Description; + [Write, Description("")] String DisplayName; [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 843ade4037b8f9f18ff4175a3775d04bb63a32c6 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 11 Sep 2024 07:52:42 -0400 Subject: [PATCH 135/465] Update M365DSCUtil.psm1 --- Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 9397159c76..614ea78655 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1771,7 +1771,6 @@ function New-M365DSCConnection [System.Boolean] $SkipModuleReload = $false ) - $verbosepreference = 'Continue' $Global:MaximumFunctionCount = 32767 if ($Workload -eq 'MicrosoftTeams') { From 5856236151789b1dfc03ee6287f4b095cf37c04a Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 11:52:50 +0000 Subject: [PATCH 136/465] Updated Resources and Cmdlet documentation pages --- .../SCUnifiedAuditLogRetentionPolicy.md | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 docs/docs/resources/security-compliance/SCUnifiedAuditLogRetentionPolicy.md diff --git a/docs/docs/resources/security-compliance/SCUnifiedAuditLogRetentionPolicy.md b/docs/docs/resources/security-compliance/SCUnifiedAuditLogRetentionPolicy.md new file mode 100644 index 0000000000..c3406169eb --- /dev/null +++ b/docs/docs/resources/security-compliance/SCUnifiedAuditLogRetentionPolicy.md @@ -0,0 +1,58 @@ +# SCUnifiedAuditLogRetentionPolicy + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Description** | Write | String | The description for the audit log retention policy | | +| **Name** | Key | String | Unique name for the audit log retention policy | | +| **Operations** | Write | StringArray[] | Specifies the audit log operations that are retained by the policy | | +| **Priority** | Write | UInt32 | Priority value for the policy that determines the order of policy processing. | | +| **RecordTypes** | Write | StringArray[] | Specifies the audit logs of a specific record type that are retained by the policy. | | +| **RetentionDuration** | Write | String | How long audit log records are kept | `SevenDays`, `OneMonth`, `ThreeMonths`, `SixMonths`, `NineMonths`, `TwelveMonths`, `ThreeYears`, `FiveYears`, `SevenYears`, `TenYears` | +| **UserIds** | Write | StringArray[] | Specifies the audit logs that are retained by the policy based on the ID of the user who performed the action | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | + + +## Description + +The resource configured the Unified Audit Log Retention Policy in the Security and Compliance. + +## Permissions + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter(Mandatory = $true)] + [PSCredential] + $Credentials + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + SCUnifiedAuditLogRetentionPolicy 'Example' + { + Credential = $Credentials; + Ensure = "Present"; + Name = "Test Policy"; + Priority = 1; + RetentionDuration = "SevenDays"; + } + } +} +``` + From 7939e0c2f83bed9fab153d2ec0b6efb0de526cf2 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 11:54:24 +0000 Subject: [PATCH 137/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 44a4eb2643..bf6be527ff 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -39684,6 +39684,76 @@ } ] }, + { + "ClassName": "MSFT_SCUnifiedAuditLogRetentionPolicy", + "Parameters": [ + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Name", + "Option": "Key" + }, + { + "CIMType": "String[]", + "Name": "Operations", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "Priority", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "RecordTypes", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "RetentionDuration", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "UserIds", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_SentinelSetting", "Parameters": [ From 29277bd0e4eb4b615784807dd1ddd56c529a4164 Mon Sep 17 00:00:00 2001 From: Alex Floca Date: Wed, 11 Sep 2024 14:24:42 +0200 Subject: [PATCH 138/465] resolve comments --- .../DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.psm1 | 1 + .../DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.schema.mof | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.psm1 index 14c3e57243..171c460360 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.psm1 @@ -10,6 +10,7 @@ function Get-TargetResource $Name, [Parameter()] + [ValidateLength(1, 256)] [System.String] $DisplayName, diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.schema.mof index f4c0b669a4..466581fdae 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRoleGroup/MSFT_SCRoleGroup.schema.mof @@ -2,7 +2,7 @@ class MSFT_SCRoleGroup : OMI_BaseResource { [Key, Description("The Name parameter specifies the name of the role. The maximum length of the name is 64 characters.")] String Name; - [Write, Description("The DisplayName parameter specifies the name of the role. The maximum length of the name is 256 characters.")] String DisplayName; + [Write, Description("The DisplayName parameter specifies the friendly name of the role group. If the name contains spaces, enclose the name in quotation marks. This parameter has a maximum length of 256 characters.")] String DisplayName; [Write, Description("The Description parameter specifies the description that's displayed when the role group is viewed using the Get-RoleGroup cmdlet. Enclose the description in quotation marks")] String Description; [Write, Description("The Roles parameter specifies the management roles to assign to the role group when it's created. If a role name contains spaces, enclose the name in quotation marks. If you want to assign more that one role, separate the role names with commas.")] String Roles[]; [Write, Description("Specify if the Role Group should exist or not."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; From b6a2504a8f3ec898fd766b94370a8efbfc3b03f2 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 12:44:38 +0000 Subject: [PATCH 139/465] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/security-compliance/SCRoleGroup.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/resources/security-compliance/SCRoleGroup.md b/docs/docs/resources/security-compliance/SCRoleGroup.md index db061cc3ed..da49632bb6 100644 --- a/docs/docs/resources/security-compliance/SCRoleGroup.md +++ b/docs/docs/resources/security-compliance/SCRoleGroup.md @@ -5,6 +5,7 @@ | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **Name** | Key | String | The Name parameter specifies the name of the role. The maximum length of the name is 64 characters. | | +| **DisplayName** | Write | String | The DisplayName parameter specifies the friendly name of the role group. If the name contains spaces, enclose the name in quotation marks. This parameter has a maximum length of 256 characters. | | | **Description** | Write | String | The Description parameter specifies the description that's displayed when the role group is viewed using the Get-RoleGroup cmdlet. Enclose the description in quotation marks | | | **Roles** | Write | StringArray[] | The Roles parameter specifies the management roles to assign to the role group when it's created. If a role name contains spaces, enclose the name in quotation marks. If you want to assign more that one role, separate the role names with commas. | | | **Ensure** | Write | String | Specify if the Role Group should exist or not. | `Present`, `Absent` | From 84f09b702bafed86fd23f3aac5137b5a54e2939b Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 12:47:05 +0000 Subject: [PATCH 140/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index bf6be527ff..2e763f0bc3 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -39092,6 +39092,11 @@ "Name": "Name", "Option": "Key" }, + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Write" + }, { "CIMType": "String", "Name": "Description", From 5431df51021e0feae610279748918dfe9bf97f3c Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Wed, 11 Sep 2024 14:57:05 +0200 Subject: [PATCH 141/465] Add missing AccessTokens parameter to export --- CHANGELOG.md | 3 +++ ...eviceConfigurationSharedMultiDevicePolicyWindows10.psm1 | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a44d48dfab..d4874b76dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,9 @@ * IntuneAntivirusPolicyWindows10SettingCatalog * Fixes an issue with invalid parameter definition. FIXES [#5015](https://github.com/microsoft/Microsoft365DSC/issues/5015) +* IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10 + * Add missing `AccessTokens` parameter to `Export-TargetResource` + FIXES [#5034](https://github.com/microsoft/Microsoft365DSC/issues/5034) * SCRoleGroup * Fixes an issue with creation without specifying Displayname * Fixes an issue with Drifts because of returned Role format diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10/MSFT_IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10/MSFT_IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10.psm1 index f99ba0c052..6b55829931 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10/MSFT_IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10/MSFT_IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10.psm1 @@ -775,7 +775,11 @@ function Export-TargetResource [Parameter()] [Switch] - $ManagedIdentity + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` @@ -836,6 +840,7 @@ function Export-TargetResource ApplicationSecret = $ApplicationSecret CertificateThumbprint = $CertificateThumbprint Managedidentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens } $Results = Get-TargetResource @Params From 5f7f1f0fb6c69c043c5423eec6a6d267fdaa7ef6 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 11 Sep 2024 08:59:37 -0400 Subject: [PATCH 142/465] Updates --- .../MSFT_SCInsiderRiskEntityList.psm1 | 5 +++++ .../MSFT_SCInsiderRiskEntityList.schema.mof | 2 +- Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 index c477dc7fc2..fdd2b985bc 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 @@ -20,6 +20,11 @@ function Get-TargetResource [System.String] $DisplayName, + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + [Parameter()] [System.Management.Automation.PSCredential] $Credential, diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof index 0343b1604a..21cf04215e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof @@ -5,7 +5,7 @@ class MSFT_SCInsiderRiskEntityList : OMI_BaseResource [Required, Description("")] String ListType; [Write, Description("")] String Description; [Write, Description("")] String DisplayName; - + [Write, Description("Specify if this entity should exist or not."), 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; diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 614ea78655..b43cd56a1f 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -3668,7 +3668,7 @@ function Get-M365DSCExportContentForResource { $primaryKey = '' } - elseif ($Keys.Contains('DisplayName')) + elseif ($Keys.Contains('DisplayName') -and -not [System.String]::IsNullOrEmpty($Results.DisplayName)) { $primaryKey = $Results.DisplayName } From f4d70a7f8935276447ac10f4fd6269557ec271f3 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 11 Sep 2024 09:43:08 -0400 Subject: [PATCH 143/465] ADOSecurityPolicy - Initial Release --- .../MSFT_ADOSecurityPolicy.psm1 | 351 ++++++++++++++++++ .../MSFT_ADOSecurityPolicy.schema.mof | 13 + .../MSFT_ADOSecurityPolicy/readme.md | 6 + .../MSFT_ADOSecurityPolicy/settings.json | 32 ++ .../Resources/ADOSecurityPolicy/1-Create.ps1 | 26 ++ .../Resources/ADOSecurityPolicy/2-Update.ps1 | 26 ++ .../Resources/ADOSecurityPolicy/3-Remove.ps1 | 26 ++ ...icrosoft365DSC.ADOSecurityPolicy.Tests.ps1 | 176 +++++++++ 8 files changed, 656 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOSecurityPolicy.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 new file mode 100644 index 0000000000..c6f63d3927 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 @@ -0,0 +1,351 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace the workload by the one associated to your resource + New-M365DSCConnection -Workload 'Workload' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + ##TODO - Replace the PrimaryKey in the Filter by the one for the resource + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.PrimaryKey -eq $PrimaryKey} + } + else + { + ##TODO - Replace the cmdlet by the one to retrieve a specific instance. + $instance = Get-cmdlet -PrimaryKey $PrimaryKey -ErrorAction Stop + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + ##TODO - Add the list of parameters to be returned + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + ##TODO - Replace by the New cmdlet for the resource + New-Cmdlet @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Update/Set cmdlet for the resource + Set-cmdlet @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Remove cmdlet for the resource + Remove-cmdlet @SetParameters + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace workload + $ConnectionMode = New-M365DSCConnection -Workload 'Workload' ` + -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 + { + $Script:ExportMode = $true + ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances + [array] $Script:exportedInstances = Get-Cmdlet -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + ##TODO - Specify the Primary Key + #PrimaryKey = $config.PrimaryKey + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.schema.mof new file mode 100644 index 0000000000..6fa43ce435 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.schema.mof @@ -0,0 +1,13 @@ +[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] +class MSFT_ResourceName : OMI_BaseResource +{ + [Key, Description("")] String PrimaryKey; + [Write, Description("")] String OtherProperties; + + [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; \ No newline at end of file diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/readme.md new file mode 100644 index 0000000000..53f0d03cb4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/readme.md @@ -0,0 +1,6 @@ + +# ADOSecurityPolicy + +## Description + +##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/settings.json new file mode 100644 index 0000000000..d95903b900 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "ADOSecurityPolicy", + "description": "Description of what the resource is about.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/1-Create.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/1-Create.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/2-Update.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/3-Remove.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/3-Remove.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOSecurityPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOSecurityPolicy.Tests.ps1 new file mode 100644 index 0000000000..20857e0393 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOSecurityPolicy.Tests.ps1 @@ -0,0 +1,176 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -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 a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 remove the instance from the Set method' { + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + 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 + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 2527a5f5e10d6ac7f8ecc02be086459a28f2b2ff Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 11 Sep 2024 12:40:08 -0400 Subject: [PATCH 144/465] AzureSubscription - Initial Release --- CHANGELOG.md | 2 + .../MSFT_AzureSubscription.psm1 | 395 ++++++++++++++++++ .../MSFT_AzureSubscription.schema.mof | 14 + .../MSFT_AzureSubscription/readme.md | 6 + .../MSFT_AzureSubscription/settings.json | 20 + .../Resources/AzureSubscription/2-Update.ps1 | 34 ++ ...icrosoft365DSC.AzureSubscription.Tests.ps1 | 136 ++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 34 ++ .../MSFT_ResourceName/MSFT_ResourceName.psm1 | 15 + .../MSFT_ResourceName.schema.mof | 3 +- 10 files changed, 658 insertions(+), 1 deletion(-) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/MSFT_AzureSubscription.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/MSFT_AzureSubscription.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AzureSubscription/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.AzureSubscription.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index d4874b76dd..ff92720a98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ * AADPasswordRuleSettings * Initial release +* AzureSubscription + * Initial Release. * EXOArcConfig * Initial Release. * EXOFocusedInbox diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/MSFT_AzureSubscription.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/MSFT_AzureSubscription.psm1 new file mode 100644 index 0000000000..d3076e1a9c --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/MSFT_AzureSubscription.psm1 @@ -0,0 +1,395 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Boolean] + $Enabled, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'Azure' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + if (-not [System.String]::IsNullOrEmpty($Id)) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} + } + elseif ($null -eq $instance -and -not [System.String]::IsNullOrEmpty($Name)) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Name -eq $Name} + } + } + else + { + if (-not [System.String]::IsNullOrEmpty($Id)) + { + $instance = Get-AzSubscription -SubscriptionId $Id + } + elseif ($null -eq $instance -and -not [System.String]::IsNullOrEmpty($Name)) + { + $instance = Get-AzSubscription -SubscriptionName $Name + } + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + Name = $instance.Name + Id = $instance.Id + Enabled = $instance.Enabled + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Boolean] + $Enabled, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + throw "This resource cannot create new Azure subscriptions." + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + if ($Enabled) + { + Enable-AzSubscription -Id $currentInstance.Id | Out-Null + } + elseif (-not $Enabled) + { + Disable-AzSubscription -Id $currentInstance.Id | Out-Null + } + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + throw "This resource cannot remove Azure subscriptions." + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Boolean] + $Enabled, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace workload + $ConnectionMode = New-M365DSCConnection -Workload 'Workload' ` + -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 + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-AzSubscription -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Name + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Name = $config.Name + Id = $config.Id + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_AzureSubscription/MSFT_AzureSubscription.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/MSFT_AzureSubscription.schema.mof new file mode 100644 index 0000000000..c93d7b5bb2 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/MSFT_AzureSubscription.schema.mof @@ -0,0 +1,14 @@ +[ClassVersion("1.0.0.0"), FriendlyName("AzureSubscription")] +class MSFT_AzureSubscription : OMI_BaseResource +{ + [Key, Description("The display name of the subscription.")] String Name; + [Write, Description("The unique identifier of the subscription.")] String Id; + [Write, Description("Enables or disables the subscription")] Boolean Enaled; + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] 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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/readme.md new file mode 100644 index 0000000000..3899577f38 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/readme.md @@ -0,0 +1,6 @@ + +# AzureSubscription + +## Description + +This resource controls the properties of an Azure subscription. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/settings.json new file mode 100644 index 0000000000..344c77f592 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/settings.json @@ -0,0 +1,20 @@ +{ + "resourceName": "AzureSubscription", + "description": "This resource controls the properties of an Azure subscription.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AzureSubscription/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AzureSubscription/2-Update.ps1 new file mode 100644 index 0000000000..2c95a634c1 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AzureSubscription/2-Update.ps1 @@ -0,0 +1,34 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AzureSubscription 'TestSubscription' + { + Name = 'MyTestSubscription' + Id = 'd620d94d-916d-4dd9-9de5-179292873e20' + Enabled = $true + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AzureSubscription.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AzureSubscription.Tests.ps1 new file mode 100644 index 0000000000..4bde1dd612 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AzureSubscription.Tests.ps1 @@ -0,0 +1,136 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Enable-AzSubscription -MockWith { + } + + Mock -CommandName Disable-AzSubscription -MockWith { + } + + # 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 instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Test" + Enabled = $true + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-AzSubscription -MockWith { + return @( + @{ + Id = (New-Guid).ToString() + Name = 'Test' + Enabled = $true + } + ) + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Test" + Enabled = $true + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-AzSubscription -MockWith { + return @( + @{ + Id = (New-Guid).ToString() + Name = 'Test' + Enabled = $false #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 Enable-AzSubscription -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-AzSubscription -MockWith { + return @( + @{ + Id = (New-Guid).ToString() + Name = 'Test' + Enabled = $false #drift + } + ) + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 53aa0e0f60..90fba5b23a 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -52,6 +52,40 @@ function Get-AzResource $ResourceType ) } + +function Get-AzSubscription +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $SubscriptionId, + + [Parameter()] + [System.String] + $SubscriptionName + ) +} + +function Enable-AzSubscription +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Id + ) +} + +function Disable-AzSubscription +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Id + ) +} #endregion # region ExchangeOnlineManagement diff --git a/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.psm1 b/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.psm1 index c6f63d3927..0990631700 100644 --- a/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.psm1 +++ b/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.psm1 @@ -11,6 +11,11 @@ function Get-TargetResource ##TODO - Add the list of Parameters + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -108,6 +113,11 @@ function Set-TargetResource ##TODO - Add the list of Parameters + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -182,6 +192,11 @@ function Test-TargetResource ##TODO - Add the list of Parameters + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + [Parameter()] [System.Management.Automation.PSCredential] $Credential, diff --git a/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.schema.mof b/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.schema.mof index 6fa43ce435..be6b06c877 100644 --- a/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.schema.mof +++ b/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.schema.mof @@ -4,10 +4,11 @@ class MSFT_ResourceName : OMI_BaseResource [Key, Description("")] String PrimaryKey; [Write, Description("")] String OtherProperties; + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] 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("Managed ID being used for authentication.")] Boolean ManagedIdentity; [Write, Description("Access token used for authentication.")] String AccessTokens[]; -}; \ No newline at end of file +}; From c9f6cc36a3dd73403a07fefe26b0882c0f6dcc93 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 11 Sep 2024 12:46:02 -0400 Subject: [PATCH 145/465] Update MSFT_AzureSubscription.schema.mof --- .../MSFT_AzureSubscription/MSFT_AzureSubscription.schema.mof | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/MSFT_AzureSubscription.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/MSFT_AzureSubscription.schema.mof index c93d7b5bb2..3d74c750c9 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/MSFT_AzureSubscription.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AzureSubscription/MSFT_AzureSubscription.schema.mof @@ -3,7 +3,7 @@ class MSFT_AzureSubscription : OMI_BaseResource { [Key, Description("The display name of the subscription.")] String Name; [Write, Description("The unique identifier of the subscription.")] String Id; - [Write, Description("Enables or disables the subscription")] Boolean Enaled; + [Write, Description("Enables or disables the subscription")] Boolean Enabled; [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] 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 13624667f09d109a0826a6299fceccc0d4903189 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 16:59:26 +0000 Subject: [PATCH 146/465] Updated Resources and Cmdlet documentation pages --- .../resources/azure-ad/AzureSubscription.md | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 docs/docs/resources/azure-ad/AzureSubscription.md diff --git a/docs/docs/resources/azure-ad/AzureSubscription.md b/docs/docs/resources/azure-ad/AzureSubscription.md new file mode 100644 index 0000000000..481e5a8eb0 --- /dev/null +++ b/docs/docs/resources/azure-ad/AzureSubscription.md @@ -0,0 +1,87 @@ +# AzureSubscription + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Name** | Key | String | The display name of the subscription. | | +| **Id** | Write | String | The unique identifier of the subscription. | | +| **Enabled** | Write | Boolean | Enables or disables the subscription | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +This resource controls the properties of an Azure subscription. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AzureSubscription 'TestSubscription' + { + Name = 'MyTestSubscription' + Id = 'd620d94d-916d-4dd9-9de5-179292873e20' + Enabled = $true + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + From 4d2e83db08eb1feec10e6f1d3ca413409171f1ae Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 17:01:33 +0000 Subject: [PATCH 147/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 2e763f0bc3..185b0a0229 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -5154,6 +5154,61 @@ } ] }, + { + "ClassName": "MSFT_AzureSubscription", + "Parameters": [ + { + "CIMType": "String", + "Name": "Name", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "Enabled", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOAcceptedDomain", "Parameters": [ From e2698c5ac659e66cab91153d561707e8f7f86ad6 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 11 Sep 2024 13:06:16 -0400 Subject: [PATCH 148/465] ADOOrganizationOwner - Initial Release --- CHANGELOG.md | 2 + .../MSFT_ADOOrganizationOwner.psm1 | 351 ++++++++++++++++++ .../MSFT_ADOOrganizationOwner.schema.mof | 13 + .../MSFT_ADOOrganizationOwner/readme.md | 6 + .../MSFT_ADOOrganizationOwner/settings.json | 32 ++ .../ADOOrganizationOwner/2-Update.ps1 | 26 ++ ...osoft365DSC.ADOOrganizationOwner.Tests.ps1 | 176 +++++++++ 7 files changed, 606 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ADOOrganizationOwner/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOOrganizationOwner.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index d4874b76dd..bad9636542 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ * AADPasswordRuleSettings * Initial release +* ADOOrganizationOwner + * Initial release. * EXOArcConfig * Initial Release. * EXOFocusedInbox diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 new file mode 100644 index 0000000000..c6f63d3927 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 @@ -0,0 +1,351 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace the workload by the one associated to your resource + New-M365DSCConnection -Workload 'Workload' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + ##TODO - Replace the PrimaryKey in the Filter by the one for the resource + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.PrimaryKey -eq $PrimaryKey} + } + else + { + ##TODO - Replace the cmdlet by the one to retrieve a specific instance. + $instance = Get-cmdlet -PrimaryKey $PrimaryKey -ErrorAction Stop + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + ##TODO - Add the list of parameters to be returned + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + ##TODO - Replace by the New cmdlet for the resource + New-Cmdlet @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Update/Set cmdlet for the resource + Set-cmdlet @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Remove cmdlet for the resource + Remove-cmdlet @SetParameters + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace workload + $ConnectionMode = New-M365DSCConnection -Workload 'Workload' ` + -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 + { + $Script:ExportMode = $true + ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances + [array] $Script:exportedInstances = Get-Cmdlet -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + ##TODO - Specify the Primary Key + #PrimaryKey = $config.PrimaryKey + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.schema.mof new file mode 100644 index 0000000000..158f518689 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.schema.mof @@ -0,0 +1,13 @@ +[ClassVersion("1.0.0.0"), FriendlyName("ADOOrganizationOwner")] +class MSFT_ADOOrganizationOwner : OMI_BaseResource +{ + [Key, Description("")] String PrimaryKey; + [Write, Description("")] String OtherProperties; + + [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/readme.md new file mode 100644 index 0000000000..75e6f5299d --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/readme.md @@ -0,0 +1,6 @@ + +# ADOOrganizationOwner + +## Description + +##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/settings.json new file mode 100644 index 0000000000..edf14b05e4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "ResourceName", + "description": "Description of what the resource is about.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ADOOrganizationOwner/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ADOOrganizationOwner/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ADOOrganizationOwner/2-Update.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOOrganizationOwner.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOOrganizationOwner.Tests.ps1 new file mode 100644 index 0000000000..20857e0393 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOOrganizationOwner.Tests.ps1 @@ -0,0 +1,176 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -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 a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 remove the instance from the Set method' { + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + 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 + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 49c519f58ced6313ad85014fa1ab8b17f8aa351b Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 11 Sep 2024 14:55:59 -0400 Subject: [PATCH 149/465] Updates --- .../MSFT_ADOOrganizationOwner.psm1 | 174 +++++++++++++----- .../MSFT_ADOOrganizationOwner/settings.json | 2 +- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 1 - 3 files changed, 125 insertions(+), 52 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 index c6f63d3927..16737611db 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 @@ -4,12 +4,22 @@ function Get-TargetResource [OutputType([System.Collections.Hashtable])] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $Name, - ##TODO - Add the list of Parameters + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $Owner, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', [Parameter()] [System.Management.Automation.PSCredential] @@ -36,8 +46,7 @@ function Get-TargetResource $AccessTokens ) - ##TODO - Replace the workload by the one associated to your resource - New-M365DSCConnection -Workload 'Workload' ` + New-M365DSCConnection -Workload 'AzureDevOPS' ` -InboundParameters $PSBoundParameters | Out-Null #Ensure the proper dependencies are installed in the current environment. @@ -58,21 +67,33 @@ function Get-TargetResource { if ($null -ne $Script:exportedInstances -and $Script:ExportMode) { - ##TODO - Replace the PrimaryKey in the Filter by the one for the resource - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.PrimaryKey -eq $PrimaryKey} + if (-not [System.String]::IsNullOrEmpty($Id)) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} + } + if ($null -eq $instance -and -not [System.String]::IsNullOrEmpty($Name)) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Name -eq $Name} + } } else { - ##TODO - Replace the cmdlet by the one to retrieve a specific instance. - $instance = Get-cmdlet -PrimaryKey $PrimaryKey -ErrorAction Stop + $instance = Get-M365DSCADOOrganization -Name $Name -ErrorAction Stop } if ($null -eq $instance) { return $nullResult } + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters | Out-Null + + $owner = Get-MgUser -UserId $instance.owner + $results = @{ - ##TODO - Add the list of parameters to be returned + Name = $instance.Name + Id = $instance.Id + Owner = $owner.UserPrincipalName Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -271,7 +292,7 @@ function Export-TargetResource ) ##TODO - Replace workload - $ConnectionMode = New-M365DSCConnection -Workload 'Workload' ` + $ConnectionMode = New-M365DSCConnection -Workload 'AzureDevOPS' ` -InboundParameters $PSBoundParameters #Ensure the proper dependencies are installed in the current environment. @@ -289,48 +310,56 @@ function Export-TargetResource try { $Script:ExportMode = $true - ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances - [array] $Script:exportedInstances = Get-Cmdlet -ErrorAction Stop + $organizations = Get-M365DSCADOOrganizationList - $i = 1 - $dscContent = '' - if ($Script:exportedInstances.Length -eq 0) - { - Write-Host $Global:M365DSCEmojiGreenCheckMark - } - else + foreach ($organization in $organizations) { - Write-Host "`r`n" -NoNewline - } - foreach ($config in $Script:exportedInstances) - { - $displayedKey = $config.Id - Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline - $params = @{ - ##TODO - Specify the Primary Key - #PrimaryKey = $config.PrimaryKey - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens - } + [array] $Script:exportedInstances = Get-M365DSCADOOrganization -Name 'O365DSC-Dev' - $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 + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + $displayedKey = $config.name + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Name = $config.name + Id = $config.id + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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 } @@ -348,4 +377,49 @@ function Export-TargetResource } } +function Get-M365DSCADOOrganization +{ + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [System.String] + $Name + ) + + $headers = @{ + Authorization = $Global:MSCloudLoginConnectionProfile.AzureDevOPS.AccessToken + 'Content-Type' = "application/json-patch+json" + } + + $uri = "https://vssps.dev.azure.com/$Name/_apis/Organization/Collections/Me" + + $response = Invoke-WebRequest -Method GET ` + -Uri $uri ` + -Headers $headers + + $results = ConvertFrom-Json ($response.Content) + return $results +} + +function Get-M365DSCADOOrganizationList +{ + [CmdletBinding()] + param( + ) + + $headers = @{ + Authorization = $Global:MSCloudLoginConnectionProfile.AzureDevOPS.AccessToken + 'Content-Type' = "application/json-patch+json" + } + + $uri = "https://app.vssps.visualstudio.com/_apis/profile/profiles/me" + + $response = Invoke-WebRequest -Method GET ` + -Uri $uri ` + -Headers $headers + + $results = ConvertFrom-Json ($response.Content) + return $results +} + Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/settings.json index edf14b05e4..db44440221 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/settings.json @@ -1,5 +1,5 @@ { - "resourceName": "ResourceName", + "resourceName": "ADOOrganizationOwner", "description": "Description of what the resource is about.", "roles": { "read": [ diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 9397159c76..614ea78655 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1771,7 +1771,6 @@ function New-M365DSCConnection [System.Boolean] $SkipModuleReload = $false ) - $verbosepreference = 'Continue' $Global:MaximumFunctionCount = 32767 if ($Workload -eq 'MicrosoftTeams') { From 74cc42a68a6cbcccb3966c3211135090f1a5d05c Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 11 Sep 2024 15:03:03 -0400 Subject: [PATCH 150/465] Updated Dependencies --- CHANGELOG.md | 3 ++- Modules/Microsoft365DSC/Dependencies/Manifest.psd1 | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff92720a98..c43051379a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,8 @@ * Added support for property EnableRestrictedAccessControl. * DEPENDENCIES * Added dependencies on Az.Accounts, Az.Resources and Az.SecurityInsights - * Updated MSCloudLoginAssistant to version 1.1.22. + * Updated DSCParser to version 2.0.0.9. + * Updated MSCloudLoginAssistant to version 1.1.23. # 1.24.904.1 diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 54b3565d09..52fccf5596 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -14,7 +14,7 @@ }, @{ ModuleName = 'DSCParser' - RequiredVersion = '2.0.0.8' + RequiredVersion = '2.0.0.9' }, @{ ModuleName = 'ExchangeOnlineManagement' @@ -102,7 +102,7 @@ }, @{ ModuleName = "MSCloudLoginAssistant" - RequiredVersion = "1.1.22" + RequiredVersion = "1.1.23" }, @{ ModuleName = 'PnP.PowerShell' From 6eacf4f0408bdb458d5b3f5097968a24f87fd3be Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Wed, 11 Sep 2024 23:39:20 +0200 Subject: [PATCH 151/465] Fix operating system build range in Intune device compliance policy --- CHANGELOG.md | 4 + ...IntuneDeviceCompliancePolicyWindows10.psm1 | 90 +++++++++++++++---- ...DeviceCompliancePolicyWindows10.schema.mof | 10 ++- 3 files changed, 86 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c43051379a..edc788b229 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,10 @@ * IntuneAntivirusPolicyWindows10SettingCatalog * Fixes an issue with invalid parameter definition. FIXES [#5015](https://github.com/microsoft/Microsoft365DSC/issues/5015) +* IntuneDeviceCompliancePolicyWindows10 + * Fixes an issue where the property `ValidOperatingSystemBuildRanges` was + not exported properly. + FIXES [#5030](https://github.com/microsoft/Microsoft365DSC/issues/5030) * IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10 * Add missing `AccessTokens` parameter to `Export-TargetResource` FIXES [#5034](https://github.com/microsoft/Microsoft365DSC/issues/5034) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyWindows10/MSFT_IntuneDeviceCompliancePolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyWindows10/MSFT_IntuneDeviceCompliancePolicyWindows10.psm1 index 81f4c3aa3b..40d34cd35b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyWindows10/MSFT_IntuneDeviceCompliancePolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyWindows10/MSFT_IntuneDeviceCompliancePolicyWindows10.psm1 @@ -139,7 +139,7 @@ function Get-TargetResource $DeviceCompliancePolicyScript, [Parameter()] - [System.Array] + [Microsoft.Management.Infrastructure.CimInstance[]] $ValidOperatingSystemBuildRanges, [Parameter()] @@ -214,6 +214,28 @@ function Get-TargetResource return $nullResult } + $complexValidOperatingSystemBuildRanges = @() + foreach ($currentValidOperatingSystemBuildRanges in $devicePolicy.AdditionalProperties.validOperatingSystemBuildRanges) + { + $myValidOperatingSystemBuildRanges = @{} + if ($null -ne $currentValidOperatingSystemBuildRanges.lowestVersion) + { + $myValidOperatingSystemBuildRanges.Add('LowestVersion', $currentValidOperatingSystemBuildRanges.lowestVersion.ToString()) + } + if ($null -ne $currentValidOperatingSystemBuildRanges.highestVersion) + { + $myValidOperatingSystemBuildRanges.Add('HighestVersion', $currentValidOperatingSystemBuildRanges.highestVersion.ToString()) + } + if ($null -ne $currentValidOperatingSystemBuildRanges.description) + { + $myValidOperatingSystemBuildRanges.Add('Description', $currentValidOperatingSystemBuildRanges.description) + } + if ($myValidOperatingSystemBuildRanges.values.Where({$null -ne $_}).Count -gt 0) + { + $complexValidOperatingSystemBuildRanges += $myValidOperatingSystemBuildRanges + } + } + Write-Verbose -Message "Found Windows 10 Device Compliance Policy with displayName {$DisplayName}" $results = @{ DisplayName = $devicePolicy.DisplayName @@ -249,7 +271,7 @@ function Get-TargetResource ConfigurationManagerComplianceRequired = $devicePolicy.AdditionalProperties.configurationManagerComplianceRequired TpmRequired = $devicePolicy.AdditionalProperties.tpmRequired DeviceCompliancePolicyScript = $devicePolicy.AdditionalProperties.deviceCompliancePolicyScript - ValidOperatingSystemBuildRanges = $devicePolicy.AdditionalProperties.validOperatingSystemBuildRanges + ValidOperatingSystemBuildRanges = $complexValidOperatingSystemBuildRanges Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -262,7 +284,7 @@ function Get-TargetResource $returnAssignments = @() $graphAssignments = Get-MgBetaDeviceManagementDeviceCompliancePolicyAssignment -DeviceCompliancePolicyId $devicePolicy.Id - if ($graphAssignments.count -gt 0) + if ($graphAssignments.Count -gt 0) { $returnAssignments += ConvertFrom-IntunePolicyAssignment ` -IncludeDeviceFilter:$true ` @@ -425,7 +447,7 @@ function Set-TargetResource $DeviceCompliancePolicyScript, [Parameter()] - [System.Array] + [Microsoft.Management.Infrastructure.CimInstance[]] $ValidOperatingSystemBuildRanges, [Parameter()] @@ -701,7 +723,7 @@ function Test-TargetResource $DeviceCompliancePolicyScript, [Parameter()] - [System.Array] + [Microsoft.Management.Infrastructure.CimInstance[]] $ValidOperatingSystemBuildRanges, [Parameter()] @@ -763,25 +785,36 @@ function Test-TargetResource throw "An error occured in Get-TargetResource, the policy {$displayName} will not be processed. Refer to the event viewer logs for more information." } - Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" - - $ValuesToCheck = $PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() $testResult = $true if ($CurrentValues.Ensure -ne $Ensure) { $testResult = $false } - #region Assignments - if ($testResult) + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) { - $source = Get-M365DSCDRGComplexTypeToHashtable -ComplexObject $PSBoundParameters.Assignments - $target = $CurrentValues.Assignments - $testResult = Compare-M365DSCIntunePolicyAssignment -Source $source -Target $target - $ValuesToCheck.Remove('Assignments') | Out-Null + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-not $testResult) + { + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } } - #endregion + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" if ($testResult) { @@ -887,7 +920,7 @@ function Export-TargetResource TenantId = $TenantId ApplicationSecret = $ApplicationSecret CertificateThumbprint = $CertificateThumbprint - Managedidentity = $ManagedIdentity.IsPresent + ManagedIdentity = $ManagedIdentity.IsPresent AccessTokens = $AccessTokens } $Results = Get-TargetResource @params @@ -899,6 +932,21 @@ function Export-TargetResource $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` -Results $Results + if ($null -ne $Results.ValidOperatingSystemBuildRanges) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.ValidOperatingSystemBuildRanges ` + -CIMInstanceName 'MicrosoftGraphOperatingSystemVersionRange' ` + -IsArray + if (-not [string]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.ValidOperatingSystemBuildRanges = $complexTypeStringResult + } + else + { + $Results.Remove('ValidOperatingSystemBuildRanges') | Out-Null + } + } if ($Results.Assignments) { $complexTypeStringResult = Get-M365DSCAssignmentsAsString -Params $Results.Assignments @@ -916,6 +964,10 @@ function Export-TargetResource -ModulePath $PSScriptRoot ` -Results $Results ` -Credential $Credential + if ($Results.ValidOperatingSystemBuildRanges) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ValidOperatingSystemBuildRanges' + } if ($Results.Assignments) { $isCIMArray = $false @@ -974,6 +1026,10 @@ function Get-M365DSCIntuneDeviceCompliancePolicyWindows10AdditionalProperties { $propertyName = $property[0].ToString().ToLower() + $property.Substring(1, $property.Length - 1) $propertyValue = $properties.$property + if ($null -ne $propertyValue -and $propertyValue.GetType().Name -like '*cimInstance*') + { + $propertyValue = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $propertyValue + } $results.Add($propertyName, $propertyValue) } } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyWindows10/MSFT_IntuneDeviceCompliancePolicyWindows10.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyWindows10/MSFT_IntuneDeviceCompliancePolicyWindows10.schema.mof index 3dd4d6a55b..ac822b9aa6 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyWindows10/MSFT_IntuneDeviceCompliancePolicyWindows10.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyWindows10/MSFT_IntuneDeviceCompliancePolicyWindows10.schema.mof @@ -9,6 +9,14 @@ class MSFT_DeviceManagementConfigurationPolicyAssignments [Write, Description("The collection Id that is the target of the assignment.(ConfigMgr)")] String collectionId; }; +[ClassVersion("1.0.0.0")] +class MSFT_MicrosoftGraphOperatingSystemVersionRange +{ + [Write, Description("The description of this range (e.g. Valid 1702 builds)")] String Description; + [Write, Description("The lowest inclusive version that this range contains.")] String LowestVersion; + [Write, Description("The highest inclusive version that this range contains.")] String HighestVersion; +}; + [ClassVersion("1.0.0.0"), FriendlyName("IntuneDeviceCompliancePolicyWindows10")] class MSFT_IntuneDeviceCompliancePolicyWindows10 : OMI_BaseResource { @@ -46,7 +54,7 @@ class MSFT_IntuneDeviceCompliancePolicyWindows10 : OMI_BaseResource [Write, Description("ConfigurationManagerComplianceRequired of the Windows 10 device compliance policy.")] Boolean ConfigurationManagerComplianceRequired; [Write, Description("TpmRequired of the Windows 10 device compliance policy.")] Boolean TpmRequired; [Write, Description("DeviceCompliancePolicyScript of the Windows 10 device compliance policy.")] String DeviceCompliancePolicyScript; - [Write, Description("ValidOperatingSystemBuildRanges of the Windows 10 device compliance policy.")] String ValidOperatingSystemBuildRanges[]; + [Write, Description("ValidOperatingSystemBuildRanges of the Windows 10 device compliance policy."), EmbeddedInstance("MSFT_MicrosoftGraphOperatingSystemVersionRange")] String ValidOperatingSystemBuildRanges[]; [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; [Write, Description("Credentials of the Intune Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; From e7ebe620c9520bbbef6543a4ccd3c2d84b952073 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 22:13:10 +0000 Subject: [PATCH 152/465] Updated Resources and Cmdlet documentation pages --- .../intune/IntuneDeviceCompliancePolicyWindows10.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/docs/resources/intune/IntuneDeviceCompliancePolicyWindows10.md b/docs/docs/resources/intune/IntuneDeviceCompliancePolicyWindows10.md index ee9498d7cd..540cb06564 100644 --- a/docs/docs/resources/intune/IntuneDeviceCompliancePolicyWindows10.md +++ b/docs/docs/resources/intune/IntuneDeviceCompliancePolicyWindows10.md @@ -38,7 +38,7 @@ | **ConfigurationManagerComplianceRequired** | Write | Boolean | ConfigurationManagerComplianceRequired of the Windows 10 device compliance policy. | | | **TpmRequired** | Write | Boolean | TpmRequired of the Windows 10 device compliance policy. | | | **DeviceCompliancePolicyScript** | Write | String | DeviceCompliancePolicyScript of the Windows 10 device compliance policy. | | -| **ValidOperatingSystemBuildRanges** | Write | StringArray[] | ValidOperatingSystemBuildRanges of the Windows 10 device compliance policy. | | +| **ValidOperatingSystemBuildRanges** | Write | MSFT_MicrosoftGraphOperatingSystemVersionRange[] | ValidOperatingSystemBuildRanges of the Windows 10 device compliance policy. | | | **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | | **Credential** | Write | PSCredential | Credentials of the Intune Admin | | | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | @@ -61,6 +61,16 @@ | **groupDisplayName** | Write | String | The group Display Name that is the target of the assignment. | | | **collectionId** | Write | String | The collection Id that is the target of the assignment.(ConfigMgr) | | +### MSFT_MicrosoftGraphOperatingSystemVersionRange + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Description** | Write | String | The description of this range (e.g. Valid 1702 builds) | | +| **LowestVersion** | Write | String | The lowest inclusive version that this range contains. | | +| **HighestVersion** | Write | String | The highest inclusive version that this range contains. | | + ## Description From ba0965eea4a98f79233dbc8ac054e39b7c7cec26 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 11 Sep 2024 22:15:19 +0000 Subject: [PATCH 153/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 185b0a0229..467491a96f 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -20104,6 +20104,26 @@ } ] }, + { + "ClassName": "MSFT_MicrosoftGraphOperatingSystemVersionRange", + "Parameters": [ + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "LowestVersion", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "HighestVersion", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_IntuneDeviceCompliancePolicyWindows10", "Parameters": [ @@ -20278,7 +20298,7 @@ "Option": "Write" }, { - "CIMType": "String[]", + "CIMType": "MSFT_MicrosoftGraphOperatingSystemVersionRange[]", "Name": "ValidOperatingSystemBuildRanges", "Option": "Write" }, From 727bdc53af1a5b75d8d41b9fe489bcec3e902be5 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 11 Sep 2024 18:58:03 -0400 Subject: [PATCH 154/465] Fixing Dependency issue --- CHANGELOG.md | 2 +- Modules/Microsoft365DSC/Dependencies/Manifest.psd1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c43051379a..44caa774c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,7 +37,7 @@ * DEPENDENCIES * Added dependencies on Az.Accounts, Az.Resources and Az.SecurityInsights * Updated DSCParser to version 2.0.0.9. - * Updated MSCloudLoginAssistant to version 1.1.23. + * Updated MSCloudLoginAssistant to version 1.1.24. # 1.24.904.1 diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 52fccf5596..afd204cd31 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -102,7 +102,7 @@ }, @{ ModuleName = "MSCloudLoginAssistant" - RequiredVersion = "1.1.23" + RequiredVersion = "1.1.24" }, @{ ModuleName = 'PnP.PowerShell' From b2094f881e71ead5c402946b64d6378eaa2736a8 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Wed, 11 Sep 2024 16:03:13 -0700 Subject: [PATCH 155/465] Stub implementation of TABL functionality --- .../MSFT_EXOTenantAllowBlockListItems.psm1 | 535 ++++++++++++++++++ ...FT_EXOTenantAllowBlockListItems.schema.mof | 18 + .../readme.md | 10 + .../settings.json | 10 + ...-EXOTenantAllowBlockListItems-Example.psm1 | 21 + ...DSC.EXOTenantAllowBlockListItems.Tests.ps1 | 187 ++++++ 6 files changed, 781 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/EXOTenantAllowBlockListItems/1-EXOTenantAllowBlockListItems-Example.psm1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 new file mode 100644 index 0000000000..7d758ebd48 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 @@ -0,0 +1,535 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter()] + [ValidateSet('Allow', 'Block')] + [System.String] + $Action, + + [Parameter(Mandatory = $true)] + [System.String] + $Value, + + [Parameter()] + [System.DateTime] + $ExpirationDate, + + [Parameter()] + [System.Object] + $ListSubType, + + [Parameter(Mandatory = $true)] + [System.Object] + $ListType, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $LogExtraDetails, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $OutputJson, + + [Parameter()] + [System.Int32] + $RemoveAfter, + + [Parameter()] + [System.String] + $SubmissionID, + + [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 'ExchangeOnline' ` + -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 + { + $getParams = @{ ListType = $ListType; Entry = $Value; } + if ($Action -eq 'Allow') + { + $getParams.Allow = $true + } + elseif ($Action -eq 'Block') + { + $getParams.Block = $true + } + $instance = Get-TenantAllowBlockListItems @getParams -ErrorAction SilentlyContinue + if ($null -eq $instance) + { + return $nullResult + } + + Write-Verbose -Message "Found an instance with Action {$Action}, Value {$Value}, and ListType {$ListType}" + $results = @{ + Action = $Action + Value = $instance.Value + ExpirationDate = $instance.ExpirationDate + ListSubType = $instance.ListSubType + ListType = $ListType + LogExtraDetails = $instance.LogExtraDetails + Notes = $instance.Notes + OutputJson = $instance.OutputJson + RemoveAfter = $instance.RemoveAfter + SubmissionID = $instance.SubmissionID + 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.Management.Automation.SwitchParameter] + $Allow, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Block, + + [Parameter(Mandatory = $true)] + [System.String[]] + $Entries, + + [Parameter()] + [System.DateTime] + $ExpirationDate, + + [Parameter()] + [System.Object] + $ListSubType, + + [Parameter(Mandatory = $true)] + [System.Object] + $ListType, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $LogExtraDetails, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $OutputJson, + + [Parameter()] + [System.Int32] + $RemoveAfter, + + [Parameter()] + [System.String] + $SubmissionID, + + [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 'ExchangeOnline' ` + -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 {$Entries} with Parameters:`r`n$(Convert-M365DscHashtableToString -Hashtable $CreateParameters)" + New-TenantAllowBlockListItems @CreateParameters | Out-Null + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating {$Entries}" + + $UpdateParameters = ([Hashtable]$BoundParameters).Clone() + $UpdateParameters.Remove('Verbose') | Out-Null + + $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-TenantAllowBlockListItems @UpdateParameters | Out-Null + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing {$Entries}" + Remove-TenantAllowBlockListItems -Entries $currentInstance.Entries + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Allow, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Block, + + [Parameter(Mandatory = $true)] + [System.String[]] + $Entries, + + [Parameter()] + [System.DateTime] + $ExpirationDate, + + [Parameter()] + [System.Object] + $ListSubType, + + [Parameter(Mandatory = $true)] + [System.Object] + $ListType, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $LogExtraDetails, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $OutputJson, + + [Parameter()] + [System.Int32] + $RemoveAfter, + + [Parameter()] + [System.String] + $SubmissionID, + + [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 {$Entries}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + $ValuesToCheck.Remove('Entries') | 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 'ExchangeOnline' ` + -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 + { + $ListTypes = ("FileHash", "Sender", "Url"); + + [array]$getValues = @() + + foreach ($ListType in $ListTypes) + { + $listValues = Get-TenantAllowBlockListItems -ListType $ListType -ErrorAction Stop + $listValues | ForEach-Object { + $getValues += @{ + Action = $_.Action + Value = $_.Value + ListType = $ListType + } + } + } + + $i = 1 + $dscContent = '' + if ($getValues.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $getValues) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = "[$($config.Action)] [$($config.ListType)] $($config.Value)" + if (-not [String]::IsNullOrEmpty($config.displayName)) + { + $displayedKey = $config.displayName + } + Write-Host " |---[$i/$($getValues.Count)] $displayedKey" -NoNewline + $params = @{ + Action = $config.Action + ListType = $config.ListType + Value = $config.Value + 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_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.schema.mof new file mode 100644 index 0000000000..2eaa2fe3a0 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.schema.mof @@ -0,0 +1,18 @@ +[ClassVersion("1.0.0.0"), FriendlyName("EXOTenantAllowBlockListItems")] +class MSFT_EXOTenantAllowBlockListItems : OMI_BaseResource +{ + [Key, Description("")] String Action; + [Key, Description("")] String Value; + [Write, Description("")] DateTime ExpirationDate; + [Write, Description("")] String ListSubType; + [Key, Description("")] String ListType; + [Write, Description("")] String Notes; + [Write, Description("")] UInt32 RemoveAfter; + [Write, Description("")] String SubmissionID; + [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_EXOTenantAllowBlockListItems/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/readme.md new file mode 100644 index 0000000000..42219633c8 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/readme.md @@ -0,0 +1,10 @@ + +# EXOTenantAllowBlockListItems + +## Description + + +New-TenantAllowBlockListItems -Entries -ListType [-Allow] [-Block] [-ExpirationDate ] [-ListSubType ] [-LogExtraDetails] [-Notes ] [-OutputJson] [-RemoveAfter ] [-SubmissionID ] [] + +New-TenantAllowBlockListItems -Entries -ListType -NoExpiration [-Allow] [-Block] [-ListSubType ] [-LogExtraDetails] [-Notes ] [-OutputJson] [-RemoveAfter ] [-SubmissionID ] [] + diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/settings.json new file mode 100644 index 0000000000..e2df4807ae --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/settings.json @@ -0,0 +1,10 @@ +{ + "resourceName": "EXOTenantAllowBlockListItems", + "description": "This resource configures an +New-TenantAllowBlockListItems -Entries -ListType [-Allow] [-Block] [-ExpirationDate ] [-ListSubType ] [-LogExtraDetails] [-Notes ] [-OutputJson] [-RemoveAfter ] [-SubmissionID ] [] + +New-TenantAllowBlockListItems -Entries -ListType -NoExpiration [-Allow] [-Block] [-ListSubType ] [-LogExtraDetails] [-Notes ] [-OutputJson] [-RemoveAfter ] [-SubmissionID ] [] +.", + "permissions":[] + +} diff --git a/Modules/Microsoft365DSC/Examples/EXOTenantAllowBlockListItems/1-EXOTenantAllowBlockListItems-Example.psm1 b/Modules/Microsoft365DSC/Examples/EXOTenantAllowBlockListItems/1-EXOTenantAllowBlockListItems-Example.psm1 new file mode 100644 index 0000000000..43e0d749ca --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/EXOTenantAllowBlockListItems/1-EXOTenantAllowBlockListItems-Example.psm1 @@ -0,0 +1,21 @@ +<# +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 + { + EXOTenantAllowBlockListItems 'Example' + { + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 new file mode 100644 index 0000000000..549858d548 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.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 "EXOTenantAllowBlockListItems" -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-TenantAllowBlockListItems -MockWith { + } + + Mock -CommandName New-TenantAllowBlockListItems -MockWith { + } + + Mock -CommandName Remove-TenantAllowBlockListItems -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 EXOTenantAllowBlockListItems should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = "Present" + Credential = $Credential; + } + + Mock -CommandName Get-TenantAllowBlockListItems -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-TenantAllowBlockListItems -Exactly 1 + } + } + + Context -Name "The EXOTenantAllowBlockListItems exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Absent' + Credential = $Credential; + } + + Mock -CommandName Get-TenantAllowBlockListItems -MockWith { + return @{ + SubmissionID = "FakeStringValue" + RemoveAfter = 3 + Notes = "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-TenantAllowBlockListItems -Exactly 1 + } + } + Context -Name "The EXOTenantAllowBlockListItems Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-TenantAllowBlockListItems -MockWith { + return @{ + SubmissionID = "FakeStringValue" + RemoveAfter = 3 + Notes = "FakeStringValue" + + } + } + } + + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The EXOTenantAllowBlockListItems exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-TenantAllowBlockListItems -MockWith { + return @{ + SubmissionID = "FakeStringValueDrift #Drift" + RemoveAfter = 2 + Notes = "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-TenantAllowBlockListItems -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-TenantAllowBlockListItems -MockWith { + return @{ + SubmissionID = "FakeStringValue" + RemoveAfter = 3 + Notes = "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 4e67e22551bc6f071df19a27007fae4198b6ee55 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Wed, 11 Sep 2024 17:00:38 -0700 Subject: [PATCH 156/465] Unit tests passing --- .../MSFT_EXOTenantAllowBlockListItems.psm1 | 104 ++++++------ ...FT_EXOTenantAllowBlockListItems.schema.mof | 2 +- ...DSC.EXOTenantAllowBlockListItems.Tests.ps1 | 51 ++++-- Tests/Unit/Stubs/Microsoft365.psm1 | 152 ++++++++++++++++++ 4 files changed, 240 insertions(+), 69 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 index 7d758ebd48..683c5a5971 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 @@ -1,10 +1,34 @@ +function Add-ActionParameters +{ + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [System.String] + $Action, + + [Parameter(Mandatory = $true)] + [System.Collections.Hashtable] + $Parameters + ) + + if ($Action -eq 'Allow') + { + $Parameters.Add('Allow', $true) | Out-Null + } + elseif ($Action -eq 'Block') + { + $Parameters.Add('Block', $true) | Out-Null + } + $Parameters.Remove('Action') | Out-Null +} + function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( - [Parameter()] + [Parameter(Mandatory = $true)] [ValidateSet('Allow', 'Block')] [System.String] $Action, @@ -18,25 +42,17 @@ function Get-TargetResource $ExpirationDate, [Parameter()] - [System.Object] + [System.String] $ListSubType, [Parameter(Mandatory = $true)] - [System.Object] + [System.String] $ListType, - [Parameter()] - [System.Management.Automation.SwitchParameter] - $LogExtraDetails, - [Parameter()] [System.String] $Notes, - [Parameter()] - [System.Management.Automation.SwitchParameter] - $OutputJson, - [Parameter()] [System.Int32] $RemoveAfter, @@ -143,42 +159,31 @@ function Set-TargetResource [CmdletBinding()] param ( - [Parameter()] - [System.Management.Automation.SwitchParameter] - $Allow, - - [Parameter()] - [System.Management.Automation.SwitchParameter] - $Block, + [Parameter(Mandatory = $true)] + [ValidateSet('Allow', 'Block')] + [System.String] + $Action, [Parameter(Mandatory = $true)] - [System.String[]] - $Entries, + [System.String] + $Value, [Parameter()] [System.DateTime] $ExpirationDate, [Parameter()] - [System.Object] + [System.String] $ListSubType, [Parameter(Mandatory = $true)] - [System.Object] + [System.String] $ListType, - [Parameter()] - [System.Management.Automation.SwitchParameter] - $LogExtraDetails, - [Parameter()] [System.String] $Notes, - [Parameter()] - [System.Management.Automation.SwitchParameter] - $OutputJson, - [Parameter()] [System.Int32] $RemoveAfter, @@ -237,6 +242,9 @@ function Set-TargetResource $CreateParameters = ([Hashtable]$BoundParameters).Clone() $CreateParameters.Remove('Verbose') | Out-Null + $CreateParameters.Remove('Value') | Out-Null + $CreateParameters.Add('Entries', @($Value)) | Out-Null + Add-ActionParameters -Action $Action -Parameters $CreateParameters $keys = $CreateParameters.Keys foreach ($key in $keys) @@ -257,6 +265,9 @@ function Set-TargetResource $UpdateParameters = ([Hashtable]$BoundParameters).Clone() $UpdateParameters.Remove('Verbose') | Out-Null + $UpdateParameters.Remove('Value') | Out-Null + $UpdateParameters.Add('Entries', @($Value)) | Out-Null + Add-ActionParameters -Action $Action -Parameters $UpdateParameters $keys = $UpdateParameters.Keys foreach ($key in $keys) @@ -274,7 +285,7 @@ function Set-TargetResource elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { Write-Verbose -Message "Removing {$Entries}" - Remove-TenantAllowBlockListItems -Entries $currentInstance.Entries + Remove-TenantAllowBlockListItems -Entries $currentInstance.Value -ListType $currentInstance.$ListType } } @@ -284,42 +295,31 @@ function Test-TargetResource [OutputType([System.Boolean])] param ( - [Parameter()] - [System.Management.Automation.SwitchParameter] - $Allow, + [Parameter(Mandatory = $true)] + [ValidateSet('Allow', 'Block')] + [System.String] + $Action, - [Parameter()] - [System.Management.Automation.SwitchParameter] - $Block, + [Parameter(Mandatory = $true)] + [System.String] + $Value, [Parameter(Mandatory = $true)] - [System.String[]] - $Entries, + [System.String] + $ListType, [Parameter()] [System.DateTime] $ExpirationDate, [Parameter()] - [System.Object] + [System.String] $ListSubType, - [Parameter(Mandatory = $true)] - [System.Object] - $ListType, - - [Parameter()] - [System.Management.Automation.SwitchParameter] - $LogExtraDetails, - [Parameter()] [System.String] $Notes, - [Parameter()] - [System.Management.Automation.SwitchParameter] - $OutputJson, - [Parameter()] [System.Int32] $RemoveAfter, diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.schema.mof index 2eaa2fe3a0..f7cd9403e0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.schema.mof @@ -1,7 +1,7 @@ [ClassVersion("1.0.0.0"), FriendlyName("EXOTenantAllowBlockListItems")] class MSFT_EXOTenantAllowBlockListItems : OMI_BaseResource { - [Key, Description("")] String Action; + [Key, Description(""), ValueMap{"Allow","Block"}, Values{"Allow","Block"}] String Action; [Key, Description("")] String Value; [Write, Description("")] DateTime ExpirationDate; [Write, Description("")] String ListSubType; diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 index 549858d548..f0b1689297 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.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 EXOTenantAllowBlockListItems should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ - Ensure = "Present" + Action = "Block"; + ListType = "Url"; + Value = "example.com"; + Ensure = "Present"; Credential = $Credential; } @@ -79,7 +82,10 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The EXOTenantAllowBlockListItems exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ - Ensure = 'Absent' + Action = "Block"; + ListType = "Url"; + Value = "example.com"; + Ensure = 'Absent' Credential = $Credential; } @@ -109,16 +115,22 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The EXOTenantAllowBlockListItems Exists and Values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - Ensure = 'Present' + Action = "Block"; + ListType = "Url"; + Value = "example.com"; + Ensure = 'Present' Credential = $Credential; } Mock -CommandName Get-TenantAllowBlockListItems -MockWith { return @{ - SubmissionID = "FakeStringValue" - RemoveAfter = 3 - Notes = "FakeStringValue" - + Action = "Block"; + ListType = "Url"; + Value = "example.com"; + Ensure = 'Present' + SubmissionID = "FakeStringValue" + RemoveAfter = 3 + Notes = "FakeStringValue" } } } @@ -132,15 +144,20 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The EXOTenantAllowBlockListItems exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - Ensure = 'Present' + Action = "Block"; + ListType = "Url"; + Value = "example.com"; + Ensure = 'Present' + Notes = "FakeStringValueDrift" Credential = $Credential; } Mock -CommandName Get-TenantAllowBlockListItems -MockWith { return @{ - SubmissionID = "FakeStringValueDrift #Drift" - RemoveAfter = 2 - Notes = "FakeStringValueDrift #Drift" + Action = "Block"; + ListType = "Url"; + Value = "example.com"; + Notes = "FakeStringValueDrift #Drift" } } } @@ -169,10 +186,12 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-TenantAllowBlockListItems -MockWith { return @{ - SubmissionID = "FakeStringValue" - RemoveAfter = 3 - Notes = "FakeStringValue" - + Action = "Block"; + ListType = "Url"; + Value = "example.com"; + SubmissionID = "FakeStringValue" + RemoveAfter = 3 + Notes = "FakeStringValue" } } } diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 53aa0e0f60..b469ea0497 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -72497,6 +72497,37 @@ function Get-TenantSettings $ApiVersion ) } + +function Get-TenantAllowBlockListItems +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $ListType, + + [Parameter()] + [System.DateTime] + $ExpirationDate, + + [Parameter()] + [switch] + $Allow, + + [Parameter()] + [switch] + $Block, + + [Parameter()] + [System.String] + $Entry, + + [Parameter()] + [System.Object[]] + $ListSubType + ) +} + function New-AdminPowerAppEnvironment { [CmdletBinding()] @@ -72622,6 +72653,53 @@ function Set-TenantSettings $RequestBody ) } + +function Set-TenantAllowBlockListItems +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $ListType, + + [Parameter()] + [System.DateTime] + $ExpirationDate, + + [Parameter()] + [switch] + $Allow, + + [Parameter()] + [switch] + $Block, + + [Parameter()] + [System.String[]] + $Entries, + + [Parameter()] + [System.Object[]] + $ListSubType, + + [Parameter()] + [switch] + $NoExpiration, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [switch] + $OutputJson, + + [Parameter()] + [System.Int32] + $RemoveAfter + ) +} + #endregion #region MicrosoftTeams function Add-TeamUser @@ -74554,6 +74632,57 @@ function New-TeamChannel $GroupId ) } + +function New-TenantAllowBlockListItems +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Entries, + + [Parameter()] + [System.String] + $ListType, + + [Parameter()] + [System.DateTime] + $ExpirationDate, + + [Parameter()] + [switch] + $Allow, + + [Parameter()] + [switch] + $Block, + + [Parameter()] + [System.Object] + $ListSubType, + + [Parameter()] + [switch] + $LogExtraDetails, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [switch] + $OutputJson, + + [Parameter()] + [System.Int32] + $RemoveAfter, + + [Parameter()] + [System.String] + $SubmissionID + ) +} + function Remove-CsOnlineVoicemailPolicy { [CmdletBinding()] @@ -74882,6 +75011,29 @@ function Remove-TeamUser $Role ) } + +function Remove-TenantAllowBlockListItems +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $ListType, + + [Parameter()] + [System.String[]] + $Entries, + + [Parameter()] + [System.String] + $ListSubType, + + [Parameter()] + [switch] + $OutputJson + ) +} + function Set-CsOnlineVoicemailPolicy { [CmdletBinding()] From c028ed47f2334bbcc260595d9f948ade9db95732 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 12 Sep 2024 07:56:49 -0400 Subject: [PATCH 157/465] O365OrgSettings - Added Support for CustomerLockboxEnabled --- CHANGELOG.md | 2 + .../MSFT_O365OrgSettings.psm1 | 88 +++++-------------- .../MSFT_O365OrgSettings.schema.mof | 1 + .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 1 - 4 files changed, 26 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cbff6c93a..f5f8336f10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ * IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10 * Add missing `AccessTokens` parameter to `Export-TargetResource` FIXES [#5034](https://github.com/microsoft/Microsoft365DSC/issues/5034) +* O365OrgSettings + * Added support for the CustomerLockboxEnabled property. * SCRoleGroup * Fixes an issue with creation without specifying Displayname * Fixes an issue with Drifts because of returned Role format diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.psm1 index 2381352852..7e5cab828a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.psm1 @@ -17,6 +17,10 @@ function Get-TargetResource [System.Boolean] $AppsAndServicesIsOfficeStoreEnabled, + [Parameter()] + [System.Boolean] + $CustomerLockboxEnabled, + [Parameter()] [System.Boolean] $AppsAndServicesIsAppAndServicesTrialEnabled, @@ -235,61 +239,6 @@ function Get-TargetResource } } - # DEPRECATED - Microsoft Viva Briefing Email - <# - $vivaBriefingEmailValue = $false - try - { - $currentBriefingConfig = Get-DefaultTenantBriefingConfig -ErrorAction Stop -Verbose:$false - if ($currentBriefingConfig.IsEnabledByDefault -eq 'opt-in') - { - $vivaBriefingEmailValue = $true - } - } - catch - { - if ($_.Exception.Message -like "*Unexpected character encountered while parsing value*") - { - $vivaBriefingEmailValue = $true - } - elseif ($_.Exception.Message -like "*A task was canceled*") - { - $retries = 1 - $errorContent = $null - while ($retries -le 5) - { - try - { - Start-Sleep -Seconds 2 - $currentBriefingConfig = Get-DefaultTenantBriefingConfig -ErrorAction Stop -Verbose:$false - } - catch - { - $errorContent = $_ - $retries++ - } - } - if ($null -eq $currentBriefingConfig) - { - throw $errorContent - } - else - { - if ($currentBriefingConfig.IsEnabledByDefault -eq 'opt-in') - { - $vivaBriefingEmailValue = $true - } - } - } - else - { - throw $_ - } - } - $results += @{ - MicrosoftVivaBriefingEmail = $vivaBriefingEmailValue - }#> - # Viva Insights settings $currentVivaInsightsSettings = Get-DefaultTenantMyAnalyticsFeatureConfig -Verbose:$false if ($null -ne $currentVivaInsightsSettings) @@ -305,11 +254,11 @@ function Get-TargetResource $MRODeviceManagerService = 'ebe0c285-db95-403f-a1a3-a793bd6d7767' try { - $servicePrincipal = Get-MgServicePrincipal -Filter "appid eq 'ebe0c285-db95-403f-a1a3-a793bd6d7767'" + $servicePrincipal = Get-MgServicePrincipal -Filter "appid eq '$MRODeviceManagerService'" if ($null -eq $servicePrincipal) { Write-Verbose -Message "Registering the MRO Device Manager Service Principal" - New-MgServicePrincipal -AppId 'ebe0c285-db95-403f-a1a3-a793bd6d7767' -ErrorAction Stop | Out-Null + New-MgServicePrincipal -AppId $MRODeviceManagerService -ErrorAction Stop | Out-Null } } catch @@ -401,6 +350,9 @@ function Get-TargetResource } } + $OrganizationConfig = Get-OrganizationConfig + $results.Add('CustomerLockboxEnabled', $OrganizationConfig.CustomerLockboxEnabled) + return $results } catch @@ -437,6 +389,10 @@ function Set-TargetResource [System.Boolean] $AppsAndServicesIsAppAndServicesTrialEnabled, + [Parameter()] + [System.Boolean] + $CustomerLockboxEnabled, + [Parameter()] [System.Boolean] $DynamicsCustomerVoiceIsRestrictedSurveyAccessEnabled, @@ -626,14 +582,6 @@ function Set-TargetResource { Write-Verbose -Message "DEPRECATED - The MicrosoftVivaBriefingEmail parameter is deprecated and will be ignored." } - #$briefingValue = 'opt-out' - - <# DEPRECATED - if ($currentValues.MicrosoftVivaBriefingEmail -and $MicrosoftVivaBriefingEmail -ne $currentValues.MicrosoftVivaBriefingEmail) - { - Write-Verbose -Message "Updating Microsoft Viva Briefing Email settings." - Set-DefaultTenantBriefingConfig -IsEnabledByDefault $briefingValue -Verbose:$false | Out-Null - }#> # Viva Insights if ($PSBoundParameters.ContainsKey('VivaInsightsWebExperience') -and ` @@ -844,6 +792,12 @@ function Set-TargetResource Write-Verbose -Message "Updating the To Do settings with values:$(Convert-M365DscHashtableToString -Hashtable $ToDoParametersToUpdate)" Update-M365DSCOrgSettingsToDo -Options $ToDoParametersToUpdate } + + # Customer Lockbox + if ($PSBoundParameters.ContainsKey('CustomerLockboxEnabled')) + { + Set-OrganizationConfig -CustomerLockboxEnabled $CustomerLockboxEnabled | Out-Null + } } function Test-TargetResource @@ -869,6 +823,10 @@ function Test-TargetResource [System.Boolean] $AppsAndServicesIsAppAndServicesTrialEnabled, + [Parameter()] + [System.Boolean] + $CustomerLockboxEnabled, + [Parameter()] [System.Boolean] $DynamicsCustomerVoiceIsRestrictedSurveyAccessEnabled, diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.schema.mof index 2eb2767c73..9d5fcb118b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.schema.mof @@ -26,6 +26,7 @@ class MSFT_O365OrgSettings : OMI_BaseResource [Write, Description("To Do - Allow sharing with external users.")] Boolean ToDoIsExternalShareEnabled; [Write, Description("To Do - Allow your users to receive push notifications.")] Boolean ToDoIsPushNotificationEnabled; [Write, Description("Controls whether or not the Admin Center reports will conceale user, group and site names.")] Boolean AdminCenterReportDisplayConcealedNames; + [Write, Description("Determines if the customer lockbox should require approval for all data access requests or not.")] Boolean CustomerLockboxEnabled; [Write, Description("Defines how often you want your users to get feature updates for Microsoft 365 apps installed on devices running Windows"), ValueMap{"current","monthlyEnterprise","semiAnnual"}, Values{"current","monthlyEnterprise","semiAnnual"}] String InstallationOptionsUpdateChannel; [Write, Description("Defines the apps users can install on Windows and mobile devices."), ValueMap{"isVisioEnabled","isSkypeForBusinessEnabled","isProjectEnabled","isMicrosoft365AppsEnabled"}, Values{"isVisioEnabled","isSkypeForBusinessEnabled","isProjectEnabled","isMicrosoft365AppsEnabled"}] String InstallationOptionsAppsForWindows[]; [Write, Description("Defines the apps users can install on Mac devices."), ValueMap{"isSkypeForBusinessEnabled","isMicrosoft365AppsEnabled"}, Values{"isSkypeForBusinessEnabled","isMicrosoft365AppsEnabled"}] String InstallationOptionsAppsForMac[]; diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 9397159c76..614ea78655 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1771,7 +1771,6 @@ function New-M365DSCConnection [System.Boolean] $SkipModuleReload = $false ) - $verbosepreference = 'Continue' $Global:MaximumFunctionCount = 32767 if ($Workload -eq 'MicrosoftTeams') { From 3533b09d5b7fecde7e48d308b6e0bd4036bc2422 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 12 Sep 2024 12:15:33 +0000 Subject: [PATCH 158/465] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/office365/O365OrgSettings.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/resources/office365/O365OrgSettings.md b/docs/docs/resources/office365/O365OrgSettings.md index a7c8b31216..f80359b12b 100644 --- a/docs/docs/resources/office365/O365OrgSettings.md +++ b/docs/docs/resources/office365/O365OrgSettings.md @@ -29,6 +29,7 @@ | **ToDoIsExternalShareEnabled** | Write | Boolean | To Do - Allow sharing with external users. | | | **ToDoIsPushNotificationEnabled** | Write | Boolean | To Do - Allow your users to receive push notifications. | | | **AdminCenterReportDisplayConcealedNames** | Write | Boolean | Controls whether or not the Admin Center reports will conceale user, group and site names. | | +| **CustomerLockboxEnabled** | Write | Boolean | Determines if the customer lockbox should require approval for all data access requests or not. | | | **InstallationOptionsUpdateChannel** | Write | String | Defines how often you want your users to get feature updates for Microsoft 365 apps installed on devices running Windows | `current`, `monthlyEnterprise`, `semiAnnual` | | **InstallationOptionsAppsForWindows** | Write | StringArray[] | Defines the apps users can install on Windows and mobile devices. | `isVisioEnabled`, `isSkypeForBusinessEnabled`, `isProjectEnabled`, `isMicrosoft365AppsEnabled` | | **InstallationOptionsAppsForMac** | Write | StringArray[] | Defines the apps users can install on Mac devices. | `isSkypeForBusinessEnabled`, `isMicrosoft365AppsEnabled` | From 8e34d0f8ea55c756e9e2bd8646346a25309adab0 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 12 Sep 2024 12:17:25 +0000 Subject: [PATCH 159/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 467491a96f..40944f41cd 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -35752,6 +35752,11 @@ "Name": "AdminCenterReportDisplayConcealedNames", "Option": "Write" }, + { + "CIMType": "Boolean", + "Name": "CustomerLockboxEnabled", + "Option": "Write" + }, { "CIMType": "String", "Name": "InstallationOptionsUpdateChannel", From 48f6178f5aae512d9f28bfd7f6f6990ce2aaa27e Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Thu, 12 Sep 2024 18:51:00 +0530 Subject: [PATCH 160/465] Initial commit --- .../MSFT_AADAuthenticationMethodPolicy.psm1 | 78 +++++++++++++++++++ ...T_AADAuthenticationMethodPolicy.schema.mof | 8 ++ 2 files changed, 86 insertions(+) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.psm1 index e792ad65e9..ca5ad7562a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.psm1 @@ -30,6 +30,10 @@ function Get-TargetResource [Microsoft.Management.Infrastructure.CimInstance] $RegistrationEnforcement, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $ReportSuspiciousActivitySettings, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $SystemCredentialPreferences, @@ -172,6 +176,35 @@ function Get-TargetResource $complexRegistrationEnforcement = $null } + $complexReportSuspiciousActivitySettings = @{} + $complexIncludeTargets = @() + foreach ($currentIncludeTargets in $getValue.ReportSuspiciousActivitySettings.includeTargets) + { + $myIncludeTargets = @{} + $myIncludeTargets.Add('Id', $currentIncludeTargets.id) + if ($null -ne $currentIncludeTargets.targetType) + { + $myIncludeTargets.Add('TargetType', $currentIncludeTargets.targetType.toString()) + } + if ($myIncludeTargets.values.Where({$null -ne $_}).count -gt 0) + { + $complexIncludeTargets += $myIncludeTargets + } + } + $complexReportSuspiciousActivitySettings.Add('IncludeTargets',$complexIncludeTargets) + if ($null -ne $getValue.ReportSuspiciousActivitySettings.state) + { + $complexReportSuspiciousActivitySettings.Add('State', $getValue.ReportSuspiciousActivitySettings.state.toString()) + } + if($null -ne $getValue.ReportSuspiciousActivitySettings.VoiceReportingCode) + { + $complexReportSuspiciousActivitySettings.Add('VoiceReportingCode', $getValue.ReportSuspiciousActivitySettings.VoiceReportingCode) + } + if ($complexReportSuspiciousActivitySettings.values.Where({$null -ne $_}).count -eq 0) + { + $complexReportSuspiciousActivitySettings = $null + } + $complexSystemCredentialPreferences = @{} $complexExcludeTargets = @() foreach ($currentExcludeTargets in $getValue.SystemCredentialPreferences.excludeTargets) @@ -229,6 +262,7 @@ function Get-TargetResource PolicyVersion = $getValue.PolicyVersion ReconfirmationInDays = $getValue.ReconfirmationInDays RegistrationEnforcement = $complexRegistrationEnforcement + ReportSuspiciousActivitySettings = $complexReportSuspiciousActivitySettings SystemCredentialPreferences = $complexSystemCredentialPreferences Id = $getValue.Id Ensure = 'Present' @@ -287,6 +321,10 @@ function Set-TargetResource [Microsoft.Management.Infrastructure.CimInstance] $RegistrationEnforcement, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $ReportSuspiciousActivitySettings, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $SystemCredentialPreferences, @@ -407,6 +445,10 @@ function Test-TargetResource [Microsoft.Management.Infrastructure.CimInstance] $RegistrationEnforcement, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $ReportSuspiciousActivitySettings, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $SystemCredentialPreferences, @@ -648,6 +690,37 @@ function Export-TargetResource $Results.Remove('RegistrationEnforcement') | Out-Null } } + + if ($null -ne $Results.ReportSuspiciousActivitySettings) + { + $complexMapping = @( + @{ + Name = 'ReportSuspiciousActivitySettings' + CimInstanceName = 'MicrosoftGraphReportSuspiciousActivitySettings' + IsRequired = $False + } + @{ + Name = 'IncludeTargets' + CimInstanceName = 'AADAuthenticationMethodPolicyIncludeTarget' + IsRequired = $False + } + ) + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.ReportSuspiciousActivitySettings ` + -CIMInstanceName 'MicrosoftGraphsystemCredentialPreferences' ` + -ComplexTypeMapping $complexMapping + + if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.ReportSuspiciousActivitySettings = $complexTypeStringResult + } + else + { + $Results.Remove('ReportSuspiciousActivitySettings') | Out-Null + } + } + + if ($null -ne $Results.SystemCredentialPreferences) { $complexMapping = @( @@ -695,6 +768,11 @@ function Export-TargetResource { $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "SystemCredentialPreferences" -isCIMArray:$False } + + if ($Results.ReportSuspiciousActivitySettings) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "ReportSuspiciousActivitySettings" -isCIMArray:$False + } $dscContent += $currentDSCBlock Save-M365DSCPartialExport -Content $currentDSCBlock ` -FileName $Global:PartialExportFileName diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.schema.mof index fb55f22adf..8be20c6e70 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.schema.mof @@ -43,6 +43,13 @@ class MSFT_MicrosoftGraphSystemCredentialPreferences [Write, Description("Users and groups included in the preferred authentication method experience of the system."), EmbeddedInstance("MSFT_AADAuthenticationMethodPolicyIncludeTarget")] String IncludeTargets[]; [Write, Description("Indicates whether the feature is enabled or disabled. Possible values are: default, enabled, disabled, unknownFutureValue. The default value is used when the configuration hasn't been explicitly set, and uses the default behavior of Azure Active Directory for the setting. The default value is disabled."), ValueMap{"default","enabled","disabled","unknownFutureValue"}, Values{"default","enabled","disabled","unknownFutureValue"}] String State; }; +[ClassVersion("1.0.0")] +class MSFT_MicrosoftGraphReportSuspiciousActivitySettings +{ + [Write, Description(""), EmbeddedInstance("MSFT_AADAuthenticationMethodPolicyIncludeTarget")] String IncludeTargets[]; + [Write, Description(""), ValueMap{"default","enabled","disabled","unknownFutureValue"}, Values{"default","enabled","disabled","unknownFutureValue"}] String State; + [Write, Description("")] UInt32 VoiceReportingCode; +}; [ClassVersion("1.0.0.0"), FriendlyName("AADAuthenticationMethodPolicy")] class MSFT_AADAuthenticationMethodPolicy : OMI_BaseResource @@ -53,6 +60,7 @@ class MSFT_AADAuthenticationMethodPolicy : OMI_BaseResource [Write, Description("The version of the policy in use.")] String PolicyVersion; [Write, Description("Days before the user will be asked to reconfirm their method.")] UInt32 ReconfirmationInDays; [Write, Description("Enforce registration at sign-in time. This property can be used to remind users to set up targeted authentication methods."), EmbeddedInstance("MSFT_MicrosoftGraphregistrationEnforcement")] String RegistrationEnforcement; + [Write, Description(""), EmbeddedInstance("MSFT_MicrosoftGraphreportSuspiciousActivitySettings")] String ReportSuspiciousActivitySettings; [Write, Description("Prompt users with their most-preferred credential for multifactor authentication."), EmbeddedInstance("MSFT_MicrosoftGraphsystemCredentialPreferences")] String SystemCredentialPreferences; [Write, Description("The unique identifier for an entity. Read-only.")] String Id; [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; From b0e1c2effb8477e36d1acd8cb148949b365ac6f1 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Thu, 12 Sep 2024 12:08:23 -0700 Subject: [PATCH 161/465] End-to-end fixes --- .../MSFT_EXOTenantAllowBlockListItems.psm1 | 53 ++++++++++++++----- ...FT_EXOTenantAllowBlockListItems.schema.mof | 16 +++--- .../readme.md | 5 +- .../settings.json | 28 +++++++--- ...DSC.EXOTenantAllowBlockListItems.Tests.ps1 | 11 ++-- 5 files changed, 77 insertions(+), 36 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 index 683c5a5971..79f73e562b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 @@ -42,6 +42,7 @@ function Get-TargetResource $ExpirationDate, [Parameter()] + [ValidateSet('AdvancedDelivery', 'Tenant')] [System.String] $ListSubType, @@ -54,7 +55,7 @@ function Get-TargetResource $Notes, [Parameter()] - [System.Int32] + [System.UInt32] $RemoveAfter, [Parameter()] @@ -104,6 +105,7 @@ function Get-TargetResource $nullResult = $PSBoundParameters $nullResult.Ensure = 'Absent' + $nullResult.ListType = $ListType try { $getParams = @{ ListType = $ListType; Entry = $Value; } @@ -128,9 +130,7 @@ function Get-TargetResource ExpirationDate = $instance.ExpirationDate ListSubType = $instance.ListSubType ListType = $ListType - LogExtraDetails = $instance.LogExtraDetails Notes = $instance.Notes - OutputJson = $instance.OutputJson RemoveAfter = $instance.RemoveAfter SubmissionID = $instance.SubmissionID Ensure = 'Present' @@ -173,6 +173,7 @@ function Set-TargetResource $ExpirationDate, [Parameter()] + [ValidateSet('AdvancedDelivery', 'Tenant')] [System.String] $ListSubType, @@ -185,7 +186,7 @@ function Set-TargetResource $Notes, [Parameter()] - [System.Int32] + [System.UInt32] $RemoveAfter, [Parameter()] @@ -256,18 +257,37 @@ function Set-TargetResource $CreateParameters.Add($keyName, $keyValue) } } - Write-Verbose -Message "Creating {$Entries} with Parameters:`r`n$(Convert-M365DscHashtableToString -Hashtable $CreateParameters)" + Write-Verbose -Message "Creating {$Value} with Parameters:`r`n$(Convert-M365DscHashtableToString -Hashtable $CreateParameters)" New-TenantAllowBlockListItems @CreateParameters | Out-Null } elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - Write-Verbose -Message "Updating {$Entries}" + Write-Verbose -Message "Updating {$Value}" + + if ($currentInstance.Action -ne $Action) + { + throw "Updating Action from {$currentInstance.Action} to {$Action} is not allowed" + } + + if ($currentInstance.Value -ne $Value -and + $currentInstance.ListType -ne 'Url' -and + $currentInstance.Action -ne 'Allow' -and + $currentInstance.ListSubType -ne 'AdvancedDelivery') + { + throw "Updating Value is only allowed for Action=Allow ListType=Url ListSubType=AdvancedDelivery" + } + + if ($currentInstance.SubmissionID -ne $SubmissionID) + { + throw "SubmissionID can not be changed" + } $UpdateParameters = ([Hashtable]$BoundParameters).Clone() $UpdateParameters.Remove('Verbose') | Out-Null $UpdateParameters.Remove('Value') | Out-Null + $UpdateParameters.Remove('SubmissionID') | Out-Null #SubmissionID can not be changed $UpdateParameters.Add('Entries', @($Value)) | Out-Null - Add-ActionParameters -Action $Action -Parameters $UpdateParameters + $UpdateParameters.Remove('Action') | Out-Null $keys = $UpdateParameters.Keys foreach ($key in $keys) @@ -284,8 +304,8 @@ function Set-TargetResource } elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - Write-Verbose -Message "Removing {$Entries}" - Remove-TenantAllowBlockListItems -Entries $currentInstance.Value -ListType $currentInstance.$ListType + Write-Verbose -Message "Removing {$Value}" + Remove-TenantAllowBlockListItems -Entries $currentInstance.Value -ListType $currentInstance.ListType } } @@ -313,6 +333,7 @@ function Test-TargetResource $ExpirationDate, [Parameter()] + [ValidateSet('AdvancedDelivery', 'Tenant')] [System.String] $ListSubType, @@ -371,6 +392,10 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() $ValuesToCheck.Remove('Entries') | Out-Null + if ($null -ne $ValuesToCheck.ExpirationDate -and $ValuesToCheck.ExpirationDate.Kind -eq 'Local') + { + $ValuesToCheck.ExpirationDate = $ValuesToCheck.ExpirationDate.ToUniversalTime().ToString() + } if ($CurrentValues.Ensure -eq 'Absent') { @@ -382,18 +407,22 @@ function Test-TargetResource Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" #Convert any DateTime to String - foreach ($key in $ValuesToCheck.Keys) + $keys = $ValuesToCheck.Keys + foreach ($key in $keys) { if (($null -ne $CurrentValues[$key]) ` -and ($CurrentValues[$key].GetType().Name -eq 'DateTime')) { - $CurrentValues[$key] = $CurrentValues[$key].toString() + #Write-Verbose -Message "*** Current Value for $key is a DateTime, kind=$($CurrentValues[$key].Kind)" + #Write-Verbose -Message "*** Desired Value for $key is a DateTime, kind=$($ValuesToCheck[$key].Kind)" + $CurrentValues[$key] = $CurrentValues[$key].ToString() + Write-Verbose -Message "*** Current=$($CurrentValues[$key]) Desired=$($ValuesToCheck[$key])" } } $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` + -DesiredValues $ValuesToCheck ` -ValuesToCheck $ValuesToCheck.Keys Write-Verbose -Message "Test-TargetResource returned $testResult" diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.schema.mof index f7cd9403e0..a5cc03a1f6 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.schema.mof @@ -1,14 +1,14 @@ [ClassVersion("1.0.0.0"), FriendlyName("EXOTenantAllowBlockListItems")] class MSFT_EXOTenantAllowBlockListItems : OMI_BaseResource { - [Key, Description(""), ValueMap{"Allow","Block"}, Values{"Allow","Block"}] String Action; - [Key, Description("")] String Value; - [Write, Description("")] DateTime ExpirationDate; - [Write, Description("")] String ListSubType; - [Key, Description("")] String ListType; - [Write, Description("")] String Notes; - [Write, Description("")] UInt32 RemoveAfter; - [Write, Description("")] String SubmissionID; + [Key, Description("The action (allow/block) to take for this list entry"), ValueMap{"Allow","Block"}, Values{"Allow","Block"}] String Action; + [Key, Description("The value that you want to add to the Tenant Allow/Block List based on the ListType parameter value")] String Value; + [Write, Description("The expiration date of the entry in Coordinated Universal Time (UTC)")] DateTime ExpirationDate; + [Write, Description("The subtype for this entry"), ValueMap{"AdvancedDelivery", "Tenant"}, Values{"AdvancedDelivery", "Tenant"}] String ListSubType; + [Key, Description("The type of entry to add."), ValueMap{"FileHash","Sender","Url"}, Values{"FileHash","Sender","Url"}] String ListType; + [Write, Description("Additional information about the object")] String Notes; + [Write, Description("Number of days after the entry is first used for it to removed")] UInt32 RemoveAfter; + [Write, Description("Reserved for internal Microsoft use")] String SubmissionID; [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; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/readme.md index 42219633c8..ab32bd5a82 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/readme.md @@ -3,8 +3,5 @@ ## Description - -New-TenantAllowBlockListItems -Entries -ListType [-Allow] [-Block] [-ExpirationDate ] [-ListSubType ] [-LogExtraDetails] [-Notes ] [-OutputJson] [-RemoveAfter ] [-SubmissionID ] [] - -New-TenantAllowBlockListItems -Entries -ListType -NoExpiration [-Allow] [-Block] [-ListSubType ] [-LogExtraDetails] [-Notes ] [-OutputJson] [-RemoveAfter ] [-SubmissionID ] [] +Use this resource to manage the Exchange Online Tenant Allow/Block List items. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/settings.json index e2df4807ae..104a649436 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/settings.json @@ -1,10 +1,24 @@ { "resourceName": "EXOTenantAllowBlockListItems", - "description": "This resource configures an -New-TenantAllowBlockListItems -Entries -ListType [-Allow] [-Block] [-ExpirationDate ] [-ListSubType ] [-LogExtraDetails] [-Notes ] [-OutputJson] [-RemoveAfter ] [-SubmissionID ] [] - -New-TenantAllowBlockListItems -Entries -ListType -NoExpiration [-Allow] [-Block] [-ListSubType ] [-LogExtraDetails] [-Notes ] [-OutputJson] [-RemoveAfter ] [-SubmissionID ] [] -.", - "permissions":[] - + "description": "This resource configures the tenant allow/block list (TABL) entries", + "roles": { + "read": [ + "Exchange Admin" + ], + "update": [ + "Exchange Admin" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + } + } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 index f0b1689297..a74b01e8ca 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 @@ -120,6 +120,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Value = "example.com"; Ensure = 'Present' Credential = $Credential; + ExpirationDate = [DateTime]::new(2022, 12, 31, 0, 0, 0, 0, 0, 'Local') } Mock -CommandName Get-TenantAllowBlockListItems -MockWith { @@ -127,10 +128,10 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Action = "Block"; ListType = "Url"; Value = "example.com"; - Ensure = 'Present' - SubmissionID = "FakeStringValue" - RemoveAfter = 3 - Notes = "FakeStringValue" + Ensure = 'Present'; + SubmissionID = "FakeStringValue"; + Notes = "FakeStringValue"; + ExpirationDate = [DateTime]::new(2022, 12, 31, 0, 0, 0, 0, 0, 'Utc') } } } @@ -157,7 +158,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Action = "Block"; ListType = "Url"; Value = "example.com"; - Notes = "FakeStringValueDrift #Drift" + Notes = "FakeStringValueDrift #Drift"; } } } From 075ff46f7c09d3cafa3bede58c6b68bf325e1a21 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Thu, 12 Sep 2024 12:19:48 -0700 Subject: [PATCH 162/465] Add examples --- ...-EXOTenantAllowBlockListItems-Example.psm1 | 21 ---------- .../EXOTenantAllowBlockListItems/1-Create.ps1 | 40 +++++++++++++++++++ .../EXOTenantAllowBlockListItems/2-Update.ps1 | 40 +++++++++++++++++++ .../EXOTenantAllowBlockListItems/3-Delete.ps1 | 40 +++++++++++++++++++ 4 files changed, 120 insertions(+), 21 deletions(-) delete mode 100644 Modules/Microsoft365DSC/Examples/EXOTenantAllowBlockListItems/1-EXOTenantAllowBlockListItems-Example.psm1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOTenantAllowBlockListItems/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOTenantAllowBlockListItems/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOTenantAllowBlockListItems/3-Delete.ps1 diff --git a/Modules/Microsoft365DSC/Examples/EXOTenantAllowBlockListItems/1-EXOTenantAllowBlockListItems-Example.psm1 b/Modules/Microsoft365DSC/Examples/EXOTenantAllowBlockListItems/1-EXOTenantAllowBlockListItems-Example.psm1 deleted file mode 100644 index 43e0d749ca..0000000000 --- a/Modules/Microsoft365DSC/Examples/EXOTenantAllowBlockListItems/1-EXOTenantAllowBlockListItems-Example.psm1 +++ /dev/null @@ -1,21 +0,0 @@ -<# -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 - { - EXOTenantAllowBlockListItems 'Example' - { - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOTenantAllowBlockListItems/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOTenantAllowBlockListItems/1-Create.ps1 new file mode 100644 index 0000000000..9a31d33f3a --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOTenantAllowBlockListItems/1-Create.ps1 @@ -0,0 +1,40 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + EXOTenantAllowBlockListItems "Example" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + TenantId = $TenantId; + Action = "Block"; + Ensure = "Present"; + ExpirationDate = "10/11/2024 9:00:00 PM"; + ListSubType = "Tenant"; + ListType = "Sender"; + Notes = "Test block"; + SubmissionID = "Non-Submission"; + Value = "example.com"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOTenantAllowBlockListItems/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOTenantAllowBlockListItems/2-Update.ps1 new file mode 100644 index 0000000000..73d5842fbd --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOTenantAllowBlockListItems/2-Update.ps1 @@ -0,0 +1,40 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + EXOTenantAllowBlockListItems "Example" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + TenantId = $TenantId; + Action = "Block"; + Ensure = "Present"; + ExpirationDate = "10/11/2024 9:00:00 PM"; + ListSubType = "Tenant"; + ListType = "Sender"; + Notes = "Test block with updated notes"; + SubmissionID = "Non-Submission"; + Value = "example.com"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOTenantAllowBlockListItems/3-Delete.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOTenantAllowBlockListItems/3-Delete.ps1 new file mode 100644 index 0000000000..2f78d5db6f --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOTenantAllowBlockListItems/3-Delete.ps1 @@ -0,0 +1,40 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + EXOTenantAllowBlockListItems "Example" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + TenantId = $TenantId; + Action = "Block"; + Ensure = "Absent"; + ExpirationDate = "10/11/2024 9:00:00 PM"; + ListSubType = "Tenant"; + ListType = "Sender"; + Notes = "Test block"; + SubmissionID = "Non-Submission"; + Value = "example.com"; + } + } +} From c13f6b462a0431f63099f061ea691f895d5fb57f Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Thu, 12 Sep 2024 12:44:32 -0700 Subject: [PATCH 163/465] Update tests --- .../MSFT_EXOTenantAllowBlockListItems.psm1 | 18 +------------ ...DSC.EXOTenantAllowBlockListItems.Tests.ps1 | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 index 79f73e562b..08fd6b85e3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTenantAllowBlockListItems/MSFT_EXOTenantAllowBlockListItems.psm1 @@ -264,19 +264,6 @@ function Set-TargetResource { Write-Verbose -Message "Updating {$Value}" - if ($currentInstance.Action -ne $Action) - { - throw "Updating Action from {$currentInstance.Action} to {$Action} is not allowed" - } - - if ($currentInstance.Value -ne $Value -and - $currentInstance.ListType -ne 'Url' -and - $currentInstance.Action -ne 'Allow' -and - $currentInstance.ListSubType -ne 'AdvancedDelivery') - { - throw "Updating Value is only allowed for Action=Allow ListType=Url ListSubType=AdvancedDelivery" - } - if ($currentInstance.SubmissionID -ne $SubmissionID) { throw "SubmissionID can not be changed" @@ -387,7 +374,7 @@ function Test-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - Write-Verbose -Message "Testing configuration of {$Entries}" + Write-Verbose -Message "Testing configuration of {$Value}" $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() @@ -413,10 +400,7 @@ function Test-TargetResource if (($null -ne $CurrentValues[$key]) ` -and ($CurrentValues[$key].GetType().Name -eq 'DateTime')) { - #Write-Verbose -Message "*** Current Value for $key is a DateTime, kind=$($CurrentValues[$key].Kind)" - #Write-Verbose -Message "*** Desired Value for $key is a DateTime, kind=$($ValuesToCheck[$key].Kind)" $CurrentValues[$key] = $CurrentValues[$key].ToString() - Write-Verbose -Message "*** Current=$($CurrentValues[$key]) Desired=$($ValuesToCheck[$key])" } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 index a74b01e8ca..057e9017d3 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 @@ -177,6 +177,32 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } + Context -Name 'Disallowed Updates' -Fixture { + BeforeAll { + $testParams = @{ + Action = "Block"; + ListType = "Url"; + Value = "example.com"; + Ensure = 'Present' + SubmissionID = "SubmissionID" + Credential = $Credential; + } + + Mock -CommandName Get-TenantAllowBlockListItems -MockWith { + return @{ + Action = "Block"; + ListType = "Url"; + Value = "example.com"; + SubmissionID = "SubmissionID" + } + } + } + It 'Should throw if SubmissionID is changed' { + $testParams['SubmissionID'] = "SubmissionID 2" + { Set-TargetResource @testParams } | Should -Throw + } + } + Context -Name 'ReverseDSC Tests' -Fixture { BeforeAll { $Global:CurrentModeIsExport = $true From a109fd133794602a8d7d05dd0246ae35d3a1e683 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Thu, 12 Sep 2024 12:49:11 -0700 Subject: [PATCH 164/465] Add integration tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 14 ++++++++++++++ .../M365DSCIntegration.EXO.Remove.Tests.ps1 | 16 +++++++++++++++- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 14 ++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index 09ec18abf2..ff34e096e8 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -940,6 +940,20 @@ SourceFolder = "Test2:\Inbox"; TenantId = $TenantId; } + EXOTenantAllowBlockListItems "TenantAllowBlowListItem" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + TenantId = $TenantId; + Action = "Block"; + Ensure = "Present"; + ExpirationDate = "10/11/2024 9:00:00 PM"; + ListSubType = "Tenant"; + ListType = "Sender"; + Notes = "Test block"; + SubmissionID = "Non-Submission"; + Value = "example.com"; + } EXOTransportRule 'ConfigureTransportRule' { Name = "Ethical Wall - Sales and Executives Departments" diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 index 9561195d84..4f14860330 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 @@ -455,7 +455,7 @@ } EXORecipientPermission 'AddSendAs' { - + Identity = 'AdeleV@$Domain' Trustee = "admin@$TenantId" Ensure = 'Absent' @@ -580,6 +580,20 @@ Name = "From Michelle"; TenantId = $TenantId; } + EXOTenantAllowBlockListItems "TenantAllowBlowListItem" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + TenantId = $TenantId; + Action = "Block"; + Ensure = "Absent"; + ExpirationDate = "10/11/2024 9:00:00 PM"; + ListSubType = "Tenant"; + ListType = "Sender"; + Notes = "Test block"; + SubmissionID = "Non-Submission"; + Value = "example.com"; + } EXOTransportRule 'ConfigureTransportRule' { Name = "Ethical Wall - Sales and Brokerage Departments" diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index e3fd8c95b0..6ef76d1f08 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -1373,6 +1373,20 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOTenantAllowBlockListItems "TenantAllowBlowListItem" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + TenantId = $TenantId; + Action = "Block"; + Ensure = "Present"; + ExpirationDate = "10/11/2024 9:00:00 PM"; + ListSubType = "Tenant"; + ListType = "Sender"; + Notes = "Test block - Updated"; # Updated Property + SubmissionID = "Non-Submission"; + Value = "example.com"; + } EXOTransportRule 'ConfigureTransportRule' { Name = "Ethical Wall - Sales and Executives Departments" From 4929ecb5ee063ce9134485936dcdac9f82aed439 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Thu, 12 Sep 2024 15:22:41 -0700 Subject: [PATCH 165/465] Fix unit tests --- ...rosoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 index 057e9017d3..e7f1ba251a 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTenantAllowBlockListItems.Tests.ps1 @@ -119,8 +119,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ListType = "Url"; Value = "example.com"; Ensure = 'Present' + SubmissionID = "FakeStringValue"; + Notes = "FakeStringValue"; Credential = $Credential; - ExpirationDate = [DateTime]::new(2022, 12, 31, 0, 0, 0, 0, 0, 'Local') } Mock -CommandName Get-TenantAllowBlockListItems -MockWith { @@ -129,9 +130,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ListType = "Url"; Value = "example.com"; Ensure = 'Present'; - SubmissionID = "FakeStringValue"; - Notes = "FakeStringValue"; - ExpirationDate = [DateTime]::new(2022, 12, 31, 0, 0, 0, 0, 0, 'Utc') + SubmissionID = "FakeStringValue"; + Notes = "FakeStringValue"; } } } @@ -150,6 +150,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Value = "example.com"; Ensure = 'Present' Notes = "FakeStringValueDrift" + SubmissionID = "FakeStringValue"; Credential = $Credential; } @@ -159,6 +160,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ListType = "Url"; Value = "example.com"; Notes = "FakeStringValueDrift #Drift"; + SubmissionID = "FakeStringValue"; } } } From 71a1b2433885dbce645a1f3fa7cc78fda2b79c52 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Fri, 13 Sep 2024 16:02:59 +0530 Subject: [PATCH 166/465] Fixed bugs and added UTs --- .../MSFT_AADAuthenticationMethodPolicy.psm1 | 23 +++------ ...T_AADAuthenticationMethodPolicy.schema.mof | 2 +- ...SC.AADAuthenticationMethodPolicy.Tests.ps1 | 50 ++++++++++++++++++- 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.psm1 index ca5ad7562a..f67f0d12f3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.psm1 @@ -177,21 +177,14 @@ function Get-TargetResource } $complexReportSuspiciousActivitySettings = @{} - $complexIncludeTargets = @() - foreach ($currentIncludeTargets in $getValue.ReportSuspiciousActivitySettings.includeTargets) + $newComplexIncludeTarget = @{} + $newComplexIncludeTarget.Add('Id', $getValue.ReportSuspiciousActivitySettings.IncludeTarget.id) + if ($null -ne $getValue.ReportSuspiciousActivitySettings.IncludeTarget.targetType) { - $myIncludeTargets = @{} - $myIncludeTargets.Add('Id', $currentIncludeTargets.id) - if ($null -ne $currentIncludeTargets.targetType) - { - $myIncludeTargets.Add('TargetType', $currentIncludeTargets.targetType.toString()) - } - if ($myIncludeTargets.values.Where({$null -ne $_}).count -gt 0) - { - $complexIncludeTargets += $myIncludeTargets - } + $newComplexIncludeTarget.Add('TargetType', $getValue.ReportSuspiciousActivitySettings.IncludeTarget.targetType.toString()) } - $complexReportSuspiciousActivitySettings.Add('IncludeTargets',$complexIncludeTargets) + $complexReportSuspiciousActivitySettings.Add('IncludeTarget',$newComplexIncludeTarget) + if ($null -ne $getValue.ReportSuspiciousActivitySettings.state) { $complexReportSuspiciousActivitySettings.Add('State', $getValue.ReportSuspiciousActivitySettings.state.toString()) @@ -700,14 +693,14 @@ function Export-TargetResource IsRequired = $False } @{ - Name = 'IncludeTargets' + Name = 'IncludeTarget' CimInstanceName = 'AADAuthenticationMethodPolicyIncludeTarget' IsRequired = $False } ) $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` -ComplexObject $Results.ReportSuspiciousActivitySettings ` - -CIMInstanceName 'MicrosoftGraphsystemCredentialPreferences' ` + -CIMInstanceName 'MicrosoftGraphreportSuspiciousActivitySettings' ` -ComplexTypeMapping $complexMapping if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.schema.mof index 8be20c6e70..f7eaa81c67 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.schema.mof @@ -46,7 +46,7 @@ class MSFT_MicrosoftGraphSystemCredentialPreferences [ClassVersion("1.0.0")] class MSFT_MicrosoftGraphReportSuspiciousActivitySettings { - [Write, Description(""), EmbeddedInstance("MSFT_AADAuthenticationMethodPolicyIncludeTarget")] String IncludeTargets[]; + [Write, Description(""), EmbeddedInstance("MSFT_AADAuthenticationMethodPolicyIncludeTarget")] String IncludeTarget; [Write, Description(""), ValueMap{"default","enabled","disabled","unknownFutureValue"}, Values{"default","enabled","disabled","unknownFutureValue"}] String State; [Write, Description("")] UInt32 VoiceReportingCode; }; diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationMethodPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationMethodPolicy.Tests.ps1 index 17999530eb..1246e426c3 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationMethodPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationMethodPolicy.Tests.ps1 @@ -71,7 +71,15 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } -ClientOnly) ) } -ClientOnly) - } -ClientOnly) + } -ClientOnly) + ReportSuspiciousActivitySettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphreportSuspiciousActivitySettings -Property @{ + VoiceReportingCode = 0 + State = 'default' + IncludeTarget = (New-CimInstance -ClassName MSFT_AADAuthenticationMethodPolicyIncludeTarget -Property @{ + Id = 'a8ab05ba-6680-4f93-88ae-71099eedfda1' + TargetType = 'group' + } -ClientOnly) + } -ClientOnly); SystemCredentialPreferences = (New-CimInstance -ClassName MSFT_MicrosoftGraphsystemCredentialPreferences -Property @{ State = "default" IncludeTargets = [CimInstance[]]@( @@ -131,6 +139,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ) } -ClientOnly) } -ClientOnly) + ReportSuspiciousActivitySettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphreportSuspiciousActivitySettings -Property @{ + VoiceReportingCode = 0 + State = 'default' + IncludeTarget = (New-CimInstance -ClassName MSFT_AADAuthenticationMethodPolicyIncludeTarget -Property @{ + Id = 'a8ab05ba-6680-4f93-88ae-71099eedfda1' + TargetType = 'group' + } -ClientOnly) + } -ClientOnly); SystemCredentialPreferences = (New-CimInstance -ClassName MSFT_MicrosoftGraphsystemCredentialPreferences -Property @{ State = "default" IncludeTargets = [CimInstance[]]@( @@ -180,6 +196,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ) } } + ReportSuspiciousActivitySettings = @{ + State = 'default' + IncludeTarget = @{ + TargetType = 'group' + Id = "a8ab05ba-6680-4f93-88ae-71099eedfda1" + } + VoiceReportingCode = 0 + } SystemCredentialPreferences = @{ State = "default" IncludeTargets = @( @@ -234,6 +258,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ) } -ClientOnly) } -ClientOnly) + ReportSuspiciousActivitySettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphreportSuspiciousActivitySettings -Property @{ + VoiceReportingCode = 0 + State = 'default' + IncludeTarget = (New-CimInstance -ClassName MSFT_AADAuthenticationMethodPolicyIncludeTarget -Property @{ + Id = 'a8ab05ba-6680-4f93-88ae-71099eedfda1' + TargetType = 'group' + } -ClientOnly) + } -ClientOnly); SystemCredentialPreferences = (New-CimInstance -ClassName MSFT_MicrosoftGraphsystemCredentialPreferences -Property @{ State = "default" IncludeTargets = [CimInstance[]]@( @@ -280,6 +312,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ) } } + ReportSuspiciousActivitySettings = @{ + State = "default" + IncludeTarget = @{ + TargetType = "user" #drift + Id = "a8ab05ba-6680-4f93-88ae-71099eedfda1" + } + VoiceReportingCode = 1 #drift + } SystemCredentialPreferences = @{ State = "default" IncludeTargets = @( @@ -351,6 +391,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ) } } + ReportSuspiciousActivitySettings = @{ + State = "default" + IncludeTarget = @{ + TargetType = "user" #drift + Id = "a8ab05ba-6680-4f93-88ae-71099eedfda1" + } + VoiceReportingCode = 1 #drift + } SystemCredentialPreferences = @{ State = "default" IncludeTargets = @( From e38718e94d801a644fd73d84c69aa24f91c9e8cd Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 13 Sep 2024 10:49:30 +0000 Subject: [PATCH 167/465] Updated Resources and Cmdlet documentation pages --- .../exchange/EXOTenantAllowBlockListItems.md | 184 ++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 docs/docs/resources/exchange/EXOTenantAllowBlockListItems.md diff --git a/docs/docs/resources/exchange/EXOTenantAllowBlockListItems.md b/docs/docs/resources/exchange/EXOTenantAllowBlockListItems.md new file mode 100644 index 0000000000..d7b82a5fcc --- /dev/null +++ b/docs/docs/resources/exchange/EXOTenantAllowBlockListItems.md @@ -0,0 +1,184 @@ +# EXOTenantAllowBlockListItems + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Action** | Key | String | The action (allow/block) to take for this list entry | `Allow`, `Block` | +| **Value** | Key | String | The value that you want to add to the Tenant Allow/Block List based on the ListType parameter value | | +| **ExpirationDate** | Write | DateTime | The expiration date of the entry in Coordinated Universal Time (UTC) | | +| **ListSubType** | Write | String | The subtype for this entry | `AdvancedDelivery`, `Tenant` | +| **ListType** | Key | String | The type of entry to add. | `FileHash`, `Sender`, `Url` | +| **Notes** | Write | String | Additional information about the object | | +| **RemoveAfter** | Write | UInt32 | Number of days after the entry is first used for it to removed | | +| **SubmissionID** | Write | String | Reserved for internal Microsoft use | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | + + +## Description + +Use this resource to manage the Exchange Online Tenant Allow/Block List items. + + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + EXOTenantAllowBlockListItems "Example" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + TenantId = $TenantId; + Action = "Block"; + Ensure = "Present"; + ExpirationDate = "10/11/2024 9:00:00 PM"; + ListSubType = "Tenant"; + ListType = "Sender"; + Notes = "Test block"; + SubmissionID = "Non-Submission"; + Value = "example.com"; + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + EXOTenantAllowBlockListItems "Example" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + TenantId = $TenantId; + Action = "Block"; + Ensure = "Present"; + ExpirationDate = "10/11/2024 9:00:00 PM"; + ListSubType = "Tenant"; + ListType = "Sender"; + Notes = "Test block with updated notes"; + SubmissionID = "Non-Submission"; + Value = "example.com"; + } + } +} +``` + +### Example 3 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + EXOTenantAllowBlockListItems "Example" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + TenantId = $TenantId; + Action = "Block"; + Ensure = "Absent"; + ExpirationDate = "10/11/2024 9:00:00 PM"; + ListSubType = "Tenant"; + ListType = "Sender"; + Notes = "Test block"; + SubmissionID = "Non-Submission"; + Value = "example.com"; + } + } +} +``` + From 1446969d3348ef70084e8f3e6d0fdfdbaa0181e9 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 13 Sep 2024 10:51:43 +0000 Subject: [PATCH 168/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 40944f41cd..5a24406c0f 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -15074,6 +15074,81 @@ } ] }, + { + "ClassName": "MSFT_EXOTenantAllowBlockListItems", + "Parameters": [ + { + "CIMType": "String", + "Name": "Action", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Value", + "Option": "Key" + }, + { + "CIMType": "DateTime", + "Name": "ExpirationDate", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ListSubType", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ListType", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Notes", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "RemoveAfter", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SubmissionID", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOTransportConfig", "Parameters": [ From 30a5bd09249377877bd68dc6843932a14b2e251c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 13 Sep 2024 10:52:46 +0000 Subject: [PATCH 169/465] Updated {Create} EXO Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index ff34e096e8..02a55ca59e 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -940,7 +940,7 @@ SourceFolder = "Test2:\Inbox"; TenantId = $TenantId; } - EXOTenantAllowBlockListItems "TenantAllowBlowListItem" + EXOTenantAllowBlockListItems 'Example' { ApplicationId = $ApplicationId; CertificateThumbprint = $CertificateThumbprint; From 2b57741ecfbdb738a8ae2308d3709d0ddef4fec7 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 13 Sep 2024 10:53:14 +0000 Subject: [PATCH 170/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index 6ef76d1f08..b1c89d5d9f 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -1345,6 +1345,20 @@ SourceFolder = "Test2:\Inbox"; TenantId = $TenantId; } + EXOTenantAllowBlockListItems 'Example' + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + TenantId = $TenantId; + Action = "Block"; + Ensure = "Present"; + ExpirationDate = "10/11/2024 9:00:00 PM"; + ListSubType = "Tenant"; + ListType = "Sender"; + Notes = "Test block with updated notes"; + SubmissionID = "Non-Submission"; + Value = "example.com"; + } EXOTransportConfig 'EXOTransportConfig ' { IsSingleInstance = "Yes"; @@ -1373,20 +1387,6 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } - EXOTenantAllowBlockListItems "TenantAllowBlowListItem" - { - ApplicationId = $ApplicationId; - CertificateThumbprint = $CertificateThumbprint; - TenantId = $TenantId; - Action = "Block"; - Ensure = "Present"; - ExpirationDate = "10/11/2024 9:00:00 PM"; - ListSubType = "Tenant"; - ListType = "Sender"; - Notes = "Test block - Updated"; # Updated Property - SubmissionID = "Non-Submission"; - Value = "example.com"; - } EXOTransportRule 'ConfigureTransportRule' { Name = "Ethical Wall - Sales and Executives Departments" From fd624db0a3c5c4569c3a7113fc3dba377f5f43ba Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 13 Sep 2024 10:53:34 +0000 Subject: [PATCH 171/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Remove.Tests.ps1 | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 index 4f14860330..9561195d84 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 @@ -455,7 +455,7 @@ } EXORecipientPermission 'AddSendAs' { - + Identity = 'AdeleV@$Domain' Trustee = "admin@$TenantId" Ensure = 'Absent' @@ -580,20 +580,6 @@ Name = "From Michelle"; TenantId = $TenantId; } - EXOTenantAllowBlockListItems "TenantAllowBlowListItem" - { - ApplicationId = $ApplicationId; - CertificateThumbprint = $CertificateThumbprint; - TenantId = $TenantId; - Action = "Block"; - Ensure = "Absent"; - ExpirationDate = "10/11/2024 9:00:00 PM"; - ListSubType = "Tenant"; - ListType = "Sender"; - Notes = "Test block"; - SubmissionID = "Non-Submission"; - Value = "example.com"; - } EXOTransportRule 'ConfigureTransportRule' { Name = "Ethical Wall - Sales and Brokerage Departments" From e349a987844bb96a8c2fbf19892414fe9ce2c57f Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Fri, 13 Sep 2024 16:45:32 +0530 Subject: [PATCH 172/465] adding implementation --- .../MSFT_EXOMailboxFolderPermission.psm1 | 324 +++++++++++------- ...MSFT_EXOMailboxFolderPermission.schema.mof | 16 +- 2 files changed, 209 insertions(+), 131 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 index 52c04f2ae6..3575ea8ce3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 @@ -8,18 +8,9 @@ function Get-TargetResource [System.String] $Identity, - [Parameter(Mandatory = $true)] - [System.String[]] - $AccessRights, - - [Parameter(Mandatory = $true)] - [System.String] - [ValidateSet("None", "Delegate", "CanViewPrivateItems")] - $SharingPermissionFlags, - - [Parameter(Mandatory = $true)] - [System.String] - $User, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $UserPermissions, [Parameter()] [ValidateSet('Present', 'Absent')] @@ -42,6 +33,14 @@ function Get-TargetResource [System.String] $CertificateThumbprint, + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + [Parameter()] [Switch] $ManagedIdentity, @@ -73,29 +72,39 @@ function Get-TargetResource { if ($null -ne $Script:exportedInstances -and $Script:ExportMode) { - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Identity -eq $Identity -and $_.User -eq $User} + $instances = $Script:exportedInstances | Where-Object -FilterScript {$_.Identity -eq $Identity} } else { - $instance = Get-MailboxFolderPermission -Identity $Identity -User $User -ErrorAction Stop + $instances = Get-MailboxFolderPermission -Identity $Identity -ErrorAction Stop } - if ($null -eq $instance) + if ($null -eq $instances) { return $nullResult } + [Array]$permissionsObj = @() + + foreach($mailboxfolderPermission in $instances){ + $currentPermission = @{} + $currentPermission.Add('User', $mailboxFolderPermission.User) + $currentPermission.Add('AccessRights', $mailboxFolderPermission.AccessRights) + if($null -ne $mailboxFolderPermission.SharingPermissionFlags) { + $currentPermission.Add('SharingPermissionFlags', $mailboxFolderPermission.SharingPermissionFlags) + } + $permissionsObj += $currentPermission + } + $results = @{ - Identity = $Identity - User = $User - AccessRights = $instance.AccessRights - SharingPermissionFlags = $instance.SharingPermissionFlags - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens + Identity = $Identity + UserPermissions = [Array]$permissionsObj + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens } return [System.Collections.Hashtable] $results } @@ -120,18 +129,9 @@ function Set-TargetResource [System.String] $Identity, - [Parameter(Mandatory = $true)] - [System.String[]] - $AccessRights, - - [Parameter(Mandatory = $true)] - [System.String] - [ValidateSet("None", "Delegate", "CanViewPrivateItems")] - $SharingPermissionFlags, - - [Parameter(Mandatory = $true)] - [System.String] - $User, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $UserPermissions, [Parameter()] [ValidateSet('Present', 'Absent')] @@ -154,6 +154,14 @@ function Set-TargetResource [System.String] $CertificateThumbprint, + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + [Parameter()] [Switch] $ManagedIdentity, @@ -176,26 +184,55 @@ function Set-TargetResource #endregion $currentInstance = Get-TargetResource @PSBoundParameters + $currentMailboxFolderPermissions = $currentInstance.UserPermissions $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters - # CREATE - if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') - { - Add-MailboxFolderPermission @SetParameters - } - # UPDATE - elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') - { - Set-MailboxFolderPermission @SetParameters + # Remove all the current existing pemrissions on this folder. + # Skip removing the default and anonymous permissions, as can't be removed, and should just be directly updated. + foreach($currentUserPermission in $currentMailboxFolderPermissions) { + if($currentUserPermission.User.ToString().ToLower() -ne "default" -and $currentUserPermission.User.ToString().ToLower() -ne "anonymous"){ + Remove-MailboxFolderPermission -Identity $Identity -User $currentUserPermission.User -Confirm:$false + } } - # REMOVE - elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') - { - $instanceParams.Remove('AccessTokens') | Out-Null - $instanceParams.Remove('SharingPermissionFlags') | Out-Null - Remove-MailboxFolderPermission @SetParameters -Confirm:$false + + # + foreach($userPermission in $UserPermissions) { + if($userPermission.User.ToString().ToLower() -eq "default" -or $userPermission.User.ToString().ToLower() -eq "anonymous"){ + if ($userPermission.SharingPermissionFlags -eq ""){ + Set-MailboxFolderPermission -Identity $Identity -User $userPermission.User -AccessRights $userPermission.AccessRights + } + else { + Set-MailboxFolderPermission -Identity $Identity -User $userPermission.User -AccessRights $userPermission.AccessRights -SharingPermissionFlags $userPermission.SharingPermissionFlags + } + } + else { + if ($userPermission.SharingPermissionFlags -eq ""){ + Add-MailboxFolderPermission -Identity $Identity -User $userPermission.User -AccessRights $userPermission.AccessRights + } + else { + Add-MailboxFolderPermission -Identity $Identity -User $userPermission.User -AccessRights $userPermission.AccessRights -SharingPermissionFlags $userPermission.SharingPermissionFlags + } + } } + + # # CREATE + # if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + # { + # Add-MailboxFolderPermission @SetParameters + # } + # # UPDATE + # elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + # { + # Set-MailboxFolderPermission @SetParameters + # } + # # REMOVE + # elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + # { + # $instanceParams.Remove('AccessTokens') | Out-Null + # $instanceParams.Remove('SharingPermissionFlags') | Out-Null + # Remove-MailboxFolderPermission @SetParameters -Confirm:$false + # } } function Test-TargetResource @@ -208,18 +245,9 @@ function Test-TargetResource [System.String] $Identity, - [Parameter(Mandatory = $true)] - [System.String[]] - $AccessRights, - - [Parameter(Mandatory = $true)] - [System.String] - [ValidateSet("None", "Delegate", "CanViewPrivateItems")] - $SharingPermissionFlags, - - [Parameter(Mandatory = $true)] - [System.String] - $User, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $UserPermissions, [Parameter()] [ValidateSet('Present', 'Absent')] @@ -242,6 +270,14 @@ function Test-TargetResource [System.String] $CertificateThumbprint, + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + [Parameter()] [Switch] $ManagedIdentity, @@ -266,6 +302,23 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + # foreach($value in $ValuesToCheck.UserPermissions) { + # Write-Host $value + # Write-Host $value.SharingPermissionFlags.IsNullOrEmpty() + # if($value.SharingPermissionFlags.IsNullOrEmpty()) { + # $value.SharingPermissionFlags = $null + # } + # } + # Write-Host "DONE HERE ###################################################################" + + # foreach($value in $ValuesToCheck.UserPermissions) { + # Write-Host $value.SharingPermissionFlags + # Write-Host $value.SharingPermissionFlags.IsNullOrEmpty() + # if($value.SharingPermissionFlags.IsNullOrEmpty()) { + # $value.SharingPermissionFlags = $null + # } + # } + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" @@ -298,12 +351,16 @@ function Export-TargetResource $TenantId, [Parameter()] - [System.Management.Automation.PSCredential] - $ApplicationSecret, + [System.String] + $CertificateThumbprint, [Parameter()] [System.String] - $CertificateThumbprint, + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, [Parameter()] [Switch] @@ -314,7 +371,6 @@ function Export-TargetResource $AccessTokens ) - ##TODO - Replace workload $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` -InboundParameters $PSBoundParameters @@ -332,7 +388,12 @@ function Export-TargetResource try { - [array]$mailboxes = Get-Mailbox -ResultSize 'Unlimited' -ErrorAction Stop + Write-Host "`r`n" -NoNewline + Write-Host " |---Getting the mailbox folders on behalf of the current admin" -NoNewline + + [Array]$mailboxFolders = Get-MailboxFolder -Recurse + + Write-Host "`r`n" -NoNewline if ($mailboxes.Length -eq 0) { @@ -342,67 +403,51 @@ function Export-TargetResource { Write-Host "`r`n" -NoNewline } - $dscContent = '' - $i = 1 - foreach ($mailbox in $mailboxes) + + $j = 1 + foreach ($mailboxFolder in $mailboxFolders) { - Write-Host " |---[$i/$($mailboxes.Count)] $($mailbox.UserPrincipalName)" -NoNewline + Write-Host " |---[$j/$($mailboxFolders.count)] $($mailboxFolder.Identity)" -NoNewline + Write-Host "`r`n" -NoNewline - [Array]$mailboxFolders = Get-MailboxFolder -Identity $mailbox.UserPrincipalName -Recurse + $Params = @{ + Identity = $mailboxFolder.Identity + UserPermissions = $null + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Managedidentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } - $j = 1 - Write-Host "`r`n" -NoNewline - foreach ($mailboxFolder in $mailboxFolders) + $MailboxFolderPermissions = Get-TargetResource @Params + + $Result = $MailboxFolderPermissions + $Result = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Result + if ($Result.UserPermissions.Count -gt 0) + { + $Result.UserPermissions = Get-M365DSCEXOUserPermissionsList $Result.UserPermissions + } + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Result ` + -Credential $Credential + + if ($null -ne $Result.UserPermissions) { - [Array]$mailboxFolderPermissions = Get-MailboxFolderPermission -Identity $mailboxFolder.Identity - - Write-Host " |---[$j/$($mailboxFolders.count)] $($mailboxFolder.Identity)" -NoNewline - Write-Host "`r`n" -NoNewline - - foreach ($permission in $mailboxFolderPermissions) - { - if ($null -ne $Global:M365DSCExportResourceInstancesCount) - { - $Global:M365DSCExportResourceInstancesCount++ - } - - Write-Host " |---[$j/$($mailboxFolderPermissions.Count)] $($permission.User)" -NoNewline - Write-Host "`r`n" -NoNewline - - $dscIRMAccess = @{ - Identity = $permission.Identity - User = $permission.User - AccessRights = $permission.AccessRights - SharingPermissionFlags = $permission.SharingPermissionFlags - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - CertificatePassword = $CertificatePassword - Managedidentity = $ManagedIdentity.IsPresent - CertificatePath = $CertificatePath - AccessTokens = $AccessTokens - } - - $Result = $dscIRMAccess - $Result = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` - -Results $Result - $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` - -ConnectionMode $ConnectionMode ` - -ModulePath $PSScriptRoot ` - -Results $Result ` - -Credential $Credential - $dscContent += $currentDSCBlock - - Save-M365DSCPartialExport -Content $currentDSCBlock ` - -FileName $Global:PartialExportFileName - - } - $j++ + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock ` + -ParameterName 'UserPermissions' } - $i++ + $dscContent += $currentDSCBlock + + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + + $j++ } return $dscContent } @@ -420,4 +465,31 @@ function Export-TargetResource } } -Export-ModuleMember -Function *-TargetResource +function Get-M365DSCEXOUserPermissionsList +{ + [CmdletBinding()] + [OutputType([System.String])] + param( + [Parameter(Mandatory = $true)] + [System.Collections.ArrayList] + $Permissions + ) + + $StringContent = '@(' + foreach ($permission in $Permissions) + { + $StringContent += "MSFT_EXOMailboxFolderUserPermission {`r`n" + $StringContent += " User = '" + $permission.User + "'`r`n" + $StringContent += " AccessRights = '" + $permission.AccessRights + "'`r`n" + if($null -ne $permission.SharingPermissionFlags){ + # $StringContent += " SharingPermissionFlags = `$null" + "`r`n" + # } else { + $StringContent += " SharingPermissionFlags = '" + $permission.SharingPermissionFlags + "'`r`n" + } + $StringContent += " }`r`n" + } + $StringContent += ' )' + return $StringContent +} + +Export-ModuleMember -Function * diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.schema.mof index 5a396e560c..6867096ccc 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.schema.mof @@ -1,10 +1,16 @@ -[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] -class MSFT_ResourceName : OMI_BaseResource +[ClassVersion("1.0.0")] +class MSFT_EXOMailboxFolderUserPermission { - [Key, Description("The Identity parameter specifies the target mailbox and folder. The syntax is MailboxID:\ParentFolder[\SubFolder]. For the MailboxID you can use any value that uniquely identifies the mailbox.")] String Identity; [Required, Description("The AccessRights parameter specifies the permissions that you want to add for the user on the mailbox folder.")] String AccessRights[]; - [Key, Description("The User parameter specifies who gets the permissions on the mailbox folder.")] String User; - [Key, Description("The SharingPermissionFlags parameter assigns calendar delegate permissions. This parameter only applies to calendar folders and can only be used when the AccessRights parameter value is Editor. Valid values are: None, Delegate, CanViewPrivateItems"), ValueMap{"None", "Delegate", "CanViewPrivateItems"}, Values{"None", "Delegate", "CanViewPrivateItems"}] String SharingPermissionFlags; + [Required, Description("The User parameter specifies who gets the permissions on the mailbox folder.")] String User; + [Write, Description("The SharingPermissionFlags parameter assigns calendar delegate permissions. This parameter only applies to calendar folders and can only be used when the AccessRights parameter value is Editor. Valid values are: None, Delegate, CanViewPrivateItems")] String SharingPermissionFlags; +}; + +[ClassVersion("1.0.0.0"), FriendlyName("EXOMailboxFolderPermission")] +class MSFT_EXOMailboxFolderPermission : OMI_BaseResource +{ + [Key, Description("The Identity parameter specifies the target mailbox and folder. The syntax is MailboxID:\\ParentFolder[\\SubFolder]. For the MailboxID you can use any value that uniquely identifies the mailbox.")] String Identity; + [Write, Description("Mailbox Folder Permissions for the current user."),EmbeddedInstance("MSFT_EXOMailboxFolderUserPermission")] String UserPermissions[]; [Write, Description("Determines wheter or not the permission should exist on the mailbox."), ValueMap{"Present"}, Values{"Present"}] String Ensure; [Write, Description("Credentials of the Exchange Global Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; From 0e6939864a800728a48efdd6c9ce7a108494fc48 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Fri, 13 Sep 2024 17:22:34 +0530 Subject: [PATCH 173/465] Added Examples --- .../MSFT_AADAuthenticationMethodPolicy.schema.mof | 8 ++++---- .../Resources/AADAuthenticationMethodPolicy/2-Update.ps1 | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.schema.mof index f7eaa81c67..40541252d5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.schema.mof @@ -46,9 +46,9 @@ class MSFT_MicrosoftGraphSystemCredentialPreferences [ClassVersion("1.0.0")] class MSFT_MicrosoftGraphReportSuspiciousActivitySettings { - [Write, Description(""), EmbeddedInstance("MSFT_AADAuthenticationMethodPolicyIncludeTarget")] String IncludeTarget; - [Write, Description(""), ValueMap{"default","enabled","disabled","unknownFutureValue"}, Values{"default","enabled","disabled","unknownFutureValue"}] String State; - [Write, Description("")] UInt32 VoiceReportingCode; + [Write, Description("Group IDs in scope for report suspicious activity."), EmbeddedInstance("MSFT_AADAuthenticationMethodPolicyIncludeTarget")] String IncludeTarget; + [Write, Description("Specifies the state of the reportSuspiciousActivitySettings object."), ValueMap{"default","enabled","disabled","unknownFutureValue"}, Values{"default","enabled","disabled","unknownFutureValue"}] String State; + [Write, Description("Specifies the number the user enters on their phone to report the MFA prompt as suspicious.")] UInt32 VoiceReportingCode; }; [ClassVersion("1.0.0.0"), FriendlyName("AADAuthenticationMethodPolicy")] @@ -60,7 +60,7 @@ class MSFT_AADAuthenticationMethodPolicy : OMI_BaseResource [Write, Description("The version of the policy in use.")] String PolicyVersion; [Write, Description("Days before the user will be asked to reconfirm their method.")] UInt32 ReconfirmationInDays; [Write, Description("Enforce registration at sign-in time. This property can be used to remind users to set up targeted authentication methods."), EmbeddedInstance("MSFT_MicrosoftGraphregistrationEnforcement")] String RegistrationEnforcement; - [Write, Description(""), EmbeddedInstance("MSFT_MicrosoftGraphreportSuspiciousActivitySettings")] String ReportSuspiciousActivitySettings; + [Write, Description("Allows users to report suspicious activities if they receive an authentication request that they did not initiate."), EmbeddedInstance("MSFT_MicrosoftGraphreportSuspiciousActivitySettings")] String ReportSuspiciousActivitySettings; [Write, Description("Prompt users with their most-preferred credential for multifactor authentication."), EmbeddedInstance("MSFT_MicrosoftGraphsystemCredentialPreferences")] String SystemCredentialPreferences; [Write, Description("The unique identifier for an entity. Read-only.")] String Id; [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationMethodPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationMethodPolicy/2-Update.ps1 index 533b73f0bb..38cc0fb25f 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationMethodPolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationMethodPolicy/2-Update.ps1 @@ -42,6 +42,14 @@ Configuration Example State = 'default' } }; + ReportSuspiciousActivitySettings = MSFT_MicrosoftGraphreportSuspiciousActivitySettings{ + VoiceReportingCode = 0 + IncludeTarget = MSFT_AADAuthenticationMethodPolicyIncludeTarget{ + Id = 'all_users' + TargetType = 'group' + } + State = 'default' + }; ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint From 4cb719da16aa1263edbce95d7b186f86e3cd7fa0 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Fri, 13 Sep 2024 17:23:40 +0530 Subject: [PATCH 174/465] Updated Change Log --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cbff6c93a..5824c2f510 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* AADAuthenticationMethodPolicy + * Added ReportSuspiciousActivitySettings * AADPasswordRuleSettings * Initial release * AzureSubscription From 41a9b61b0c90481af94dfed0cd90f51c1ab242f6 Mon Sep 17 00:00:00 2001 From: Sai Sistla Date: Fri, 13 Sep 2024 17:23:56 +0530 Subject: [PATCH 175/465] Addressed comments --- CHANGELOG.md | 2 + .../MSFT_EXOEmailTenantSettings.psm1 | 414 ++++++++++++++++++ .../MSFT_EXOEmailTenantSettings.schema.mof | 18 + .../MSFT_EXOEmailTenantSettings/readme.md | 5 + .../MSFT_EXOEmailTenantSettings/settings.json | 34 ++ .../EXOEmailTenantSettings/2-Update.ps1 | 38 ++ ...oft365DSC.EXOEmailTenantSettings.Tests.ps1 | 134 ++++++ 7 files changed, 645 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOEmailTenantSettings.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index f5f8336f10..bd3f851627 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ * Initial Release. * EXOArcConfig * Initial Release. +* EXOEmailTenantSettings + * Initial Release. * EXOFocusedInbox * Initial Release. * EXOMailboxCalendarConfiguration diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 new file mode 100644 index 0000000000..3173f29bae --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 @@ -0,0 +1,414 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + [ValidateSet('Yes')] + $IsSingleInstance, + + [Parameter()] + [System.Boolean] + $EnablePriorityAccountProtection, + + [Parameter()] + [System.Boolean] + $IsValid, + + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $ObjectState, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + Write-Verbose -Message 'Getting EXO Email Tenant Settings' + + if ($Global:CurrentModeIsExport) + { + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters ` + -SkipModuleReload $true + } + else + { + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + + $nullReturn = $PSBoundParameters + + try + { + $EmailTenantSettings = Get-EmailTenantSettings -ErrorAction Stop + + $result = @{ + IsSingleInstance = 'Yes' + Identity = $EmailTenantSettings.Identity + EnablePriorityAccountProtection = $EmailTenantSettings.EnablePriorityAccountProtection + Name = $EmailTenantSettings.Name + IsValid = $EmailTenantSettings.IsValid + ObjectState = $EmailTenantSettings.ObjectState + Credential = $Credential + ApplicationId = $ApplicationId + CertificateThumbprint = $CertificateThumbprint + CertificatePath = $CertificatePath + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + TenantId = $TenantId + AccessTokens = $AccessTokens + } + + Write-Verbose -Message 'Found Email Tenant Settings config ' + Write-Verbose -Message "Get-TargetResource Result: `n $(Convert-M365DscHashtableToString -Hashtable $result)" + return $result + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullReturn + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + [ValidateSet('Yes')] + $IsSingleInstance, + + [Parameter()] + [System.Boolean] + $EnablePriorityAccountProtection, + + [Parameter()] + [System.Boolean] + $IsValid, + + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $ObjectState, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + #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 'Setting configuration of Email tenant setings' + + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + #removing params that cannot be set. + $EmailTenantSettingsParams.Remove('Name') | Out-Null + $EmailTenantSettingsParams.Remove('IsValid') | Out-Null + $EmailTenantSettingsParams.Remove('ObjectState') | Out-Null +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + [ValidateSet('Yes')] + $IsSingleInstance, + + [Parameter()] + [System.Boolean] + $EnablePriorityAccountProtection, + + [Parameter()] + [System.Boolean] + $IsValid, + + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $ObjectState, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + #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 Email tenant settings' + + $CurrentValues = Get-TargetResource @PSBoundParameters + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + $ValuesToCheck = $PSBoundParameters + + $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.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' -InboundParameters $PSBoundParameters -SkipModuleReload $true + + #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 + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $EmailTenantSettings = Get-EmailTenantSettings -ErrorAction Stop + $dscContent = '' + Write-Host "`r`n" -NoNewline + + Write-Host " |---[1/1] $($EmailTenantSettings.Identity)" -NoNewline + + $Params = @{ + IsSingleInstance = 'Yes' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + CertificatePath = $CertificatePath + AccessTokens = $AccessTokens + } + + $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 + 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_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.schema.mof new file mode 100644 index 0000000000..3f6bdbbd6e --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.schema.mof @@ -0,0 +1,18 @@ +[ClassVersion("1.0.0.0"), FriendlyName("EXOEmailTenantSettings")] +class MSFT_EXOEmailTenantSettings : OMI_BaseResource +{ + [Key, Description("Only valid value is 'Yes'."), ValueMap{"Yes"}, Values{"Yes"}] String IsSingleInstance; + [Write, Description("Identity which indicates the organization name.")] String Identity; + [Write, Description("Specifies whether priority account protection is enabled.")] Boolean EnablePriorityAccountProtection; + [Write, Description("Specifies whether the migration configuration is valid.")] Boolean IsValid; + [Write, Description("Specifies the state of the object.")] String ObjectState; + [Write, Description("Specifies the name of the object.")] String Name; + [Write, Description("Credentials of the Exchange Global 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("Path to certificate used in service principal usually a PFX file.")] String CertificatePath; + [Write, Description("Username can be made up to anything but password will be used for CertificatePassword"), EmbeddedInstance("MSFT_Credential")] String CertificatePassword; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/readme.md new file mode 100644 index 0000000000..b07d58c77b --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/readme.md @@ -0,0 +1,5 @@ +EXOEmailTenantSettings + +## Description + +This resource allows users to manage email tenant settings. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/settings.json new file mode 100644 index 0000000000..a3fb9d4fcf --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/settings.json @@ -0,0 +1,34 @@ +{ + "resourceName": "EXOEmailTenantSettings", + "description": "", + "roles": { + "read": [ + "Global Reader" + ], + "update": [ + "Exchange Administrator" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + }, + "exchange": { + "requiredroles": [ + "Organization Management", + "Security Reader" + ], + "requiredrolegroups": [ + "Organization Management", + "Security Administrator" + ] + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 new file mode 100644 index 0000000000..59e7cd4060 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 @@ -0,0 +1,38 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOEmailTenantSettings "EXOEmailTenantSettings-Test" + { + IsSingleInstance = "Yes" + EnablePriorityAccountProtection = $True; + Identity = $TenantId; + IsValid = $True; + ObjectState = "Unchanged" + Ensure = "Present"; + Name = "Default" + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationId = $ApplicationId + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOEmailTenantSettings.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOEmailTenantSettings.Tests.ps1 new file mode 100644 index 0000000000..7d00da460f --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOEmailTenantSettings.Tests.ps1 @@ -0,0 +1,134 @@ +[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 'EXOEmailTenantSettings' -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 New-M365DSCConnection -MockWith { + return 'Credentials' + } + + Mock -CommandName Get-PSSession -MockWith { + } + + Mock -CommandName Remove-PSSession -MockWith { + } + + Mock -CommandName Set-EmailTenantSettings -MockWith { + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + + # Test contexts + Context -Name 'Configuration needs updating' -Fixture { + BeforeAll { + $testParams = @{ + IsSingleInstance = 'Yes' + EnablePriorityAccountProtection = $True; + Identity = "sotmcpoc.onmicrosoft.com\Default"; + IsValid = $True; + ObjectState = "New" + Credential = $Credential + Name = "Default" + Ensure = "Present" + } + + Mock -CommandName Get-EmailTenantSettings -MockWith { + return @{ + EnablePriorityAccountProtection = $False; + IsValid = $True; + ObjectState = "New" + } + } + } + + 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-EmailTenantSettings -Exactly 1 + } + } + + Context -Name 'Update not required.' -Fixture { + BeforeAll { + $testParams = @{ + IsSingleInstance = 'Yes' + EnablePriorityAccountProtection = $True; + Identity = "sotmcpoc.onmicrosoft.com\Default"; + IsValid = $True; + ObjectState = "New" + Credential = $Credential + Name = "Default" + Ensure = "Present" + } + + Mock -CommandName Get-MigrationConfig -MockWith { + return @{ + EnablePriorityAccountProtection = $False; + IsValid = $True; + ObjectState = "New" + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-EmailTenantSettings -MockWith { + return @{ + EnablePriorityAccountProtection = $False; + IsValid = $True; + ObjectState = "New" + } + } + } + + 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 8f98d582430f61857f2a8c1a439e2933cc509dc2 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Sat, 14 Sep 2024 18:07:29 +0530 Subject: [PATCH 176/465] made changes to EXOManagementScope UT, to remove TODO prompts --- .../Microsoft365DSC.EXOManagementScope.Tests.ps1 | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOManagementScope.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOManagementScope.Tests.ps1 index dde34a4529..1ebcd0c4ad 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOManagementScope.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOManagementScope.Tests.ps1 @@ -35,7 +35,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets Mock -CommandName New-ManagementScope -MockWith { } @@ -66,7 +65,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { RecipientRestrictionFilter = "Name -like 'Nik*'"; } - ##TODO - Mock the Get-Cmdlet to return $null Mock -CommandName Get-ManagementScope -MockWith { return $null } @@ -95,7 +93,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { RecipientRestrictionFilter = "Name -like 'Nik*'"; } - ##TODO - Mock the Get-Cmdlet to return an instance Mock -CommandName Get-ManagementScope -MockWith { return @{ Exclusive = $False; @@ -129,7 +126,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { RecipientRestrictionFilter = "Name -like 'Nik*'"; } - ##TODO - Mock the Get-Cmdlet to return the desired values Mock -CommandName Get-ManagementScope -MockWith { return @{ Exclusive = $False; @@ -141,7 +137,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should return true from the Test method' { - Test-TargetResource -Verbose @testParams | Should -Be $true + Test-TargetResource @testParams | Should -Be $true } } @@ -156,7 +152,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { RecipientRestrictionFilter = "Name -like 'Nik*'"; } - ##TODO - Mock the Get-Cmdlet to return a drift Mock -CommandName Get-ManagementScope -MockWith { return @{ Exclusive = $False; @@ -189,7 +184,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance Mock -CommandName Get-ManagementScope -MockWith { return @{ Exclusive = $False; From 5b80a4593f2e72343b98428aa64a85a5e4fd4bda Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sat, 14 Sep 2024 12:56:52 +0000 Subject: [PATCH 177/465] Updated Resources and Cmdlet documentation pages --- .../resources/exchange/EXOMailboxIRMAccess.md | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 docs/docs/resources/exchange/EXOMailboxIRMAccess.md diff --git a/docs/docs/resources/exchange/EXOMailboxIRMAccess.md b/docs/docs/resources/exchange/EXOMailboxIRMAccess.md new file mode 100644 index 0000000000..d349b97793 --- /dev/null +++ b/docs/docs/resources/exchange/EXOMailboxIRMAccess.md @@ -0,0 +1,103 @@ +# EXOMailboxIRMAccess + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Identity** | Key | String | The Identity parameter specifies the mailbox that you want to modify | | +| **User** | Key | String | The User parameter specifies the delegate who is blocked from reading IRM-protected messages in the mailbox. | | +| **AccessLevel** | Write | String | The AccessLevel parameter specifies what delegates can do to IRM-protected messages in the mailbox that's specified by the Identity parameter. | `Block` | +| **Ensure** | Write | String | Present ensures the resource exists, absent ensures it is removed | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Use this resource to set MailboxIRMAccess settings + +## Permissions + +### Exchange + +To authenticate with Microsoft Exchange, this resource required the following permissions: + +#### Roles + +- Hygiene Management, Compliance Management, Organization Management, View-Only Organization Management + +#### Role Groups + +- Organization Management + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOMailboxIRMAccess "EXOMailboxIRMAccess-qwe@testorg.onmicrosoft.com" + { + AccessLevel = "Block"; + Credential = $Credscredential; + Ensure = "Present"; + Identity = "qwe@$OrganizationName"; + User = "admin@$OrganizationName"; + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} +``` + From d04dc6895459dcd496cbb10d92f0aca594c0df68 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sat, 14 Sep 2024 12:58:29 +0000 Subject: [PATCH 178/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 5a24406c0f..591e58e1c8 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -9924,6 +9924,61 @@ } ] }, + { + "ClassName": "MSFT_EXOMailboxIRMAccess", + "Parameters": [ + { + "CIMType": "String", + "Name": "Identity", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "User", + "Option": "Key" + }, + { + "CIMType": "string", + "Name": "AccessLevel", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOMailboxPermission", "Parameters": [ From e2d05efd84d43bbe9b392905dd2ab3fc61494fc1 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sat, 14 Sep 2024 12:58:55 +0000 Subject: [PATCH 179/465] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index 02a55ca59e..d96a63f694 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -385,6 +385,14 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOMailboxIRMAccess 'EXOMailboxIRMAccess-qwe@testorg.onmicrosoft.com' + { + AccessLevel = "Block"; + Credential = $Credscredential; + Ensure = "Present"; + Identity = "qwe@$OrganizationName"; + User = "admin@$OrganizationName"; + } EXOMailContact 'TestMailContact' { Alias = 'TestMailContact' From 65108316836d007d8a45de155ee9783c98c8c2ca Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 16 Sep 2024 07:34:06 -0400 Subject: [PATCH 180/465] Revert "O365OrgSettings - Added Support for CustomerLockboxEnabled" --- CHANGELOG.md | 2 - .../MSFT_O365OrgSettings.psm1 | 88 ++++++++++++++----- .../MSFT_O365OrgSettings.schema.mof | 1 - .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 1 + 4 files changed, 66 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dbda4f640..9cb19259c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,8 +32,6 @@ * IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10 * Add missing `AccessTokens` parameter to `Export-TargetResource` FIXES [#5034](https://github.com/microsoft/Microsoft365DSC/issues/5034) -* O365OrgSettings - * Added support for the CustomerLockboxEnabled property. * SCRoleGroup * Fixes an issue with creation without specifying Displayname * Fixes an issue with Drifts because of returned Role format diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.psm1 index 7e5cab828a..2381352852 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.psm1 @@ -17,10 +17,6 @@ function Get-TargetResource [System.Boolean] $AppsAndServicesIsOfficeStoreEnabled, - [Parameter()] - [System.Boolean] - $CustomerLockboxEnabled, - [Parameter()] [System.Boolean] $AppsAndServicesIsAppAndServicesTrialEnabled, @@ -239,6 +235,61 @@ function Get-TargetResource } } + # DEPRECATED - Microsoft Viva Briefing Email + <# + $vivaBriefingEmailValue = $false + try + { + $currentBriefingConfig = Get-DefaultTenantBriefingConfig -ErrorAction Stop -Verbose:$false + if ($currentBriefingConfig.IsEnabledByDefault -eq 'opt-in') + { + $vivaBriefingEmailValue = $true + } + } + catch + { + if ($_.Exception.Message -like "*Unexpected character encountered while parsing value*") + { + $vivaBriefingEmailValue = $true + } + elseif ($_.Exception.Message -like "*A task was canceled*") + { + $retries = 1 + $errorContent = $null + while ($retries -le 5) + { + try + { + Start-Sleep -Seconds 2 + $currentBriefingConfig = Get-DefaultTenantBriefingConfig -ErrorAction Stop -Verbose:$false + } + catch + { + $errorContent = $_ + $retries++ + } + } + if ($null -eq $currentBriefingConfig) + { + throw $errorContent + } + else + { + if ($currentBriefingConfig.IsEnabledByDefault -eq 'opt-in') + { + $vivaBriefingEmailValue = $true + } + } + } + else + { + throw $_ + } + } + $results += @{ + MicrosoftVivaBriefingEmail = $vivaBriefingEmailValue + }#> + # Viva Insights settings $currentVivaInsightsSettings = Get-DefaultTenantMyAnalyticsFeatureConfig -Verbose:$false if ($null -ne $currentVivaInsightsSettings) @@ -254,11 +305,11 @@ function Get-TargetResource $MRODeviceManagerService = 'ebe0c285-db95-403f-a1a3-a793bd6d7767' try { - $servicePrincipal = Get-MgServicePrincipal -Filter "appid eq '$MRODeviceManagerService'" + $servicePrincipal = Get-MgServicePrincipal -Filter "appid eq 'ebe0c285-db95-403f-a1a3-a793bd6d7767'" if ($null -eq $servicePrincipal) { Write-Verbose -Message "Registering the MRO Device Manager Service Principal" - New-MgServicePrincipal -AppId $MRODeviceManagerService -ErrorAction Stop | Out-Null + New-MgServicePrincipal -AppId 'ebe0c285-db95-403f-a1a3-a793bd6d7767' -ErrorAction Stop | Out-Null } } catch @@ -350,9 +401,6 @@ function Get-TargetResource } } - $OrganizationConfig = Get-OrganizationConfig - $results.Add('CustomerLockboxEnabled', $OrganizationConfig.CustomerLockboxEnabled) - return $results } catch @@ -389,10 +437,6 @@ function Set-TargetResource [System.Boolean] $AppsAndServicesIsAppAndServicesTrialEnabled, - [Parameter()] - [System.Boolean] - $CustomerLockboxEnabled, - [Parameter()] [System.Boolean] $DynamicsCustomerVoiceIsRestrictedSurveyAccessEnabled, @@ -582,6 +626,14 @@ function Set-TargetResource { Write-Verbose -Message "DEPRECATED - The MicrosoftVivaBriefingEmail parameter is deprecated and will be ignored." } + #$briefingValue = 'opt-out' + + <# DEPRECATED + if ($currentValues.MicrosoftVivaBriefingEmail -and $MicrosoftVivaBriefingEmail -ne $currentValues.MicrosoftVivaBriefingEmail) + { + Write-Verbose -Message "Updating Microsoft Viva Briefing Email settings." + Set-DefaultTenantBriefingConfig -IsEnabledByDefault $briefingValue -Verbose:$false | Out-Null + }#> # Viva Insights if ($PSBoundParameters.ContainsKey('VivaInsightsWebExperience') -and ` @@ -792,12 +844,6 @@ function Set-TargetResource Write-Verbose -Message "Updating the To Do settings with values:$(Convert-M365DscHashtableToString -Hashtable $ToDoParametersToUpdate)" Update-M365DSCOrgSettingsToDo -Options $ToDoParametersToUpdate } - - # Customer Lockbox - if ($PSBoundParameters.ContainsKey('CustomerLockboxEnabled')) - { - Set-OrganizationConfig -CustomerLockboxEnabled $CustomerLockboxEnabled | Out-Null - } } function Test-TargetResource @@ -823,10 +869,6 @@ function Test-TargetResource [System.Boolean] $AppsAndServicesIsAppAndServicesTrialEnabled, - [Parameter()] - [System.Boolean] - $CustomerLockboxEnabled, - [Parameter()] [System.Boolean] $DynamicsCustomerVoiceIsRestrictedSurveyAccessEnabled, diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.schema.mof index 9d5fcb118b..2eb2767c73 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_O365OrgSettings/MSFT_O365OrgSettings.schema.mof @@ -26,7 +26,6 @@ class MSFT_O365OrgSettings : OMI_BaseResource [Write, Description("To Do - Allow sharing with external users.")] Boolean ToDoIsExternalShareEnabled; [Write, Description("To Do - Allow your users to receive push notifications.")] Boolean ToDoIsPushNotificationEnabled; [Write, Description("Controls whether or not the Admin Center reports will conceale user, group and site names.")] Boolean AdminCenterReportDisplayConcealedNames; - [Write, Description("Determines if the customer lockbox should require approval for all data access requests or not.")] Boolean CustomerLockboxEnabled; [Write, Description("Defines how often you want your users to get feature updates for Microsoft 365 apps installed on devices running Windows"), ValueMap{"current","monthlyEnterprise","semiAnnual"}, Values{"current","monthlyEnterprise","semiAnnual"}] String InstallationOptionsUpdateChannel; [Write, Description("Defines the apps users can install on Windows and mobile devices."), ValueMap{"isVisioEnabled","isSkypeForBusinessEnabled","isProjectEnabled","isMicrosoft365AppsEnabled"}, Values{"isVisioEnabled","isSkypeForBusinessEnabled","isProjectEnabled","isMicrosoft365AppsEnabled"}] String InstallationOptionsAppsForWindows[]; [Write, Description("Defines the apps users can install on Mac devices."), ValueMap{"isSkypeForBusinessEnabled","isMicrosoft365AppsEnabled"}, Values{"isSkypeForBusinessEnabled","isMicrosoft365AppsEnabled"}] String InstallationOptionsAppsForMac[]; diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 614ea78655..9397159c76 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1771,6 +1771,7 @@ function New-M365DSCConnection [System.Boolean] $SkipModuleReload = $false ) + $verbosepreference = 'Continue' $Global:MaximumFunctionCount = 32767 if ($Workload -eq 'MicrosoftTeams') { From 26e7e669f0b85226673f1edac937cce8919ab86d Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 16 Sep 2024 11:36:33 +0000 Subject: [PATCH 181/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 591e58e1c8..7add973497 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -35882,11 +35882,6 @@ "Name": "AdminCenterReportDisplayConcealedNames", "Option": "Write" }, - { - "CIMType": "Boolean", - "Name": "CustomerLockboxEnabled", - "Option": "Write" - }, { "CIMType": "String", "Name": "InstallationOptionsUpdateChannel", From f9879afc1ac91eb343addfeb2d56876af0cd672e Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 16 Sep 2024 11:47:33 +0000 Subject: [PATCH 182/465] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/office365/O365OrgSettings.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/docs/resources/office365/O365OrgSettings.md b/docs/docs/resources/office365/O365OrgSettings.md index f80359b12b..a7c8b31216 100644 --- a/docs/docs/resources/office365/O365OrgSettings.md +++ b/docs/docs/resources/office365/O365OrgSettings.md @@ -29,7 +29,6 @@ | **ToDoIsExternalShareEnabled** | Write | Boolean | To Do - Allow sharing with external users. | | | **ToDoIsPushNotificationEnabled** | Write | Boolean | To Do - Allow your users to receive push notifications. | | | **AdminCenterReportDisplayConcealedNames** | Write | Boolean | Controls whether or not the Admin Center reports will conceale user, group and site names. | | -| **CustomerLockboxEnabled** | Write | Boolean | Determines if the customer lockbox should require approval for all data access requests or not. | | | **InstallationOptionsUpdateChannel** | Write | String | Defines how often you want your users to get feature updates for Microsoft 365 apps installed on devices running Windows | `current`, `monthlyEnterprise`, `semiAnnual` | | **InstallationOptionsAppsForWindows** | Write | StringArray[] | Defines the apps users can install on Windows and mobile devices. | `isVisioEnabled`, `isSkypeForBusinessEnabled`, `isProjectEnabled`, `isMicrosoft365AppsEnabled` | | **InstallationOptionsAppsForMac** | Write | StringArray[] | Defines the apps users can install on Mac devices. | `isSkypeForBusinessEnabled`, `isMicrosoft365AppsEnabled` | From 1022ef331de649b37c5f1fa1c8064e696af9f22a Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 16 Sep 2024 13:12:14 -0400 Subject: [PATCH 183/465] Updates --- .../MSFT_SCInsiderRiskEntityList.psm1 | 357 ++++++++++++++++-- .../MSFT_SCInsiderRiskEntityList.schema.mof | 9 + .../Dependencies/Manifest.psd1 | 4 +- 3 files changed, 342 insertions(+), 28 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 index fdd2b985bc..a684573e73 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 @@ -20,6 +20,34 @@ function Get-TargetResource [System.String] $DisplayName, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Domains, + + [Parameter()] + [System.String[]] + $FilePaths, + + [Parameter()] + [System.String[]] + $FileTypes, + + [Parameter()] + [System.String[]] + $Keywords, + + [Parameter()] + [System.String[]] + $SensitiveInformationTypes, + + [Parameter()] + [System.String[]] + $Sites, + + [Parameter()] + [System.String[]] + $TrainableClassifiers, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -70,38 +98,231 @@ function Get-TargetResource $nullResult.Ensure = 'Absent' try { - if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + $instance = Get-InsiderRiskEntityList -Identity $Name -ErrorAction Stop + + if ($null -eq $instance) + { + return $nullResult + } + + # CustomDomainLists + $DmnValues = @() + if ($instance.ListType -eq 'CustomDomainLists' -or ` + $instance.Name -eq 'IrmWhitelistDomains') { - if (-not [System.String]::IsNullOrEmpty($DisplayName)) + foreach ($entity in $instance.Entities) { - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.ListType -eq $ListType -and $_.DisplayName -eq $DisplayName} + $entity = ConvertFrom-Json $entity + $current = @{ + Dmn = $entity.Dmn + isMLSubDmn = $entity.isMLSubDmn + } + $DmnValues += $current } - else + } + + # CustomFilePathRegexLists + $FilePathValues = @() + if ($instance.ListType -eq 'CustomFilePathRegexLists' -or ` + $instance.Name -eq 'IrmCustomExWinFilePaths') + { + foreach ($entity in $instance.Entities) { - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.ListType -eq $ListType -and $_.Name -eq $Name} + $entity = ConvertFrom-Json $entity + $FilePathValues += $entity.FlPthRgx } } - else + + # CustomFileTypeLists + $FileTypeValues = @() + if ($instance.ListType -eq 'CustomFileTypeLists') { - $instance = Get-InsiderRiskEntityList -Type $ListType -ErrorAction Stop + foreach ($entity in $instance.Entities) + { + $entity = ConvertFrom-Json $entity + $FileTypeValues += $entity.Ext + } } - if ($null -eq $instance) + + # CustomKeywordLists + $KeywordValues = @() + if ($instance.ListType -eq 'CustomKeywordLists' -or ` + $instance.Name -eq 'IrmExcludedKeywords' -or $instance.Name -eq 'IrmNotExcludedKeywords') { - return $nullResult + foreach ($entity in $instance.Entities) + { + $entity = ConvertFrom-Json $entity + $KeywordValues += $entity.Name + } + } + + # CustomSensitiveInformationTypeLists + $SITValues = @() + if ($instance.ListType -eq 'CustomSensitiveInformationTypeLists' -or ` + $instance.Name -eq 'IrmCustomExSensitiveTypes') + { + foreach ($entity in $instance.Entities) + { + $entity = ConvertFrom-Json $entity + $SITObject = Get-DLPSensitiveInformationType -Identity $entity.GUID + $SITValues += $SITObject.Name + } + } + + # CustomSiteLists + $SiteValues = @() + if ($instance.ListType -eq 'CustomSiteLists' -or ` + $instance.Name -eq 'IrmExcludedSites') + { + foreach ($entity in $instance.Entities) + { + $entity = ConvertFrom-Json $entity + $SiteValues += $entity.Url + } + } + + # CustomMLClassifierTypeLists + $TrainableClassifierValues = @() + if ($instance.ListType -eq 'CustomMLClassifierTypeLists' -or $instance.Name -eq 'IrmCustomExMLClassifiers') + { + foreach ($entity in $instance.Entities) + { + $entity = ConvertFrom-Json $entity + $SiteValues += $entity.Url + } + } + + # Global Exclusions - Excluded Keyword Groups + $excludedKeywordGroupValue = @() + if ($instance.Name -eq 'IrmXSGExcludedKeywords') + { + $entities = $instance.Entities + foreach ($entity in $entities) + { + $entity = ConvertFrom-Json $entity + $group = Get-InsiderRiskEntityList -Identity $entity.GroupId + $excludedKeywordGroupValue += $group.DisplayName + } + } + + # Global Exclusions - Exception Keyword Groups + $exceptionKeywordGroupValue = @() + if ($instance.Name -eq 'IrmXSGExceptionKeywords') + { + $entities = $instance.Entities + foreach ($entity in $entities) + { + $entity = ConvertFrom-Json $entity + $group = Get-InsiderRiskEntityList -Identity $entity.GroupId + $exceptionKeywordGroupValue += $group.DisplayName + } + } + + # Global Exclusions - Excluded Classifier Groups + $excludedClassifierGroupValue = @() + if ($instance.Name -eq 'IrmXSGMLClassifierTypes') + { + $entities = $instance.Entities + foreach ($entity in $entities) + { + $entity = ConvertFrom-Json $entity + $group = Get-InsiderRiskEntityList -Identity $entity.GroupId + $excludedClassifierGroupValue += $group.DisplayName + } + } + + # Global Exclusions - Excluded Domain Groups + $excludedDomainGroupValue = @() + if ($instance.Name -eq 'IrmXSGDomains') + { + $entities = $instance.Entities + foreach ($entity in $entities) + { + $entity = ConvertFrom-Json $entity + $group = Get-InsiderRiskEntityList -Identity $entity.GroupId + $excludedDomainGroupValue += $group.DisplayName + } + } + + # Global Exclusions - Excluded File Path Groups + $excludedFilePathGroupValue = @() + if ($instance.Name -eq 'IrmXSGFilePaths') + { + $entities = $instance.Entities + foreach ($entity in $entities) + { + $entity = ConvertFrom-Json $entity + $group = Get-InsiderRiskEntityList -Identity $entity.GroupId + $excludedFilePathGroupValue += $group.DisplayName + } + } + + # Global Exclusions - Excluded Site Groups + $excludedSiteGroupValue = @() + if ($instance.Name -eq 'IrmXSGSites') + { + $entities = $instance.Entities + foreach ($entity in $entities) + { + $entity = ConvertFrom-Json $entity + $group = Get-InsiderRiskEntityList -Identity $entity.GroupId + $excludedSiteGroupValue += $group.DisplayName + } + } + + # Global Exclusions - Excluded Sensitive Info Type Groups + $excludedSITGroupValue = @() + if ($instance.Name -eq 'IrmXSGSensitiveInfoTypes') + { + $entities = $instance.Entities + foreach ($entity in $entities) + { + $entity = ConvertFrom-Json $entity + $group = Get-InsiderRiskEntityList -Identity $entity.GroupId + $excludedSITGroupValue += $group.DisplayName + } + } + + # Global Exclusions - Excluded File Type Groups + $excludedFileTypeGroupValue = @() + if ($instance.Name -eq 'IrmXSGFiletypes') + { + $entities = $instance.Entities + foreach ($entity in $entities) + { + $entity = ConvertFrom-Json $entity + $group = Get-InsiderRiskEntityList -Identity $entity.GroupId + $excludedFileTypeGroupValue += $group.DisplayName + } } $results = @{ - DisplayName = $instance.DisplayName - Name = $instance.Name - Description = $instance.Description - ListType = $instance.ListType - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens + DisplayName = $instance.DisplayName + Name = $instance.Name + Description = $instance.Description + ListType = $instance.ListType + Domains = $DmnValues + FilePaths = $FilePathValues + FileTypes = $FileTypeValues + Keywords = $KeywordValues + SensitiveInformationTypes = $SITValues + Sites = $SiteValues + #TrainableClassifiers = + ExcludedKeyworkGroups = $excludedKeywordGroupValue + ExceptionKeyworkGroups = $exceptionKeywordGroupValue + ExcludedClassifierGroups = $excludedClassifierGroupValue + ExcludedDomainGroups = $excludedDomainGroupValue + ExcludedFilePathGroup = $excludedFilePathGroupValue + ExcludedSiteGroups = $excludedSiteGroupValue + ExcludedSensitiveInformationTypeGroups = $excludedSITGroupValue + ExcludedFileTypeGroups = $excludedFileTypeGroupValue + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens } return [System.Collections.Hashtable] $results } @@ -122,12 +343,54 @@ function Set-TargetResource [CmdletBinding()] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $ListType, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Domains, + + [Parameter()] + [System.String[]] + $FilePaths, - ##TODO - Add the list of Parameters + [Parameter()] + [System.String[]] + $FileTypes, + + [Parameter()] + [System.String[]] + $Keywords, + + [Parameter()] + [System.String[]] + $SensitiveInformationTypes, + + [Parameter()] + [System.String[]] + $Sites, + + [Parameter()] + [System.String[]] + $TrainableClassifiers, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', [Parameter()] [System.Management.Automation.PSCredential] @@ -196,12 +459,54 @@ function Test-TargetResource [OutputType([System.Boolean])] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $Name, - ##TODO - Add the list of Parameters + [Parameter(Mandatory = $true)] + [System.String] + $ListType, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Domains, + + [Parameter()] + [System.String[]] + $FilePaths, + + [Parameter()] + [System.String[]] + $FileTypes, + + [Parameter()] + [System.String[]] + $Keywords, + + [Parameter()] + [System.String[]] + $SensitiveInformationTypes, + + [Parameter()] + [System.String[]] + $Sites, + + [Parameter()] + [System.String[]] + $TrainableClassifiers, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', [Parameter()] [System.Management.Automation.PSCredential] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof index 21cf04215e..23af1989e8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof @@ -1,3 +1,11 @@ +[ClassVersion("1.0.0")] +class MSFT_SCInsiderRiskEntityListDomain +{ + [Required, Description("Domain name.")] String Dmn; + [Write, Description("Defines if the entry should include multi-level subdomains or not.")] Boolean isMLSubDmn; + [Write, Description("Type of the Sensitive Information label")] String type; +}; + [ClassVersion("1.0.0.0"), FriendlyName("SCInsiderRiskEntityList")] class MSFT_SCInsiderRiskEntityList : OMI_BaseResource { @@ -5,6 +13,7 @@ class MSFT_SCInsiderRiskEntityList : OMI_BaseResource [Required, Description("")] String ListType; [Write, Description("")] String Description; [Write, Description("")] String DisplayName; + [Write, Description("Domain group."), EmbeddedInstance("MSFT_SCInsiderRiskEntityListDomain")] string Domains; [Write, Description("Specify if this entity should exist or not."), 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; diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 54b3565d09..afd204cd31 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -14,7 +14,7 @@ }, @{ ModuleName = 'DSCParser' - RequiredVersion = '2.0.0.8' + RequiredVersion = '2.0.0.9' }, @{ ModuleName = 'ExchangeOnlineManagement' @@ -102,7 +102,7 @@ }, @{ ModuleName = "MSCloudLoginAssistant" - RequiredVersion = "1.1.22" + RequiredVersion = "1.1.24" }, @{ ModuleName = 'PnP.PowerShell' From 683917271e0a6bbb87c76f953a557c022f2af42c Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 16 Sep 2024 13:33:01 -0400 Subject: [PATCH 184/465] Fixes --- .../MSFT_SCInsiderRiskEntityList.psm1 | 96 +++++++++++++++++++ .../MSFT_SCInsiderRiskEntityList.schema.mof | 17 +++- 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 index a684573e73..b0a67fdcbc 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 @@ -48,6 +48,38 @@ function Get-TargetResource [System.String[]] $TrainableClassifiers, + [Parameter()] + [System.String[]] + $ExceptionKeyworkGroups, + + [Parameter()] + [System.String[]] + $ExcludedClassifierGroups, + + [Parameter()] + [System.String[]] + $ExcludedDomainGroups, + + [Parameter()] + [System.String[]] + $ExcludedFilePathGroup, + + [Parameter()] + [System.String[]] + $ExcludedFileTypeGroups, + + [Parameter()] + [System.String[]] + $ExcludedKeyworkGroups, + + [Parameter()] + [System.String[]] + $ExcludedSensitiveInformationTypeGroups, + + [Parameter()] + [System.String[]] + $ExcludedSiteGroups, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -387,6 +419,38 @@ function Set-TargetResource [System.String[]] $TrainableClassifiers, + [Parameter()] + [System.String[]] + $ExceptionKeyworkGroups, + + [Parameter()] + [System.String[]] + $ExcludedClassifierGroups, + + [Parameter()] + [System.String[]] + $ExcludedDomainGroups, + + [Parameter()] + [System.String[]] + $ExcludedFilePathGroup, + + [Parameter()] + [System.String[]] + $ExcludedFileTypeGroups, + + [Parameter()] + [System.String[]] + $ExcludedKeyworkGroups, + + [Parameter()] + [System.String[]] + $ExcludedSensitiveInformationTypeGroups, + + [Parameter()] + [System.String[]] + $ExcludedSiteGroups, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -503,6 +567,38 @@ function Test-TargetResource [System.String[]] $TrainableClassifiers, + [Parameter()] + [System.String[]] + $ExceptionKeyworkGroups, + + [Parameter()] + [System.String[]] + $ExcludedClassifierGroups, + + [Parameter()] + [System.String[]] + $ExcludedDomainGroups, + + [Parameter()] + [System.String[]] + $ExcludedFilePathGroup, + + [Parameter()] + [System.String[]] + $ExcludedFileTypeGroups, + + [Parameter()] + [System.String[]] + $ExcludedKeyworkGroups, + + [Parameter()] + [System.String[]] + $ExcludedSensitiveInformationTypeGroups, + + [Parameter()] + [System.String[]] + $ExcludedSiteGroups, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof index 23af1989e8..e1d0a0bbb0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof @@ -13,7 +13,22 @@ class MSFT_SCInsiderRiskEntityList : OMI_BaseResource [Required, Description("")] String ListType; [Write, Description("")] String Description; [Write, Description("")] String DisplayName; - [Write, Description("Domain group."), EmbeddedInstance("MSFT_SCInsiderRiskEntityListDomain")] string Domains; + [Write, Description(""), EmbeddedInstance("MSFT_SCInsiderRiskEntityListDomain")] String Domains[]; + [Write, Description("")] String FilePaths[]; + [Write, Description("")] String FileTypes[]; + [Write, Description("")] String Keywords[]; + [Write, Description("")] String SensitiveInformationTypes[]; + [Write, Description("")] String Sites[]; + [Write, Description("")] String TrainableClassifiers[]; + [Write, Description("")] String ExceptionKeyworkGroups[]; + [Write, Description("")] String ExcludedClassifierGroups[]; + [Write, Description("")] String ExcludedDomainGroups[]; + [Write, Description("")] String ExcludedFilePathGroup[]; + [Write, Description("")] String ExcludedFileTypeGroups[]; + [Write, Description("")] String ExcludedKeyworkGroups[]; + [Write, Description("")] String ExcludedSensitiveInformationTypeGroups[]; + [Write, Description("")] String ExcludedSiteGroups[]; + [Write, Description("Domain group.")] string Domains; [Write, Description("Specify if this entity should exist or not."), 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 8991ae205ed1dcd116bf28b3c01efaddc2cbeeed Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 16 Sep 2024 14:10:06 -0400 Subject: [PATCH 185/465] Updates --- .../MSFT_ADOSecurityPolicy.psm1 | 44 +++++++------------ .../M365DSCAzureDevOPSHelper.psm1 | 26 +++++++++++ 2 files changed, 43 insertions(+), 27 deletions(-) create mode 100644 Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 index c6f63d3927..8c075397c5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 @@ -37,7 +37,7 @@ function Get-TargetResource ) ##TODO - Replace the workload by the one associated to your resource - New-M365DSCConnection -Workload 'Workload' ` + New-M365DSCConnection -Workload 'AzureDevOPS' ` -InboundParameters $PSBoundParameters | Out-Null #Ensure the proper dependencies are installed in the current environment. @@ -53,27 +53,13 @@ function Get-TargetResource #endregion $nullResult = $PSBoundParameters - $nullResult.Ensure = 'Absent' try { - if ($null -ne $Script:exportedInstances -and $Script:ExportMode) - { - ##TODO - Replace the PrimaryKey in the Filter by the one for the resource - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.PrimaryKey -eq $PrimaryKey} - } - else - { - ##TODO - Replace the cmdlet by the one to retrieve a specific instance. - $instance = Get-cmdlet -PrimaryKey $PrimaryKey -ErrorAction Stop - } - if ($null -eq $instance) - { - return $nullResult - } + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.DisallowAadGuestUserAccess?defaultValue" + $DisallowAadGuestUserAccessValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value $results = @{ - ##TODO - Add the list of parameters to be returned - Ensure = 'Present' + DisallowAadGuestUserAccessValue = [Boolean] $DisallowAadGuestUserAccessValue Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId @@ -271,7 +257,7 @@ function Export-TargetResource ) ##TODO - Replace workload - $ConnectionMode = New-M365DSCConnection -Workload 'Workload' ` + $ConnectionMode = New-M365DSCConnection -Workload 'AzureDevOPS' ` -InboundParameters $PSBoundParameters #Ensure the proper dependencies are installed in the current environment. @@ -289,12 +275,13 @@ function Export-TargetResource try { $Script:ExportMode = $true - ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances - [array] $Script:exportedInstances = Get-Cmdlet -ErrorAction Stop + + $profile = Invoke-M365DSCAzureDevOPSWebRequest -Uri 'https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=5.1' + $accounts = Invoke-M365DSCAzureDevOPSWebRequest -Uri "https://app.vssps.visualstudio.com/_apis/accounts?api-version=7.1-preview.1&memberId=$($profile.Id)" $i = 1 $dscContent = '' - if ($Script:exportedInstances.Length -eq 0) + if ($accounts.Length -eq 0) { Write-Host $Global:M365DSCEmojiGreenCheckMark } @@ -302,13 +289,16 @@ function Export-TargetResource { Write-Host "`r`n" -NoNewline } - foreach ($config in $Script:exportedInstances) + + $accounts = @{ + accountName = 'O365DSC-Dev' + } + foreach ($organization in $accounts.accountName) { - $displayedKey = $config.Id - Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $displayedKey = $organization + Write-Host " |---[$i/$($accounts.accountName.Count)] $displayedKey" -NoNewline $params = @{ - ##TODO - Specify the Primary Key - #PrimaryKey = $config.PrimaryKey + OrganizationName = $organization Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 b/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 new file mode 100644 index 0000000000..1382cd373f --- /dev/null +++ b/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 @@ -0,0 +1,26 @@ +function Invoke-M365DSCAzureDevOPSWebRequest +{ + [OutputType([PSCustomObject])] + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [System.String] + $Uri, + + [Parameter()] + [System.String] + $Method = 'GET', + + [Parameter()] + [System.Collections.Hashtable] + $Body + ) + + $headers = @{ + Authorization = $global:MsCloudLoginConnectionProfile.AzureDevOPS.AccessToken + } + + $response = Invoke-WebRequest -Method $Method -Uri $Uri -Headers $headers -Body $Body + $result = ConvertFrom-Json $response.Content + return $result +} From 1d6c3ade3fe57ed2aec33fd5d9c6621999fbf1a9 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 16 Sep 2024 16:24:18 -0400 Subject: [PATCH 186/465] Update --- .../MSFT_AADUser.psm1 | 0 .../MSFT_ADOSecurityPolicy.psm1 | 223 +++++++++++++++--- .../MSFT_ADOSecurityPolicy.schema.mof | 19 +- Modules/Microsoft365DSC/Microsoft365DSC.psd1 | 1 + .../M365DSCAzureDevOPSHelper.psm1 | 1 + 5 files changed, 199 insertions(+), 45 deletions(-) rename Modules/Microsoft365DSC/DSCResources/{MSFT_AADUser => MSFT_ADOSecurityPolicy}/MSFT_AADUser.psm1 (100%) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADUser/MSFT_AADUser.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_AADUser.psm1 similarity index 100% rename from Modules/Microsoft365DSC/DSCResources/MSFT_AADUser/MSFT_AADUser.psm1 rename to Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_AADUser.psm1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 index 8c075397c5..75efc7b886 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 @@ -4,12 +4,45 @@ function Get-TargetResource [OutputType([System.Collections.Hashtable])] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $OrganizationName, - ##TODO - Add the list of Parameters + [Parameter()] + [System.Boolean] + $DisallowAadGuestUserAccess, + + [Parameter()] + [System.Boolean] + $DisallowOAuthAuthentication, + + [Parameter()] + [System.Boolean] + $DisallowSecureShell, + + [Parameter()] + [System.Boolean] + $LogAuditEvents, + + [Parameter()] + [System.Boolean] + $AllowAnonymousAccess, + + [Parameter()] + [System.Boolean] + $ArtifactsExternalPackageProtectionToken, + + [Parameter()] + [System.Boolean] + $EnforceAADConditionalAccess, + + [Parameter()] + [System.Boolean] + $AllowTeamAdminsInvitationsAccessToken, + + [Parameter()] + [System.Boolean] + $AllowRequestAccessToken, [Parameter()] [System.Management.Automation.PSCredential] @@ -35,8 +68,6 @@ function Get-TargetResource [System.String[]] $AccessTokens ) - - ##TODO - Replace the workload by the one associated to your resource New-M365DSCConnection -Workload 'AzureDevOPS' ` -InboundParameters $PSBoundParameters | Out-Null @@ -58,14 +89,46 @@ function Get-TargetResource $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.DisallowAadGuestUserAccess?defaultValue" $DisallowAadGuestUserAccessValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.DisallowOAuthAuthentication?defaultValue" + $DisallowOAuthAuthenticationValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.DisallowSecureShell?defaultValue" + $DisallowSecureShellValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.LogAuditEvents?defaultValue" + $LogAuditEventsValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.AllowAnonymousAccess?defaultValue" + $AllowAnonymousAccessValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.ArtifactsExternalPackageProtectionToken?defaultValue" + $ArtifactsExternalPackageProtectionTokenValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.EnforceAADConditionalAccess?defaultValue" + $EnforceAADConditionalAccessValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.AllowTeamAdminsInvitationsAccessToken?defaultValue" + $AllowTeamAdminsInvitationsAccessTokenValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.AllowRequestAccessToken?defaultValue" + $AllowRequestAccessTokenValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + $results = @{ - DisallowAadGuestUserAccessValue = [Boolean] $DisallowAadGuestUserAccessValue - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens + DisallowAadGuestUserAccess = [Boolean]::Parse($DisallowAadGuestUserAccessValue) + DisallowOAuthAuthentication = [Boolean]::Parse($DisallowOAuthAuthenticationValue) + DisallowSecureShell = [Boolean]::Parse($DisallowSecureShellValue) + LogAuditEvents = [Boolean]::Parse($LogAuditEventsValue) + AllowAnonymousAccess = [Boolean]::Parse($AllowAnonymousAccessValue) + ArtifactsExternalPackageProtectionToken = [Boolean]::Parse($ArtifactsExternalPackageProtectionTokenValue) + EnforceAADConditionalAccess = [Boolean]::Parse($EnforceAADConditionalAccessValue) + AllowTeamAdminsInvitationsAccessToken = [Boolean]::Parse($AllowTeamAdminsInvitationsAccessTokenValue) + AllowRequestAccessToken = [Boolean]::Parse($AllowRequestAccessTokenValue) + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens } return [System.Collections.Hashtable] $results } @@ -87,12 +150,46 @@ function Set-TargetResource [CmdletBinding()] param ( - ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $OrganizationName, + + [Parameter()] + [System.Boolean] + $DisallowAadGuestUserAccess, + + [Parameter()] + [System.Boolean] + $DisallowOAuthAuthentication, + + [Parameter()] + [System.Boolean] + $DisallowSecureShell, + + [Parameter()] + [System.Boolean] + $LogAuditEvents, + + [Parameter()] + [System.Boolean] + $AllowAnonymousAccess, + + [Parameter()] + [System.Boolean] + $ArtifactsExternalPackageProtectionToken, - ##TODO - Add the list of Parameters + [Parameter()] + [System.Boolean] + $EnforceAADConditionalAccess, + + [Parameter()] + [System.Boolean] + $AllowTeamAdminsInvitationsAccessToken, + + [Parameter()] + [System.Boolean] + $AllowRequestAccessToken, [Parameter()] [System.Management.Automation.PSCredential] @@ -131,28 +228,42 @@ function Set-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - $currentInstance = Get-TargetResource @PSBoundParameters - - $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + New-M365DSCConnection -Workload 'AzureDevOPS' ` + -InboundParameters $PSBoundParameters | Out-Null - # CREATE - if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') - { - ##TODO - Replace by the New cmdlet for the resource - New-Cmdlet @SetParameters - } - # UPDATE - elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + if ($PSBoundParameters.ContainsKey('DisallowAadGuestUserAccess')) { - ##TODO - Replace by the Update/Set cmdlet for the resource - Set-cmdlet @SetParameters - } - # REMOVE - elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') - { - ##TODO - Replace by the Remove cmdlet for the resource - Remove-cmdlet @SetParameters + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.DisallowAadGuestUserAccess" + $body = @{ + path = '/value' + value = $DisallowAadGuestUserAccess + } + DisallowAadGuestUserAccessValue = Invoke-M365DSCAzureDevOPSWebRequest -uri $uri -Method 'PATCH' } +<# + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.DisallowOAuthAuthentication?defaultValue" + $DisallowOAuthAuthenticationValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.DisallowSecureShell?defaultValue" + $DisallowSecureShellValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.LogAuditEvents?defaultValue" + $LogAuditEventsValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.AllowAnonymousAccess?defaultValue" + $AllowAnonymousAccessValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.ArtifactsExternalPackageProtectionToken?defaultValue" + $ArtifactsExternalPackageProtectionTokenValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.EnforceAADConditionalAccess?defaultValue" + $EnforceAADConditionalAccessValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.AllowTeamAdminsInvitationsAccessToken?defaultValue" + $AllowTeamAdminsInvitationsAccessTokenValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.AllowRequestAccessToken?defaultValue" + $AllowRequestAccessTokenValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value#> } function Test-TargetResource @@ -161,12 +272,46 @@ function Test-TargetResource [OutputType([System.Boolean])] param ( - ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $OrganizationName, + + [Parameter()] + [System.Boolean] + $DisallowAadGuestUserAccess, + + [Parameter()] + [System.Boolean] + $DisallowOAuthAuthentication, - ##TODO - Add the list of Parameters + [Parameter()] + [System.Boolean] + $DisallowSecureShell, + + [Parameter()] + [System.Boolean] + $LogAuditEvents, + + [Parameter()] + [System.Boolean] + $AllowAnonymousAccess, + + [Parameter()] + [System.Boolean] + $ArtifactsExternalPackageProtectionToken, + + [Parameter()] + [System.Boolean] + $EnforceAADConditionalAccess, + + [Parameter()] + [System.Boolean] + $AllowTeamAdminsInvitationsAccessToken, + + [Parameter()] + [System.Boolean] + $AllowRequestAccessToken, [Parameter()] [System.Management.Automation.PSCredential] @@ -256,7 +401,6 @@ function Export-TargetResource $AccessTokens ) - ##TODO - Replace workload $ConnectionMode = New-M365DSCConnection -Workload 'AzureDevOPS' ` -InboundParameters $PSBoundParameters @@ -277,7 +421,7 @@ function Export-TargetResource $Script:ExportMode = $true $profile = Invoke-M365DSCAzureDevOPSWebRequest -Uri 'https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=5.1' - $accounts = Invoke-M365DSCAzureDevOPSWebRequest -Uri "https://app.vssps.visualstudio.com/_apis/accounts?api-version=7.1-preview.1&memberId=$($profile.Id)" + $accounts = Invoke-M365DSCAzureDevOPSWebRequest -Uri "https://app.vssps.visualstudio.com/_apis/accounts?api-version=7.1-preview.1&memberId=$($profile.id)" $i = 1 $dscContent = '' @@ -295,6 +439,7 @@ function Export-TargetResource } foreach ($organization in $accounts.accountName) { + $displayedKey = $organization Write-Host " |---[$i/$($accounts.accountName.Count)] $displayedKey" -NoNewline $params = @{ diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.schema.mof index 6fa43ce435..9b769f1b90 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.schema.mof @@ -1,13 +1,20 @@ -[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] -class MSFT_ResourceName : OMI_BaseResource +[ClassVersion("1.0.0.0"), FriendlyName("ADOSecurityPolicy")] +class MSFT_ADOSecurityPolicy : OMI_BaseResource { - [Key, Description("")] String PrimaryKey; - [Write, Description("")] String OtherProperties; - + [Key, Description("The name of the Azure DevOPS Organization.")] String OrganizationName; + [Write, Description("Controls the external guest access.")] Boolean DisallowAadGuestUserAccess; + [Write, Description("Controls the Third-party application access via OAuth.")] Boolean DisallowOAuthAuthentication; + [Write, Description("Controls SSH Authentication.")] Boolean DisallowSecureShell; + [Write, Description("Controls Log Audit Events.")] Boolean LogAuditEvents; + [Write, Description("Controls the Allow public projects setting.")] Boolean AllowAnonymousAccess; + [Write, Description("Controls the Additional protections when using public package registries setting.")] Boolean ArtifactsExternalPackageProtectionToken; + [Write, Description("Controls the Enable IP Conditional Access policy validation setting.")] Boolean EnforceAADConditionalAccess; + [Write, Description("Controls the Allow team and project administrators to invite new user setting.")] Boolean AllowTeamAdminsInvitationsAccessToken; + [Write, Description("Controls the Request access setting.")] Boolean AllowRequestAccessTokenValue; [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; [Write, Description("Access token used for authentication.")] String AccessTokens[]; -}; \ No newline at end of file +}; diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index 829a2cef89..0d8b221bdd 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -79,6 +79,7 @@ 'Modules/M365DSCDRGUtil.psm1', 'Modules/EncodingHelpers/M365DSCEmojis.psm1', 'Modules/EncodingHelpers/M365DSCStringEncoding.psm1', + 'Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1', 'Modules/WorkloadHelpers/M365DSCFabricHelper.psm1', 'Modules/M365DSCConfigurationHelper.psm1' ) diff --git a/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 b/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 index 1382cd373f..dc1c8f8948 100644 --- a/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 +++ b/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 @@ -18,6 +18,7 @@ function Invoke-M365DSCAzureDevOPSWebRequest $headers = @{ Authorization = $global:MsCloudLoginConnectionProfile.AzureDevOPS.AccessToken + 'Content-Type' = 'application/json-patch+json' } $response = Invoke-WebRequest -Method $Method -Uri $Uri -Headers $headers -Body $Body From ed304ee9e2c5c175e5cfb503d8241541e6c34e99 Mon Sep 17 00:00:00 2001 From: Sai Sistla Date: Tue, 17 Sep 2024 10:04:34 +0530 Subject: [PATCH 187/465] Addressed comments --- CHANGELOG.md | 2 ++ .../MSFT_EXOEmailTenantSettings.psm1 | 31 ++----------------- .../MSFT_EXOEmailTenantSettings.schema.mof | 1 - .../EXOEmailTenantSettings/2-Update.ps1 | 1 + 4 files changed, 5 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cb19259c2..ed39936aec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* EXOEmailTenantSettings + * Initial Release * EXOMailboxIRMAccess * Initial Release. * AADPasswordRuleSettings diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 index 89d50d48a3..a43d086c64 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 @@ -29,11 +29,6 @@ function Get-TargetResource [System.String] $ObjectState, - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -107,7 +102,6 @@ function Get-TargetResource IsValid = $EmailTenantSettings.IsValid ObjectState = $EmailTenantSettings.ObjectState Credential = $Credential - Ensure = 'Present' ApplicationId = $ApplicationId CertificateThumbprint = $CertificateThumbprint CertificatePath = $CertificatePath @@ -163,11 +157,6 @@ function Set-TargetResource [System.String] $ObjectState, - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -217,24 +206,14 @@ function Set-TargetResource $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` -InboundParameters $PSBoundParameters - $EmailTenantSettingsParams = [System.Collections.Hashtable]($PSBoundParameters) - $EmailTenantSettingsParams.Remove('Ensure') | Out-Null - $EmailTenantSettingsParams.Remove('Credential') | Out-Null - $EmailTenantSettingsParams.Remove('ApplicationId') | Out-Null - $EmailTenantSettingsParams.Remove('TenantId') | Out-Null - $EmailTenantSettingsParams.Remove('CertificateThumbprint') | Out-Null - $EmailTenantSettingsParams.Remove('CertificatePath') | Out-Null - $EmailTenantSettingsParams.Remove('CertificatePassword') | Out-Null - $EmailTenantSettingsParams.Remove('ManagedIdentity') | Out-Null - $EmailTenantSettingsParams.Remove('IsSingleInstance') | Out-Null - $EmailTenantSettingsParams.Remove('AccessTokens') | Out-Null + $EmailTenantSettingsParams = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters #removing params that cannot be set. $EmailTenantSettingsParams.Remove('Name') | Out-Null $EmailTenantSettingsParams.Remove('IsValid') | Out-Null $EmailTenantSettingsParams.Remove('ObjectState') | Out-Null - if (('Present' -eq $Ensure ) -and ($Null -ne $EmailTenantSettingsParams)) + if ($Null -ne $EmailTenantSettingsParams) { Write-Verbose -Message "Setting Email tenant settings with values: $(Convert-M365DscHashtableToString -Hashtable $EmailTenantSettingsParams)" Set-EmailTenantSettings @EmailTenantSettingsParams @@ -274,11 +253,6 @@ function Test-TargetResource [System.String] $ObjectState, - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -331,7 +305,6 @@ function Test-TargetResource Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" $ValuesToCheck = $PSBoundParameters - $ValuesToCheck.Remove('Ensure') | Out-Null $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.schema.mof index 722a76bcd3..3f6bdbbd6e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.schema.mof @@ -7,7 +7,6 @@ class MSFT_EXOEmailTenantSettings : OMI_BaseResource [Write, Description("Specifies whether the migration configuration is valid.")] Boolean IsValid; [Write, Description("Specifies the state of the object.")] String ObjectState; [Write, Description("Specifies the name of the object.")] String Name; - [Write, Description("Specifies if this EmailTenantSettings should exist."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; [Write, Description("Credentials of the Exchange Global 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; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 index c94feac8ee..c09677e388 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 @@ -23,6 +23,7 @@ Configuration Example { EXOEmailTenantSettings "EXOEmailTenantSettings-Test" { + IsSingleInstance = = $True; EnablePriorityAccountProtection = $True; Identity = $TenantId; IsValid = $True; From f4eaadd3b429d41f701107740d2da105dc470121 Mon Sep 17 00:00:00 2001 From: Sai Sistla Date: Tue, 17 Sep 2024 11:10:22 +0530 Subject: [PATCH 188/465] Fixed unit tests --- .../MSFT_EXOEmailTenantSettings.psm1 | 1 + .../Microsoft365DSC.EXOEmailTenantSettings.Tests.ps1 | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 index a43d086c64..dd5a345ee6 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOEmailTenantSettings/MSFT_EXOEmailTenantSettings.psm1 @@ -212,6 +212,7 @@ function Set-TargetResource $EmailTenantSettingsParams.Remove('Name') | Out-Null $EmailTenantSettingsParams.Remove('IsValid') | Out-Null $EmailTenantSettingsParams.Remove('ObjectState') | Out-Null + $EmailTenantSettingsParams.Remove('IsSingleInstance') | Out-Null if ($Null -ne $EmailTenantSettingsParams) { diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOEmailTenantSettings.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOEmailTenantSettings.Tests.ps1 index 43cf5d4ba9..cec4d939c4 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOEmailTenantSettings.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOEmailTenantSettings.Tests.ps1 @@ -52,12 +52,10 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $testParams = @{ IsSingleInstance = 'Yes' EnablePriorityAccountProtection = $True; - Identity = "sotmcpoc.onmicrosoft.com\Default"; IsValid = $True; ObjectState = "New" Credential = $Credential Name = "Default" - Ensure = "Present" } Mock -CommandName Get-EmailTenantSettings -MockWith { @@ -89,7 +87,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ObjectState = "New" Credential = $Credential Name = "Default" - Ensure = "Present" } Mock -CommandName Get-EmailTenantSettings -MockWith { From 463032feb499445493037b3063c9412cecdd98d0 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 17 Sep 2024 11:15:31 -0400 Subject: [PATCH 189/465] ADOSecurityPolicy - Initial Release --- CHANGELOG.md | 8 +- .../MSFT_AADUser.psm1 | 0 .../MSFT_ADOSecurityPolicy.psm1 | 108 +++++++++++++----- .../MSFT_ADOSecurityPolicy.schema.mof | 2 +- .../Dependencies/Manifest.psd1 | 2 +- .../Resources/ADOSecurityPolicy/1-Create.ps1 | 26 ----- .../Resources/ADOSecurityPolicy/2-Update.ps1 | 17 ++- .../Resources/ADOSecurityPolicy/3-Remove.ps1 | 26 ----- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 5 +- .../M365DSCAzureDevOPSHelper.psm1 | 22 +++- ...icrosoft365DSC.ADOSecurityPolicy.Tests.ps1 | 93 ++------------- 11 files changed, 136 insertions(+), 173 deletions(-) rename Modules/Microsoft365DSC/DSCResources/{MSFT_ADOSecurityPolicy => MSFT_AADUser}/MSFT_AADUser.psm1 (100%) delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/1-Create.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/3-Remove.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cb19259c2..f5a0b0d71c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,10 @@ # UNRELEASED -* EXOMailboxIRMAccess - * Initial Release. * AADPasswordRuleSettings * Initial release +* ADOSecurityPolicy + * Initial release. * AzureSubscription * Initial Release. * EXOArcConfig @@ -14,6 +14,8 @@ * Initial Release. * EXOMailboxCalendarConfiguration * Initial Release. +* EXOMailboxIRMAccess + * Initial Release. * EXOManagementScope * Initial Release. * EXOManagementScope @@ -43,7 +45,7 @@ * DEPENDENCIES * Added dependencies on Az.Accounts, Az.Resources and Az.SecurityInsights * Updated DSCParser to version 2.0.0.9. - * Updated MSCloudLoginAssistant to version 1.1.24. + * Updated MSCloudLoginAssistant to version 1.1.25. # 1.24.904.1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_AADUser.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADUser/MSFT_AADUser.psm1 similarity index 100% rename from Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_AADUser.psm1 rename to Modules/Microsoft365DSC/DSCResources/MSFT_AADUser/MSFT_AADUser.psm1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 index 75efc7b886..e6c10774cd 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.psm1 @@ -114,6 +114,7 @@ function Get-TargetResource $AllowRequestAccessTokenValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value $results = @{ + OrganizationName = $OrganizationName DisallowAadGuestUserAccess = [Boolean]::Parse($DisallowAadGuestUserAccessValue) DisallowOAuthAuthentication = [Boolean]::Parse($DisallowOAuthAuthenticationValue) DisallowSecureShell = [Boolean]::Parse($DisallowSecureShellValue) @@ -233,37 +234,84 @@ function Set-TargetResource if ($PSBoundParameters.ContainsKey('DisallowAadGuestUserAccess')) { - $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.DisallowAadGuestUserAccess" - $body = @{ - path = '/value' - value = $DisallowAadGuestUserAccess - } - DisallowAadGuestUserAccessValue = Invoke-M365DSCAzureDevOPSWebRequest -uri $uri -Method 'PATCH' + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.DisallowAadGuestUserAccess?api-version=5.0-preview" + $body = "[{`"from`":`"`",`"op`":2,`"path`":`"/Value`",`"value`":`"$($DisallowAadGuestUserAccess.ToString().ToLower())`"}]" + Write-Verbose -Message "Updating DisallowAadGuestUserAccess policy with values: $($body)" + + Invoke-M365DSCAzureDevOPSWebRequest -uri $uri -Method 'PATCH' -Body $body + } + + if ($PSBoundParameters.ContainsKey('DisallowOAuthAuthentication')) + { + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.DisallowOAuthAuthentication?api-version=5.0-preview" + $body = "[{`"from`":`"`",`"op`":2,`"path`":`"/Value`",`"value`":`"$($DisallowOAuthAuthentication.ToString().ToLower())`"}]" + Write-Verbose -Message "Updating DisallowOAuthAuthentication policy with values: $($body)" + + Invoke-M365DSCAzureDevOPSWebRequest -uri $uri -Method 'PATCH' -Body $body + } + + if ($PSBoundParameters.ContainsKey('DisallowSecureShell')) + { + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.DisallowSecureShell?api-version=5.0-preview" + $body = "[{`"from`":`"`",`"op`":2,`"path`":`"/Value`",`"value`":`"$($DisallowSecureShell.ToString().ToLower())`"}]" + Write-Verbose -Message "Updating DisallowSecureShell policy with values: $($body)" + + Invoke-M365DSCAzureDevOPSWebRequest -uri $uri -Method 'PATCH' -Body $body } -<# - $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.DisallowOAuthAuthentication?defaultValue" - $DisallowOAuthAuthenticationValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value - $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.DisallowSecureShell?defaultValue" - $DisallowSecureShellValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + if ($PSBoundParameters.ContainsKey('LogAuditEvents')) + { + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.LogAuditEvents?api-version=5.0-preview" + $body = "[{`"from`":`"`",`"op`":2,`"path`":`"/Value`",`"value`":`"$($LogAuditEvents.ToString().ToLower())`"}]" + Write-Verbose -Message "Updating LogAuditEvents policy with values: $($body)" - $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.LogAuditEvents?defaultValue" - $LogAuditEventsValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + Invoke-M365DSCAzureDevOPSWebRequest -uri $uri -Method 'PATCH' -Body $body + } - $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.AllowAnonymousAccess?defaultValue" - $AllowAnonymousAccessValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + if ($PSBoundParameters.ContainsKey('AllowAnonymousAccess')) + { + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.AllowAnonymousAccess?api-version=5.0-preview" + $body = "[{`"from`":`"`",`"op`":2,`"path`":`"/Value`",`"value`":`"$($AllowAnonymousAccess.ToString().ToLower())`"}]" + Write-Verbose -Message "Updating AllowAnonymousAccess policy with values: $($body)" - $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.ArtifactsExternalPackageProtectionToken?defaultValue" - $ArtifactsExternalPackageProtectionTokenValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + Invoke-M365DSCAzureDevOPSWebRequest -uri $uri -Method 'PATCH' -Body $body + } - $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.EnforceAADConditionalAccess?defaultValue" - $EnforceAADConditionalAccessValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + if ($PSBoundParameters.ContainsKey('ArtifactsExternalPackageProtectionToken')) + { + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.ArtifactsExternalPackageProtectionToken?api-version=5.0-preview" + $body = "[{`"from`":`"`",`"op`":2,`"path`":`"/Value`",`"value`":`"$($ArtifactsExternalPackageProtectionToken.ToString().ToLower())`"}]" + Write-Verbose -Message "Updating ArtifactsExternalPackageProtectionToken policy with values: $($body)" - $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.AllowTeamAdminsInvitationsAccessToken?defaultValue" - $AllowTeamAdminsInvitationsAccessTokenValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value + Invoke-M365DSCAzureDevOPSWebRequest -uri $uri -Method 'PATCH' -Body $body + } - $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.AllowRequestAccessToken?defaultValue" - $AllowRequestAccessTokenValue = (Invoke-M365DSCAzureDevOPSWebRequest -uri $uri).Value#> + if ($PSBoundParameters.ContainsKey('EnforceAADConditionalAccess')) + { + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.EnforceAADConditionalAccess?api-version=5.0-preview" + $body = "[{`"from`":`"`",`"op`":2,`"path`":`"/Value`",`"value`":`"$($EnforceAADConditionalAccess.ToString().ToLower())`"}]" + Write-Verbose -Message "Updating EnforceAADConditionalAccess policy with values: $($body)" + + Invoke-M365DSCAzureDevOPSWebRequest -uri $uri -Method 'PATCH' -Body $body + } + + if ($PSBoundParameters.ContainsKey('AllowTeamAdminsInvitationsAccessToken')) + { + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.AllowTeamAdminsInvitationsAccessToken?api-version=5.0-preview" + $body = "[{`"from`":`"`",`"op`":2,`"path`":`"/Value`",`"value`":`"$($AllowTeamAdminsInvitationsAccessToken.ToString().ToLower())`"}]" + Write-Verbose -Message "Updating AllowTeamAdminsInvitationsAccessToken policy with values: $($body)" + + Invoke-M365DSCAzureDevOPSWebRequest -uri $uri -Method 'PATCH' -Body $body + } + + if ($PSBoundParameters.ContainsKey('AllowRequestAccessToken')) + { + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/OrganizationPolicy/Policies/Policy.AllowRequestAccessToken?api-version=5.0-preview" + $body = "[{`"from`":`"`",`"op`":2,`"path`":`"/Value`",`"value`":`"$($AllowRequestAccessToken.ToString().ToLower())`"}]" + Write-Verbose -Message "Updating AllowRequestAccessToken policy with values: $($body)" + + Invoke-M365DSCAzureDevOPSWebRequest -uri $uri -Method 'PATCH' -Body $body + } } function Test-TargetResource @@ -272,7 +320,6 @@ function Test-TargetResource [OutputType([System.Boolean])] param ( - [Parameter(Mandatory = $true)] [System.String] $OrganizationName, @@ -433,15 +480,16 @@ function Export-TargetResource { Write-Host "`r`n" -NoNewline } - - $accounts = @{ - accountName = 'O365DSC-Dev' - } - foreach ($organization in $accounts.accountName) + foreach ($account in $accounts) { + $organization = $account.Value.accountName + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } $displayedKey = $organization - Write-Host " |---[$i/$($accounts.accountName.Count)] $displayedKey" -NoNewline + Write-Host " |---[$i/$($accounts.Count)] $displayedKey" -NoNewline $params = @{ OrganizationName = $organization Credential = $Credential diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.schema.mof index 9b769f1b90..51e606ca11 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/MSFT_ADOSecurityPolicy.schema.mof @@ -10,7 +10,7 @@ class MSFT_ADOSecurityPolicy : OMI_BaseResource [Write, Description("Controls the Additional protections when using public package registries setting.")] Boolean ArtifactsExternalPackageProtectionToken; [Write, Description("Controls the Enable IP Conditional Access policy validation setting.")] Boolean EnforceAADConditionalAccess; [Write, Description("Controls the Allow team and project administrators to invite new user setting.")] Boolean AllowTeamAdminsInvitationsAccessToken; - [Write, Description("Controls the Request access setting.")] Boolean AllowRequestAccessTokenValue; + [Write, Description("Controls the Request access setting.")] Boolean AllowRequestAccessToken; [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; diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index afd204cd31..1b2afb7550 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -102,7 +102,7 @@ }, @{ ModuleName = "MSCloudLoginAssistant" - RequiredVersion = "1.1.24" + RequiredVersion = "1.1.25" }, @{ ModuleName = 'PnP.PowerShell' diff --git a/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/1-Create.ps1 deleted file mode 100644 index b516274848..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/1-Create.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -<# -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()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/2-Update.ps1 index b516274848..d226a0df30 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/2-Update.ps1 @@ -21,6 +21,21 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + ADOSecurityPolicy "ADOPolicy" + { + AllowAnonymousAccess = $True; + AllowRequestAccessToken = $False; + AllowTeamAdminsInvitationsAccessToken = $True; + ApplicationId = $ApplicationId; + ArtifactsExternalPackageProtectionToken = $False; + CertificateThumbprint = $CertificateThumbprint; + DisallowAadGuestUserAccess = $True; + DisallowOAuthAuthentication = $True; + DisallowSecureShell = $False; + EnforceAADConditionalAccess = $False; + LogAuditEvents = $True; + OrganizationName = "O365DSC-Dev"; + TenantId = $TenantId; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/3-Remove.ps1 deleted file mode 100644 index b516274848..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/ADOSecurityPolicy/3-Remove.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -<# -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()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - - } -} diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 9397159c76..756b3c0a86 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1771,7 +1771,6 @@ function New-M365DSCConnection [System.Boolean] $SkipModuleReload = $false ) - $verbosepreference = 'Continue' $Global:MaximumFunctionCount = 32767 if ($Workload -eq 'MicrosoftTeams') { @@ -3697,6 +3696,10 @@ function Get-M365DSCExportContentForResource { $primaryKey = $Results.WorkspaceName } + elseif ($Keys.Contains('OrganizationName')) + { + $primaryKey = $Results.OrganizationName + } if ([String]::IsNullOrEmpty($primaryKey) -and ` -not $Keys.Contains('IsSingleInstance')) diff --git a/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 b/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 index dc1c8f8948..19f3105cf7 100644 --- a/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 +++ b/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 @@ -12,7 +12,7 @@ function Invoke-M365DSCAzureDevOPSWebRequest $Method = 'GET', [Parameter()] - [System.Collections.Hashtable] + [System.String] $Body ) @@ -21,7 +21,23 @@ function Invoke-M365DSCAzureDevOPSWebRequest 'Content-Type' = 'application/json-patch+json' } - $response = Invoke-WebRequest -Method $Method -Uri $Uri -Headers $headers -Body $Body - $result = ConvertFrom-Json $response.Content + $params = @{ + Headers = $headers + Uri = $Uri + Method = $Method + + } + + if ($Method -ne 'GET') + { + $params.Add('Body', $Body) + } + + $response = Invoke-WebRequest @params -UseBasicParsing + $result = $null + if (-not [System.String]::IsNullOrEmpty($response.Content)) + { + $result = ConvertFrom-Json $response.Content + } return $result } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOSecurityPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOSecurityPolicy.Tests.ps1 index 20857e0393..2b107124ba 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOSecurityPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOSecurityPolicy.Tests.ps1 @@ -35,81 +35,24 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets - # 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 instance should exist but it DOES NOT" -Fixture { - BeforeAll { - $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; - } - - ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -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 a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one - Should -Invoke -CommandName New-Cmdlet -Exactly 1 - } - } - - Context -Name "The instance exists but it SHOULD NOT" -Fixture { - BeforeAll { - $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Absent' - Credential = $Credential; - } - - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - - } - } - } - 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 remove the instance from the Set method' { - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 - } - } Context -Name "The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + LogAuditEvents = $True; + OrganizationName = "MyOrg"; + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Invoke-M365DSCAzureDevOPSWebRequest -MockWith { return @{ - + Value = $true } } } @@ -122,32 +65,21 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + LogAuditEvents = $True; + OrganizationName = "MyOrg"; + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Invoke-M365DSCAzureDevOPSWebRequest -MockWith { return @{ - + Value = $false } } } - 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 - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 - } } Context -Name 'ReverseDSC Tests' -Fixture { @@ -158,10 +90,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Invoke-M365DSCAzureDevOPSWebRequest -MockWith { return @{ - + Value = $true } } } From 0b4db15395df577572bbd76016ab4d126b6b098d Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 17 Sep 2024 11:17:24 -0400 Subject: [PATCH 190/465] Update M365DSCUtil.psm1 --- Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 756b3c0a86..b498f41a3f 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -6,7 +6,8 @@ $Global:SessionSecurityCompliance = $null #region Extraction Modes $Global:DefaultComponents = @('SPOApp', 'SPOSiteDesign') -$Global:FullComponents = @('AADGroup', 'AADServicePrincipal', 'EXOCalendarProcessing', 'EXODistributionGroup', 'EXOMailboxAutoReplyConfiguration', ` +$Global:FullComponents = @('AADGroup', 'AADServicePrincipal', 'ADOSecurityPolicy', 'AzureSubscription','FabricAdminTenantSettings', ` + 'EXOCalendarProcessing', 'EXODistributionGroup', 'EXOMailboxAutoReplyConfiguration', ` 'EXOMailboxPermission','EXOMailboxCalendarFolder','EXOMailboxSettings', 'EXOManagementRole', 'O365Group', 'AADUser', ` 'PlannerPlan', 'PlannerBucket', 'PlannerTask', 'PPPowerAppsEnvironment', 'PPTenantSettings', ` 'SPOSiteAuditSettings', 'SPOSiteGroup', 'SPOSite', 'SPOUserProfileProperty', 'SPOPropertyBag', 'TeamsTeam', 'TeamsChannel', ` From 9f7366e030878b564f55cba82aa585d6c4fa52e7 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 17 Sep 2024 11:23:26 -0400 Subject: [PATCH 191/465] Updates --- .../MSFT_ADOSecurityPolicy/readme.md | 2 +- .../MSFT_ADOSecurityPolicy/settings.json | 22 +++++-------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/readme.md index 53f0d03cb4..46a7607129 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/readme.md @@ -3,4 +3,4 @@ ## Description -##TODO - Provide a short description of what the resource is set to configure. +Configures Azure DevOPS Security Policies. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/settings.json index d95903b900..0a92ea98a7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOSecurityPolicy/settings.json @@ -1,13 +1,9 @@ { "resourceName": "ADOSecurityPolicy", - "description": "Description of what the resource is about.", + "description": "Configures Azure DevOPS Security Policies.", "roles": { - "read": [ - "Role" - ], - "update": [ - "Role" - ] + "read": [], + "update": [] }, "permissions": { "graph": { @@ -16,16 +12,8 @@ "update": [] }, "application": { - "read": [ - { - "name": "Permission for Monitoring and Export" - } - ], - "update": [ - { - "name": "Permission for deploying" - } - ] + "read": [], + "update": [] } } } From 6abf7d80df34b03a8fdb21ef1b74dc102a1da43b Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 17 Sep 2024 11:48:43 -0400 Subject: [PATCH 192/465] Update Microsoft365DSC.ADOSecurityPolicy.Tests.ps1 --- ...icrosoft365DSC.ADOSecurityPolicy.Tests.ps1 | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOSecurityPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOSecurityPolicy.Tests.ps1 index 2b107124ba..1c3c5a591c 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOSecurityPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOSecurityPolicy.Tests.ps1 @@ -90,9 +90,29 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } + $Script:callCount = 0 Mock -CommandName Invoke-M365DSCAzureDevOPSWebRequest -MockWith { - return @{ - Value = $true + if ($Script:callCount -eq 0) + { + $Script:callCount++ + return @{ + id = '12345-12345-12345-12345' + } + } + elseif ($Script:callCount -eq 1) + { + $Script:callCount++ + return @{ + value = @{ + accountName = 'TestOrg' + } + } + } + else + { + return @{ + Value = $true + } } } } From 7c824d0401fcda3f654eaa13e556aea853e177ef Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 17 Sep 2024 16:01:23 +0000 Subject: [PATCH 193/465] Updated Resources and Cmdlet documentation pages --- .../resources/azure-ad/ADOSecurityPolicy.md | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 docs/docs/resources/azure-ad/ADOSecurityPolicy.md diff --git a/docs/docs/resources/azure-ad/ADOSecurityPolicy.md b/docs/docs/resources/azure-ad/ADOSecurityPolicy.md new file mode 100644 index 0000000000..097db8ee32 --- /dev/null +++ b/docs/docs/resources/azure-ad/ADOSecurityPolicy.md @@ -0,0 +1,100 @@ +# ADOSecurityPolicy + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **OrganizationName** | Key | String | The name of the Azure DevOPS Organization. | | +| **DisallowAadGuestUserAccess** | Write | Boolean | Controls the external guest access. | | +| **DisallowOAuthAuthentication** | Write | Boolean | Controls the Third-party application access via OAuth. | | +| **DisallowSecureShell** | Write | Boolean | Controls SSH Authentication. | | +| **LogAuditEvents** | Write | Boolean | Controls Log Audit Events. | | +| **AllowAnonymousAccess** | Write | Boolean | Controls the Allow public projects setting. | | +| **ArtifactsExternalPackageProtectionToken** | Write | Boolean | Controls the Additional protections when using public package registries setting. | | +| **EnforceAADConditionalAccess** | Write | Boolean | Controls the Enable IP Conditional Access policy validation setting. | | +| **AllowTeamAdminsInvitationsAccessToken** | Write | Boolean | Controls the Allow team and project administrators to invite new user setting. | | +| **AllowRequestAccessToken** | Write | Boolean | Controls the Request access setting. | | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Configures Azure DevOPS Security Policies. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + ADOSecurityPolicy "ADOPolicy" + { + AllowAnonymousAccess = $True; + AllowRequestAccessToken = $False; + AllowTeamAdminsInvitationsAccessToken = $True; + ApplicationId = $ApplicationId; + ArtifactsExternalPackageProtectionToken = $False; + CertificateThumbprint = $CertificateThumbprint; + DisallowAadGuestUserAccess = $True; + DisallowOAuthAuthentication = $True; + DisallowSecureShell = $False; + EnforceAADConditionalAccess = $False; + LogAuditEvents = $True; + OrganizationName = "O365DSC-Dev"; + TenantId = $TenantId; + } + } +} +``` + From 5c4d8553ce8716d262e883a062743afbee0b9935 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 17 Sep 2024 16:03:32 +0000 Subject: [PATCH 194/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 7add973497..f7129c1b7b 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -5154,6 +5154,91 @@ } ] }, + { + "ClassName": "MSFT_ADOSecurityPolicy", + "Parameters": [ + { + "CIMType": "String", + "Name": "OrganizationName", + "Option": "Key" + }, + { + "CIMType": "Boolean", + "Name": "DisallowAadGuestUserAccess", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "DisallowOAuthAuthentication", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "DisallowSecureShell", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "LogAuditEvents", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowAnonymousAccess", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ArtifactsExternalPackageProtectionToken", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EnforceAADConditionalAccess", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowTeamAdminsInvitationsAccessToken", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowRequestAccessToken", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AzureSubscription", "Parameters": [ From ed7720371239675cd34d543f4f9671344a23a999 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Tue, 17 Sep 2024 09:26:49 -0700 Subject: [PATCH 195/465] Add initial EXOATPProtectionPolicyRule resource --- .../MSFT_EXOATPProtectionPolicyRule.psm1 | 533 ++++++++++++++++++ ...MSFT_EXOATPProtectionPolicyRule.schema.mof | 25 + .../MSFT_EXOATPProtectionPolicyRule/readme.md | 6 + .../settings.json | 32 ++ .../EXOATPProtectionPolicyRule/1-Create.ps1 | 26 + .../EXOATPProtectionPolicyRule/2-Update.ps1 | 26 + .../EXOATPProtectionPolicyRule/3-Remove.ps1 | 26 + ...65DSC.EXOATPProtectionPolicyRule.Tests.ps1 | 176 ++++++ 8 files changed, 850 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPProtectionPolicyRule.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.psm1 new file mode 100644 index 0000000000..c8a612eb27 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.psm1 @@ -0,0 +1,533 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Comments, + + [Parameter()] + [System.Boolean] + $Enabled, + + [Parameter()] + [System.String[]] + $ExceptIfRecipientDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfSentTo, + + [Parameter()] + [System.String[]] + $ExceptIfSentToMemberOf, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.UInt32] + $Priority, + + [Parameter()] + [System.String[]] + $RecipientDomainIs, + + [Parameter()] + [System.String] + $SafeAttachmentPolicy, + + [Parameter()] + [System.String] + $SafeLinksPolicy, + + [Parameter()] + [System.String[]] + $SentTo, + + [Parameter()] + [System.String[]] + $SentToMemberOf, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Identity -eq $Identity} + } + else + { + $instance = Get-ATPProtectionPolicyRule -Identity $Identity -ErrorAction Stop + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + Identity = $instance.Identity + Ensure = 'Present' + Comments = $instance.Comments + Enabled = $instance.State -eq 'Enabled' + ExceptIfRecipientDomainIs = $instance.ExceptIfRecipientDomainIs + ExceptIfSentTo = $instance.ExceptIfSentTo + ExceptIfSentToMemberOf = $instance.ExceptIfSentToMemberOf + Name = $instance.Name + Priority = $instance.Priority + RecipientDomainIs = $instance.RecipientDomainIs + SafeAttachmentPolicy = $instance.SafeAttachmentPolicy + SafeLinksPolicy = $instance.SafeLinksPolicy + SentTo = $instance.SentTo + SentToMemberOf = $instance.SentToMemberOf + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Comments, + + [Parameter()] + [System.Boolean] + $Enabled, + + [Parameter()] + [System.String[]] + $ExceptIfRecipientDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfSentTo, + + [Parameter()] + [System.String[]] + $ExceptIfSentToMemberOf, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.UInt32] + $Priority, + + [Parameter()] + [System.String[]] + $RecipientDomainIs, + + [Parameter()] + [System.String] + $SafeAttachmentPolicy, + + [Parameter()] + [System.String] + $SafeLinksPolicy, + + [Parameter()] + [System.String[]] + $SentTo, + + [Parameter()] + [System.String[]] + $SentToMemberOf, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + New-ATPProtectionPolicyRule @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + if ($currentInstance.SafeAttachmentPolicy -ne $SetParameters.SafeAttachmentPolicy) + { + throw "SafeAttachmentPolicy cannot be changed after creation" + } + if ($currentInstance.SafeLinksPolicy -ne $SetParameters.SafeLinksPolicy) + { + throw "SafeLinksPolicy cannot be changed after creation" + } + + # Enabled state can only be changed by the Enabled/Disable-ATPProtectionPolicyRule cmdlets + if ($currentInstance.Enabled -ne $setParameters.Enabled) + { + Write-Verbose -Message "Changing Enabled state of the ATPProtectionPolicyRule $($currentInstance.Identity) from $($currentInstance.Enabled) to $($setParameters.Enabled)" + if ($setParameters.Enabled) + { + Enable-ATPProtectionPolicyRule -Identity $currentInstance.Identity + } + else + { + Disable-ATPProtectionPolicyRule -Identity $currentInstance.Identity + } + } + + $SetParameters.Remove("SafeLinksPolicy") | Out-Null + $SetParameters.Remove("SafeAttachmentPolicy") | Out-Null + $SetParameters.Remove("Enabled") | Out-Null + + Set-ATPProtectionPolicyRule @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Remove cmdlet for the resource + Remove-ATPProtectionPolicyRule -Identity $currentInstance.Identity + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Comments, + + [Parameter()] + [System.Boolean] + $Enabled, + + [Parameter()] + [System.String[]] + $ExceptIfRecipientDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfSentTo, + + [Parameter()] + [System.String[]] + $ExceptIfSentToMemberOf, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.UInt32] + $Priority, + + [Parameter()] + [System.String[]] + $RecipientDomainIs, + + [Parameter()] + [System.String] + $SafeAttachmentPolicy, + + [Parameter()] + [System.String] + $SafeLinksPolicy, + + [Parameter()] + [System.String[]] + $SentTo, + + [Parameter()] + [System.String[]] + $SentToMemberOf, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace workload + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-ATPProtectionPolicyRule -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Identity + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Identity = $config.Identity + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.schema.mof new file mode 100644 index 0000000000..2c7fcdfa6a --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.schema.mof @@ -0,0 +1,25 @@ +[ClassVersion("1.0.0.0"), FriendlyName("EXOATPProtectionPolicyRule")] +class MSFT_EXOATPProtectionPolicyRule : OMI_BaseResource +{ + [Key, Description("Identifier for the rule")] String Identity; + [Write, Description("Specifies whether the rule is enabled")] Boolean Enabled; + [Write, Description("Informative comments for the rule, such as what the rule is used for or how it has changed over time. The length of the comment can't exceed 1024 characters.")] String Comments; + [Write, Description("Specifies an exception that looks for recipients with email addresses in the specified domains.")] String ExceptIfRecipientDomainIs[]; + [Write, Description("Specifies an exception that looks for recipients in messages. You can use any value that uniquely identifies the recipient")] String ExceptIfSentTo[]; + [Write, Description("Specifies an exception that looks for messages sent to members of groups. You can use any value that uniquely identifies the group.")] String ExceptIfSentToMemberOf[]; + [Write, Description("Unique name for the rule. The maximum length is 64 characters.")] String Name; + [Write, Description("Specifies a priority value for the rule that determines the order of rule processing. A lower integer value indicates a higher priority, the value 0 is the highest priority, and rules can't have the same priority value.")] UInt32 Priority; + [Write, Description("Specifies a condition that looks for recipients with email addresses in the specified domains.")] String RecipientDomainIs[]; + [Write, Description("Specifies the existing Safe Attachments policy that's associated with the preset security policy.")] String SafeAttachmentPolicy; + [Write, Description("Specifies the existing Safe Links policy that's associated with the preset security policy.")] String SafeLinksPolicy; + [Write, Description("Specifies a condition that looks for recipients in messages. You can use any value that uniquely identifies the recipient.")] String SentTo[]; + [Write, Description("Specifies a condition that looks for messages sent to members of distribution groups, dynamic distribution groups, or mail-enabled security groups. ")] String SentToMemberOf[]; + + [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/readme.md new file mode 100644 index 0000000000..32e0e7fb27 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/readme.md @@ -0,0 +1,6 @@ + +# ResourceName + +## Description + +##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/settings.json new file mode 100644 index 0000000000..edf14b05e4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "ResourceName", + "description": "Description of what the resource is about.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/1-Create.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/1-Create.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/2-Update.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/3-Remove.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/3-Remove.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPProtectionPolicyRule.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPProtectionPolicyRule.Tests.ps1 new file mode 100644 index 0000000000..20857e0393 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPProtectionPolicyRule.Tests.ps1 @@ -0,0 +1,176 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -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 a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 remove the instance from the Set method' { + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + 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 + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 c9fe30291e82d0cb6d93f3190d972a69ac6fe38e Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Tue, 17 Sep 2024 11:07:00 -0700 Subject: [PATCH 196/465] Working unit tests --- .../MSFT_EXOATPProtectionPolicyRule.psm1 | 1 + ...65DSC.EXOATPProtectionPolicyRule.Tests.ps1 | 134 +++++++++++++--- Tests/Unit/Stubs/Microsoft365.psm1 | 148 ++++++++++++++++++ 3 files changed, 258 insertions(+), 25 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.psm1 index c8a612eb27..46ffac1760 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.psm1 @@ -261,6 +261,7 @@ function Set-TargetResource # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { + $SetParameters.Remove('Identity') | Out-Null New-ATPProtectionPolicyRule @SetParameters } # UPDATE diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPProtectionPolicyRule.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPProtectionPolicyRule.Tests.ps1 index 20857e0393..fe48cd1ed0 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPProtectionPolicyRule.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPProtectionPolicyRule.Tests.ps1 @@ -35,8 +35,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets - # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { } @@ -47,15 +45,20 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters + Identity = 'TestRule' Ensure = 'Present' Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-ATPProtectionPolicyRule -MockWith { return $null } + + Mock -CommandName New-ATPProtectionPolicyRule -MockWith { + return @{ + Identity = 'TestRule' + } + } } It 'Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' @@ -65,25 +68,28 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should create a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one - Should -Invoke -CommandName New-Cmdlet -Exactly 1 + Set-TargetResource @testParams + Should -Invoke -CommandName New-ATPProtectionPolicyRule -Exactly 1 } } Context -Name "The instance exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters + Identity = 'TestRule' Ensure = 'Absent' Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-ATPProtectionPolicyRule -MockWith { return @{ - + Identity = 'TestRule' } } + + Mock -CommandName Remove-ATPProtectionPolicyRule -MockWith { + return $null + } } It 'Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Present' @@ -93,23 +99,28 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should remove the instance from the Set method' { - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-ATPProtectionPolicyRule -Exactly 1 } } Context -Name "The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters + Identity = 'TestRule' Ensure = 'Present' Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-ATPProtectionPolicyRule -MockWith { return @{ + Identity = 'TestRule' + } + } + Mock -CommandName Set-ATPProtectionPolicyRule -MockWith { + return @{ + Identity = 'TestRule' } } } @@ -122,17 +133,22 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters + Identity = 'TestRule' + Comments = 'TestComment' Ensure = 'Present' Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-ATPProtectionPolicyRule -MockWith { return @{ - + Identity = 'TestRule' + Comments = 'TestComment #DriftValue' } } + + Mock -CommandName Set-ATPProtectionPolicyRule -MockWith { + return $testParams + } } It 'Should return Values from the Get method' { @@ -145,8 +161,77 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the Set method' { Set-TargetResource @testParams - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + Should -Invoke -CommandName Set-ATPProtectionPolicyRule -Exactly 1 + } + } + + Context -Name "The instance exists and should be disabled, but is not" -Fixture { + BeforeAll { + $testParams = @{ + Identity = 'TestRule' + Ensure = 'Present' + Enabled = $false + Credential = $Credential; + } + + Mock -CommandName Get-ATPProtectionPolicyRule -MockWith { + return @{ + Identity = 'TestRule' + State = 'Enabled' + } + } + + Mock -CommandName Set-ATPProtectionPolicyRule -MockWith { + return $testParams + } + + Mock -CommandName Disable-ATPProtectionPolicyRule -MockWith { + return $null + } + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Disable method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Disable-ATPProtectionPolicyRule -Exactly 1 + } + } + + Context -Name "The instance exists and should be enabled, but is not" -Fixture { + BeforeAll { + $testParams = @{ + Identity = 'TestRule' + Ensure = 'Present' + Enabled = $True + Credential = $Credential; + } + + Mock -CommandName Get-ATPProtectionPolicyRule -MockWith { + return @{ + Identity = 'TestRule' + State = 'Disabled' + } + } + + Mock -CommandName Set-ATPProtectionPolicyRule -MockWith { + return $testParams + } + + Mock -CommandName Enable-ATPProtectionPolicyRule -MockWith { + return $null + } + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Enable method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Enable-ATPProtectionPolicyRule -Exactly 1 } } @@ -158,10 +243,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-ATPProtectionPolicyRule -MockWith { return @{ - + Identity = 'TestRule' } } } diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 36fb0879a9..c0d69578be 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -67,6 +67,16 @@ function Get-AzSubscription ) } +function Enable-ATPProtectionPolicyRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Identity + ) +} + function Enable-AzSubscription { [CmdletBinding()] @@ -77,6 +87,16 @@ function Enable-AzSubscription ) } +function Disable-ATPProtectionPolicyRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Identity + ) +} + function Disable-AzSubscription { [CmdletBinding()] @@ -1234,6 +1254,21 @@ function Get-ApplicationAccessPolicy $Identity ) } + +function Get-ATPProtectionPolicyRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $State + ) +} + function Get-AtpPolicyForO365 { [CmdletBinding()] @@ -3410,6 +3445,61 @@ function New-ApplicationAccessPolicy $AppId ) } + +function New-ATPProtectionPolicyRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $SafeAttachmentPolicy, + + [Parameter()] + [System.String] + $SafeLinksPolicy, + + [Parameter()] + [System.String] + $Comments, + + [Parameter()] + [System.Boolean] + $Enabled, + + [Parameter()] + [System.String[]] + $ExceptIfRecipientDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfSentTo, + + [Parameter()] + [System.String[]] + $ExceptIfSentToMemberOf, + + [Parameter()] + [System.UInt32] + $Priority, + + [Parameter()] + [System.String[]] + $RecipientDomainIs, + + [Parameter()] + [System.String[]] + $SentTo, + + [Parameter()] + [System.String[]] + $SentToMemberOf + ) +} + function New-AuthenticationPolicy { [CmdletBinding()] @@ -7121,6 +7211,17 @@ function Remove-ApplicationAccessPolicy $Identity ) } + +function Remove-ATPProtectionPolicyRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Identity + ) +} + function Remove-AuditConfigurationPolicy { [CmdletBinding()] @@ -8370,6 +8471,53 @@ function Set-AtpPolicyForO365 $Confirm ) } + +function Set-ATPProtectionPolicyRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Comments, + + [Parameter()] + [System.String] + $ExceptIfRecipientDomainIs, + + [Parameter()] + [System.String] + $ExceptIfSentTo, + + [Parameter()] + [System.String] + $ExceptIfSentToMemberOf, + + [Parameter()] + [System.String] + $String, + + [Parameter()] + [System.UInt32] + $Priority, + + [Parameter()] + [System.String[]] + $RecipientDomainIs, + + [Parameter()] + [System.String[]] + $SentTo, + + [Parameter()] + [System.String[]] + $SentToMemberOf + ) +} + function Set-AuthenticationPolicy { [CmdletBinding()] From 82c9c91cd8a9c5aea9362a4acd8331c87a95b5c7 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 17 Sep 2024 14:51:10 -0400 Subject: [PATCH 197/465] Updates --- .../MSFT_ADOOrganizationOwner.psm1 | 252 ++++++------------ .../MSFT_ADOOrganizationOwner.schema.mof | 4 +- 2 files changed, 81 insertions(+), 175 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 index 16737611db..def4556018 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 @@ -6,21 +6,12 @@ function Get-TargetResource ( [Parameter(Mandatory = $true)] [System.String] - $Name, - - [Parameter()] - [System.String] - $Id, + $OrganizationName, [Parameter()] [System.String] $Owner, - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', - [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -46,8 +37,8 @@ function Get-TargetResource $AccessTokens ) - New-M365DSCConnection -Workload 'AzureDevOPS' ` - -InboundParameters $PSBoundParameters | Out-Null + $ConnectionMode = New-M365DSCConnection -Workload 'AzureDevOPS' ` + -InboundParameters $PSBoundParameters #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -62,38 +53,17 @@ function Get-TargetResource #endregion $nullResult = $PSBoundParameters - $nullResult.Ensure = 'Absent' try { - if ($null -ne $Script:exportedInstances -and $Script:ExportMode) - { - if (-not [System.String]::IsNullOrEmpty($Id)) - { - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} - } - if ($null -eq $instance -and -not [System.String]::IsNullOrEmpty($Name)) - { - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Name -eq $Name} - } - } - else - { - $instance = Get-M365DSCADOOrganization -Name $Name -ErrorAction Stop - } - if ($null -eq $instance) - { - return $nullResult - } - - New-M365DSCConnection -Workload 'MicrosoftGraph' ` - -InboundParameters $PSBoundParameters | Out-Null + $uri = "https://vssps.dev.azure.com/$OrganizationName/_apis/Organization/Collections/Me" + $organizationInfo = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri - $owner = Get-MgUser -UserId $instance.owner + $uri = "https://app.vssps.visualstudio.com/_apis/profile/profiles/$($organizationInfo.Owner)?api-version=7.1-preview.3" + $ownerInfo = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri $results = @{ - Name = $instance.Name - Id = $instance.Id - Owner = $owner.UserPrincipalName + OrganizationName = $OrganizationName + Owner = $ownerInfo.EmailAddress Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -122,12 +92,13 @@ function Set-TargetResource [CmdletBinding()] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $OrganizationName, - ##TODO - Add the list of Parameters + [Parameter()] + [System.String] + $Owner, [Parameter()] [System.Management.Automation.PSCredential] @@ -153,6 +124,8 @@ function Set-TargetResource [System.String[]] $AccessTokens ) + $ConnectionMode = New-M365DSCConnection -Workload 'AzureDevOPS' ` + -InboundParameters $PSBoundParameters #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -166,28 +139,12 @@ function Set-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - $currentInstance = Get-TargetResource @PSBoundParameters + - $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters - - # CREATE - if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') - { - ##TODO - Replace by the New cmdlet for the resource - New-Cmdlet @SetParameters - } - # UPDATE - elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') - { - ##TODO - Replace by the Update/Set cmdlet for the resource - Set-cmdlet @SetParameters - } - # REMOVE - elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') - { - ##TODO - Replace by the Remove cmdlet for the resource - Remove-cmdlet @SetParameters - } + $body = "[{`"from`":`"`",`"op`":2,`"path`":`"/Owner`",`"value`":`"a76a2017-0aee-69fd-9300-cf624aaff3a9`"}]" + $uri ='https://vssps.dev.azure.com/O365DSC-Dev/_apis/Organization/Collections/Me?api-version=7.1-preview.1' + $org = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri + Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri -Method PATCH -Body $body } function Test-TargetResource @@ -196,12 +153,13 @@ function Test-TargetResource [OutputType([System.Boolean])] param ( - ##TODO - Replace the PrimaryKey [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $OrganizationName, - ##TODO - Add the list of Parameters + [Parameter()] + [System.String] + $Owner, [Parameter()] [System.Management.Automation.PSCredential] @@ -255,7 +213,6 @@ function Test-TargetResource return $testResult } - function Export-TargetResource { [CmdletBinding()] @@ -291,75 +248,69 @@ function Export-TargetResource $AccessTokens ) - ##TODO - Replace workload - $ConnectionMode = New-M365DSCConnection -Workload 'AzureDevOPS' ` - -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 { + $ConnectionMode = New-M365DSCConnection -Workload 'AzureDevOPS' ` + -InboundParameters $PSBoundParameters + + #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 + $Script:ExportMode = $true - $organizations = Get-M365DSCADOOrganizationList - foreach ($organization in $organizations) - { - [array] $Script:exportedInstances = Get-M365DSCADOOrganization -Name 'O365DSC-Dev' + $profile = Invoke-M365DSCAzureDevOPSWebRequest -Uri 'https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=5.1' + $accounts = Invoke-M365DSCAzureDevOPSWebRequest -Uri "https://app.vssps.visualstudio.com/_apis/accounts?api-version=7.1-preview.1&memberId=$($profile.id)" - $i = 1 - $dscContent = '' - if ($Script:exportedInstances.Length -eq 0) - { - Write-Host $Global:M365DSCEmojiGreenCheckMark - } - else + $i = 1 + $dscContent = '' + if ($accounts.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($account in $accounts) + { + $organization = $account.Value.accountName + if ($null -ne $Global:M365DSCExportResourceInstancesCount) { - Write-Host "`r`n" -NoNewline + $Global:M365DSCExportResourceInstancesCount++ } - foreach ($config in $Script:exportedInstances) - { - if ($null -ne $Global:M365DSCExportResourceInstancesCount) - { - $Global:M365DSCExportResourceInstancesCount++ - } - $displayedKey = $config.name - Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline - $params = @{ - Name = $config.name - Id = $config.id - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens - } - - $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 + + $displayedKey = $organization + Write-Host " |---[$i/$($accounts.Count)] $displayedKey" -NoNewline + $params = @{ + OrganizationName = $organization + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens } + + $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 } @@ -377,49 +328,4 @@ function Export-TargetResource } } -function Get-M365DSCADOOrganization -{ - [CmdletBinding()] - param( - [Parameter(Mandatory = $true)] - [System.String] - $Name - ) - - $headers = @{ - Authorization = $Global:MSCloudLoginConnectionProfile.AzureDevOPS.AccessToken - 'Content-Type' = "application/json-patch+json" - } - - $uri = "https://vssps.dev.azure.com/$Name/_apis/Organization/Collections/Me" - - $response = Invoke-WebRequest -Method GET ` - -Uri $uri ` - -Headers $headers - - $results = ConvertFrom-Json ($response.Content) - return $results -} - -function Get-M365DSCADOOrganizationList -{ - [CmdletBinding()] - param( - ) - - $headers = @{ - Authorization = $Global:MSCloudLoginConnectionProfile.AzureDevOPS.AccessToken - 'Content-Type' = "application/json-patch+json" - } - - $uri = "https://app.vssps.visualstudio.com/_apis/profile/profiles/me" - - $response = Invoke-WebRequest -Method GET ` - -Uri $uri ` - -Headers $headers - - $results = ConvertFrom-Json ($response.Content) - return $results -} - Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.schema.mof index 158f518689..57ba50bb59 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.schema.mof @@ -1,8 +1,8 @@ [ClassVersion("1.0.0.0"), FriendlyName("ADOOrganizationOwner")] class MSFT_ADOOrganizationOwner : OMI_BaseResource { - [Key, Description("")] String PrimaryKey; - [Write, Description("")] String OtherProperties; + [Key, Description("")] String OrganizationName; + [Write, Description("")] String Owner; [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 0e452a620ae7b235afc9f1f36879857fd05c6d18 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Tue, 17 Sep 2024 12:03:11 -0700 Subject: [PATCH 198/465] Update Readme + settings.json --- .../MSFT_EXOATPProtectionPolicyRule/readme.md | 4 +-- .../settings.json | 27 ++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/readme.md index 32e0e7fb27..5d125b34c4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/readme.md @@ -1,6 +1,6 @@ -# ResourceName +# EXOATPProtectionPolicyRule ## Description -##TODO - Provide a short description of what the resource is set to configure. +Manage ATP Protection policy rules that are associated with Microsoft Defender for Office 365 protections in preset security policies. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/settings.json index edf14b05e4..8ca47640d7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/settings.json @@ -1,12 +1,12 @@ { "resourceName": "ResourceName", - "description": "Description of what the resource is about.", + "description": "Manage ATP Protection policy rules that are associated with Microsoft Defender for Office 365 protections in preset security policies.", "roles": { "read": [ - "Role" + "Security Reader" ], "update": [ - "Role" + "Security Administrator" ] }, "permissions": { @@ -16,17 +16,18 @@ "update": [] }, "application": { - "read": [ - { - "name": "Permission for Monitoring and Export" - } - ], - "update": [ - { - "name": "Permission for deploying" - } - ] + "read": [], + "update": [] } + }, + "exchange": { + "requiredroles": [ + "Transport Hygiene", + "Security Admin", + "View-Only Configuration", + "Security Reader" + ], + "requiredrolegroups": "Organization Management" } } } From ca43fcabb51accb0cb88b9b20570123cf3b7838c Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Tue, 17 Sep 2024 12:13:58 -0700 Subject: [PATCH 199/465] Fix casing of resource name --- .../MSFT_EXOAtpProtectionPolicyRule.psm1} | 0 .../MSFT_EXOAtpProtectionPolicyRule.schema.mof} | 4 ++-- .../readme.md | 0 .../settings.json | 0 .../1-Create.ps1 | 0 .../2-Update.ps1 | 0 .../3-Remove.ps1 | 0 ...1 => Microsoft365DSC.EXOAtpProtectionPolicyRule.Tests.ps1} | 0 8 files changed, 2 insertions(+), 2 deletions(-) rename Modules/Microsoft365DSC/DSCResources/{MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.psm1 => MSFT_EXOAtpProtectionPolicyRule/MSFT_EXOAtpProtectionPolicyRule.psm1} (100%) rename Modules/Microsoft365DSC/DSCResources/{MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.schema.mof => MSFT_EXOAtpProtectionPolicyRule/MSFT_EXOAtpProtectionPolicyRule.schema.mof} (96%) rename Modules/Microsoft365DSC/DSCResources/{MSFT_EXOATPProtectionPolicyRule => MSFT_EXOAtpProtectionPolicyRule}/readme.md (100%) rename Modules/Microsoft365DSC/DSCResources/{MSFT_EXOATPProtectionPolicyRule => MSFT_EXOAtpProtectionPolicyRule}/settings.json (100%) rename Modules/Microsoft365DSC/Examples/Resources/{EXOATPProtectionPolicyRule => EXOAtpProtectionPolicyRule}/1-Create.ps1 (100%) rename Modules/Microsoft365DSC/Examples/Resources/{EXOATPProtectionPolicyRule => EXOAtpProtectionPolicyRule}/2-Update.ps1 (100%) rename Modules/Microsoft365DSC/Examples/Resources/{EXOATPProtectionPolicyRule => EXOAtpProtectionPolicyRule}/3-Remove.ps1 (100%) rename Tests/Unit/Microsoft365DSC/{Microsoft365DSC.EXOATPProtectionPolicyRule.Tests.ps1 => Microsoft365DSC.EXOAtpProtectionPolicyRule.Tests.ps1} (100%) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAtpProtectionPolicyRule/MSFT_EXOAtpProtectionPolicyRule.psm1 similarity index 100% rename from Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.psm1 rename to Modules/Microsoft365DSC/DSCResources/MSFT_EXOAtpProtectionPolicyRule/MSFT_EXOAtpProtectionPolicyRule.psm1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAtpProtectionPolicyRule/MSFT_EXOAtpProtectionPolicyRule.schema.mof similarity index 96% rename from Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.schema.mof rename to Modules/Microsoft365DSC/DSCResources/MSFT_EXOAtpProtectionPolicyRule/MSFT_EXOAtpProtectionPolicyRule.schema.mof index 2c7fcdfa6a..436b9628c8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/MSFT_EXOATPProtectionPolicyRule.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAtpProtectionPolicyRule/MSFT_EXOAtpProtectionPolicyRule.schema.mof @@ -1,5 +1,5 @@ -[ClassVersion("1.0.0.0"), FriendlyName("EXOATPProtectionPolicyRule")] -class MSFT_EXOATPProtectionPolicyRule : OMI_BaseResource +[ClassVersion("1.0.0.0"), FriendlyName("EXOAtpProtectionPolicyRule")] +class MSFT_EXOAtpProtectionPolicyRule : OMI_BaseResource { [Key, Description("Identifier for the rule")] String Identity; [Write, Description("Specifies whether the rule is enabled")] Boolean Enabled; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAtpProtectionPolicyRule/readme.md similarity index 100% rename from Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/readme.md rename to Modules/Microsoft365DSC/DSCResources/MSFT_EXOAtpProtectionPolicyRule/readme.md diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAtpProtectionPolicyRule/settings.json similarity index 100% rename from Modules/Microsoft365DSC/DSCResources/MSFT_EXOATPProtectionPolicyRule/settings.json rename to Modules/Microsoft365DSC/DSCResources/MSFT_EXOAtpProtectionPolicyRule/settings.json diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/1-Create.ps1 similarity index 100% rename from Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/1-Create.ps1 rename to Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/1-Create.ps1 diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/2-Update.ps1 similarity index 100% rename from Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/2-Update.ps1 rename to Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/2-Update.ps1 diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/3-Remove.ps1 similarity index 100% rename from Modules/Microsoft365DSC/Examples/Resources/EXOATPProtectionPolicyRule/3-Remove.ps1 rename to Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/3-Remove.ps1 diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPProtectionPolicyRule.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAtpProtectionPolicyRule.Tests.ps1 similarity index 100% rename from Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOATPProtectionPolicyRule.Tests.ps1 rename to Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAtpProtectionPolicyRule.Tests.ps1 From a8bd28515cfd37967fc2ec310844876c988cedbc Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Tue, 17 Sep 2024 12:20:44 -0700 Subject: [PATCH 200/465] Update examples --- .../EXOAtpProtectionPolicyRule/1-Create.ps1 | 15 ++++++++++++++- .../EXOAtpProtectionPolicyRule/2-Update.ps1 | 15 ++++++++++++++- .../EXOAtpProtectionPolicyRule/3-Remove.ps1 | 15 ++++++++++++++- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/1-Create.ps1 index b516274848..747e49a549 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/1-Create.ps1 @@ -21,6 +21,19 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + EXOATPProtectionPolicyRule "EXOATPProtectionPolicyRule-Strict Preset Security Policy" + { + Comments = "Built-in Strict Preset Security Policy"; + Enabled = $False; + Identity = "Strict Preset Security Policy"; + Name = "Strict Preset Security Policy"; + Priority = 0; + SafeAttachmentPolicy = "Strict Preset Security Policy1725468967835"; + SafeLinksPolicy = "Strict Preset Security Policy1725468969412"; + Ensure = "Present" + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/2-Update.ps1 index b516274848..1cd2df9588 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/2-Update.ps1 @@ -21,6 +21,19 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + EXOATPProtectionPolicyRule "EXOATPProtectionPolicyRule-Strict Preset Security Policy" + { + Comments = "Built-in Strict Preset Security Policy with comments"; # Changed value + Enabled = $True; # Changed value + Identity = "Strict Preset Security Policy"; + Name = "Strict Preset Security Policy"; + Priority = 0; + SafeAttachmentPolicy = "Strict Preset Security Policy1725468967835"; + SafeLinksPolicy = "Strict Preset Security Policy1725468969412"; + Ensure = "Present" + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/3-Remove.ps1 index b516274848..2052e05050 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAtpProtectionPolicyRule/3-Remove.ps1 @@ -21,6 +21,19 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + EXOATPProtectionPolicyRule "EXOATPProtectionPolicyRule-Strict Preset Security Policy" + { + Comments = "Built-in Strict Preset Security Policy"; + Enabled = $False; + Identity = "Strict Preset Security Policy"; + Name = "Strict Preset Security Policy"; + Priority = 0; + SafeAttachmentPolicy = "Strict Preset Security Policy1725468967835"; + SafeLinksPolicy = "Strict Preset Security Policy1725468969412"; + Ensure = "Absent" + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } } } From 06c9dff52f05ed0e0f420b2a74b28452252ab6e6 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Sat, 14 Sep 2024 14:40:59 +0200 Subject: [PATCH 201/465] Update Settings Catalog resource generation --- .../M365DSCResourceGenerator.psm1 | 154 ++++++++++++++---- 1 file changed, 125 insertions(+), 29 deletions(-) diff --git a/ResourceGenerator/M365DSCResourceGenerator.psm1 b/ResourceGenerator/M365DSCResourceGenerator.psm1 index 803062322d..23560cbd98 100644 --- a/ResourceGenerator/M365DSCResourceGenerator.psm1 +++ b/ResourceGenerator/M365DSCResourceGenerator.psm1 @@ -245,11 +245,13 @@ function New-M365DSCResource } $templateSettings = @() + $allSettingDefinitions = $SettingsCatalogSettingTemplates.SettingDefinitions foreach ($settingTemplate in $SettingsCatalogSettingTemplates) { $templateSettings += New-SettingsCatalogSettingDefinitionSettingsFromTemplate ` -FromRoot ` - -SettingTemplate $settingTemplate + -SettingTemplate $settingTemplate ` + -AllSettingDefinitions $allSettingDefinitions } $definitionSettings = @() @@ -3749,6 +3751,10 @@ function New-SettingsCatalogSettingDefinitionSettingsFromTemplate { [Parameter(ParameterSetName = "Start")] [switch] $FromRoot, + [Parameter(Mandatory = $true)] + [System.Array] + $AllSettingDefinitions, + [Parameter(ParameterSetName = "ParseChild")] [System.String]$ParentInstanceName, @@ -3766,7 +3772,8 @@ function New-SettingsCatalogSettingDefinitionSettingsFromTemplate { return New-SettingsCatalogSettingDefinitionSettingsFromTemplate ` -SettingTemplate $SettingTemplate ` -RootSettingDefinitions $RootSettingDefinitions ` - -SettingDefinitionIdPrefix $settingDefinitionIdPrefix + -SettingDefinitionIdPrefix $settingDefinitionIdPrefix ` + -AllSettingDefinitions $AllSettingDefinitions } if ($PSCmdlet.ParameterSetName -eq "ParseRoot") { @@ -3777,7 +3784,8 @@ function New-SettingsCatalogSettingDefinitionSettingsFromTemplate { -SettingDefinition $RootSettingDefinition ` -SettingDefinitionIdPrefix $settingDefinitionIdPrefix ` -Level 1 ` - -ParentInstanceName "MSFT_MicrosoftGraphIntuneSettingsCatalog" + -ParentInstanceName "MSFT_MicrosoftGraphIntuneSettingsCatalog" ` + -AllSettingDefinitions $AllSettingDefinitions } return $settings } @@ -3789,39 +3797,53 @@ function New-SettingsCatalogSettingDefinitionSettingsFromTemplate { $settingName = $SettingDefinition.Name - $settingsWithSameName = $SettingTemplate.SettingDefinitions | Where-Object -FilterScript { $_.Name -eq $settingName } - if ($settingsWithSameName.Count -gt 1) { + $settingsWithSameName = $AllSettingDefinitions | Where-Object -FilterScript { $_.Name -eq $settingName } + if ($settingsWithSameName.Count -gt 1) + { # Get the parent setting of the current setting - if ($SettingDefinition.AdditionalProperties.dependentOn.parentSettingId.Count -gt 0) + $parentSetting = Get-ParentSettingDefinition -SettingDefinition $SettingDefinition -AllSettingDefinitions $AllSettingDefinitions + if ($null -ne $parentSetting) { - $parentSetting = $SettingTemplate.SettingDefinitions | Where-Object -FilterScript { - $_.Id -eq ($SettingDefinition.AdditionalProperties.dependentOn.parentSettingId | Select-Object -Unique -First 1) + $combinationMatchesWithParent = $settingsWithSameName | Where-Object -FilterScript { + "$($parentSetting.Name)_$($_.Name)" -eq "$($parentSetting.Name)_$settingName" } - } - elseif ($SettingDefinition.AdditionalProperties.options.dependentOn.parentSettingId.Count -gt 0) - { - $parentSetting = $SettingTemplate.SettingDefinitions | Where-Object -FilterScript { - $_.Id -eq ($SettingDefinition.AdditionalProperties.options.dependentOn.parentSettingId | Select-Object -Unique -First 1) + # If the combination of parent setting and setting name is unique, add the parent setting name to the setting name + if ($combinationMatchesWithParent.Count -eq 1) + { + $settingName = $parentSetting.Name + "_" + $settingName } - } + # If the combination of parent setting and setting name is still not unique, do it with the OffsetUri of the current setting + else + { + $skip = 0 + $newSettingName = $settingName + do { + $previousSettingName = $newSettingName + $newSettingName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $SettingDefinition.OffsetUri -SettingName $newSettingName -Skip $skip - $combinationMatches = $SettingTemplate.SettingDefinitions | Where-Object -FilterScript { - $_.Name -eq $settingName -and - (($_.AdditionalProperties.dependentOn.Count -gt 0 -and $_.AdditionalProperties.dependentOn.parentSettingId -contains $parentSetting.Id) -or - ($_.AdditionalProperties.options.dependentOn.Count -gt 0 -and $_.AdditionalProperties.options.dependentOn.parentSettingId -contains $parentSetting.Id)) - } + $combinationMatchesWithOffsetUri = @() + $settingsWithSameName | ForEach-Object { + $newName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $_.OffsetUri -SettingName $previousSettingName -Skip $skip + if ($newName -eq $newSettingName) + { + $combinationMatchesWithOffsetUri += $_ + } + } + $settingsWithSameName = $combinationMatchesWithOffsetUri + $skip++ + } while ($combinationMatchesWithOffsetUri.Count -gt 1) - # If the combination of parent setting and setting name is unique, add the parent setting name to the setting name - if ($combinationMatches.Count -eq 1) { - $settingName = $parentSetting.Name + "_" + $settingName + $settingName = $newSettingName + } } - # If the combination of parent setting and setting name is still not unique, get the last part of the setting id as the name - else + + # When there is no parent, we can't use the parent setting name to make the setting name unique + # Instead, we traverse up the OffsetUri. Since no parent setting can only happen at the root level, the result + # of Get-SettingDefinitionNameWithParentFromOffsetUri is absolute and cannot change. There cannot be multiple settings with the same name + # in the same level of OffsetUri + if ($null -eq $parentSetting) { - $parentSettingIdProperty = $parentSetting.Id.Split('_')[-1] - $parentSettingIdWithoutProperty = $parentSetting.Id.Replace("_$parentSettingIdProperty", "") - # We can't use the entire setting here, because the child setting id does not have to come after the parent setting id - $settingName = $SettingDefinition.Id.Replace($parentSettingIdWithoutProperty + "_", "").Replace($parentSettingIdProperty + "_", "") + $settingName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $SettingDefinition.OffsetUri -SettingName $settingName } } @@ -3845,7 +3867,8 @@ function New-SettingsCatalogSettingDefinitionSettingsFromTemplate { -SettingDefinition $childSetting ` -SettingDefinitionIdPrefix $SettingDefinitionIdPrefix ` -Level $($Level + 1) ` - -ParentInstanceName $instanceName + -ParentInstanceName $instanceName ` + -AllSettingDefinitions $AllSettingDefinitions } $setting = [ordered]@{ @@ -3869,6 +3892,79 @@ function New-SettingsCatalogSettingDefinitionSettingsFromTemplate { $setting } +<# + This function also exists in M365DSCDRGUtil.psm1. Changes here must be added there as well for compatibility. +#> +function Get-SettingDefinitionNameWithParentFromOffsetUri { + param ( + [Parameter(Mandatory = $true)] + [System.String] + $OffsetUri, + + [Parameter(Mandatory = $true)] + [System.String] + $SettingName, + + [Parameter(Mandatory = $false)] + [System.Int32] + $Skip = 0 + ) + + # If the last part of the OffsetUri is the same as the setting name or it contains invalid characters, we traverse up until we reach the first element + # Invalid characters are { and } which are used in the OffsetUri to indicate a variable + $splittedOffsetUri = $OffsetUri.Split("/") + if ([string]::IsNullOrEmpty($splittedOffsetUri[0])) + { + $splittedOffsetUri = $splittedOffsetUri[1..($splittedOffsetUri.Length - 1)] + } + $splittedOffsetUri = $splittedOffsetUri[0..($splittedOffsetUri.Length - 1 - $Skip)] + $traversed = $false + while (-not $traversed -and $splittedOffsetUri.Length -gt 1) # Prevent adding the first element of the OffsetUri + { + $traversed = $true + if ($splittedOffsetUri[-1] -eq $SettingName -or $splittedOffsetUri[-1] -match "[\{\}]" -or $SettingName.StartsWith($splittedOffsetUri[-1])) + { + $splittedOffsetUri = $splittedOffsetUri[0..($splittedOffsetUri.Length - 2)] + $traversed = $false + } + } + + if ($splittedOffsetUri.Length -gt 1) + { + $splittedOffsetUri[-1] + "_" + $SettingName + } + else + { + $SettingName + } +} + +function Get-ParentSettingDefinition { + param( + [Parameter(Mandatory = $true)] + $SettingDefinition, + + [Parameter(Mandatory = $true)] + $AllSettingDefinitions + ) + + $parentSetting = $null + if ($SettingDefinition.AdditionalProperties.dependentOn.parentSettingId.Count -gt 0) + { + $parentSetting = $AllSettingDefinitions | Where-Object -FilterScript { + $_.Id -eq ($SettingDefinition.AdditionalProperties.dependentOn.parentSettingId | Select-Object -Unique -First 1) + } + } + elseif ($SettingDefinition.AdditionalProperties.options.dependentOn.parentSettingId.Count -gt 0) + { + $parentSetting = $AllSettingDefinitions | Where-Object -FilterScript { + $_.Id -eq ($SettingDefinition.AdditionalProperties.options.dependentOn.parentSettingId | Select-Object -Unique -First 1) + } + } + + $parentSetting +} + function New-ParameterDefinitionFromSettingsCatalogTemplateSetting { param( [Parameter(Mandatory = $true)] From 7f1933ec7b4aee4cea404f9943bf35fcecba4b8d Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Tue, 17 Sep 2024 20:56:16 +0200 Subject: [PATCH 202/465] Improve Intune Settings Catalog handling for Firewall profiles --- .../Modules/M365DSCDRGUtil.psm1 | 275 +++++++++++++++--- 1 file changed, 234 insertions(+), 41 deletions(-) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index 6bf838c5d6..68d95b87d0 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -1860,17 +1860,20 @@ function Get-IntuneSettingCatalogPolicySettingInstanceValue $values = $valueResult.Value - # We iterate over all the values in the DSC params and add them to the choice setting collection - foreach ($value in $values) + if ($null -ne $values) { - $choiceSettingValueCollection += @{ - value = $value - children = @() - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' + # We iterate over all the values in the DSC params and add them to the choice setting collection + foreach ($value in $values) + { + $choiceSettingValueCollection += @{ + value = $value + children = @() + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' + } } - } - $settingValuesToReturn.Add('choiceSettingCollectionValue', $choiceSettingValueCollection) + $settingValuesToReturn.Add('choiceSettingCollectionValue', $choiceSettingValueCollection) + } } # SimpleSettingCollections are collections of simple settings, e.g. strings or integers { $_ -eq '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance' -or $_ -eq '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionDefinition' } @@ -1968,6 +1971,7 @@ function Get-IntuneSettingCatalogPolicySettingDSCValue { $matchCombined = $false $matchesId = $false + $matchesOffsetUri = $false $settingDefinitions = $SettingTemplates.SettingDefinitions ` | Where-Object -FilterScript { $_.Name -eq $key } @@ -1989,6 +1993,20 @@ function Get-IntuneSettingCatalogPolicySettingDSCValue { $parentSettingName = $key.Split('_')[0] $parentDefinition = $SettingTemplates.SettingDefinitions | Where-Object -FilterScript { $_.Name -eq $parentSettingName } + + # If no parent definition is found, it might have been combined with the OffsetUri + if ($null -eq $parentDefinition) + { + $definition = Get-SettingDefinitionFromNameWithParentFromOffsetUri -OffsetUriName $key -SettingDefinitions $SettingTemplates.SettingDefinitions + if ($null -ne $definition) + { + $offsetUriFound = $true + if ($SettingDefinition.Id -eq $definition.Id) + { + $matchesOffsetUri = $true + } + } + } $childDefinition = $SettingTemplates.SettingDefinitions | Where-Object -FilterScript { $_.Name -eq $SettingName -and (($_.AdditionalProperties.dependentOn.Count -gt 0 -and $_.AdditionalProperties.dependentOn.parentSettingId -contains $parentDefinition.Id) -or @@ -2010,9 +2028,9 @@ function Get-IntuneSettingCatalogPolicySettingDSCValue } } - if (-not $matchCombined) + if (-not $matchCombined -and -not $offsetUriFound) { - # Parent was not combined, look for the id + # Parent was not combined, look for the combination of name and id $SettingTemplates.SettingDefinitions | ForEach-Object { if ($_.Id -notin $global:excludedDefinitionIds -and $_.Name -eq $SettingName -and $_.Id -like "*$key") { @@ -2026,7 +2044,7 @@ function Get-IntuneSettingCatalogPolicySettingDSCValue } # If there is exactly one setting with the name, the setting is combined or the id matches, we get the DSC value and update the real setting value type - if (($name.Count -eq 1 -and $SettingName -eq $key) -or $matchCombined -or $matchesId) + if (($name.Count -eq 1 -and $SettingName -eq $key) -or $matchCombined -or $matchesId -or $matchesOffsetUri) { $isArray = $false if ($SettingValueType -like "*Simple*") @@ -2084,6 +2102,156 @@ function Get-IntuneSettingCatalogPolicySettingDSCValue } } +function Get-SettingDefinitionFromNameWithParentFromOffsetUri +{ + param( + [Parameter(Mandatory = $true)] + [System.String] + $OffsetUriName, + + [Parameter(Mandatory = $true)] + [System.Array] + $SettingDefinitions + ) + + $offsetUriParts = [System.Collections.ArrayList]::new() + $SettingDefinitions | ForEach-Object { + $splittedOffsetUri = $_.OffsetUri.Split('/') + # Remove first element since it is always empty + $splittedOffsetUri = $splittedOffsetUri[1..($splittedOffsetUri.Length - 1)] + foreach ($part in $splittedOffsetUri) + { + if (-not $offsetUriParts.Contains($part)) + { + $offsetUriParts.Add($part) | Out-Null + } + } + } + + $settingName = $OffsetUriName + $offsetUriPrefix = "" + foreach ($part in $offsetUriParts) + { + if ($settingName -like "*$($part)_*") + { + $settingName = $settingName.Replace("$($part)_", "") + # Add wildcards to match removed parts with invalid characters + $offsetUriPrefix += "*$($part)*" + } + } + + $filteredDefinitions = $SettingDefinitions | Where-Object -FilterScript { + $_.Name -eq $settingName -and $_.OffsetUri -like "*$offsetUriPrefix*" + } + + if ($filteredDefinitions.Count -eq 1) + { + return $filteredDefinitions + } + else + { + $settingsWithSameName = $filteredDefinitions + foreach ($definition in $filteredDefinitions) + { + $skip = 0 + $newSettingName = $settingName + do { + $previousSettingName = $newSettingName + $newSettingName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $definition.OffsetUri -SettingName $newSettingName -Skip $skip + + $combinationMatchesWithOffsetUri = @() + $settingsWithSameName | ForEach-Object { + $newName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $_.OffsetUri -SettingName $previousSettingName -Skip $skip + if ($newName -eq $newSettingName) + { + $combinationMatchesWithOffsetUri += $_ + } + } + $settingsWithSameName = $combinationMatchesWithOffsetUri + $skip++ + } while ($combinationMatchesWithOffsetUri.Count -gt 1) + + if ($newSettingName -eq $OffsetUriName) + { + return $definition + } + } + } +} + +function Get-ParentSettingDefinition { + param( + [Parameter(Mandatory = $true)] + $SettingDefinition, + + [Parameter(Mandatory = $true)] + $AllSettingDefinitions + ) + + $parentSetting = $null + if ($SettingDefinition.AdditionalProperties.dependentOn.parentSettingId.Count -gt 0) + { + $parentSetting = $AllSettingDefinitions | Where-Object -FilterScript { + $_.Id -eq ($SettingDefinition.AdditionalProperties.dependentOn.parentSettingId | Select-Object -Unique -First 1) + } + } + elseif ($SettingDefinition.AdditionalProperties.options.dependentOn.parentSettingId.Count -gt 0) + { + $parentSetting = $AllSettingDefinitions | Where-Object -FilterScript { + $_.Id -eq ($SettingDefinition.AdditionalProperties.options.dependentOn.parentSettingId | Select-Object -Unique -First 1) + } + } + + $parentSetting +} + +<# + This function also exists in M365DSCResourceGenerator.psm1. Changes here must be added there as well for compatibility. +#> +function Get-SettingDefinitionNameWithParentFromOffsetUri { + param ( + [Parameter(Mandatory = $true)] + [System.String] + $OffsetUri, + + [Parameter(Mandatory = $true)] + [System.String] + $SettingName, + + [Parameter(Mandatory = $false)] + [System.Int32] + $Skip = 0 + ) + + # If the last part of the OffsetUri is the same as the setting name or it contains invalid characters, we traverse up until we reach the first element + # Invalid characters are { and } which are used in the OffsetUri to indicate a variable + $splittedOffsetUri = $OffsetUri.Split("/") + if ([string]::IsNullOrEmpty($splittedOffsetUri[0])) + { + $splittedOffsetUri = $splittedOffsetUri[1..($splittedOffsetUri.Length - 1)] + } + $splittedOffsetUri = $splittedOffsetUri[0..($splittedOffsetUri.Length - 1 - $Skip)] + $traversed = $false + while (-not $traversed -and $splittedOffsetUri.Length -gt 1) # Prevent adding the first element of the OffsetUri + { + $traversed = $true + if ($splittedOffsetUri[-1] -eq $SettingName -or $splittedOffsetUri[-1] -match "[\{\}]" -or $SettingName.StartsWith($splittedOffsetUri[-1])) + { + $splittedOffsetUri = $splittedOffsetUri[0..($splittedOffsetUri.Length - 2)] + $traversed = $false + } + } + + if ($splittedOffsetUri.Length -gt 1) + { + $splittedOffsetUri[-1] + "_" + $SettingName + } + else + { + $SettingName + } +} + function Export-IntuneSettingCatalogPolicySettings { [CmdletBinding()] @@ -2112,6 +2280,13 @@ function Export-IntuneSettingCatalogPolicySettings )] $SettingDefinitions, + [Parameter( + Mandatory = $true, + ParameterSetName = 'Setting' + )] + [System.Array] + $AllSettingDefinitions, + [Parameter( ParameterSetName = 'Setting' )] @@ -2122,7 +2297,7 @@ function Export-IntuneSettingCatalogPolicySettings { foreach ($setting in $Settings) { - Export-IntuneSettingCatalogPolicySettings -SettingInstance $setting.SettingInstance -SettingDefinitions $setting.SettingDefinitions -ReturnHashtable $ReturnHashtable -IsRoot + Export-IntuneSettingCatalogPolicySettings -SettingInstance $setting.SettingInstance -SettingDefinitions $setting.SettingDefinitions -ReturnHashtable $ReturnHashtable -AllSettingDefinitions $Settings.SettingDefinitions -IsRoot } return $ReturnHashtable } @@ -2132,36 +2307,54 @@ function Export-IntuneSettingCatalogPolicySettings $settingName = $settingDefinition.Name # Check if the name is unique - $settingMatches = @($SettingDefinitions | Where-Object -FilterScript { $_.Name -eq $settingName }) - if ($settingMatches.Count -gt 1) + $settingsWithSameName = @($AllSettingDefinitions | Where-Object -FilterScript { $_.Name -eq $settingName }) + if ($settingsWithSameName.Count -gt 1) { - if ($settingDefinition.AdditionalProperties.dependentOn.parentSettingId.Count -gt 0) - { - $parentSetting = $SettingDefinitions | Where-Object -FilterScript { $_.Id -eq $($settingDefinition.AdditionalProperties.dependentOn.parentSettingId | Select-Object -Unique -First 1) } - } - elseif ($settingDefinition.AdditionalProperties.options.dependentOn.parentSettingId.Count -gt 0) + $parentSetting = Get-ParentSettingDefinition -SettingDefinition $settingDefinition -AllSettingDefinitions $AllSettingDefinitions + + if ($null -ne $parentSetting) { - $parentSetting = $SettingDefinitions | Where-Object -FilterScript { $_.Id -eq $($settingDefinition.AdditionalProperties.options.dependentOn.parentSettingId | Select-Object -Unique -First 1) } - } + $combinationMatchesWithParent = $settingsWithSameName | Where-Object -FilterScript { + "$($parentSetting.Name)_$($_.Name)" -eq "$($parentSetting.Name)_$settingName" + } - $combinationMatches = $SettingDefinitions | Where-Object -FilterScript { - $_.Name -eq $settingName -and ` - (($_.AdditionalProperties.dependentOn.parentSettingId.Count -gt 0 -and $_.AdditionalProperties.dependentOn.parentSettingId.Contains($parentSetting.Id)) -or ` - ($_.AdditionalProperties.options.dependentOn.parentSettingId.Count -gt 0 -and $_.AdditionalProperties.options.dependentOn.parentSettingId.Contains($parentSetting.Id))) - } + # If the combination of parent setting and setting name is unique, add the parent setting name to the setting name + if ($combinationMatchesWithParent.Count -eq 1) + { + $settingName = $($parentSetting.Name) + "_" + $settingName + } + # If the combination of parent setting and setting name is still not unique, do it with the OffsetUri of the current setting + else + { + $skip = 0 + $newSettingName = $settingName + do { + $previousSettingName = $newSettingName + $newSettingName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $settingDefinition.OffsetUri -SettingName $newSettingName -Skip $skip - # If the combination of parent setting and setting name is unique, add the parent setting name to the setting name - if ($combinationMatches.Count -eq 1) - { - $settingName = $($parentSetting.Name) + "_" + $settingName + $combinationMatchesWithOffsetUri = @() + $settingsWithSameName | ForEach-Object { + $newName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $_.OffsetUri -SettingName $previousSettingName -Skip $skip + if ($newName -eq $newSettingName) + { + $combinationMatchesWithOffsetUri += $_ + } + } + $settingsWithSameName = $combinationMatchesWithOffsetUri + $skip++ + } while ($combinationMatchesWithOffsetUri.Count -gt 1) + + $settingName = $newSettingName + } } - # If the combination of parent setting and setting name is still not unique, grab the last part of the setting id - else + + # When there is no parent, we can't use the parent setting name to make the setting name unique + # Instead, we traverse up the OffsetUri. Since no parent setting can only happen at the root level, the result + # of Get-SettingDefinitionNameWithParentFromOffsetUri is absolute and cannot change. There cannot be multiple settings with the same name + # in the same level of OffsetUri + if ($null -eq $parentSetting) { - $parentSettingIdProperty = $parentSetting.Id.Split('_')[-1] - $parentSettingIdWithoutProperty = $parentSetting.Id.Replace("_$parentSettingIdProperty", "") - # We can't use the entire setting here, because the child setting id does not have to come after the parent setting id - $settingName = $settingDefinition.Id.Replace($parentSettingIdWithoutProperty + "_", "").Replace($parentSettingIdProperty + "_", "") + $settingName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $settingDefinition.OffsetUri -SettingName $settingName } } @@ -2179,7 +2372,7 @@ function Export-IntuneSettingCatalogPolicySettings $childSettings = if ($IsRoot) { $SettingInstance.AdditionalProperties.choiceSettingValue.children } else { $SettingInstance.choiceSettingValue.children } foreach ($childSetting in $childSettings) { - Export-IntuneSettingCatalogPolicySettings -SettingInstance $childSetting -SettingDefinitions $SettingDefinitions -ReturnHashtable $ReturnHashtable + Export-IntuneSettingCatalogPolicySettings -SettingInstance $childSetting -SettingDefinitions $SettingDefinitions -ReturnHashtable $ReturnHashtable -AllSettingDefinitions $AllSettingDefinitions } } '#microsoft.graph.deviceManagementConfigurationChoiceSettingCollectionInstance' @@ -2207,7 +2400,7 @@ function Export-IntuneSettingCatalogPolicySettings $childInstances = $child.children foreach ($childInstance in $childInstances) { - Export-IntuneSettingCatalogPolicySettings -SettingInstance $childInstance -SettingDefinitions $SettingDefinitions -ReturnHashtable $ReturnHashtable + Export-IntuneSettingCatalogPolicySettings -SettingInstance $childInstance -SettingDefinitions $SettingDefinitions -ReturnHashtable $ReturnHashtable -AllSettingDefinitions $AllSettingDefinitions } } $addToParameters = $false @@ -2226,7 +2419,7 @@ function Export-IntuneSettingCatalogPolicySettings $childHashtable = @{} foreach ($childInstance in $child.children) { - Export-IntuneSettingCatalogPolicySettings -SettingInstance $childInstance -SettingDefinitions $SettingDefinitions -ReturnHashtable $childHashtable + Export-IntuneSettingCatalogPolicySettings -SettingInstance $childInstance -SettingDefinitions $SettingDefinitions -ReturnHashtable $childHashtable -AllSettingDefinitions $AllSettingDefinitions } $childValue += $childHashtable } @@ -2237,7 +2430,7 @@ function Export-IntuneSettingCatalogPolicySettings $childSettings = $groupSettingCollectionValue.children foreach ($value in $childSettings) { - Export-IntuneSettingCatalogPolicySettings -SettingInstance $value -SettingDefinitions $SettingDefinitions -ReturnHashtable $ReturnHashtable + Export-IntuneSettingCatalogPolicySettings -SettingInstance $value -SettingDefinitions $SettingDefinitions -ReturnHashtable $ReturnHashtable -AllSettingDefinitions $AllSettingDefinitions $addToParameters = $false } } @@ -2331,7 +2524,7 @@ function Update-IntuneDeviceConfigurationPolicy -TenantId $TenantId ` -Credential $Credential - return $null + throw } } From 7cb2783c30abe570ddd4fd2bb10d01c91a77f3c3 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Tue, 17 Sep 2024 21:00:34 +0200 Subject: [PATCH 203/465] Add Intune Firewall Policy for Windows 10 --- ...FT_IntuneDeviceControlPolicyWindows10.psm1 | 5 +- .../MSFT_IntuneFirewallPolicyWindows10.psm1 | 1746 +++++++++++++++++ ...T_IntuneFirewallPolicyWindows10.schema.mof | 106 + .../readme.md | 6 + .../settings.json | 33 + .../1-Create.ps1 | 53 + .../2-Update.ps1 | 53 + .../3-Remove.ps1 | 34 + ...SC.IntuneFirewallPolicyWindows10.Tests.ps1 | 444 +++++ 9 files changed, 2476 insertions(+), 4 deletions(-) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneFirewallPolicyWindows10/MSFT_IntuneFirewallPolicyWindows10.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneFirewallPolicyWindows10/MSFT_IntuneFirewallPolicyWindows10.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneFirewallPolicyWindows10/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneFirewallPolicyWindows10/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneFirewallPolicyWindows10/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneFirewallPolicyWindows10/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneFirewallPolicyWindows10/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneFirewallPolicyWindows10.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceControlPolicyWindows10/MSFT_IntuneDeviceControlPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceControlPolicyWindows10/MSFT_IntuneDeviceControlPolicyWindows10.psm1 index e9a0626642..1582907087 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceControlPolicyWindows10/MSFT_IntuneDeviceControlPolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceControlPolicyWindows10/MSFT_IntuneDeviceControlPolicyWindows10.psm1 @@ -266,10 +266,7 @@ function Get-TargetResource { $getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` -Filter "Name eq '$DisplayName'" ` - -ErrorAction SilentlyContinue | Where-Object ` - -FilterScript { - $_.AdditionalProperties.'@odata.type' -eq "#microsoft.graph.DeviceManagementConfigurationPolicy" - } + -ErrorAction SilentlyContinue } } #endregion diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneFirewallPolicyWindows10/MSFT_IntuneFirewallPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneFirewallPolicyWindows10/MSFT_IntuneFirewallPolicyWindows10.psm1 new file mode 100644 index 0000000000..5ab2f94e5b --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneFirewallPolicyWindows10/MSFT_IntuneFirewallPolicyWindows10.psm1 @@ -0,0 +1,1746 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [ValidateSet('0', '1', '2')] + [System.String] + $CRLcheck, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DisableStatefulFtp, + + [Parameter()] + [ValidateSet('0', '1', '2')] + [System.Int32[]] + $EnablePacketQueue, + + [Parameter()] + [ValidateSet('0', '1', '2', '4', '8')] + [System.Int32[]] + $IPsecExempt, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $OpportunisticallyMatchAuthSetPerKM, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PresharedKeyEncoding, + + [Parameter()] + [ValidateRange(300, 3600)] + [System.Int32] + $SaIdleTime, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_DisableUnicastResponsesToMulticastBroadcast, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_EnableLogIgnoredRules, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_GlobalPortsAllowUserPrefMerge, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $DomainProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_DisableStealthModeIpsecSecuredPacketExemption, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_EnableLogSuccessConnections, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_AllowLocalIpsecPolicyMerge, + + [Parameter()] + [ValidateLength(0, 87516)] + [System.String] + $DomainProfile_LogFilePath, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_DisableStealthMode, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_AuthAppsAllowUserPrefMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_EnableLogDroppedPackets, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_Shielded, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $DomainProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_DisableInboundNotifications, + + [Parameter()] + [ValidateRange(0, 4294967295)] + [System.Int32] + $DomainProfile_LogMaxFileSize, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_AllowLocalIpsecPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_DisableStealthModeIpsecSecuredPacketExemption, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_DisableInboundNotifications, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_Shielded, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PrivateProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_AuthAppsAllowUserPrefMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_EnableLogIgnoredRules, + + [Parameter()] + [ValidateRange(0, 4294967295)] + [System.Int32] + $PrivateProfile_LogMaxFileSize, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PrivateProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_DisableUnicastResponsesToMulticastBroadcast, + + [Parameter()] + [ValidateLength(0, 87516)] + [System.String] + $PrivateProfile_LogFilePath, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_DisableStealthMode, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_EnableLogSuccessConnections, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_GlobalPortsAllowUserPrefMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_EnableLogDroppedPackets, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PublicProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_DisableInboundNotifications, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_DisableStealthModeIpsecSecuredPacketExemption, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_Shielded, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_AuthAppsAllowUserPrefMerge, + + [Parameter()] + [ValidateLength(0, 87516)] + [System.String] + $PublicProfile_LogFilePath, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PublicProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_DisableUnicastResponsesToMulticastBroadcast, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_GlobalPortsAllowUserPrefMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_EnableLogSuccessConnections, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_AllowLocalIpsecPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_EnableLogDroppedPackets, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_EnableLogIgnoredRules, + + [Parameter()] + [ValidateRange(0, 4294967295)] + [System.Int32] + $PublicProfile_LogMaxFileSize, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_DisableStealthMode, + + [Parameter()] + [ValidateSet('0', '1', '2', '3')] + [System.String] + $ObjectAccess_AuditFilteringPlatformConnection, + + [Parameter()] + [ValidateSet('0', '1', '2', '3')] + [System.String] + $ObjectAccess_AuditFilteringPlatformPacketDrop, + + [Parameter()] + [ValidateLength(0, 87516)] + [System.String[]] + $AllowedTlsAuthenticationEndpoints, + + [Parameter()] + [ValidateLength(0, 87516)] + [System.String] + $ConfiguredTlsAuthenticationNetworkName, + + [Parameter()] + [ValidateSet('wsl')] + [System.String] + $Target, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_DomainProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_DomainProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_DomainProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_DomainProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $EnableLoopback, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_PublicProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_PublicProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_PublicProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_PublicProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_PrivateProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_PrivateProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_PrivateProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_PrivateProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $AllowHostPolicyMerge, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + try + { + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -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 + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + $getValue = $null + #region resource generator code + $getValue = Get-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $Id -ErrorAction SilentlyContinue + + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune Firewall Policy for Windows10 with Id {$Id}" + + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + $getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter "Name eq '$DisplayName'" ` + -ErrorAction SilentlyContinue + } + } + #endregion + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune Firewall Policy for Windows10 with Name {$DisplayName}." + return $nullResult + } + $Id = $getValue.Id + Write-Verbose -Message "An Intune Firewall Policy for Windows10 with Id {$Id} and Name {$DisplayName} was found" + + # Retrieve policy specific settings + [array]$settings = Get-MgBetaDeviceManagementConfigurationPolicySetting ` + -DeviceManagementConfigurationPolicyId $Id ` + -ExpandProperty 'settingDefinitions' ` + -ErrorAction Stop + + $policySettings = @{} + $policySettings = Export-IntuneSettingCatalogPolicySettings -Settings $settings -ReturnHashtable $policySettings + + $results = @{ + #region resource generator code + Description = $getValue.Description + DisplayName = $getValue.Name + RoleScopeTagIds = $getValue.RoleScopeTagIds + Id = $getValue.Id + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + #endregion + } + $results += $policySettings + + $assignmentsValues = Get-MgBetaDeviceManagementConfigurationPolicyAssignment -DeviceManagementConfigurationPolicyId $Id + $assignmentResult = @() + if ($assignmentsValues.Count -gt 0) + { + $assignmentResult += ConvertFrom-IntunePolicyAssignment -Assignments $assignmentsValues -IncludeDeviceFilter $true + } + $results.Add('Assignments', $assignmentResult) + + 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 + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [ValidateSet('0', '1', '2')] + [System.String] + $CRLcheck, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DisableStatefulFtp, + + [Parameter()] + [ValidateSet('0', '1', '2')] + [System.Int32[]] + $EnablePacketQueue, + + [Parameter()] + [ValidateSet('0', '1', '2', '4', '8')] + [System.Int32[]] + $IPsecExempt, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $OpportunisticallyMatchAuthSetPerKM, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PresharedKeyEncoding, + + [Parameter()] + [ValidateRange(300, 3600)] + [System.Int32] + $SaIdleTime, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_DisableUnicastResponsesToMulticastBroadcast, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_EnableLogIgnoredRules, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_GlobalPortsAllowUserPrefMerge, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $DomainProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_DisableStealthModeIpsecSecuredPacketExemption, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_EnableLogSuccessConnections, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_AllowLocalIpsecPolicyMerge, + + [Parameter()] + [ValidateLength(0, 87516)] + [System.String] + $DomainProfile_LogFilePath, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_DisableStealthMode, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_AuthAppsAllowUserPrefMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_EnableLogDroppedPackets, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_Shielded, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $DomainProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_DisableInboundNotifications, + + [Parameter()] + [ValidateRange(0, 4294967295)] + [System.Int32] + $DomainProfile_LogMaxFileSize, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_AllowLocalIpsecPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_DisableStealthModeIpsecSecuredPacketExemption, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_DisableInboundNotifications, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_Shielded, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PrivateProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_AuthAppsAllowUserPrefMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_EnableLogIgnoredRules, + + [Parameter()] + [ValidateRange(0, 4294967295)] + [System.Int32] + $PrivateProfile_LogMaxFileSize, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PrivateProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_DisableUnicastResponsesToMulticastBroadcast, + + [Parameter()] + [ValidateLength(0, 87516)] + [System.String] + $PrivateProfile_LogFilePath, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_DisableStealthMode, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_EnableLogSuccessConnections, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_GlobalPortsAllowUserPrefMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_EnableLogDroppedPackets, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PublicProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_DisableInboundNotifications, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_DisableStealthModeIpsecSecuredPacketExemption, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_Shielded, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_AuthAppsAllowUserPrefMerge, + + [Parameter()] + [ValidateLength(0, 87516)] + [System.String] + $PublicProfile_LogFilePath, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PublicProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_DisableUnicastResponsesToMulticastBroadcast, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_GlobalPortsAllowUserPrefMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_EnableLogSuccessConnections, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_AllowLocalIpsecPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_EnableLogDroppedPackets, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_EnableLogIgnoredRules, + + [Parameter()] + [ValidateRange(0, 4294967295)] + [System.Int32] + $PublicProfile_LogMaxFileSize, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_DisableStealthMode, + + [Parameter()] + [ValidateSet('0', '1', '2', '3')] + [System.String] + $ObjectAccess_AuditFilteringPlatformConnection, + + [Parameter()] + [ValidateSet('0', '1', '2', '3')] + [System.String] + $ObjectAccess_AuditFilteringPlatformPacketDrop, + + [Parameter()] + [ValidateLength(0, 87516)] + [System.String[]] + $AllowedTlsAuthenticationEndpoints, + + [Parameter()] + [ValidateLength(0, 87516)] + [System.String] + $ConfiguredTlsAuthenticationNetworkName, + + [Parameter()] + [ValidateSet('wsl')] + [System.String] + $Target, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_DomainProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_DomainProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_DomainProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_DomainProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $EnableLoopback, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_PublicProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_PublicProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_PublicProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_PublicProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_PrivateProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_PrivateProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_PrivateProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_PrivateProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $AllowHostPolicyMerge, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $templateReferenceId = '6078910e-d808-4a9f-a51d-1b8a7bacb7c0_1' + $platforms = 'windows10' + $technologies = 'mdm,microsoftSense' + + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating an Intune Firewall Policy for Windows10 with Name {$DisplayName}" + $BoundParameters.Remove("Assignments") | Out-Null + + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId + + $createParameters = @{ + Name = $DisplayName + Description = $Description + TemplateReference = @{ templateId = $templateReferenceId } + Platforms = $platforms + Technologies = $technologies + Settings = $settings + } + + #region resource generator code + $policy = New-MgBetaDeviceManagementConfigurationPolicy -BodyParameter $createParameters + + if ($policy.Id) + { + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $policy.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + } + #endregion + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating the Intune Firewall Policy for Windows10 with Id {$($currentInstance.Id)}" + $BoundParameters.Remove("Assignments") | Out-Null + + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId + + Update-IntuneDeviceConfigurationPolicy ` + -DeviceConfigurationPolicyId $currentInstance.Id ` + -Name $DisplayName ` + -Description $Description ` + -TemplateReferenceId $templateReferenceId ` + -Platforms $platforms ` + -Technologies $technologies ` + -Settings $settings + + #region resource generator code + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $currentInstance.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + #endregion + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing the Intune Firewall Policy for Windows10 with Id {$($currentInstance.Id)}" + #region resource generator code + Remove-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $currentInstance.Id + #endregion + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [ValidateSet('0', '1', '2')] + [System.String] + $CRLcheck, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DisableStatefulFtp, + + [Parameter()] + [ValidateSet('0', '1', '2')] + [System.Int32[]] + $EnablePacketQueue, + + [Parameter()] + [ValidateSet('0', '1', '2', '4', '8')] + [System.Int32[]] + $IPsecExempt, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $OpportunisticallyMatchAuthSetPerKM, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PresharedKeyEncoding, + + [Parameter()] + [ValidateRange(300, 3600)] + [System.Int32] + $SaIdleTime, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_DisableUnicastResponsesToMulticastBroadcast, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_EnableLogIgnoredRules, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_GlobalPortsAllowUserPrefMerge, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $DomainProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_DisableStealthModeIpsecSecuredPacketExemption, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_EnableLogSuccessConnections, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_AllowLocalIpsecPolicyMerge, + + [Parameter()] + [ValidateLength(0, 87516)] + [System.String] + $DomainProfile_LogFilePath, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_DisableStealthMode, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_AuthAppsAllowUserPrefMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_EnableLogDroppedPackets, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_Shielded, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $DomainProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $DomainProfile_DisableInboundNotifications, + + [Parameter()] + [ValidateRange(0, 4294967295)] + [System.Int32] + $DomainProfile_LogMaxFileSize, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_AllowLocalIpsecPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_DisableStealthModeIpsecSecuredPacketExemption, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_DisableInboundNotifications, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_Shielded, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PrivateProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_AuthAppsAllowUserPrefMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_EnableLogIgnoredRules, + + [Parameter()] + [ValidateRange(0, 4294967295)] + [System.Int32] + $PrivateProfile_LogMaxFileSize, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PrivateProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_DisableUnicastResponsesToMulticastBroadcast, + + [Parameter()] + [ValidateLength(0, 87516)] + [System.String] + $PrivateProfile_LogFilePath, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_DisableStealthMode, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_EnableLogSuccessConnections, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_GlobalPortsAllowUserPrefMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PrivateProfile_EnableLogDroppedPackets, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PublicProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_DisableInboundNotifications, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_DisableStealthModeIpsecSecuredPacketExemption, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_Shielded, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_AuthAppsAllowUserPrefMerge, + + [Parameter()] + [ValidateLength(0, 87516)] + [System.String] + $PublicProfile_LogFilePath, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $PublicProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_DisableUnicastResponsesToMulticastBroadcast, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_GlobalPortsAllowUserPrefMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_EnableLogSuccessConnections, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_AllowLocalIpsecPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_EnableLogDroppedPackets, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_EnableLogIgnoredRules, + + [Parameter()] + [ValidateRange(0, 4294967295)] + [System.Int32] + $PublicProfile_LogMaxFileSize, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $PublicProfile_DisableStealthMode, + + [Parameter()] + [ValidateSet('0', '1', '2', '3')] + [System.String] + $ObjectAccess_AuditFilteringPlatformConnection, + + [Parameter()] + [ValidateSet('0', '1', '2', '3')] + [System.String] + $ObjectAccess_AuditFilteringPlatformPacketDrop, + + [Parameter()] + [ValidateLength(0, 87516)] + [System.String[]] + $AllowedTlsAuthenticationEndpoints, + + [Parameter()] + [ValidateLength(0, 87516)] + [System.String] + $ConfiguredTlsAuthenticationNetworkName, + + [Parameter()] + [ValidateSet('wsl')] + [System.String] + $Target, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_DomainProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_DomainProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_DomainProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_DomainProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $EnableLoopback, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_PublicProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_PublicProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_PublicProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_PublicProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_PrivateProfile_EnableFirewall, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_PrivateProfile_DefaultOutboundAction, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $HyperVVMSettings_PrivateProfile_DefaultInboundAction, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $HyperVVMSettings_PrivateProfile_AllowLocalPolicyMerge, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $AllowHostPolicyMerge, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 the Intune Firewall Policy for Windows10 with Id {$Id} and Name {$DisplayName}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + [Hashtable]$ValuesToCheck = @{} + $MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + if ($_.Key -notlike '*Variable' -or $_.Key -notin @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction')) + { + if ($null -ne $CurrentValues[$_.Key] -or $null -ne $PSBoundParameters[$_.Key]) + { + $ValuesToCheck.Add($_.Key, $null) + if (-not $PSBoundParameters.ContainsKey($_.Key)) + { + $PSBoundParameters.Add($_.Key, $null) + } + } + } + } + + if ($CurrentValues.Ensure -ne $Ensure) + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + $testResult = $true + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $targetVariable = $CurrentValues.$key + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($targetVariable) + + if (-not $testResult) + { + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } + + $ValuesToCheck.Remove('Id') | Out-Null + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + if ($testResult) + { + $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.String] + $Filter, + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -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 + { + #region resource generator code + $policyTemplateID = "6078910e-d808-4a9f-a51d-1b8a7bacb7c0_1" + [array]$getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter $Filter ` + -All ` + -ErrorAction Stop | Where-Object ` + -FilterScript { + $_.TemplateReference.TemplateId -eq $policyTemplateID + } + #endregion + + $i = 1 + $dscContent = '' + if ($getValue.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $getValue) + { + $displayedKey = $config.Id + if (-not [String]::IsNullOrEmpty($config.displayName)) + { + $displayedKey = $config.displayName + } + elseif (-not [string]::IsNullOrEmpty($config.name)) + { + $displayedKey = $config.name + } + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + DisplayName = $config.Name + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + if ($Results.Assignments) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject $Results.Assignments -CIMInstanceName DeviceManagementConfigurationPolicyAssignments + if ($complexTypeStringResult) + { + $Results.Assignments = $complexTypeStringResult + } + else + { + $Results.Remove('Assignments') | Out-Null + } + } + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + + if ($Results.Assignments) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "Assignments" -IsCIMArray:$true + } + + $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_IntuneFirewallPolicyWindows10/MSFT_IntuneFirewallPolicyWindows10.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneFirewallPolicyWindows10/MSFT_IntuneFirewallPolicyWindows10.schema.mof new file mode 100644 index 0000000000..9a13fffd22 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneFirewallPolicyWindows10/MSFT_IntuneFirewallPolicyWindows10.schema.mof @@ -0,0 +1,106 @@ +[ClassVersion("1.0.0.0")] +class MSFT_DeviceManagementConfigurationPolicyAssignments +{ + [Write, Description("The type of the target assignment."), ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}, Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}] String dataType; + [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude."), ValueMap{"none","include","exclude"}, Values{"none","include","exclude"}] String deviceAndAppManagementAssignmentFilterType; + [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; + [Write, Description("The group Id that is the target of the assignment.")] String groupId; + [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; + [Write, Description("The collection Id that is the target of the assignment.(ConfigMgr)")] String collectionId; +}; + + +[ClassVersion("1.0.0.0"), FriendlyName("IntuneFirewallPolicyWindows10")] +class MSFT_IntuneFirewallPolicyWindows10 : OMI_BaseResource +{ + [Write, Description("Policy description")] String Description; + [Key, Description("Policy name")] String DisplayName; + [Write, Description("List of Scope Tags for this Entity instance.")] String RoleScopeTagIds[]; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("Certificate revocation list verification (0: Disables CRL checking, 1: Specifies that CRL checking is attempted and that certificate validation fails only if the certificate is revoked. Other failures that are encountered during CRL checking (such as the revocation URL being unreachable) do not cause certificate validation to fail., 2: Means that checking is required and that certificate validation fails if any error is encountered during CRL processing)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String CRLcheck; + [Write, Description("Disable Stateful Ftp (false: Stateful FTP enabled, true: Stateful FTP disabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String DisableStatefulFtp; + [Write, Description("Enable Packet Queue (0: Indicates that all queuing is to be disabled, 1: Specifies that inbound encrypted packets are to be queued, 2: Specifies that packets are to be queued after decryption is performed for forwarding)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] SInt32 EnablePacketQueue[]; + [Write, Description("IPsec Exceptions (0: FW_GLOBAL_CONFIG_IPSEC_EXEMPT_NONE: No IPsec exemptions., 1: FW_GLOBAL_CONFIG_IPSEC_EXEMPT_NEIGHBOR_DISC: Exempt neighbor discover IPv6 ICMP type-codes from IPsec., 2: FW_GLOBAL_CONFIG_IPSEC_EXEMPT_ICMP: Exempt ICMP from IPsec., 4: FW_GLOBAL_CONFIG_IPSEC_EXEMPT_ROUTER_DISC: Exempt router discover IPv6 ICMP type-codes from IPsec., 8: FW_GLOBAL_CONFIG_IPSEC_EXEMPT_DHCP: Exempt both IPv4 and IPv6 DHCP traffic from IPsec.)"), ValueMap{"0", "1", "2", "4", "8"}, Values{"0", "1", "2", "4", "8"}] SInt32 IPsecExempt[]; + [Write, Description("Opportunistically Match Auth Set Per KM (false: FALSE, true: TRUE)"), ValueMap{"false", "true"}, Values{"false", "true"}] String OpportunisticallyMatchAuthSetPerKM; + [Write, Description("Preshared Key Encoding (0: FW_GLOBAL_CONFIG_PRESHARED_KEY_ENCODING_NONE: Preshared key is not encoded. Instead, it is kept in its wide-character format. This symbolic constant has a value of 0., 1: FW_GLOBAL_CONFIG_PRESHARED_KEY_ENCODING_UTF_8: Encode the preshared key using UTF-8. This symbolic constant has a value of 1.)"), ValueMap{"0", "1"}, Values{"0", "1"}] String PresharedKeyEncoding; + [Write, Description("Security association idle time")] SInt32 SaIdleTime; + [Write, Description("Enable Domain Network Firewall (false: Disable Firewall, true: Enable Firewall)"), ValueMap{"false", "true"}, Values{"false", "true"}] String DomainProfile_EnableFirewall; + [Write, Description("Disable Unicast Responses To Multicast Broadcast (false: Unicast Responses Not Blocked, true: Unicast Responses Blocked)"), ValueMap{"false", "true"}, Values{"false", "true"}] String DomainProfile_DisableUnicastResponsesToMulticastBroadcast; + [Write, Description("Enable Log Ignored Rules (false: Disable Logging Of Ignored Rules, true: Enable Logging Of Ignored Rules)"), ValueMap{"false", "true"}, Values{"false", "true"}] String DomainProfile_EnableLogIgnoredRules; + [Write, Description("Global Ports Allow User Pref Merge (false: GlobalPortsAllowUserPrefMerge Off, true: GlobalPortsAllowUserPrefMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String DomainProfile_GlobalPortsAllowUserPrefMerge; + [Write, Description("Default Inbound Action for Domain Profile (0: Allow Inbound By Default, 1: Block Inbound By Default)"), ValueMap{"0", "1"}, Values{"0", "1"}] String DomainProfile_DefaultInboundAction; + [Write, Description("Disable Stealth Mode Ipsec Secured Packet Exemption (false: FALSE, true: TRUE)"), ValueMap{"false", "true"}, Values{"false", "true"}] String DomainProfile_DisableStealthModeIpsecSecuredPacketExemption; + [Write, Description("Allow Local Policy Merge (false: AllowLocalPolicyMerge Off, true: AllowLocalPolicyMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String DomainProfile_AllowLocalPolicyMerge; + [Write, Description("Enable Log Success Connections (false: Disable Logging Of Successful Connections, true: Enable Logging Of Successful Connections)"), ValueMap{"false", "true"}, Values{"false", "true"}] String DomainProfile_EnableLogSuccessConnections; + [Write, Description("Allow Local Ipsec Policy Merge (false: AllowLocalIpsecPolicyMerge Off, true: AllowLocalIpsecPolicyMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String DomainProfile_AllowLocalIpsecPolicyMerge; + [Write, Description("Log File Path")] String DomainProfile_LogFilePath; + [Write, Description("Disable Stealth Mode (false: Use Stealth Mode, true: Disable Stealth Mode)"), ValueMap{"false", "true"}, Values{"false", "true"}] String DomainProfile_DisableStealthMode; + [Write, Description("Auth Apps Allow User Pref Merge (false: AuthAppsAllowUserPrefMerge Off, true: AuthAppsAllowUserPrefMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String DomainProfile_AuthAppsAllowUserPrefMerge; + [Write, Description("Enable Log Dropped Packets (false: Disable Logging Of Dropped Packets, true: Enable Logging Of Dropped Packets)"), ValueMap{"false", "true"}, Values{"false", "true"}] String DomainProfile_EnableLogDroppedPackets; + [Write, Description("Shielded (false: Shielding Off, true: Shielding On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String DomainProfile_Shielded; + [Write, Description("Default Outbound Action (0: Allow Outbound By Default, 1: Block Outbound By Default)"), ValueMap{"0", "1"}, Values{"0", "1"}] String DomainProfile_DefaultOutboundAction; + [Write, Description("Disable Inbound Notifications (false: Firewall May Display Notification, true: Firewall Must Not Display Notification)"), ValueMap{"false", "true"}, Values{"false", "true"}] String DomainProfile_DisableInboundNotifications; + [Write, Description("Log Max File Size")] SInt32 DomainProfile_LogMaxFileSize; + [Write, Description("Enable Private Network Firewall (false: Disable Firewall, true: Enable Firewall)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PrivateProfile_EnableFirewall; + [Write, Description("Allow Local Ipsec Policy Merge (false: AllowLocalIpsecPolicyMerge Off, true: AllowLocalIpsecPolicyMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PrivateProfile_AllowLocalIpsecPolicyMerge; + [Write, Description("Disable Stealth Mode Ipsec Secured Packet Exemption (false: FALSE, true: TRUE)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PrivateProfile_DisableStealthModeIpsecSecuredPacketExemption; + [Write, Description("Disable Inbound Notifications (false: Firewall May Display Notification, true: Firewall Must Not Display Notification)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PrivateProfile_DisableInboundNotifications; + [Write, Description("Shielded (false: Shielding Off, true: Shielding On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PrivateProfile_Shielded; + [Write, Description("Allow Local Policy Merge (false: AllowLocalPolicyMerge Off, true: AllowLocalPolicyMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PrivateProfile_AllowLocalPolicyMerge; + [Write, Description("Default Outbound Action (0: Allow Outbound By Default, 1: Block Outbound By Default)"), ValueMap{"0", "1"}, Values{"0", "1"}] String PrivateProfile_DefaultOutboundAction; + [Write, Description("Auth Apps Allow User Pref Merge (false: AuthAppsAllowUserPrefMerge Off, true: AuthAppsAllowUserPrefMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PrivateProfile_AuthAppsAllowUserPrefMerge; + [Write, Description("Enable Log Ignored Rules (false: Disable Logging Of Ignored Rules, true: Enable Logging Of Ignored Rules)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PrivateProfile_EnableLogIgnoredRules; + [Write, Description("Log Max File Size")] SInt32 PrivateProfile_LogMaxFileSize; + [Write, Description("Default Inbound Action for Private Profile (0: Allow Inbound By Default, 1: Block Inbound By Default)"), ValueMap{"0", "1"}, Values{"0", "1"}] String PrivateProfile_DefaultInboundAction; + [Write, Description("Disable Unicast Responses To Multicast Broadcast (false: Unicast Responses Not Blocked, true: Unicast Responses Blocked)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PrivateProfile_DisableUnicastResponsesToMulticastBroadcast; + [Write, Description("Log File Path")] String PrivateProfile_LogFilePath; + [Write, Description("Disable Stealth Mode (false: Use Stealth Mode, true: Disable Stealth Mode)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PrivateProfile_DisableStealthMode; + [Write, Description("Enable Log Success Connections (false: Disable Logging Of Successful Connections, true: Enable Logging Of Successful Connections)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PrivateProfile_EnableLogSuccessConnections; + [Write, Description("Global Ports Allow User Pref Merge (false: GlobalPortsAllowUserPrefMerge Off, true: GlobalPortsAllowUserPrefMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PrivateProfile_GlobalPortsAllowUserPrefMerge; + [Write, Description("Enable Log Dropped Packets (false: Disable Logging Of Dropped Packets, true: Enable Logging Of Dropped Packets)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PrivateProfile_EnableLogDroppedPackets; + [Write, Description("Enable Public Network Firewall (false: Disable Firewall, true: Enable Firewall)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PublicProfile_EnableFirewall; + [Write, Description("Default Outbound Action (0: Allow Outbound By Default, 1: Block Outbound By Default)"), ValueMap{"0", "1"}, Values{"0", "1"}] String PublicProfile_DefaultOutboundAction; + [Write, Description("Disable Inbound Notifications (false: Firewall May Display Notification, true: Firewall Must Not Display Notification)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PublicProfile_DisableInboundNotifications; + [Write, Description("Disable Stealth Mode Ipsec Secured Packet Exemption (false: FALSE, true: TRUE)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PublicProfile_DisableStealthModeIpsecSecuredPacketExemption; + [Write, Description("Shielded (false: Shielding Off, true: Shielding On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PublicProfile_Shielded; + [Write, Description("Allow Local Policy Merge (false: AllowLocalPolicyMerge Off, true: AllowLocalPolicyMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PublicProfile_AllowLocalPolicyMerge; + [Write, Description("Auth Apps Allow User Pref Merge (false: AuthAppsAllowUserPrefMerge Off, true: AuthAppsAllowUserPrefMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PublicProfile_AuthAppsAllowUserPrefMerge; + [Write, Description("Log File Path")] String PublicProfile_LogFilePath; + [Write, Description("Default Inbound Action for Public Profile (0: Allow Inbound By Default, 1: Block Inbound By Default)"), ValueMap{"0", "1"}, Values{"0", "1"}] String PublicProfile_DefaultInboundAction; + [Write, Description("Disable Unicast Responses To Multicast Broadcast (false: Unicast Responses Not Blocked, true: Unicast Responses Blocked)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PublicProfile_DisableUnicastResponsesToMulticastBroadcast; + [Write, Description("Global Ports Allow User Pref Merge (false: GlobalPortsAllowUserPrefMerge Off, true: GlobalPortsAllowUserPrefMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PublicProfile_GlobalPortsAllowUserPrefMerge; + [Write, Description("Enable Log Success Connections (false: Disable Logging Of Successful Connections, true: Enable Logging Of Successful Connections)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PublicProfile_EnableLogSuccessConnections; + [Write, Description("Allow Local Ipsec Policy Merge (false: AllowLocalIpsecPolicyMerge Off, true: AllowLocalIpsecPolicyMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PublicProfile_AllowLocalIpsecPolicyMerge; + [Write, Description("Enable Log Dropped Packets (false: Disable Logging Of Dropped Packets, true: Enable Logging Of Dropped Packets)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PublicProfile_EnableLogDroppedPackets; + [Write, Description("Enable Log Ignored Rules (false: Disable Logging Of Ignored Rules, true: Enable Logging Of Ignored Rules)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PublicProfile_EnableLogIgnoredRules; + [Write, Description("Log Max File Size")] SInt32 PublicProfile_LogMaxFileSize; + [Write, Description("Disable Stealth Mode (false: Use Stealth Mode, true: Disable Stealth Mode)"), ValueMap{"false", "true"}, Values{"false", "true"}] String PublicProfile_DisableStealthMode; + [Write, Description("Object Access Audit Filtering Platform Connection (0: Off/None, 1: Success, 2: Failure, 3: Success+Failure)"), ValueMap{"0", "1", "2", "3"}, Values{"0", "1", "2", "3"}] String ObjectAccess_AuditFilteringPlatformConnection; + [Write, Description("Object Access Audit Filtering Platform Packet Drop (0: Off/None, 1: Success, 2: Failure, 3: Success+Failure)"), ValueMap{"0", "1", "2", "3"}, Values{"0", "1", "2", "3"}] String ObjectAccess_AuditFilteringPlatformPacketDrop; + [Write, Description("Allowed Tls Authentication Endpoints")] String AllowedTlsAuthenticationEndpoints[]; + [Write, Description("Configured Tls Authentication Network Name")] String ConfiguredTlsAuthenticationNetworkName; + [Write, Description("Hyper-V: Target (wsl: WSL)"), ValueMap{"wsl"}, Values{"wsl"}] String Target; + [Write, Description("Hyper-V: Enable Domain Network Firewall (false: Disable Firewall, true: Enable Firewall)"), ValueMap{"false", "true"}, Values{"false", "true"}] String HyperVVMSettings_DomainProfile_EnableFirewall; + [Write, Description("Hyper-V: Allow Local Policy Merge (false: AllowLocalPolicyMerge Off, true: AllowLocalPolicyMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String HyperVVMSettings_DomainProfile_AllowLocalPolicyMerge; + [Write, Description("Hyper-V: Default Inbound Action (0: Allow Inbound By Default, 1: Block Inbound By Default)"), ValueMap{"0", "1"}, Values{"0", "1"}] String HyperVVMSettings_DomainProfile_DefaultInboundAction; + [Write, Description("Hyper-V: Default Outbound Action (0: Allow Outbound By Default, 1: Block Outbound By Default)"), ValueMap{"0", "1"}, Values{"0", "1"}] String HyperVVMSettings_DomainProfile_DefaultOutboundAction; + [Write, Description("Hyper-V: Enable Loopback (false: Disable loopback, true: Enable loopback)"), ValueMap{"false", "true"}, Values{"false", "true"}] String EnableLoopback; + [Write, Description("Hyper-V: Enable Public Network Firewall (false: Disable Hyper-V Firewall, true: Enable Hyper-V Firewall)"), ValueMap{"false", "true"}, Values{"false", "true"}] String HyperVVMSettings_PublicProfile_EnableFirewall; + [Write, Description("Hyper-V: Default Inbound Action (0: Allow Inbound By Default, 1: Block Inbound By Default)"), ValueMap{"0", "1"}, Values{"0", "1"}] String HyperVVMSettings_PublicProfile_DefaultInboundAction; + [Write, Description("Hyper-V: Default Outbound Action (0: Allow Outbound By Default, 1: Block Outbound By Default)"), ValueMap{"0", "1"}, Values{"0", "1"}] String HyperVVMSettings_PublicProfile_DefaultOutboundAction; + [Write, Description("Hyper-V: Allow Local Policy Merge (false: AllowLocalPolicyMerge Off, true: AllowLocalPolicyMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String HyperVVMSettings_PublicProfile_AllowLocalPolicyMerge; + [Write, Description("Hyper-V: Enable Private Network Firewall (false: Disable Firewall, true: Enable Firewall)"), ValueMap{"false", "true"}, Values{"false", "true"}] String HyperVVMSettings_PrivateProfile_EnableFirewall; + [Write, Description("Hyper-V: Default Outbound Action (0: Allow Outbound By Default, 1: Block Outbound By Default)"), ValueMap{"0", "1"}, Values{"0", "1"}] String HyperVVMSettings_PrivateProfile_DefaultOutboundAction; + [Write, Description("Hyper-V: Default Inbound Action (0: Allow Inbound By Default, 1: Block Inbound By Default)"), ValueMap{"0", "1"}, Values{"0", "1"}] String HyperVVMSettings_PrivateProfile_DefaultInboundAction; + [Write, Description("Hyper-V: Allow Local Policy Merge (false: AllowLocalPolicyMerge Off, true: AllowLocalPolicyMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String HyperVVMSettings_PrivateProfile_AllowLocalPolicyMerge; + [Write, Description("Hyper-V: Allow Host Policy Merge (false: AllowHostPolicyMerge Off, true: AllowHostPolicyMerge On)"), ValueMap{"false", "true"}, Values{"false", "true"}] String AllowHostPolicyMerge; + [Write, Description("Represents the assignment to the Intune policy."), EmbeddedInstance("MSFT_DeviceManagementConfigurationPolicyAssignments")] String Assignments[]; + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; + [Write, Description("Credentials of the 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("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneFirewallPolicyWindows10/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneFirewallPolicyWindows10/readme.md new file mode 100644 index 0000000000..d232a97bef --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneFirewallPolicyWindows10/readme.md @@ -0,0 +1,6 @@ + +# IntuneFirewallPolicyWindows10 + +## Description + +Intune Firewall Policy for Windows10 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneFirewallPolicyWindows10/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneFirewallPolicyWindows10/settings.json new file mode 100644 index 0000000000..74e36b3081 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneFirewallPolicyWindows10/settings.json @@ -0,0 +1,33 @@ +{ + "resourceName": "IntuneFirewallPolicyWindows10", + "description": "This resource configures an Intune Firewall Policy for Windows10.", + "permissions": { + "graph": { + "delegated": { + "update": [ + { + "name": "DeviceManagementConfiguration.ReadWrite.All" + } + ], + "read": [ + { + "name": "DeviceManagementConfiguration.Read.All" + } + ] + }, + "application": { + "update": [ + { + "name": "DeviceManagementConfiguration.ReadWrite.All" + } + ], + "read": [ + { + "name": "DeviceManagementConfiguration.Read.All" + } + ] + } + } +} + +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneFirewallPolicyWindows10/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneFirewallPolicyWindows10/1-Create.ps1 new file mode 100644 index 0000000000..02e7e70edb --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneFirewallPolicyWindows10/1-Create.ps1 @@ -0,0 +1,53 @@ +<# +This example creates a new Intune Firewall Policy for Windows10. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneFirewallPolicyWindows10 'ConfigureIntuneFirewallPolicyWindows10' + { + Assignments = @( + MSFT_DeviceManagementConfigurationPolicyAssignments{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '11111111-1111-1111-1111-111111111111' + } + ); + Description = 'Description' + DisplayName = "Intune Firewall Policy Windows10"; + DisableStatefulFtp = "false"; + DomainProfile_AllowLocalIpsecPolicyMerge = "false"; + DomainProfile_EnableFirewall = "true"; + DomainProfile_LogFilePath = "%systemroot%\system32\LogFiles\Firewall\pfirewall.log"; + DomainProfile_LogMaxFileSize = 1024; + ObjectAccess_AuditFilteringPlatformPacketDrop = "1"; + PrivateProfile_EnableFirewall = "true"; + PublicProfile_EnableFirewall = "true"; + Target = "wsl"; + AllowHostPolicyMerge = "false"; + Ensure = "Present"; + Id = '00000000-0000-0000-0000-000000000000' + RoleScopeTagIds = @("0"); + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneFirewallPolicyWindows10/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneFirewallPolicyWindows10/2-Update.ps1 new file mode 100644 index 0000000000..1debf2e5b6 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneFirewallPolicyWindows10/2-Update.ps1 @@ -0,0 +1,53 @@ +<# +This example updates a Intune Firewall Policy for Windows10. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneFirewallPolicyWindows10 'ConfigureIntuneFirewallPolicyWindows10' + { + Assignments = @( + MSFT_DeviceManagementConfigurationPolicyAssignments{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '11111111-1111-1111-1111-111111111111' + } + ); + Description = 'Description' + DisplayName = "Intune Firewall Policy Windows10"; + DisableStatefulFtp = "false"; + DomainProfile_AllowLocalIpsecPolicyMerge = "true"; # Updated property + DomainProfile_EnableFirewall = "true"; + DomainProfile_LogFilePath = "%systemroot%\system32\LogFiles\Firewall\pfirewall.log"; + DomainProfile_LogMaxFileSize = 1024; + ObjectAccess_AuditFilteringPlatformPacketDrop = "1"; + PrivateProfile_EnableFirewall = "true"; + PublicProfile_EnableFirewall = "true"; + Target = "wsl"; + AllowHostPolicyMerge = "false"; + Ensure = "Present"; + Id = '00000000-0000-0000-0000-000000000000' + RoleScopeTagIds = @("0"); + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneFirewallPolicyWindows10/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneFirewallPolicyWindows10/3-Remove.ps1 new file mode 100644 index 0000000000..fba93ab0a3 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneFirewallPolicyWindows10/3-Remove.ps1 @@ -0,0 +1,34 @@ +<# +This example removes a Device Control Policy. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneFirewallPolicyWindows10 'ConfigureIntuneFirewallPolicyWindows10' + { + Id = '00000000-0000-0000-0000-000000000000' + DisplayName = 'Intune Firewall Policy Windows10' + Ensure = 'Absent' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneFirewallPolicyWindows10.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneFirewallPolicyWindows10.Tests.ps1 new file mode 100644 index 0000000000..1c18557eb3 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneFirewallPolicyWindows10.Tests.ps1 @@ -0,0 +1,444 @@ +[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 "IntuneFirewallPolicyWindows10" -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 Update-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName New-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return @{ + Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + } + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return @{ + Description = "FakeStringValue" + Id = "619bd4a4-3b3b-4441-bd6f-3f4c0c444870" + Name = "IntuneFirewallPolicyWindows10_1" + Platforms = "windows10" + RoleScopeTagIds = @("FakeStringValue") + Technologies = "mdm,microsoftSense" + TemplateReference = @{ + templateId = "6078910e-d808-4a9f-a51d-1b8a7bacb7c0_1" + } + } + } + + Mock -CommandName Remove-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName Update-IntuneDeviceConfigurationPolicy -MockWith { + } + + Mock -CommandName Get-IntuneSettingCatalogPolicySetting -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { + return @( + @{ + Id = '0' + SettingDefinitions = @( + @{ + Id = 'vendor_msft_firewall_mdmstore_global_disablestatefulftp' + Name = 'DisableStatefulFtp' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'vendor_msft_firewall_mdmstore_global_disablestatefulftp' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = '38329af6-2670-4a71-972d-482010ca97fc' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + children = @() + value = 'vendor_msft_firewall_mdmstore_global_disablestatefulftp_false' + } + } + } + }, + @{ + Id = '1' + SettingDefinitions = @( + @{ + Id = 'vendor_msft_firewall_mdmstore_domainprofile_enablefirewall' + Name = 'EnableFirewall' + OffsetUri = '/MdmStore/DomainProfile/EnableFirewall' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + }, + @{ + Id = 'vendor_msft_firewall_mdmstore_domainprofile_logfilepath' + Name = 'LogFilePath' + OffsetUri = '/MdmStore/DomainProfile/LogFilePath' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationStringSettingDefinition' + dependentOn = @( + @{ + dependentOn = 'vendor_msft_firewall_mdmstore_domainprofile_enablefirewall_true' + parentSettingId = 'vendor_msft_firewall_mdmstore_domainprofile_enablefirewall' + } + ) + } + }, + @{ + Id = 'vendor_msft_firewall_mdmstore_publicprofile_logfilepath' + Name = 'LogFilePath' + OffsetUri = '/MdmStore/PublicProfile/LogFilePath' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationStringSettingDefinition' + dependentOn = @( + @{ + dependentOn = 'vendor_msft_firewall_mdmstore_publicprofile_enablefirewall_true' + parentSettingId = 'vendor_msft_firewall_mdmstore_publicprofile_enablefirewall' + } + ) + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'vendor_msft_firewall_mdmstore_domainprofile_enablefirewall' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = '7714c373-a19a-4b64-ba6d-2e9db04a7684' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + value = 'vendor_msft_firewall_mdmstore_domainprofile_enablefirewall_true' + children = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance' + settingDefinitionId = 'vendor_msft_firewall_mdmstore_domainprofile_logfilepath' + simpleSettingValue = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationStringSettingValue' + value = '%systemroot%\system32\LogFiles\Firewall\pfirewall.log' + } + } + ) + } + } + } + }, + @{ + Id = '2' + SettingDefinitions = @( + @{ + Id = 'vendor_msft_firewall_mdmstore_hypervvmsettings_{vmcreatorid}_domainprofile_enablefirewall' + Name = 'EnableFirewall' + OffsetUri = '/MdmStore/HyperVVMSettings/{0}/DomainProfile/EnableFirewall' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + options = @( + # Only option used in the tests is defined here + @{ + name = 'Enable Firewall' + itemId = 'vendor_msft_firewall_mdmstore_hypervvmsettings_{vmcreatorid}_domainprofile_enablefirewall_true' + dependentOn = @( + @{ + dependentOn = 'vendor_msft_firewall_mdmstore_hypervvmsettings_{vmcreatorid}_target_wsl' + parentSettingId = 'vendor_msft_firewall_mdmstore_hypervvmsettings_{vmcreatorid}_target' + } + ) + + } + ) + } + }, + @{ + Id = 'vendor_msft_firewall_mdmstore_hypervvmsettings_{vmcreatorid}_target' + Name = 'Target' + OffsetUri = '/MdmStore/HyperVVMSettings/{0}/Target' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + options = @( + @{ + dependentOn = @( + @{ + dependentOn = 'vendor_msft_firewall_mdmstore_hypervvmsettings_{vmcreatorid}' + parentSettingId = 'vendor_msft_firewall_mdmstore_hypervvmsettings_{vmcreatorid}' + } + ) + name = 'WSL' + itemId = 'vendor_msft_firewall_mdmstore_hypervvmsettings_{vmcreatorid}_target_wsl' + } + ) + } + }, + @{ + Id = 'vendor_msft_firewall_mdmstore_hypervvmsettings_{vmcreatorid}' + Name = '{VMCreatorId}' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingGroupCollectionDefinition' + childIds = @( + 'vendor_msft_firewall_mdmstore_hypervvmsettings_{vmcreatorid}_target' + ) + maximumCount = 1 + minimumCount = 0 + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'vendor_msft_firewall_mdmstore_hypervvmsettings_{vmcreatorid}' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = '24805bd4-1133-4790-82ae-4caa63e16aa6' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' + groupSettingCollectionValue = @( + @{ + children = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + value = 'vendor_msft_firewall_mdmstore_hypervvmsettings_{vmcreatorid}_target_wsl' + children = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + settingDefinitionId = 'vendor_msft_firewall_mdmstore_hypervvmsettings_{vmcreatorid}_domainprofile_enablefirewall' + choiceSettingValue = @{ + children = @() + value = 'vendor_msft_firewall_mdmstore_hypervvmsettings_{vmcreatorid}_domainprofile_enablefirewall_true' + } + } + ) + } + settingDefinitionId = 'vendor_msft_firewall_mdmstore_hypervvmsettings_{vmcreatorid}_target' + } + ) + } + ) + } + } + } + ) + } + + Mock -CommandName Update-DeviceConfigurationPolicyAssignment -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 + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyAssignment -MockWith { + return @(@{ + Id = '12345-12345-12345-12345-12345' + Source = 'direct' + SourceId = '12345-12345-12345-12345-12345' + Target = @{ + DeviceAndAppManagementAssignmentFilterId = '12345-12345-12345-12345-12345' + DeviceAndAppManagementAssignmentFilterType = 'none' + AdditionalProperties = @( + @{ + '@odata.type' = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + } + ) + } + }) + } + } + # Test contexts + Context -Name "The IntuneFirewallPolicyWindows10 should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "FakeStringValue" + Id = "619bd4a4-3b3b-4441-bd6f-3f4c0c444870" + DisplayName = "IntuneFirewallPolicyWindows10_1" + RoleScopeTagIds = @("FakeStringValue") + Ensure = "Present" + Credential = $Credential; + DisableStatefulFtp = "false"; + DomainProfile_EnableFirewall = "true" + DomainProfile_LogFilePath = "%systemroot%\system32\LogFiles\Firewall\pfirewall.log"; + HyperVVMSettings_DomainProfile_EnableFirewall = "true" + Target = "wsl" + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -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-MgBetaDeviceManagementConfigurationPolicy -Exactly 1 + } + } + + Context -Name "The IntuneFirewallPolicyWindows10 exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "FakeStringValue" + Id = "619bd4a4-3b3b-4441-bd6f-3f4c0c444870" + DisplayName = "IntuneFirewallPolicyWindows10_1" + RoleScopeTagIds = @("FakeStringValue") + Ensure = 'Absent' + Credential = $Credential + DisableStatefulFtp = "false"; + DomainProfile_EnableFirewall = "true" + DomainProfile_LogFilePath = "%systemroot%\system32\LogFiles\Firewall\pfirewall.log"; + HyperVVMSettings_DomainProfile_EnableFirewall = "true" + Target = "wsl" + } + } + + 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-MgBetaDeviceManagementConfigurationPolicy -Exactly 1 + } + } + Context -Name "The IntuneFirewallPolicyWindows10 Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "FakeStringValue" + Id = "619bd4a4-3b3b-4441-bd6f-3f4c0c444870" + DisplayName = "IntuneFirewallPolicyWindows10_1" + RoleScopeTagIds = @("FakeStringValue") + Ensure = 'Present' + Credential = $Credential + DisableStatefulFtp = "false"; + DomainProfile_EnableFirewall = "true" + DomainProfile_LogFilePath = "%systemroot%\system32\LogFiles\Firewall\pfirewall.log"; + HyperVVMSettings_DomainProfile_EnableFirewall = "true" + Target = "wsl" + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The IntuneFirewallPolicyWindows10 exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "FakeStringValue" + Id = "619bd4a4-3b3b-4441-bd6f-3f4c0c444870" + DisplayName = "IntuneFirewallPolicyWindows10_1" + RoleScopeTagIds = @("FakeStringValue") + Ensure = 'Present' + Credential = $Credential + DisableStatefulFtp = "true" + DomainProfile_EnableFirewall = "true" + DomainProfile_LogFilePath = "%systemroot%\system32\LogFiles\Firewall\pfirewall_old.log"; # Updated value + HyperVVMSettings_DomainProfile_EnableFirewall = "true" + Target = "wsl" + } + } + + 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 Update-IntuneDeviceConfigurationPolicy -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + } + 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 6518aa63dede4760acc566bb9e7aa24f780287e7 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Tue, 17 Sep 2024 21:42:35 +0200 Subject: [PATCH 204/465] Reimplement fallback for endless loop --- CHANGELOG.md | 9 +++++++++ .../Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 | 17 +++++++++++++++-- ResourceGenerator/M365DSCResourceGenerator.psm1 | 17 +++++++++++++++-- ...IntuneDeviceControlPolicyWindows10.Tests.ps1 | 2 ++ 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5a0b0d71c..aa3dc58e8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,15 @@ * IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10 * Add missing `AccessTokens` parameter to `Export-TargetResource` FIXES [#5034](https://github.com/microsoft/Microsoft365DSC/issues/5034) +* IntuneFirewallPolicyWindows10 + * Initial release + FIXES [#3033](https://github.com/microsoft/Microsoft365DSC/issues/3033) +* M365DSCDRGUtil + * Add support for more complex Intune Settings Catalog properties + * Update handling of `Update-IntuneDeviceConfigurationPolicy` to throw on error + FIXES [#5055](https://github.com/microsoft/Microsoft365DSC/issues/5055) +* M365DSCResourceGenerator + * Update Intune resource generation for the Settings Catalog. * SCRoleGroup * Fixes an issue with creation without specifying Displayname * Fixes an issue with Drifts because of returned Role format diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index 68d95b87d0..542a206b3d 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -2327,6 +2327,7 @@ function Export-IntuneSettingCatalogPolicySettings else { $skip = 0 + $breakCounter = 0 $newSettingName = $settingName do { $previousSettingName = $newSettingName @@ -2342,9 +2343,21 @@ function Export-IntuneSettingCatalogPolicySettings } $settingsWithSameName = $combinationMatchesWithOffsetUri $skip++ - } while ($combinationMatchesWithOffsetUri.Count -gt 1) + $breakCounter++ + } while ($combinationMatchesWithOffsetUri.Count -gt 1 -and $breakCounter -lt 8) - $settingName = $newSettingName + if ($breakCounter -lt 8) + { + $settingName = $newSettingName + } + else + { + # Alternative way if no unique setting name can be found + $parentSettingIdProperty = $parentSetting.Id.Split('_')[-1] + $parentSettingIdWithoutProperty = $parentSetting.Id.Replace("_$parentSettingIdProperty", "") + # We can't use the entire setting here, because the child setting id does not have to come after the parent setting id + $settingName = $settingDefinition.Id.Replace($parentSettingIdWithoutProperty + "_", "").Replace($parentSettingIdProperty + "_", "") + } } } diff --git a/ResourceGenerator/M365DSCResourceGenerator.psm1 b/ResourceGenerator/M365DSCResourceGenerator.psm1 index 23560cbd98..ecdccf6a86 100644 --- a/ResourceGenerator/M365DSCResourceGenerator.psm1 +++ b/ResourceGenerator/M365DSCResourceGenerator.psm1 @@ -3816,6 +3816,7 @@ function New-SettingsCatalogSettingDefinitionSettingsFromTemplate { else { $skip = 0 + $breakCounter = 0 $newSettingName = $settingName do { $previousSettingName = $newSettingName @@ -3831,9 +3832,21 @@ function New-SettingsCatalogSettingDefinitionSettingsFromTemplate { } $settingsWithSameName = $combinationMatchesWithOffsetUri $skip++ - } while ($combinationMatchesWithOffsetUri.Count -gt 1) + $breakCounter++ + } while ($combinationMatchesWithOffsetUri.Count -gt 1 -and $breakCounter -lt 8) - $settingName = $newSettingName + if ($breakCounter -lt 8) + { + $settingName = $newSettingName + } + else + { + # Alternative way if no unique setting name can be found + $parentSettingIdProperty = $parentSetting.Id.Split('_')[-1] + $parentSettingIdWithoutProperty = $parentSetting.Id.Replace("_$parentSettingIdProperty", "") + # We can't use the entire setting here, because the child setting id does not have to come after the parent setting id + $settingName = $settingDefinition.Id.Replace($parentSettingIdWithoutProperty + "_", "").Replace($parentSettingIdProperty + "_", "") + } } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceControlPolicyWindows10.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceControlPolicyWindows10.Tests.ps1 index 31712d60ea..efe2f33002 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceControlPolicyWindows10.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceControlPolicyWindows10.Tests.ps1 @@ -260,6 +260,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { @{ Id = 'device_vendor_msft_defender_configuration_devicecontrol_policyrules_{ruleid}_ruledata_id' Name = 'Id' + OffsetUri = '/configuration/devicecontrol/policyrules/{0}/ruledata' AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingDefinition' dependentOn = @( @@ -353,6 +354,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { @{ Id = 'device_vendor_msft_defender_configuration_devicecontrol_policyrules_{ruleid}_ruledata_entry_id' Name = 'Id' + OffsetUri = '/configuration/devicecontrol/policyrules/{0}/ruledata' AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingDefinition' dependentOn = @( From a42a311b9f6be118a78555fc949cc02a333194a0 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 17 Sep 2024 16:47:31 -0400 Subject: [PATCH 205/465] Updates --- .../MSFT_SCInsiderRiskEntityList.psm1 | 64 +++++++++++++++++-- .../MSFT_SCInsiderRiskEntityList.schema.mof | 1 - .../Modules/M365DSCTelemetryEngine.psm1 | 29 +++++---- 3 files changed, 76 insertions(+), 18 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 index b0a67fdcbc..c5339bf426 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 @@ -500,14 +500,69 @@ function Set-TargetResource # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - ##TODO - Replace by the New cmdlet for the resource - New-Cmdlet @SetParameters + # Create a new Domain Group + if ($ListType -eq 'CustomDomainLists') + { + $value = @() + foreach ($domain in $Domains) + { + $value += "{`"Dmn`":`"$($domain.Dmn)`",`"isMLSubDmn`":$($domain.isMLSubDmn.ToString().ToLower())}" + } + Write-Verbose -Message "Creating new Domain Group {$Name} with values {$($value -join ',')}" + New-InsiderRiskEntityList -Type 'CustomDomainLists' ` + -Name $Name ` + -DisplayName $DisplayName ` + -Description $Description ` + -Entities $value | Out-Null + } + elseif ($ListType -eq 'CustomFilePathRegexLists') + { + $value = @() + foreach ($filePath in $FilePaths) + { + $value += "{`"FlPthRgx`":`"$($filePath)`",`"isSrc`":true,`"isTrgt`":true}" + } + Write-Verbose -Message "Creating new FilePath Group {$Name} with values {$($value -join ',')}" + New-InsiderRiskEntityList -Type 'CustomDomainLists' ` + -Name $Name ` + -DisplayName $DisplayName ` + -Description $Description ` + -Entities $value | Out-Null + } } # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - ##TODO - Replace by the Update/Set cmdlet for the resource - Set-cmdlet @SetParameters + # Update Domain Group + if ($ListType -eq 'CustomDomainLists') + { + $entitiesToAdd = @() + $entitiesToRemove = @() + $differences = Compare-Object -ReferenceObject $currentInstance.Domains.Dmn -DifferenceObject $Domains.Dmn + foreach ($diff in $differences) + { + if ($diff.SideIndicator -eq '=>') + { + $instance = $Domains | Where-Object -FilterScript {$_.Dmn -eq $diff.InputObject} + $entitiesToAdd += "{`"Dmn`":`"$($instance.Dmn)`",`"isMLSubDmn`":$($instance.isMLSubDmn.ToString().ToLower())}" + } + else + { + $instance = $currentInstance.Domains | Where-Object -FilterScript {$_.Dmn -eq $diff.InputObject} + $entitiesToRemove += "{`"Dmn`":`"$($instance.Dmn)`",`"isMLSubDmn`":$($instance.isMLSubDmn.ToString().ToLower())}" + } + } + + Write-Verbose -Message "Updating Domain Group {$Name}" + Write-Verbose -Message "Adding entities: $($entitiesToAdd -join ',')" + Write-Verbose -Message "Removing entities: $($entitiesToRemove -join ',')" + + Set-InsiderRiskEntityList -Identity $Name ` + -DisplayName $DisplayName ` + -Description $Description ` + -AddEntities $entitiesToAdd ` + -RemoveEntities $entitiesToRemove | Out-Null + } } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') @@ -643,6 +698,7 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + $ValuesToCheck.Remove('Name') | Out-Null Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof index e1d0a0bbb0..e005642f04 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof @@ -28,7 +28,6 @@ class MSFT_SCInsiderRiskEntityList : OMI_BaseResource [Write, Description("")] String ExcludedKeyworkGroups[]; [Write, Description("")] String ExcludedSensitiveInformationTypeGroups[]; [Write, Description("")] String ExcludedSiteGroups[]; - [Write, Description("Domain group.")] string Domains; [Write, Description("Specify if this entity should exist or not."), 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; diff --git a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 index a62b0907b7..6d0b9f27e7 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 @@ -368,7 +368,10 @@ function Add-M365DSCTelemetryEvent # LCM Metadata Information try { - $LCMInfo = Get-DscLocalConfigurationManager -ErrorAction Stop + if ($null -eq $Global:LCMInfo) + { + $Global:LCMInfo = Get-DscLocalConfigurationManager -ErrorAction Stop + } $certificateConfigured = $false if (-not [System.String]::IsNullOrEmpty($LCMInfo.CertificateID)) @@ -377,17 +380,17 @@ function Add-M365DSCTelemetryEvent } $partialConfiguration = $false - if (-not [System.String]::IsNullOrEmpty($LCMInfo.PartialConfigurations)) + if (-not [System.String]::IsNullOrEmpty($Global:LCMInfo.PartialConfigurations)) { $partialConfiguration = $true } $Data.Add('LCMUsesPartialConfigurations', $partialConfiguration) $Data.Add('LCMCertificateConfigured', $certificateConfigured) - $Data.Add('LCMConfigurationMode', $LCMInfo.ConfigurationMode) - $Data.Add('LCMConfigurationModeFrequencyMins', $LCMInfo.ConfigurationModeFrequencyMins) - $Data.Add('LCMRefreshMode', $LCMInfo.RefreshMode) - $Data.Add('LCMState', $LCMInfo.LCMState) - $Data.Add('LCMStateDetail', $LCMInfo.LCMStateDetail) + $Data.Add('LCMConfigurationMode', $Global:LCMInfo.ConfigurationMode) + $Data.Add('LCMConfigurationModeFrequencyMins', $Global:LCMInfo.ConfigurationModeFrequencyMins) + $Data.Add('LCMRefreshMode', $Global:LCMInfo.RefreshMode) + $Data.Add('LCMState', $Global:LCMInfo.LCMState) + $Data.Add('LCMStateDetail', $Global:LCMInfo.LCMStateDetail) if ([System.String]::IsNullOrEmpty($Type)) { @@ -395,18 +398,18 @@ function Add-M365DSCTelemetryEvent { $Type = 'Export' } - elseif ($LCMInfo.LCMStateDetail -eq 'LCM is performing a consistency check.' -or ` - $LCMInfo.LCMStateDetail -eq 'LCM exécute une vérification de cohérence.' -or ` - $LCMInfo.LCMStateDetail -eq 'LCM führt gerade eine Konsistenzüberprüfung durch.') + elseif ($Global:LCMInfo.LCMStateDetail -eq 'LCM is performing a consistency check.' -or ` + $Global:LCMInfo.LCMStateDetail -eq 'LCM exécute une vérification de cohérence.' -or ` + $Global:LCMInfo.LCMStateDetail -eq 'LCM führt gerade eine Konsistenzüberprüfung durch.') { $Type = 'MonitoringScheduled' } - elseif ($LCMInfo.LCMStateDetail -eq 'LCM is testing node against the configuration.') + elseif ($Global:LCMInfo.LCMStateDetail -eq 'LCM is testing node against the configuration.') { $Type = 'MonitoringManual' } - elseif ($LCMInfo.LCMStateDetail -eq 'LCM is applying a new configuration.' -or ` - $LCMInfo.LCMStateDetail -eq 'LCM applique une nouvelle configuration.') + elseif ($Global:LCMInfo.LCMStateDetail -eq 'LCM is applying a new configuration.' -or ` + $Global:LCMInfo.LCMStateDetail -eq 'LCM applique une nouvelle configuration.') { $Type = 'ApplyingConfiguration' } From c7be3bba30031705cc23be2497082ce2cd3ce580 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 17 Sep 2024 20:23:03 -0400 Subject: [PATCH 206/465] Updates --- .../MSFT_SCInsiderRiskEntityList.psm1 | 208 +++++++++++++++++- .../MSFT_SCInsiderRiskEntityList.schema.mof | 10 +- .../Modules/M365DSCTelemetryEngine.psm1 | 28 +-- 3 files changed, 225 insertions(+), 21 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 index c5339bf426..a2d00ba6ba 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 @@ -41,7 +41,7 @@ function Get-TargetResource $SensitiveInformationTypes, [Parameter()] - [System.String[]] + [System.Management.Infrastructure.CimInstance[]] $Sites, [Parameter()] @@ -412,7 +412,7 @@ function Set-TargetResource $SensitiveInformationTypes, [Parameter()] - [System.String[]] + [System.Management.Infrastructure.CimInstance[]] $Sites, [Parameter()] @@ -520,10 +520,66 @@ function Set-TargetResource $value = @() foreach ($filePath in $FilePaths) { - $value += "{`"FlPthRgx`":`"$($filePath)`",`"isSrc`":true,`"isTrgt`":true}" + $value += "{`"FlPthRgx`":`"$($filePath.Replace('\', '\\'))`",`"isSrc`":true,`"isTrgt`":true}" } Write-Verbose -Message "Creating new FilePath Group {$Name} with values {$($value -join ',')}" - New-InsiderRiskEntityList -Type 'CustomDomainLists' ` + New-InsiderRiskEntityList -Type 'CustomFilePathRegexLists' ` + -Name $Name ` + -DisplayName $DisplayName ` + -Description $Description ` + -Entities $value | Out-Null + } + elseif ($ListType -eq 'CustomFileTypeLists') + { + $value = @() + foreach ($fileType in $FileTypes) + { + $value += "{`"Ext`":`"$fileType`"}" + } + Write-Verbose -Message "Creating new FileType Group {$Name} with values {$($value -join ',')}" + New-InsiderRiskEntityList -Type 'CustomFileTypeLists ' ` + -Name $Name ` + -DisplayName $DisplayName ` + -Description $Description ` + -Entities $value | Out-Null + } + elseif ($ListType -eq 'CustomKeywordLists') + { + $value = @() + foreach ($keyword in $Keywords) + { + $value += "{`"Name`":`"$keyword`"}" + } + Write-Verbose -Message "Creating new Keyword Group {$Name} with values {$($value -join ',')}" + New-InsiderRiskEntityList -Type 'CustomKeywordLists' ` + -Name $Name ` + -DisplayName $DisplayName ` + -Description $Description ` + -Entities $value | Out-Null + } + elseif ($ListType -eq 'CustomSensitiveInformationTypeLists') + { + $value = @() + foreach ($sit in $SensitiveInformationTypes) + { + $value += "{`"Guid`":`"$sit`"}" + } + Write-Verbose -Message "Creating new SIT Group {$Name} with values {$($value -join ',')}" + New-InsiderRiskEntityList -Type 'CustomSensitiveInformationTypeLists' ` + -Name $Name ` + -DisplayName $DisplayName ` + -Description $Description ` + -Entities $value | Out-Null + } + elseif ($ListType -eq 'CustomSiteLists') + { + $value = @() + foreach ($site in $Sites) + { + $value += "{`"Url`":`"$($site.Url)`";`"Name`":`"$($site.Name)`";`"Guid`":`"$($site.Guid)`"}" + } + Write-Verbose -Message "Creating new Site Group {$Name} with values {$($value -join ',')}" + New-InsiderRiskEntityList -Type 'CustomSiteLists' ` -Name $Name ` -DisplayName $DisplayName ` -Description $Description ` @@ -557,6 +613,148 @@ function Set-TargetResource Write-Verbose -Message "Adding entities: $($entitiesToAdd -join ',')" Write-Verbose -Message "Removing entities: $($entitiesToRemove -join ',')" + Set-InsiderRiskEntityList -Identity $Name ` + -DisplayName $DisplayName ` + -Description $Description ` + -AddEntities $entitiesToAdd ` + -RemoveEntities $entitiesToRemove | Out-Null + } + # Update File Path Group + elseif ($ListType -eq 'CustomFilePathRegexLists') + { + $entitiesToAdd = @() + $entitiesToRemove = @() + $differences = Compare-Object -ReferenceObject $currentInstance.FilePaths -DifferenceObject $FilePaths + foreach ($diff in $differences) + { + if ($diff.SideIndicator -eq '=>') + { + $entitiesToAdd += "{`"FlPthRgx`":`"$($diff.InputObject.Replace('\', '\\'))`",`"isSrc`":true,`"isTrgt`":true}" + } + else + { + $entitiesToRemove += "{`"FlPthRgx`":`"$($diff.InputObject.Replace('\', '\\'))`",`"isSrc`":true,`"isTrgt`":true}" + } + } + + Write-Verbose -Message "Updating File Path Group {$Name}" + Write-Verbose -Message "Adding entities: $($entitiesToAdd -join ',')" + Write-Verbose -Message "Removing entities: $($entitiesToRemove -join ',')" + + Set-InsiderRiskEntityList -Identity $Name ` + -DisplayName $DisplayName ` + -Description $Description ` + -AddEntities $entitiesToAdd ` + -RemoveEntities $entitiesToRemove | Out-Null + } + # Update File Type Group + elseif ($ListType -eq 'CustomFileTypeLists') + { + $entitiesToAdd = @() + $entitiesToRemove = @() + $differences = Compare-Object -ReferenceObject $currentInstance.FileTypes -DifferenceObject $FileTypes + foreach ($diff in $differences) + { + if ($diff.SideIndicator -eq '=>') + { + $entitiesToAdd += "{`"Ext`":`"$($diff.InputObject)`"}" + } + else + { + $entitiesToRemove += "{`"Ext`":`"$($diff.InputObject)`"}" + } + } + + Write-Verbose -Message "Updating File Type Group {$Name}" + Write-Verbose -Message "Adding entities: $($entitiesToAdd -join ',')" + Write-Verbose -Message "Removing entities: $($entitiesToRemove -join ',')" + + Set-InsiderRiskEntityList -Identity $Name ` + -DisplayName $DisplayName ` + -Description $Description ` + -AddEntities $entitiesToAdd ` + -RemoveEntities $entitiesToRemove | Out-Null + } + # Update Keywords Group + elseif ($ListType -eq 'CustomKeywordLists') + { + $entitiesToAdd = @() + $entitiesToRemove = @() + $differences = Compare-Object -ReferenceObject $currentInstance.Keywords -DifferenceObject $Keywords + foreach ($diff in $differences) + { + if ($diff.SideIndicator -eq '=>') + { + $entitiesToAdd += "{`"Name`":`"$($diff.InputObject)`"}" + } + else + { + $entitiesToRemove += "{`"Name`":`"$($diff.InputObject)`"}" + } + } + + Write-Verbose -Message "Updating Keyword Group {$Name}" + Write-Verbose -Message "Adding entities: $($entitiesToAdd -join ',')" + Write-Verbose -Message "Removing entities: $($entitiesToRemove -join ',')" + + Set-InsiderRiskEntityList -Identity $Name ` + -DisplayName $DisplayName ` + -Description $Description ` + -AddEntities $entitiesToAdd ` + -RemoveEntities $entitiesToRemove | Out-Null + } + # Update SIT Group + elseif ($ListType -eq 'CustomSensitiveInformationTypeLists') + { + $entitiesToAdd = @() + $entitiesToRemove = @() + $differences = Compare-Object -ReferenceObject $currentInstance.SensitiveInformationTypes -DifferenceObject $SensitiveInformationTypes + foreach ($diff in $differences) + { + if ($diff.SideIndicator -eq '=>') + { + $entitiesToAdd += "{`"Guid`":`"$($diff.InputObject)`"}" + } + else + { + $entitiesToRemove += "{`"Guid`":`"$($diff.InputObject)`"}" + } + } + + Write-Verbose -Message "Updating SIT Group {$Name}" + Write-Verbose -Message "Adding entities: $($entitiesToAdd -join ',')" + Write-Verbose -Message "Removing entities: $($entitiesToRemove -join ',')" + + Set-InsiderRiskEntityList -Identity $Name ` + -DisplayName $DisplayName ` + -Description $Description ` + -AddEntities $entitiesToAdd ` + -RemoveEntities $entitiesToRemove | Out-Null + } + # Update Sites Group + elseif ($ListType -eq 'CustomSiteLists') + { + $entitiesToAdd = @() + $entitiesToRemove = @() + $differences = Compare-Object -ReferenceObject $currentInstance.Sites.Url -DifferenceObject $Sites.Url + foreach ($diff in $differences) + { + if ($diff.SideIndicator -eq '=>') + { + $entry = $Sites | Where-Object -FilterScript {$_.Url -eq $diff.InputObject} + $entitiesToAdd += "{`"Url`":`"$($entry.Url)`";`"Name`":`"$($entry.Name)`";`"Guid`":`"$($entry.Guid)`"}" + } + else + { + $entry = $currentInstance.Sites | Where-Object -FilterScript {$_.Url -eq $diff.InputObject} + $entitiesToRemove += "{`"Url`":`"$($entry.Url)`";`"Name`":`"$($entry.Name)`";`"Guid`":`"$($entry.Guid)`"}" + } + } + + Write-Verbose -Message "Updating Sites Group {$Name}" + Write-Verbose -Message "Adding entities: $($entitiesToAdd -join ',')" + Write-Verbose -Message "Removing entities: $($entitiesToRemove -join ',')" + Set-InsiderRiskEntityList -Identity $Name ` -DisplayName $DisplayName ` -Description $Description ` @@ -615,7 +813,7 @@ function Test-TargetResource $SensitiveInformationTypes, [Parameter()] - [System.String[]] + [System.Management.Infrastructure.CimInstance[]] $Sites, [Parameter()] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof index e005642f04..51d79fa639 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof @@ -5,7 +5,13 @@ class MSFT_SCInsiderRiskEntityListDomain [Write, Description("Defines if the entry should include multi-level subdomains or not.")] Boolean isMLSubDmn; [Write, Description("Type of the Sensitive Information label")] String type; }; - +[ClassVersion("1.0.0")] +class MSFT_SCInsiderRiskEntityListSite +{ + [Required, Description("Url of the site.")] String Url; + [Write, Description("Name of the site.")] String Name; + [Write, Description("Unique identifier of the site.")] String Guid; +}; [ClassVersion("1.0.0.0"), FriendlyName("SCInsiderRiskEntityList")] class MSFT_SCInsiderRiskEntityList : OMI_BaseResource { @@ -18,7 +24,7 @@ class MSFT_SCInsiderRiskEntityList : OMI_BaseResource [Write, Description("")] String FileTypes[]; [Write, Description("")] String Keywords[]; [Write, Description("")] String SensitiveInformationTypes[]; - [Write, Description("")] String Sites[]; + [Write, Description(""), EmbeddedInstance("MSFT_SCInsiderRiskEntityListSite")] String Sites[]; [Write, Description("")] String TrainableClassifiers[]; [Write, Description("")] String ExceptionKeyworkGroups[]; [Write, Description("")] String ExcludedClassifierGroups[]; diff --git a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 index 6d0b9f27e7..a393a98017 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 @@ -368,9 +368,9 @@ function Add-M365DSCTelemetryEvent # LCM Metadata Information try { - if ($null -eq $Global:LCMInfo) + if ($null -eq $Script:LCMInfo) { - $Global:LCMInfo = Get-DscLocalConfigurationManager -ErrorAction Stop + $Script:LCMInfo = Get-DscLocalConfigurationManager -ErrorAction Stop } $certificateConfigured = $false @@ -380,17 +380,17 @@ function Add-M365DSCTelemetryEvent } $partialConfiguration = $false - if (-not [System.String]::IsNullOrEmpty($Global:LCMInfo.PartialConfigurations)) + if (-not [System.String]::IsNullOrEmpty($Script:LCMInfo.PartialConfigurations)) { $partialConfiguration = $true } $Data.Add('LCMUsesPartialConfigurations', $partialConfiguration) $Data.Add('LCMCertificateConfigured', $certificateConfigured) - $Data.Add('LCMConfigurationMode', $Global:LCMInfo.ConfigurationMode) - $Data.Add('LCMConfigurationModeFrequencyMins', $Global:LCMInfo.ConfigurationModeFrequencyMins) - $Data.Add('LCMRefreshMode', $Global:LCMInfo.RefreshMode) - $Data.Add('LCMState', $Global:LCMInfo.LCMState) - $Data.Add('LCMStateDetail', $Global:LCMInfo.LCMStateDetail) + $Data.Add('LCMConfigurationMode', $Script:LCMInfo.ConfigurationMode) + $Data.Add('LCMConfigurationModeFrequencyMins', $Script:LCMInfo.ConfigurationModeFrequencyMins) + $Data.Add('LCMRefreshMode', $Script:LCMInfo.RefreshMode) + $Data.Add('LCMState', $Script:LCMInfo.LCMState) + $Data.Add('LCMStateDetail', $Script:LCMInfo.LCMStateDetail) if ([System.String]::IsNullOrEmpty($Type)) { @@ -398,18 +398,18 @@ function Add-M365DSCTelemetryEvent { $Type = 'Export' } - elseif ($Global:LCMInfo.LCMStateDetail -eq 'LCM is performing a consistency check.' -or ` - $Global:LCMInfo.LCMStateDetail -eq 'LCM exécute une vérification de cohérence.' -or ` - $Global:LCMInfo.LCMStateDetail -eq 'LCM führt gerade eine Konsistenzüberprüfung durch.') + elseif ($Script:LCMInfo.LCMStateDetail -eq 'LCM is performing a consistency check.' -or ` + $Script:LCMInfo.LCMStateDetail -eq 'LCM exécute une vérification de cohérence.' -or ` + $Script:LCMInfo.LCMStateDetail -eq 'LCM führt gerade eine Konsistenzüberprüfung durch.') { $Type = 'MonitoringScheduled' } - elseif ($Global:LCMInfo.LCMStateDetail -eq 'LCM is testing node against the configuration.') + elseif ($Script:LCMInfo.LCMStateDetail -eq 'LCM is testing node against the configuration.') { $Type = 'MonitoringManual' } - elseif ($Global:LCMInfo.LCMStateDetail -eq 'LCM is applying a new configuration.' -or ` - $Global:LCMInfo.LCMStateDetail -eq 'LCM applique une nouvelle configuration.') + elseif ($Script:LCMInfo.LCMStateDetail -eq 'LCM is applying a new configuration.' -or ` + $Script:LCMInfo.LCMStateDetail -eq 'LCM applique une nouvelle configuration.') { $Type = 'ApplyingConfiguration' } From 97f4430081c9879638784ebd8f5331245efedf18 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 17 Sep 2024 21:16:51 -0400 Subject: [PATCH 207/465] ADOOrganizationOwner - Initial Release --- CHANGELOG.md | 2 + .../MSFT_ADOOrganizationOwner.psm1 | 30 ++- .../MSFT_ADOOrganizationOwner.schema.mof | 5 +- .../MSFT_ADOOrganizationOwner/readme.md | 2 +- .../MSFT_ADOOrganizationOwner/settings.json | 22 +- .../ADOOrganizationOwner/2-Update.ps1 | 9 +- ...osoft365DSC.ADOOrganizationOwner.Tests.ps1 | 222 +++++++++++------- 7 files changed, 180 insertions(+), 112 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f353bb8605..0390105429 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ * Initial release * ADOOrganizationOwner * Initial release. +* ADOOrganizationOwner + * Initial release. * ADOSecurityPolicy * Initial release. * AzureSubscription diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 index def4556018..a6bae9c949 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 @@ -58,13 +58,14 @@ function Get-TargetResource $uri = "https://vssps.dev.azure.com/$OrganizationName/_apis/Organization/Collections/Me" $organizationInfo = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri - $uri = "https://app.vssps.visualstudio.com/_apis/profile/profiles/$($organizationInfo.Owner)?api-version=7.1-preview.3" - $ownerInfo = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri + $uri = "https://vsaex.dev.azure.com/$OrganizationName/_apis/userentitlements?api-version=7.2-preview.4" + $allUsers = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri + + $ownerInfo = $allUsers.Items | Where-Object -FilterScript {$_.id -eq $organizationInfo.owner} $results = @{ OrganizationName = $OrganizationName - Owner = $ownerInfo.EmailAddress - Ensure = 'Present' + Owner = $ownerInfo.user.principalName Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId @@ -139,12 +140,23 @@ function Set-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - + Write-Verbose -Message "Retrieving all users." + $uri = "https://vsaex.dev.azure.com/$OrganizationName/_apis/userentitlements?api-version=7.2-preview.4" + $allUsers = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri + + $ownerInfo = $allUsers.items | Where-Object -FilterScript {$_.user.principalName -eq $Owner} - $body = "[{`"from`":`"`",`"op`":2,`"path`":`"/Owner`",`"value`":`"a76a2017-0aee-69fd-9300-cf624aaff3a9`"}]" - $uri ='https://vssps.dev.azure.com/O365DSC-Dev/_apis/Organization/Collections/Me?api-version=7.1-preview.1' - $org = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri - Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri -Method PATCH -Body $body + if ($null -ne $ownerInfo) + { + Write-Verbose -Message "Updating owner for organization {$OrganizationName} to {$($ownerInfo.id)}" + $body = "[{`"from`":`"`",`"op`":2,`"path`":`"/Owner`",`"value`":`"$($ownerInfo.id)`"}]" + $uri ='https://vssps.dev.azure.com/O365DSC-Dev/_apis/Organization/Collections/Me?api-version=7.1-preview.1' + Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri -Method PATCH -Body $body + } + else + { + throw "Could not retrieve an Azure DevOPS user entitlement for {$Owner}" + } } function Test-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.schema.mof index 57ba50bb59..1f87c3b452 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.schema.mof @@ -1,9 +1,8 @@ [ClassVersion("1.0.0.0"), FriendlyName("ADOOrganizationOwner")] class MSFT_ADOOrganizationOwner : OMI_BaseResource { - [Key, Description("")] String OrganizationName; - [Write, Description("")] String Owner; - + [Key, Description("NAme of the Azure DevOPS Organization")] String OrganizationName; + [Write, Description("User principal of the organization's owner")] String Owner; [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; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/readme.md index 75e6f5299d..1ed3a6aebf 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/readme.md @@ -3,4 +3,4 @@ ## Description -##TODO - Provide a short description of what the resource is set to configure. +Configures the owner of an Azure DevOPS organization. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/settings.json index db44440221..0fedf78523 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/settings.json @@ -1,13 +1,9 @@ { "resourceName": "ADOOrganizationOwner", - "description": "Description of what the resource is about.", + "description": "Configures the owner of an Azure DevOPS organization.", "roles": { - "read": [ - "Role" - ], - "update": [ - "Role" - ] + "read": [], + "update": [] }, "permissions": { "graph": { @@ -16,16 +12,8 @@ "update": [] }, "application": { - "read": [ - { - "name": "Permission for Monitoring and Export" - } - ], - "update": [ - { - "name": "Permission for deploying" - } - ] + "read": [], + "update": [] } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/ADOOrganizationOwner/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ADOOrganizationOwner/2-Update.ps1 index b516274848..dc94d14b31 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/ADOOrganizationOwner/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/ADOOrganizationOwner/2-Update.ps1 @@ -21,6 +21,13 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + ADOOrganizationOwner "MyOrgOwner" + { + ApplicationId = $ApplicationId; + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + OrganizationName = "MyOrg"; + Owner = "john.smith@$TenantId"; + } } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOOrganizationOwner.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOOrganizationOwner.Tests.ps1 index 20857e0393..83ebe6a29a 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOOrganizationOwner.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOOrganizationOwner.Tests.ps1 @@ -35,81 +35,47 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets - # 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 instance should exist but it DOES NOT" -Fixture { - BeforeAll { - $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; - } - - ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -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 a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one - Should -Invoke -CommandName New-Cmdlet -Exactly 1 - } - } - - Context -Name "The instance exists but it SHOULD NOT" -Fixture { - BeforeAll { - $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Absent' - Credential = $Credential; - } - - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - - } - } - } - 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 remove the instance from the Set method' { - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 - } - } Context -Name "The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + OrganizationName = 'MyOrg' + Owner = "john.smith@contoso.com" + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - + $Script:callCount = 0 + Mock -CommandName Invoke-M365DSCAzureDevOPSWebRequest -MockWith { + if ($Script:callCount -eq 0) + { + $Script:callCount++ + return @{ + owner = '12345-12345-12345-12345-12345' + } + } + elseif ($Script:callCount -eq 1) + { + $Script:callCount++ + return @{ + items = @( + @{ + id = '12345-12345-12345-12345-12345' + user = @{ + principalName = 'john.smith@contoso.com' + } + } + ) + } + } + else + { + return $null } } } @@ -122,46 +88,140 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + OrganizationName = 'MyOrg' + Owner = "john.smith@contoso.com" + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - + $Script:callCount = 0 + Mock -CommandName Invoke-M365DSCAzureDevOPSWebRequest -MockWith { + if ($Script:callCount -eq 0) + { + $Script:callCount++ + return @{ + owner = '12345-12345-12345-12345-12346' + } + } + elseif ($Script:callCount -eq 1) + { + $Script:callCount++ + return @{ + items = @( + @{ + id = '12345-12345-12345-12345-12345' + user = @{ + principalName = 'john.smith@contoso.com' + } + }, + @{ + id = '12345-12345-12345-12345-12346' + user = @{ + principalName = 'bob.houle@contoso.com' + } + } + ) + } + } + elseif ($Script:callCount -eq 2) + { + $Script:callCount++ + return @{ + items = @( + @{ + id = '12345-12345-12345-12345-12345' + user = @{ + principalName = 'john.smith@contoso.com' + } + } + ) + } + } + if ($Script:callCount -eq 3) + { + $Script:callCount++ + return @{ + owner = '12345-12345-12345-12345-12345' + } + } + else + { + return $null } } } - 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 - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + Should -Invoke -CommandName Invoke-M365DSCAzureDevOPSWebRequest -Exactly 2 } } Context -Name 'ReverseDSC Tests' -Fixture { BeforeAll { + $Global:CurrentModeIsExport = $true $Global:PartialExportFileName = "$(New-Guid).partial.ps1" $testParams = @{ - Credential = $Credential; + Credential = $Credential + } + $testParams = @{ + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - + $Script:callCount = 0 + Mock -CommandName Invoke-M365DSCAzureDevOPSWebRequest -MockWith { + if ($Script:callCount -eq 0) + { + $Script:callCount++ + return @{ + id = '12345-12345-12345-12345-12346' + } + } + elseif ($Script:callCount -eq 1) + { + $Script:callCount++ + return @( + @{ + Value = @{ + accountName = 'MyOrg' + } + } + ) + } + elseif ($Script:callCount -eq 2) + { + $Script:callCount++ + return @{ + owner = '12345-12345-12345-12345-12346' + } + } + elseif ($Script:callCount -eq 3) + { + $Script:callCount++ + return @{ + items = @( + @{ + id = '12345-12345-12345-12345-12345' + user = @{ + principalName = 'john.smith@contoso.com' + } + }, + @{ + id = '12345-12345-12345-12345-12346' + user = @{ + principalName = 'bob.houle@contoso.com' + } + } + ) + } + } + else + { + return $null } } } From dea2f7a230163cc3a0003a55f62b7cd3f31fcb41 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 18 Sep 2024 01:32:47 +0000 Subject: [PATCH 208/465] Updated Resources and Cmdlet documentation pages --- .../azure-ad/ADOOrganizationOwner.md | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 docs/docs/resources/azure-ad/ADOOrganizationOwner.md diff --git a/docs/docs/resources/azure-ad/ADOOrganizationOwner.md b/docs/docs/resources/azure-ad/ADOOrganizationOwner.md new file mode 100644 index 0000000000..5112877f05 --- /dev/null +++ b/docs/docs/resources/azure-ad/ADOOrganizationOwner.md @@ -0,0 +1,84 @@ +# ADOOrganizationOwner + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **OrganizationName** | Key | String | NAme of the Azure DevOPS Organization | | +| **Owner** | Write | String | User principal of the organization's owner | | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Configures the owner of an Azure DevOPS organization. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + ADOOrganizationOwner "MyOrgOwner" + { + ApplicationId = $ApplicationId; + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + OrganizationName = "MyOrg"; + Owner = "john.smith@$TenantId"; + } + } +} +``` + From ebf2e90a6d8c6e78c321ed9532d103ce382c79f5 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 18 Sep 2024 01:34:28 +0000 Subject: [PATCH 209/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index f7129c1b7b..a1e5c97de8 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -5154,6 +5154,51 @@ } ] }, + { + "ClassName": "MSFT_ADOOrganizationOwner", + "Parameters": [ + { + "CIMType": "String", + "Name": "OrganizationName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Owner", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_ADOSecurityPolicy", "Parameters": [ From 59e6027ba9ce619c097aa4daee8bfde086c100c9 Mon Sep 17 00:00:00 2001 From: Yorick Kuijs Date: Wed, 18 Sep 2024 08:55:42 +0200 Subject: [PATCH 210/465] Fixing PSDesiredStateConfiguration v1.1 mentioned as Dependency #5051 --- CHANGELOG.md | 1 + Modules/Microsoft365DSC/Dependencies/Manifest.psd1 | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cb19259c2..834c83e913 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ * Added dependencies on Az.Accounts, Az.Resources and Az.SecurityInsights * Updated DSCParser to version 2.0.0.9. * Updated MSCloudLoginAssistant to version 1.1.24. + * Removed unnecessary dependency PSDesiredStateConfiguration v1.1 # 1.24.904.1 diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index afd204cd31..d409a61d75 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -108,11 +108,6 @@ ModuleName = 'PnP.PowerShell' RequiredVersion = '1.12.0' }, - @{ - ModuleName = 'PSDesiredStateConfiguration' - RequiredVersion = '1.1' - PowerShellCore = $false - }, @{ ModuleName = 'PSDesiredStateConfiguration' RequiredVersion = '2.0.7' From 6eaed67d8464d67d1ed84166be7b703870499761 Mon Sep 17 00:00:00 2001 From: Yorick Kuijs Date: Wed, 18 Sep 2024 08:56:26 +0200 Subject: [PATCH 211/465] Fixing unit test output --- ...365DSC.IntuneDeviceCompliancePolicyWindows10.Tests.ps1 | 3 +++ ...DSC.IntuneDeviceManagementComplianceSettings.Tests.ps1 | 3 +++ .../Microsoft365DSC.SCRoleGroupMember.Tests.ps1 | 8 +++++--- .../Microsoft365DSC.SPOSharingSettings.Tests.ps1 | 3 +++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceCompliancePolicyWindows10.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceCompliancePolicyWindows10.Tests.ps1 index e2694a7aa2..aeb1f9982d 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceCompliancePolicyWindows10.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceCompliancePolicyWindows10.Tests.ps1 @@ -56,6 +56,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { } + + Mock -CommandName Write-Verbose -MockWith { + } $Script:exportedInstances =$null $Script:ExportMode = $false } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceManagementComplianceSettings.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceManagementComplianceSettings.Tests.ps1 index 7bf483c06c..d074c4be78 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceManagementComplianceSettings.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceManagementComplianceSettings.Tests.ps1 @@ -38,6 +38,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { } + + Mock -CommandName Write-Verbose -MockWith { + } $Script:exportedInstances =$null $Script:ExportMode = $false } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCRoleGroupMember.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCRoleGroupMember.Tests.ps1 index 7da44936c3..a9b7311eb3 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCRoleGroupMember.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCRoleGroupMember.Tests.ps1 @@ -169,9 +169,11 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } Mock -CommandName Get-RoleGroupMember -MockWith { - return @{ - Name = @('Group1','User1','User2') - } + return @( + [PSCustomObject]@{Name = 'Group1' }, + [PSCustomObject]@{Name = 'User1' }, + [PSCustomObject]@{Name = 'User2' } + ) } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SPOSharingSettings.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SPOSharingSettings.Tests.ps1 index 3cf66e0d06..2c48f1841d 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SPOSharingSettings.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SPOSharingSettings.Tests.ps1 @@ -38,6 +38,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { } + + Mock -CommandName Write-Warning -MockWith { + } $Script:exportedInstances =$null $Script:ExportMode = $false } From c57dd18b3fd5a4915827979b89c5f250797df4a9 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Wed, 18 Sep 2024 13:43:17 +0530 Subject: [PATCH 212/465] Initial commit --- .../MSFT_AADApplication.psm1 | 105 ++++++++++++++++++ .../MSFT_AADApplication.schema.mof | 17 +++ 2 files changed, 122 insertions(+) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 11292d32cc..0d220f65cf 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -60,6 +60,10 @@ function Get-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $OptionalClaims, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $Permissions, @@ -163,6 +167,53 @@ function Get-TargetResource else { Write-Verbose -Message 'An instance of Azure AD App was retrieved.' + + $complexOptionalClaims = @{} + $complexAccessTokenClaims = @() + foreach ($currentAccessTokenClaim in $AADApp.OptionalClaims.AccessToken) + { + $myAccessTokenClaim = @{} + $myAccessTokenClaim.Add('Essential', $currentAccessTokenClaim.Essential) + + $myAccessTokenClaim.Add('Name', $currentAccessTokenClaim.Name) + + $myAccessTokenClaim.Add('Source', $currentAccessTokenClaim.Source) + $complexAccessTokenClaims += $myAccessTokenClaim + } + $complexOptionalClaims.Add('AccessToken',$complexAccessTokenClaims) + + + $complexIdTokenClaims = @() + foreach ($currentIdTokenClaim in $AADApp.OptionalClaims.IdToken) + { + $myIdTokenClaim = @{} + $myIdTokenClaim.Add('Essential', $currentIdTokenClaim.Essential) + + $myIdTokenClaim.Add('Name', $currentIdTokenClaim.Name) + + $myIdTokenClaim.Add('Source', $currentIdTokenClaim.Source) + $currentIdTokenClaim += $myIdTokenClaim + } + $complexOptionalClaims.Add('IdToken',$complexIdTokenClaims) + + $complexSaml2TokenClaims = @() + foreach ($currentSaml2TokenClaim in $AADApp.OptionalClaims.Saml2Token) + { + $mySaml2TokenClaim = @{} + $mySaml2TokenClaim.Add('Essential', $currentSaml2TokenClaim.Essential) + + $mySaml2TokenClaim.Add('Name', $currentSaml2TokenClaim.Name) + + $mySaml2TokenClaim.Add('Source', $currentSaml2TokenClaim.Source) + $complexSaml2TokenClaims += $mySaml2TokenClaim + } + $complexOptionalClaims.Add('Saml2Token',$complexSaml2TokenClaims) + + if ($complexOptionalClaims.values.Where({$null -ne $_}).count -eq 0) + { + $complexOptionalClaims = $null + } + $permissionsObj = Get-M365DSCAzureADAppPermissions -App $AADApp $isPublicClient = $false if (-not [System.String]::IsNullOrEmpty($AADApp.PublicClient) -and $AADApp.PublicClient -eq $true) @@ -210,6 +261,7 @@ function Get-TargetResource Owners = $OwnersValues ObjectId = $AADApp.Id AppId = $AADApp.AppId + OptionalClaims = $complexOptionalClaims Permissions = $permissionsObj Ensure = 'Present' Credential = $Credential @@ -304,6 +356,10 @@ function Set-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $OptionalClaims, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $Permissions, @@ -742,6 +798,10 @@ function Test-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $OptionalClaims, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $Permissions, @@ -941,6 +1001,45 @@ function Export-TargetResource { $Results.Permissions = Get-M365DSCAzureADAppPermissionsAsString $Results.Permissions } + + if($null -ne $Results.OptionalClaims) + { + $complexMapping = @( + @{ + Name = 'OptionalClaims' + CimInstanceName = 'AADApplicationOptionalClaims' + IsRequired = $False + } + @{ + Name = 'AccessToken' + CimInstanceName = 'MicrosoftGraphOptionalClaim' + IsRequired = $False + } + @{ + Name = 'IdToken' + CimInstanceName = 'MicrosoftGraphOptionalClaim' + IsRequired = $False + } + @{ + Name = 'Saml2Token' + CimInstanceName = 'MicrosoftGraphOptionalClaim' + IsRequired = $False + } + ) + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.OptionalClaims` + -CIMInstanceName 'AADApplicationOptionalClaims' ` + -ComplexTypeMapping $complexMapping + + if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.OptionalClaims = $complexTypeStringResult + } + else + { + $Results.Remove('OptionalClaims') | Out-Null + } + } $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` -ConnectionMode $ConnectionMode ` -ModulePath $PSScriptRoot ` @@ -953,6 +1052,12 @@ function Export-TargetResource -ParameterName 'Permissions' } + + if ($Results.OptionalClaims) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "OptionalClaims" -isCIMArray:$False + } + $dscContent.Append($currentDSCBlock) | Out-Null Save-M365DSCPartialExport -Content $currentDSCBlock ` -FileName $Global:PartialExportFileName diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof index 5396eb0fbb..7b2d7e504d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof @@ -7,6 +7,22 @@ class MSFT_AADApplicationPermission [Write, Description("Represented whether or not the Admin consent been granted on the app.")] Boolean AdminConsentGranted; }; +[ClassVersion("1.0.0")] +class MSFT_MicrosoftGraphOptionalClaim +{ + [Write, Description("")] Boolean Essential; + [Write, Description("")] String Name; + [Write, Description("")] String Source; +}; + +[ClassVersion("1.0.0")] +class MSFT_AADApplicationOptionalClaims +{ + [Write, Description(""), EmbeddedInstance("MSFT_MicrosoftGraphOptionalClaim")] String AccessToken[]; + [Write, Description(""), EmbeddedInstance("MSFT_MicrosoftGraphOptionalClaim")] String IdToken[]; + [Write, Description(""), EmbeddedInstance("MSFT_MicrosoftGraphOptionalClaim")] String Saml2Token[]; +}; + [ClassVersion("1.0.0.0"), FriendlyName("AADApplication")] class MSFT_AADApplication : OMI_BaseResource { @@ -25,6 +41,7 @@ class MSFT_AADApplication : OMI_BaseResource [Write, Description("Specifies the URLs that user tokens are sent to for sign in, or the redirect URIs that OAuth 2.0 authorization codes and access tokens are sent to.")] String ReplyURLs[]; [Write, Description("UPN or ObjectID values of the app's owners.")] String Owners[]; [Write, Description("Specify if the Azure AD App should exist or not."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Write, Description(""), EmbeddedInstance("MSFT_AADApplicationOptionalClaims")] string OptionalClaims; [Write, Description("Credentials for the Microsoft Graph delegated permissions."), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Secret of the Azure Active Directory application to authenticate with."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; From 7999032962423ac6f330316dbbdc1145d77795e0 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 18 Sep 2024 06:57:25 -0400 Subject: [PATCH 213/465] Tests --- .../MSFT_SCInsiderRiskEntityList.psm1 | 1 + .../MSFT_SCInsiderRiskEntityList.schema.mof | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 index a2d00ba6ba..8ab587b2aa 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 @@ -481,6 +481,7 @@ function Set-TargetResource $AccessTokens ) + Write-Verbose -Message "Start Set-TargetResource" #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof index 51d79fa639..7aec32fdc3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof @@ -8,9 +8,9 @@ class MSFT_SCInsiderRiskEntityListDomain [ClassVersion("1.0.0")] class MSFT_SCInsiderRiskEntityListSite { - [Required, Description("Url of the site.")] String Url; - [Write, Description("Name of the site.")] String Name; - [Write, Description("Unique identifier of the site.")] String Guid; + [Required, Description("Url of the site.")] String SiteUrl; + [Write, Description("Name of the site.")] String SiteName; + [Write, Description("Unique identifier of the site.")] String SiteGuid; }; [ClassVersion("1.0.0.0"), FriendlyName("SCInsiderRiskEntityList")] class MSFT_SCInsiderRiskEntityList : OMI_BaseResource From cbd9c3575efa7fc27057851f0d8afecfb9a3cc42 Mon Sep 17 00:00:00 2001 From: Yorick Kuijs Date: Wed, 18 Sep 2024 13:06:48 +0200 Subject: [PATCH 214/465] Implementing [SCSensitityLabel] Auto Labeling missing in export #3784 --- CHANGELOG.md | 3 + .../MSFT_SCSensitivityLabel.psm1 | 625 +++++++++++++++++- .../MSFT_SCSensitivityLabel.schema.mof | 32 + .../Resources/SCSensitivityLabel/2-Update.ps1 | 146 ++++ ...crosoft365DSC.SCSensitivityLabel.Tests.ps1 | 194 +++++- Tests/Unit/Stubs/Microsoft365.psm1 | 25 + 6 files changed, 1010 insertions(+), 15 deletions(-) create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCSensitivityLabel/2-Update.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 834c83e913..b23aceaae2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,9 @@ * Fixes an issue with creation without specifying Displayname * Fixes an issue with Drifts because of returned Role format FIXES [#5036](https://github.com/microsoft/Microsoft365DSC/issues/5036) +* SCSensitivityLabel + * Added support for Auto Labeling settings + FIXES [#3784](https://github.com/microsoft/Microsoft365DSC/issues/3784) * SentinelSetting * Initial release. * SPOAccessControlSettings diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.psm1 index 056f92cf9f..badac1d9d5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.psm1 @@ -1,3 +1,84 @@ +$allTrainableClassifiers = @( + [PSCustomObject]@{ Name = "Actuary reports"; Id = "b27df2ee-fd14-4ce9-b02f-4070a5d68132" } + [PSCustomObject]@{ Name = "Agreements"; Id = "7f12e403-5335-4da8-a91e-6c2210b7a2b1" } + [PSCustomObject]@{ Name = "Asset Management"; Id = "716fb550-90cd-493b-b29b-ceed41ee8a6f" } + [PSCustomObject]@{ Name = "Bank statement"; Id = "f426bd16-e42e-4397-824b-f17dedc5bb1c" } + [PSCustomObject]@{ Name = "Budget"; Id = "6f207592-f71e-4b4f-8c07-ebc4bd4965b9" } + [PSCustomObject]@{ Name = "Business Context"; Id = "08b772df-bf93-457f-be23-b5cbf02005fd" } + [PSCustomObject]@{ Name = "Business plan"; Id = "693f8221-ae4e-4612-80f5-746efee167c3" } + [PSCustomObject]@{ Name = "Completion Certificates"; Id = "b2580781-286b-4ad2-ab47-84e84ff331e5" } + [PSCustomObject]@{ Name = "Compliance policies"; Id = "fdad8089-651b-4877-8b66-be105b2e57da" } + [PSCustomObject]@{ Name = "Construction specifications"; Id = "bfde18ef-b4b9-4f30-9965-ef8d00861a2c" } + [PSCustomObject]@{ Name = "Control System and SCADA files"; Id = "59f1f471-687d-453b-a73e-0b0e9f350812" } + [PSCustomObject]@{ Name = "Corporate Sabotage"; Id = "d88960c3-6101-43d9-9250-8c43c71d638a" } + [PSCustomObject]@{ Name = "Credit Report"; Id = "07ce7d30-690a-4a1c-a331-8df9c944f1ab" } + [PSCustomObject]@{ Name = "Customer Complaints"; Id = "8137d8fc-fb7a-40db-9009-284f962fde96" } + [PSCustomObject]@{ Name = "Customer Files"; Id = "fdff9df2-03ba-4372-be97-82c0d2515118" } + [PSCustomObject]@{ Name = "Discrimination"; Id = "a65c4ab6-a155-11eb-921c-6c0b84aa8ea5" } + [PSCustomObject]@{ Name = "Employee disciplinary action files"; Id = "769d56c1-e737-4fc1-8673-8c99bbe24a07" } + [PSCustomObject]@{ Name = "Employee Insurance files"; Id = "fa982a9f-9454-4885-a2bf-94a155df2f33" } + [PSCustomObject]@{ Name = "Employee Pension Records"; Id = "f9ae0bbc-a1e0-4b7e-a96a-eb60b26b4434" } + [PSCustomObject]@{ Name = "Employee Stocks and Financial Bond Records"; Id = "a67b2b59-c5f0-4c66-a6c4-ca6973adfd94" } + [PSCustomObject]@{ Name = "Employment Agreement"; Id = "2a2baab7-b82c-4166-bbe4-55f9d3fd1129" } + [PSCustomObject]@{ Name = "Enterprise Risk Management"; Id = "eed09aae-6f32-47c7-9c99-9d17bad48783" } + [PSCustomObject]@{ Name = "Environmental permits and clearances"; Id = "1b7d3e51-0ecf-41bd-9794-966c94a889ba" } + [PSCustomObject]@{ Name = "Facility Permits"; Id = "914c5379-9d05-47cb-98f0-f5a2be059b5a" } + [PSCustomObject]@{ Name = "factory Incident Investigation reports"; Id = "86186144-d507-4603-bac7-50b56ba05c70" } + [PSCustomObject]@{ Name = "Finance"; Id = "1771481d-a337-4dbf-8e64-af8da0cc3ee9" } + [PSCustomObject]@{ Name = "Finance policies and procedures"; Id = "6556c5eb-0819-4618-ba2e-59925925655e" } + [PSCustomObject]@{ Name = "Financial Audit Reports"; Id = "b04b2a4e-22f8-4024-8adc-e2caaad1c2e2" } + [PSCustomObject]@{ Name = "Financial statement"; Id = "c31bfef9-8045-4a35-88a3-74b8681615c2" } + [PSCustomObject]@{ Name = "Freight Documents"; Id = "785917ed-db01-43c7-8153-8a6fc393efa3" } + [PSCustomObject]@{ Name = "Garnishment"; Id = "65e827c3-f8e8-4bc8-b08c-c31e3132b832" } + [PSCustomObject]@{ Name = "Gifts \u0026 entertainment"; Id = "3b3d817a-9190-465b-af2d-9e856f894059" } + [PSCustomObject]@{ Name = "Health/Medical forms"; Id = "7cc60f30-9e96-4d51-b26f-3d7a9df56338" } + [PSCustomObject]@{ Name = "Healthcare"; Id = "dcbada08-65bf-4561-b140-25d8fee4d143" } + [PSCustomObject]@{ Name = "HR"; Id = "11631f87-7ffe-4052-b173-abda16b231f3" } + [PSCustomObject]@{ Name = "Invoice"; Id = "bf7df7c3-fce4-4ffd-ab90-26f6463f3a00" } + [PSCustomObject]@{ Name = "IP"; Id = "495fad07-d6e4-4da4-9c64-5b9b109a5f59" } + [PSCustomObject]@{ Name = "IT"; Id = "77a140be-c29f-4155-9dc4-c3e247e47560" } + [PSCustomObject]@{ Name = "IT Infra and Network Security Documents"; Id = "bc55de38-cb72-43e6-952f-8422f584f229" } + [PSCustomObject]@{ Name = "Lease Deeds"; Id = "841f54ad-3e31-4ddd-aea0-e7f0cd6b3d18" } + [PSCustomObject]@{ Name = "Legal Affairs"; Id = "ba38aa0f-8c86-4c73-87db-95147a0f4420" } + [PSCustomObject]@{ Name = "Legal Agreements"; Id = "bee9cefb-88bd-410f-ab3e-67cab21cef46" } + [PSCustomObject]@{ Name = "Letter of Credits"; Id = "fd85acd5-59dd-49b2-a4c3-df7075885a82" } + [PSCustomObject]@{ Name = "License agreement"; Id = "b399eb17-c9c4-4205-951b-43f38eb8dffe" } + [PSCustomObject]@{ Name = "Loan agreements and offer letters"; Id = "5771fa57-34a1-48b3-93df-778b304daa54" } + [PSCustomObject]@{ Name = "M&A Files"; Id = "eeffbf7c-fd04-40ef-a156-b37bf61832f7" } + [PSCustomObject]@{ Name = "Manufacturing batch records"; Id = "834b2353-509a-4605-b4f1-fc2172a0d97c" } + [PSCustomObject]@{ Name = "Marketing Collaterals"; Id = "fcaa6d2a-601c-4bdc-947e-af1178a646ac" } + [PSCustomObject]@{ Name = "Meeting notes"; Id = "e7ff9a9e-4689-4192-b927-e6c6bdf099fc" } + [PSCustomObject]@{ Name = "Money laundering"; Id = "adbbb20e-b175-46e7-8ba2-cf3f3179d0ed" } + [PSCustomObject]@{ Name = "MoU Files (Memorandum of understanding)"; Id = "cb37c277-4b88-49c6-81fb-2eeca8c52bb9" } + [PSCustomObject]@{ Name = "Network Design files"; Id = "12587d70-9596-4c21-b09f-f1abe9d6ca13" } + [PSCustomObject]@{ Name = "Non disclosure agreement"; Id = "8dfd10db-0c72-4be4-a4f2-f615fe7aeb1c" } + [PSCustomObject]@{ Name = "OSHA records"; Id = "b11b771e-7dd1-4434-873a-d648a16e969e" } + [PSCustomObject]@{ Name = "Paystub"; Id = "31c11384-2d64-4635-9335-018295c64268" } + [PSCustomObject]@{ Name = "Personal Financial Information"; Id = "6901c616-5857-432f-b3da-f5234fa1d342" } + [PSCustomObject]@{ Name = "Procurement"; Id = "8fa64a47-6e77-4b4c-91a5-0f67525cebf5" } + [PSCustomObject]@{ Name = "Profanity"; Id = "4b0aa61d-37dc-4596-a1f1-fc5a5b21d56b" } + [PSCustomObject]@{ Name = "Project documents"; Id = "e062df90-816c-47ca-8913-db647510d3b5" } + [PSCustomObject]@{ Name = "Quality assurance files"; Id = "97b1e0d3-7788-4dd4-bb18-48ea77796743" } + [PSCustomObject]@{ Name = "Quotation"; Id = "3882e681-c437-42d8-ac75-1f9b7481fe13" } + [PSCustomObject]@{ Name = "Regulatory Collusion"; Id = "911b7815-6883-4022-a882-9cbe9462f114" } + [PSCustomObject]@{ Name = "Resume"; Id = "14b2da41-0427-47e9-a11b-c924e1d05689" } + [PSCustomObject]@{ Name = "Safety Records"; Id = "938fb100-5b1f-4bbb-aba7-73d9c89d086f" } + [PSCustomObject]@{ Name = "Sales and revenue"; Id = "9d6b864d-28c6-4be3-a9d0-cd40434a847f" } + [PSCustomObject]@{ Name = "Software Product Development Files"; Id = "813aa6d8-0727-48d8-acb7-06e1819ee339" } + [PSCustomObject]@{ Name = "Source code"; Id = "8aef6743-61aa-44b9-9ae5-3bb3d77df535" } + [PSCustomObject]@{ Name = "Standard Operating Procedures and Manuals"; Id = "32f23ad4-2ca1-4495-8048-8dc567891644" } + [PSCustomObject]@{ Name = "Statement of Accounts"; Id = "fe3676a6-0f5d-4990-bb46-9b2b31d7746a" } + [PSCustomObject]@{ Name = "Statement of Work"; Id = "611c95f9-b1ef-4253-8b36-d8ae19d02fb0" } + [PSCustomObject]@{ Name = "Stock manipulation"; Id = "1140cd79-ad87-4043-a562-c768acacc6ba" } + [PSCustomObject]@{ Name = "Strategic planning documents"; Id = "9332b317-2ca4-413a-b983-92a1bd88c6f3" } + [PSCustomObject]@{ Name = "Targeted Harassment"; Id = "a02ddb8e-3c93-44ac-87c1-2f682b1cb78e" } + [PSCustomObject]@{ Name = "Tax"; Id = "9722b51a-f920-4a81-8390-b188a0692840" } + [PSCustomObject]@{ Name = "Threat"; Id = "ef2edb64-6982-4648-b0ad-c0d8a861501b" } + [PSCustomObject]@{ Name = "Unauthorized disclosure"; Id = "839aecf8-c67b-4270-8aaf-378127b23b7f" } + [PSCustomObject]@{ Name = "Wire transfer"; Id = "05fc5ed0-58ef-4306-b65c-11b0a43895c2" } + [PSCustomObject]@{ Name = "Work Schedules"; Id = "25bb9d2d-a5b5-45b1-882e-b2581a183873" } +) + function Get-TargetResource { [CmdletBinding()] @@ -187,6 +268,10 @@ function Get-TargetResource [System.String] $SiteAndGroupExternalSharingControlType, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $AutoLabelingSettings, + [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -447,6 +532,101 @@ function Get-TargetResource $siteAndGroupBlockAccess = [Boolean]::Parse($entry.Value) } + # Auto Labelling Conditions + $getConditions = $null + if ([System.String]::IsNullOrEmpty($label.Conditions) -eq $false) + { + $currConditions = $label.Conditions | ConvertFrom-Json + + $getConditions = @{ + Groups = @() + Operator = '' + } + + $operator = $currConditions.PSObject.Properties.Name + $getConditions.Operator = $operator + + $autoApplyType = '' + $policyTip = '' + $groups = foreach ($group in $currConditions.$($operator)) + { + $grpObject = @{ + Name = '' + Operator = '' + } + + $grpOperator = $group.PSObject.Properties.Name + $grpObject.Operator = $grpOperator + + $grpName = '' + [array]$sensitiveInformationTypes = foreach ($item in $group.$grpOperator | Where-Object { $_.Key -eq 'CCSI'}) + { + if ([String]::IsNullOrEmpty($grpName)) + { + $grpName = ($item.Settings | Where-Object { $_.Key -eq 'groupname' }).Value + } + + if ([String]::IsNullOrEmpty($policyTip)) + { + $policyTip = ($item.Settings | Where-Object { $_.Key -eq 'policytip' }).Value + } + + if ([String]::IsNullOrEmpty($autoApplyType)) + { + $autoApplyType = ($item.Settings | Where-Object { $_.Key -eq 'autoapplytype' }).Value + } + + $settingsObject = @{ + name = ($item.Settings | Where-Object { $_.Key -eq 'name' }).Value + confidencelevel = ($item.Settings | Where-Object { $_.Key -eq 'confidencelevel' }).Value + mincount = ($item.Settings | Where-Object { $_.Key -eq 'mincount' }).Value + maxcount = ($item.Settings | Where-Object { $_.Key -eq 'maxcount' }).Value + } + + if ($null -ne ($item.Settings | Where-Object { $_.Key -eq 'classifiertype' })) + { + $settingsObject.classifiertype = ($item.Settings | Where-Object { $_.Key -eq 'classifiertype' }).Value + } + + # return the settings object as output to the sensitiveInformationTypes array + $settingsObject + } + + [array]$trainableClassifiers = foreach ($item in $group.$grpOperator | Where-Object { $_.Key -eq 'ContentMatchesModule'}) + { + if ([String]::IsNullOrEmpty($grpName)) + { + $grpName = ($item.Settings | Where-Object { $_.Key -eq 'groupname' }).Value + } + + @{ + name = ($item.Settings | Where-Object { $_.Key -eq 'name' }).Value + id = $item.Value + } + } + + $grpObject.Name = $grpName + $grpObject.SensitiveInformationType = $sensitiveInformationTypes + $grpObject.TrainableClassifier = $trainableClassifiers + + # return the group object as output to the groups array + $grpObject + } + $getConditions.Groups = $groups + if ([System.String]::IsNullOrEmpty($policyTip) -eq $false) + { + $getConditions.PolicyTip = $policyTip + } + if ([System.String]::IsNullOrEmpty($autoApplyType) -eq $false) + { + $getConditions.AutoApplyType = $autoApplyType + } + else + { + $getConditions.AutoApplyType = 'Automatic' + } + } + $result = @{ Name = $label.Name Comment = $label.Comment @@ -500,9 +680,9 @@ function Get-TargetResource SiteAndGroupProtectionEnabled = $siteAndGroupEnabledValue SiteAndGroupExternalSharingControlType = ($protectsite | Where-Object { $_.Key -eq 'externalsharingcontroltype' }).Value AccessTokens = $AccessTokens + AutoLabelingSettings = $getConditions } - Write-Verbose -Message "Get-TargetResource Result: `n $(Convert-M365DscHashtableToString -Hashtable $result)" return $result } } @@ -706,6 +886,10 @@ function Set-TargetResource [System.String] $SiteAndGroupExternalSharingControlType, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $AutoLabelingSettings, + [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -770,6 +954,139 @@ function Set-TargetResource Write-Warning -Message "You have specified EncryptionDoNotForward, EncryptionEncryptOnly or EncryptionPromptUser, but EncryptionProtectionType isn't set to UserDefined." } + if ('Present' -eq $Ensure -and $PSBoundParameters.ContainsKey('AutoLabelingSettings')) + { + Write-Verbose 'Generating required JSON string for AutoLabelingSettings' + + Write-Verbose 'Retrieving all existing Sensitive Information Types' + $existingSITs = Get-DlpSensitiveInformationType | Select-Object -Property Name,Id, RulePackId + + # Convert the AutoLabelingSettings to the correct JSON format, ready to be inserted into the label cmdlets + $autoLabelingSettingsHT = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $AutoLabelingSettings + + Write-Verbose 'Processing all setting groups' + [array]$grps = foreach ($group in $autoLabelingSettingsHT.Groups) + { + $groupCollection = @() + Write-Verbose 'Processing all Sensitive Information Types' + foreach ($sit in $group.SensitiveInformationType) + { + $currentSIT = $existingSITs | Where-Object { $_.Name -eq $sit.Name } + if ($null -eq $currentSIT) + { + throw "[ERROR] Provided Sensitive Information Type $($sit.Name) doesn't exist." + } + + [array]$settingsCollection = foreach ($setting in ($sit.Keys | Where-Object { $_ -ne 'id' })) + { + @{ + Key = $setting + Value = $sit[$setting] + } + } + $settingsCollection += @{ + Key = "rulepackage" + Value = $currentSIT.RulePackId + } + $settingsCollection += @{ + Key = "groupname" + Value = $group.Name + } + + if ($autoLabelingSettingsHT.ContainsKey("PolicyTip")) + { + $settingsCollection += @{ + Key = "policytip" + Value = $autoLabelingSettingsHT.PolicyTip + } + } + + if ($autoLabelingSettingsHT.ContainsKey("AutoApplyType") -and $autoLabelingSettingsHT.AutoApplyType -eq 'Recommend') + { + $settingsCollection += @{ + Key = "autoapplytype" + Value = $autoLabelingSettingsHT.AutoApplyType + } + } + + $groupCollection += @{ + Key = 'CCSI' + Value = $currentSIT.Id + Properties = $null + Settings = $settingsCollection + } + } + + Write-Verbose 'Processing all Trainable Classifiers' + foreach ($trainableClassifier in $group.TrainableClassifier) + { + $currentTrainableClassifier = $allTrainableClassifiers | Where-Object { $_.Name -eq $trainableClassifier.name } + if ($null -ne $currentTrainableClassifier) + { + if ([String]::IsNullOrEmpty($trainableClassifier.id) -eq $false -and ` + $trainableClassifier.id -ne $currentTrainableClassifier.Id) + { + Write-Verbose ("[WARNING] Provided ID ($($trainableClassifier.id)) does not match the known " + ` + "ID ($($currentTrainableClassifier.id)) for trainable classifier '$($trainableClassifier.name)'.") + } + $requiredId = $currentTrainableClassifier.Id + } + else + { + if ([String]::IsNullOrEmpty($trainableClassifier.id)) + { + throw "[ERROR] Trainable classifier $($trainableClassifier.name) isn't a default classifier and no ID was provided." + } + $requiredId = $trainableClassifier.id + } + + [array]$settingsCollection = foreach ($key in ($trainableClassifier.Keys | Where-Object { $_ -ne 'id' })) + { + @{ + Key = $key + Value = $trainableClassifier[$key] + } + } + $settingsCollection += @{ + Key = "groupname" + Value = $group.Name + } + + if ($autoLabelingSettingsHT.ContainsKey("PolicyTip")) + { + $settingsCollection += @{ + Key = "policytip" + Value = $autoLabelingSettingsHT.PolicyTip + } + } + + if ($autoLabelingSettingsHT.ContainsKey("AutoApplyType") -and $autoLabelingSettingsHT.AutoApplyType -eq 'Recommend') + { + $settingsCollection += @{ + Key = "autoapplytype" + Value = $autoLabelingSettingsHT.AutoApplyType + } + } + + $groupCollection += @{ + Key = 'ContentMatchesModule' + Value = $requiredId + Properties = $null + Settings = $settingsCollection + } + } + + @{ + $group.Operator = $groupCollection + } + } + + $desiredAutoLabelingSettings = @{ + $autoLabelingSettingsHT.Operator = $grps + } + Write-Verbose 'Completed generating required JSON string for AutoLabelingSettings' + } + if (('Present' -eq $Ensure) -and ('Absent' -eq $label.Ensure)) { Write-Verbose -Message "Label {$Name} doesn't already exist, creating it from the Set-TargetResource function." @@ -793,6 +1110,12 @@ function Set-TargetResource $CreationParams.Remove('SiteAndGroupExternalSharingControlType') } + if ($PSBoundParameters.ContainsKey('AutoLabelingSettings') -and $null -ne $desiredAutoLabelingSettings) + { + $CreationParams.Conditions = $desiredAutoLabelingSettings | ConvertTo-Json -Depth 20 + $CreationParams.Remove('AutoLabelingSettings') + } + $CreationParams.Remove('Priority') | Out-Null # Remove authentication parameters @@ -810,19 +1133,25 @@ function Set-TargetResource try { Write-Verbose -Message "Creating Label {$Name}" - New-Label @CreationParams + New-Label @CreationParams -ErrorAction Stop ## Can't set priority until label created if ($PSBoundParameters.ContainsKey('Priority')) { Start-Sleep 5 Write-Verbose -Message "Updating the priority for newly created label {$Name}" - Set-label -Identity $Name -priority $Priority + Set-label -Identity $Name -priority $Priority -ErrorAction Stop } } catch { - Write-Warning "New-Label is not available in tenant $($Credential.UserName.Split('@')[1]): $_" + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + throw $_ } } elseif (('Present' -eq $Ensure) -and ('Present' -eq $label.Ensure)) @@ -848,6 +1177,12 @@ function Set-TargetResource $SetParams.Remove('SiteAndGroupExternalSharingControlType') } + if ($PSBoundParameters.ContainsKey('AutoLabelingSettings') -and $null -ne $desiredAutoLabelingSettings) + { + $SetParams.Conditions = $desiredAutoLabelingSettings | ConvertTo-Json -Depth 20 + $SetParams.Remove('AutoLabelingSettings') + } + #Remove unused parameters for Set-Label cmdlet $SetParams.Remove('Name') | Out-Null @@ -865,11 +1200,17 @@ function Set-TargetResource try { - Set-Label @SetParams -Identity $Name + Set-Label @SetParams -Identity $Name -ErrorAction Stop } catch { - Write-Warning "Set-Label is not available in tenant $($Credential.UserName.Split('@')[1]): $_" + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + throw $_ } } elseif (('Absent' -eq $Ensure) -and ('Present' -eq $label.Ensure)) @@ -879,12 +1220,18 @@ function Set-TargetResource try { - Remove-Label -Identity $Name -Confirm:$false - Remove-Label -Identity $Name -Confirm:$false -forcedeletion:$true + Remove-Label -Identity $Name -Confirm:$false -ErrorAction Stop + Remove-Label -Identity $Name -Confirm:$false -forcedeletion:$true -ErrorAction Stop } catch { - Write-Warning "Remove-Label is not available in tenant $($Credential.UserName.Split('@')[1]): $_" + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + throw $_ } } } @@ -1078,6 +1425,10 @@ function Test-TargetResource [System.String] $SiteAndGroupExternalSharingControlType, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $AutoLabelingSettings, + [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -1127,6 +1478,7 @@ function Test-TargetResource $ValuesToCheck = $PSBoundParameters $ValuesToCheck.Remove('AdvancedSettings') | Out-Null $ValuesToCheck.Remove('LocaleSettings') | Out-Null + $ValuesToCheck.Remove('AutoLabelingSettings') | Out-Null if ($null -ne $AdvancedSettings -and $null -ne $CurrentValues.AdvancedSettings) { @@ -1148,6 +1500,20 @@ function Test-TargetResource } } + if ($null -ne $AutoLabelingSettings -and $null -ne $CurrentValues.AutoLabelingSettings) + { + Write-Verbose -Message 'Testing AutoLabelingSettings' + + # Convert the AutoLabelingSettings to the correct JSON format, ready to be inserted into the label cmdlets + $autoLabelingSettingsHT = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $AutoLabelingSettings + + $autoLabelSettingsSame = Test-AutoLabelingSettings -CurrentProperty $CurrentValues.AutoLabelingSettings -DesiredProperty $autoLabelingSettingsHT + if ($false -eq $autoLabelSettingsSame) + { + return $false + } + } + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` -DesiredValues $PSBoundParameters ` @@ -1241,6 +1607,10 @@ function Export-TargetResource { $Results.LocaleSettings = ConvertTo-LocaleSettingsString -LocaleSettings $Results.LocaleSettings } + if ($null -ne $Results.AutoLabelingSettings) + { + $Results.AutoLabelingSettings = ConvertTo-AutoLabelingSettingsString -AutoLabelingSettings $Results.AutoLabelingSettings + } $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` -Results $Results $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` @@ -1256,6 +1626,10 @@ function Export-TargetResource { $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'LocaleSettings' } + if ($null -ne $Results.AutoLabelingSettings) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'AutoLabelingSettings' + } Write-Host $Global:M365DSCEmojiGreenCheckMark $dscContent += $currentDSCBlock @@ -1566,7 +1940,160 @@ function Test-LocaleSettings } } + if ($foundSettings -eq $false) + { + New-M365DSCLogEntry -Message "LocaleSettings for label $Name do not match: $($driftedSetting -join ', ')" ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } + Write-Verbose -Message "Test LocaleSettings returns $foundSettings" + + return $foundSettings +} + +function Test-AutoLabelingSettings +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter (Mandatory = $true)] + [System.Object] + $DesiredProperty, + + [Parameter (Mandatory = $true)] + [System.Object] + $CurrentProperty + ) + + $foundSettings = $true + $driftedSetting = New-Object System.Collections.ArrayList + + if ($DesiredProperty.Operator -ne $CurrentProperty.Operator) + { + $null = $driftedSetting.Add("Parameter 'Operator' does not match. Current: '$($CurrentProperty.Operator)'. Desired: '$($DesiredProperty.Operator)'.") + $foundSettings = $false + } + + if ($DesiredProperty.AutoApplyType -ne $CurrentProperty.AutoApplyType) + { + $null = $driftedSetting.Add("Parameter 'AutoApplyType' does not match. Current: '$($CurrentProperty.AutoApplyType)'. Desired: '$($DesiredProperty.AutoApplyType)'.") + $foundSettings = $false + } + + if ($DesiredProperty.ContainsKey('PolicyTip') -and $DesiredProperty.PolicyTip -ne $CurrentProperty.PolicyTip) + { + $null = $driftedSetting.Add("Parameter 'PolicyTip' does not match. Current: '$($CurrentProperty.PolicyTip)'. Desired: '$($DesiredProperty.PolicyTip)'.") + $foundSettings = $false + } + + foreach ($group in $DesiredProperty.Groups) + { + $currentGroup = $CurrentProperty.Groups | Where-Object { $_.Name -eq $group.Name } + if ($null -eq $currentGroup) + { + $null = $driftedSetting.Add("Group '$($group.Name)' not found in the current settings.") + $foundSettings = $false + continue + } + + if ($group.Operator -ne $currentGroup.Operator) + { + $null = $driftedSetting.Add("Parameter 'Groups\$($group.Name)\Operator' does not match. Current: '$($currentGroup.Operator)'. Desired: '$($group.Operator)'.") + $foundSettings = $false + } + + foreach ($sensitiveinfotype in $group.SensitiveInformationType) + { + $currentSensitiveInfoType = $currentGroup.SensitiveInformationType | Where-Object { $_.name -eq $sensitiveinfotype.name } + if ($null -eq $currentSensitiveInfoType) + { + $null = $driftedSetting.Add("Sensitive Information Type '$($sensitiveinfotype.name)' not found in the current settings for group '$($group.Name)'.") + $foundSettings = $false + continue + } + + if ($sensitiveinfotype.ContainsKey('confidencelevel') -and $sensitiveinfotype.confidencelevel -ne $currentSensitiveInfoType.confidencelevel) + { + $null = $driftedSetting.Add("Parameter 'confidencelevel' does not match for Sensitive Information Type '$($sensitiveinfotype.name)' in group '$($group.Name)'. Current: '$($currentSensitiveInfoType.confidencelevel)'. Desired: '$($sensitiveinfotype.confidencelevel)'.") + $foundSettings = $false + } + + + if ($sensitiveinfotype.ContainsKey('classifiertype') -and $sensitiveinfotype.classifiertype -ne $currentSensitiveInfoType.classifiertype) + { + $null = $driftedSetting.Add("Parameter 'classifiertype' does not match for Sensitive Information Type '$($sensitiveinfotype.name)' in group '$($group.Name)'. Current: '$($currentSensitiveInfoType.classifiertype)'. Desired: '$($sensitiveinfotype.classifiertype)'.") + $foundSettings = $false + } + + if ($sensitiveinfotype.ContainsKey('mincount') -and $sensitiveinfotype.mincount -ne $currentSensitiveInfoType.mincount) + { + $null = $driftedSetting.Add("Parameter 'mincount' does not match for Sensitive Information Type '$($sensitiveinfotype.name)' in group '$($group.Name)'. Current: '$($currentSensitiveInfoType.mincount)'. Desired: '$($sensitiveinfotype.mincount)'.") + $foundSettings = $false + } + + if ($sensitiveinfotype.ContainsKey('maxcount') -and $sensitiveinfotype.maxcount -ne $currentSensitiveInfoType.maxcount) + { + $null = $driftedSetting.Add("Parameter 'maxcount' does not match for Sensitive Information Type '$($sensitiveinfotype.name)' in group '$($group.Name)'. Current: '$($currentSensitiveInfoType.maxcount)'. Desired: '$($sensitiveinfotype.maxcount)'.") + $foundSettings = $false + } + } + foreach ($trainableClassifier in $group.TrainableClassifier) + { + $currentTrainableClassifier = $currentGroup.trainableClassifier | Where-Object { $_.name -eq $trainableClassifier.name } + if ($null -eq $currentTrainableClassifier) + { + $null = $driftedSetting.Add("Trainable Classifier '$($trainableClassifier.name)' not found in the current settings for group '$($group.Name)'.") + $foundSettings = $false + continue + } + } + } + + foreach ($group in $CurrentProperty.Groups) + { + $desiredGroup = $DesiredProperty.Groups | Where-Object { $_.Name -eq $group.Name } + if ($null -eq $desiredGroup) + { + $null = $driftedSetting.Add("Group '$($group.Name)' not found in the desired settings.") + $foundSettings = $false + continue + } + + foreach ($sensitiveinfotype in $group.SensitiveInformationType) + { + $desiredSensitiveInfoType = $desiredGroup.SensitiveInformationType | Where-Object { $_.name -eq $sensitiveinfotype.name } + if ($null -eq $desiredSensitiveInfoType) + { + $null = $driftedSetting.Add("Sensitive Information Type '$($sensitiveinfotype.name)' not found in the desired settings for group '$($group.Name)'.") + $foundSettings = $false + continue + } + } + foreach ($trainableClassifier in $group.TrainableClassifier) + { + $desiredTrainableClassifier = $desiredGroup.trainableClassifier | Where-Object { $_.name -eq $trainableClassifier.name } + if ($null -eq $desiredTrainableClassifier) + { + $null = $driftedSetting.Add("Trainable Classifier '$($trainableClassifier.name)' not found in the desired settings for group '$($group.Name)'.") + $foundSettings = $false + continue + } + } + } + + if ($foundSettings -eq $false) + { + New-M365DSCLogEntry -Message "AutoLabelingSettings for label $Name do not match: `r`n- $($driftedSetting -join '`r`n- ')" ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } + + Write-Verbose -Message "Test AutoLabelingSettings returns $foundSettings" + return $foundSettings } @@ -1625,4 +2152,84 @@ function ConvertTo-LocaleSettingsString return $StringContent } +function ConvertTo-AutoLabelingSettingsString +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter(Mandatory = $true)] + $AutoLabelingSettings + ) + + $StringContent = "" + foreach ($autoLabelingSetting in $AutoLabelingSettings) + { + $StringContent += " MSFT_SCSLAutoLabelingSettings`r`n" + $StringContent += " {`r`n" + $StringContent += " Operator = '$($autoLabelingSetting.Operator)'`r`n" + if ($autoLabelingSetting.ContainsKey('PolicyTip')) + { + $StringContent += " PolicyTip = '$($autoLabelingSetting.PolicyTip.Replace("'", "''"))'`r`n" + } + $StringContent += " AutoApplyType = '$($autoLabelingSetting.AutoApplyType)'`r`n" + $StringContent += " Groups = @(`r`n" + foreach ($Group in $autoLabelingSetting.Groups) + { + $StringContent += " MSFT_SCSLSensitiveInformationGroup`r`n" + $StringContent += " {`r`n" + $StringContent += " Name = '$($Group.Name.Replace("'", "''"))'`r`n" + $StringContent += " Operator = '$($Group.Operator)'`r`n" + if ($Group.ContainsKey('SensitiveInformationType')) + { + $StringContent += " SensitiveInformationType = @(`r`n" + foreach ($sensitiveInformationType in $Group.SensitiveInformationType) + { + $StringContent += " MSFT_SCSLSensitiveInformationType`r`n" + $StringContent += " {`r`n" + $StringContent += " name = '$($sensitiveInformationType.name.Replace("'", "''"))'`r`n" + if ($sensitiveInformationType.ContainsKey('confidencelevel')) + { + $StringContent += " confidencelevel = '$($sensitiveInformationType.confidencelevel)'`r`n" + } + if ($sensitiveInformationType.ContainsKey('classifiertype')) + { + $StringContent += " classifiertype = '$($sensitiveInformationType.classifiertype)'`r`n" + } + if ($sensitiveInformationType.ContainsKey('mincount')) + { + $StringContent += " mincount = '$($sensitiveInformationType.mincount)'`r`n" + } + if ($sensitiveInformationType.ContainsKey('maxcount')) + { + $StringContent += " maxcount = '$($sensitiveInformationType.maxcount)'`r`n" + } + $StringContent += " }`r`n" + } + $StringContent += " )`r`n" + } + if ($Group.ContainsKey('TrainableClassifier')) + { + $StringContent += " TrainableClassifier = @(`r`n" + foreach ($trainableClassifier in $Group.TrainableClassifier) + { + $StringContent += " MSFT_SCSLTrainableClassifiers`r`n" + $StringContent += " {`r`n" + $StringContent += " name = '$($trainableClassifier.name.Replace("'", "''"))'`r`n" + if ($trainableClassifier.ContainsKey('id')) + { + $StringContent += " id = '$($trainableClassifier.id)'`r`n" + } + $StringContent += " }`r`n" + } + $StringContent += " )`r`n" + } + $StringContent += " }`r`n" + } + $StringContent += " )`r`n" + $StringContent += " }`r`n" + } + return $StringContent +} + Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.schema.mof index 1cedd8011b..4653fd23be 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.schema.mof @@ -1,4 +1,35 @@ [ClassVersion("1.0.0")] +class MSFT_SCSLSensitiveInformationType +{ + [Required, Description("Name of the Sensitive Information Type")] String name; + [Write, Description("Confidence level value for the Sensitive Information"),ValueMap{"Low","Medium","High"}, Values{"Low","Medium","High"}] String confidencelevel; + [Write, Description("Type of Classifier value for the Sensitive Information")] String classifiertype; + [Write, Description("Minimum Count value for the Sensitive Information")] String mincount; + [Write, Description("Maximum Count value for the Sensitive Information")] String maxcount; +}; +[ClassVersion("1.0.0")] +class MSFT_SCSLTrainableClassifiers +{ + [Required, Description("Name of the Trainable Classifier")] String name; + [Write, Description("Id of the Trainable Classifier")] String id; +}; +[ClassVersion("1.0.0")] +class MSFT_SCSLSensitiveInformationGroup +{ + [Write, Description("Sensitive Information Content Types"),EmbeddedInstance("MSFT_SCSLSensitiveInformationType")] String SensitiveInformationType[]; + [Write, Description("Trainable Classifiers"),EmbeddedInstance("MSFT_SCSLTrainableClassifiers")] String TrainableClassifier[]; + [Required, Description("Name of the group")] String Name; + [Required, Description("How to process the Sensitive Information Types and Trainable Classifiers"),ValueMap{"And","Or"}, Values{"And","Or"}] String Operator; +}; +[ClassVersion("1.0.0")] +class MSFT_SCSLAutoLabelingSettings +{ + [Required, Description("Groups of sensitive information types."),EmbeddedInstance("MSFT_SCSLSensitiveInformationGroup")] String Groups[]; + [Required, Description("How to process the various groups"),ValueMap{"And","Or"}, Values{"And","Or"}] String Operator; + [Write, Description("Display this message to users when the label is applied")] String PolicyTip; + [Required, Description("Specifies what to do when content matches the conditions"),ValueMap{"Automatic","Recommend"}, Values{"Automatic","Recommend"}] String AutoApplyType; +}; +[ClassVersion("1.0.0")] class MSFT_SCLabelSetting { [Write, Description("Advanced settings key.")] String Key; @@ -57,6 +88,7 @@ class MSFT_SCSensitivityLabel : OMI_BaseResource [Write, Description("The SiteAndGroupProtectionEnabled parameter enables or disables the Site and Group Protection action for the labels.")] Boolean SiteAndGroupProtectionEnabled; [Write, Description("The SiteAndGroupProtectionPrivacy parameter specifies the privacy level for the label."), ValueMap{"Public","Private","Unspecified"}, Values{"Public","Private","Unspecified"}] String SiteAndGroupProtectionPrivacy; [Write, Description("The SiteAndGroupExternalSharingControlType parameter specifies the external user sharing setting for the label."), ValueMap{"ExternalUserAndGuestSharing","ExternalUserSharingOnly","ExistingExternalUserSharingOnly","Disabled"}, Values{"ExternalUserAndGuestSharing","ExternalUserSharingOnly","ExistingExternalUserSharingOnly","Disabled"}] String SiteAndGroupExternalSharingControlType; + [Write, Description("The AutoLabelingSettings parameter specifies the conditions for label to be automatically applied to files and emails."), EmbeddedInstance("MSFT_SCSLAutoLabelingSettings")] String AutoLabelingSettings; [Write, Description("Credentials of the Exchange Global 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; diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCSensitivityLabel/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCSensitivityLabel/2-Update.ps1 new file mode 100644 index 0000000000..374d2e371c --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCSensitivityLabel/2-Update.ps1 @@ -0,0 +1,146 @@ +<# +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 + { + SCSensitivityLabel 'ConfigureSensitivityLabel' + { + Name = 'DemoLabel' + Comment = 'Demo Label comment' + ToolTip = 'Demo tool tip' + DisplayName = 'Demo Label' + ApplyContentMarkingFooterAlignment = 'Center' + ApplyContentMarkingFooterEnabled = $true + ApplyContentMarkingFooterFontColor = '#FF0000' + ApplyContentMarkingFooterFontSize = 10 + ApplyContentMarkingFooterMargin = 5 + ApplyContentMarkingFooterText = 'Demo footer text' + ApplyContentMarkingHeaderAlignment = 'Center' + ApplyContentMarkingHeaderEnabled = $true + ApplyContentMarkingHeaderFontColor = '#FF0000' + ApplyContentMarkingHeaderFontSize = 10 + ApplyContentMarkingHeaderMargin = 5 + ApplyContentMarkingHeaderText = 'demo header text' + ApplyWaterMarkingEnabled = $true + ApplyWaterMarkingFontColor = '#FF0000' + ApplyWaterMarkingFontSize = 10 + ApplyWaterMarkingLayout = 'Diagonal' + ApplyWaterMarkingText = 'demo watermark' + SiteAndGroupProtectionAllowAccessToGuestUsers = $true + SiteAndGroupProtectionAllowEmailFromGuestUsers = $true + SiteAndGroupProtectionAllowFullAccess = $true + SiteAndGroupProtectionAllowLimitedAccess = $true + SiteAndGroupProtectionBlockAccess = $true + SiteAndGroupProtectionEnabled = $true + SiteAndGroupProtectionPrivacy = 'Private' + LocaleSettings = @( + MSFT_SCLabelLocaleSettings + { + LocaleKey = 'DisplayName' + LabelSettings = @( + MSFT_SCLabelSetting + { + Key = 'en-us' + Value = 'English Display Names' + } + MSFT_SCLabelSetting + { + Key = 'fr-fr' + Value = "Nom da'ffichage francais" + } + ) + } + MSFT_SCLabelLocaleSettings + { + LocaleKey = 'StopColor' + LabelSettings = @( + MSFT_SCLabelSetting + { + Key = 'en-us' + Value = 'RedGreen' + } + MSFT_SCLabelSetting + { + Key = 'fr-fr' + Value = 'Rouge' + } + ) + } + ) + AdvancedSettings = @( + MSFT_SCLabelSetting + { + Key = 'AllowedLevel' + Value = @('Sensitive', 'Classified') + } + MSFT_SCLabelSetting + { + Key = 'LabelStatus' + Value = 'Enabled' + } + ) + AutoLabelingSettings = MSFT_SCSLAutoLabelingSettings + { + Operator = 'And' + AutoApplyType = 'Recommend' + PolicyTip = 'My Perfect Test Tip!' + Groups = @( + MSFT_SCSLSensitiveInformationGroup + { + Name = 'Group1' + Operator = 'Or' + SensitiveInformationType = @( + MSFT_SCSLSensitiveInformationType + { + name = 'ABA Routing Number' + confidencelevel = 'High' + maxcount = -1 + mincount = 1 + } + ) + TrainableClassifier = @( + MSFT_SCSLTrainableClassifiers + { + name = 'Legal Affairs' + } + ) + } + MSFT_SCSLSensitiveInformationGroup + { + Name = 'Group2' + Operator = 'And' + SensitiveInformationType = @( + MSFT_SCSLSensitiveInformationType + { + name = 'All Full Names' + confidencelevel = 'High' + maxcount = 100 + mincount = 10 + } + ) + TrainableClassifier = @( + MSFT_SCSLTrainableClassifiers + { + name = 'Threat' + } + ) + } + ) + } + ParentId = 'Personal' + Ensure = 'Present' + Credential = $Credscredential + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCSensitivityLabel.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCSensitivityLabel.Tests.ps1 index 8aff682552..4a9fbac0d0 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCSensitivityLabel.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCSensitivityLabel.Tests.ps1 @@ -55,6 +55,13 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Start-Sleep -MockWith { } + Mock -CommandName Get-DlpSensitiveInformationType -MockWith { + return @( + [PSCustomObject]@{Name = 'ABA Routing Number'; Id = 'cb353f78-2b72-4c3c-8827-92ebe4f69fdf'; RulePackId = '00000000-0000-0000-0000-000000000000' }, + [PSCustomObject]@{Name = 'All Full Names'; Id = '50b8b56b-4ef8-44c2-a924-03374f5831ce'; RulePackId = '00000000-0000-0000-0000-000000000004' } + ) + } + # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { } @@ -82,6 +89,47 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Value = 'English DisplayName' } -ClientOnly) } -ClientOnly) + AutoLabelingSettings = New-CimInstance -ClassName MSFT_SCSLAutoLabelingSettings -Property @{ + Operator = 'And' + AutoApplyType = 'Recommend' + PolicyTip = 'My Perfect Test Tip!' + Groups = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationGroup -Property @{ + Name = 'Group1' + Operator = 'Or' + SensitiveInformationType = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationType -Property @{ + name = 'ABA Routing Number' + confidencelevel = 'High' + mincount = 1 + maxcount = -1 + } -ClientOnly + ) + TrainableClassifier = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLTrainableClassifiers -Property @{ + name = 'Legal Affairs' + } -ClientOnly + ) + } -ClientOnly + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationGroup -Property @{ + Name = 'Group2' + Operator = 'And' + SensitiveInformationType = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationType -Property @{ + name = 'All Full Names' + confidencelevel = 'High' + mincount = 10 + maxcount = 100 + } -ClientOnly + ) + TrainableClassifier = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLTrainableClassifiers -Property @{ + name = 'Legal Affairs' + } -ClientOnly + ) + } -ClientOnly + ) + } -ClientOnly Credential = $Credential Ensure = 'Present' } @@ -104,7 +152,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } - Context -Name 'Label already exists' -Fixture { + Context -Name 'Label already exists, but is incorrectly configured' -Fixture { BeforeAll { $testParams = @{ Name = 'TestLabel' @@ -126,6 +174,48 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } -ClientOnly) } -ClientOnly) + AutoLabelingSettings = New-CimInstance -ClassName MSFT_SCSLAutoLabelingSettings -Property @{ + Operator = 'And' + AutoApplyType = 'Recommend' + PolicyTip = 'My Perfect Test Tip!' + Groups = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationGroup -Property @{ + Name = 'Group1' + Operator = 'Or' + SensitiveInformationType = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationType -Property @{ + name = 'ABA Routing Number' + confidencelevel = 'High' + mincount = 1 + maxcount = -1 + } -ClientOnly + ) + TrainableClassifier = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLTrainableClassifiers -Property @{ + name = 'Legal Affairs' + } -ClientOnly + ) + } -ClientOnly + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationGroup -Property @{ + Name = 'Group2' + Operator = 'And' + SensitiveInformationType = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationType -Property @{ + name = 'All Full Names' + confidencelevel = 'High' + mincount = 1 + maxcount = 100 + } -ClientOnly + ) + TrainableClassifier = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLTrainableClassifiers -Property @{ + name = 'Legal Affairs' + } -ClientOnly + ) + } -ClientOnly + ) + } -ClientOnly + Credential = $Credential Ensure = 'Present' } @@ -138,11 +228,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { DisplayName = 'Test label' ParentId = 'MyLabel' Priority = '2' - Settings = '{"Key": "LabelStatus", - "Value": "Enabled"}' - LocaleSettings = '{"LocaleKey":"DisplayName", - "LabelSettings":[ - {"Key":"en-us","Value":"English Display Names"}]}' + Settings = '[LabelStatus, Enabled]' + LocaleSettings = '{"LocaleKey":"DisplayName","Settings":[{"Key":"en-us","Value":"English Display Names"}]}' + Conditions = '{"And":[{"Or":[{"Key":"CCSI","Value":"cb353f78-2b72-4c3c-8827-92ebe4f69fdf","Properties":null,"Settings":[{"Key":"mincount","Value":"1"},{"Key":"maxconfidence","Value":"100"},{"Key":"rulepackage","Value":"00000000-0000-0000-0000-000000000000"},{"Key":"name","Value":"ABA Routing Number"},{"Key":"groupname","Value":"Group1"},{"Key":"minconfidence","Value":"85"},{"Key":"maxcount","Value":"-1"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"confidencelevel","Value":"High"},{"Key":"autoapplytype","Value":"Recommend"}]},{"Key":"ContentMatchesModule","Value":"ba38aa0f-8c86-4c73-87db-95147a0f4420","Properties":null,"Settings":[{"Key":"name","Value":"Legal Affairs"},{"Key":"groupname","Value":"Group1"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"autoapplytype","Value":"Recommend"}]}]},{"And":[{"Key":"CCSI","Value":"50b8b56b-4ef8-44c2-a924-03374f5831ce","Properties":null,"Settings":[{"Key":"mincount","Value":"10"},{"Key":"maxconfidence","Value":"100"},{"Key":"rulepackage","Value":"00000000-0000-0000-0000-000000000004"},{"Key":"name","Value":"All Full Names"},{"Key":"groupname","Value":"Group2"},{"Key":"minconfidence","Value":"85"},{"Key":"maxcount","Value":"100"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"confidencelevel","Value":"High"},{"Key":"autoapplytype","Value":"Recommend"}]},{"Key":"ContentMatchesModule","Value":"ba38aa0f-8c86-4c73-87db-95147a0f4420","Properties":null,"Settings":[{"Key":"name","Value":"Legal Affairs"},{"Key":"groupname","Value":"Group2"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"autoapplytype","Value":"Recommend"}]}]}]}' } } } @@ -160,6 +248,100 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } + Context -Name 'Label already exists and is correctly configured' -Fixture { + BeforeAll { + $testParams = @{ + Name = 'TestLabel' + Comment = 'This is a test label' + ToolTip = 'Test tool tip' + DisplayName = 'Test label' + ParentId = 'MyLabel' + + AdvancedSettings = (New-CimInstance -ClassName MSFT_SCLabelSetting -Property @{ + Key = 'LabelStatus' + Value = 'Enabled' + } -ClientOnly) + + LocaleSettings = (New-CimInstance -ClassName MSFT_SCLabelLocaleSettings -Property @{ + LocaleKey = 'DisplayName' + LabelSettings = (New-CimInstance -ClassName MSFT_SCLabelSetting -Property @{ + Key = 'en-us' + Value = 'English Display Names' + } -ClientOnly) + } -ClientOnly) + + AutoLabelingSettings = New-CimInstance -ClassName MSFT_SCSLAutoLabelingSettings -Property @{ + Operator = 'And' + AutoApplyType = 'Recommend' + PolicyTip = 'My Perfect Test Tip!' + Groups = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationGroup -Property @{ + Name = 'Group1' + Operator = 'Or' + SensitiveInformationType = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationType -Property @{ + name = 'ABA Routing Number' + confidencelevel = 'High' + mincount = 1 + maxcount = -1 + } -ClientOnly + ) + TrainableClassifier = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLTrainableClassifiers -Property @{ + name = 'Legal Affairs' + } -ClientOnly + ) + } -ClientOnly + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationGroup -Property @{ + Name = 'Group2' + Operator = 'And' + SensitiveInformationType = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationType -Property @{ + name = 'All Full Names' + confidencelevel = 'High' + mincount = 10 + maxcount = 100 + } -ClientOnly + ) + TrainableClassifier = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLTrainableClassifiers -Property @{ + name = 'Legal Affairs' + } -ClientOnly + ) + } -ClientOnly + ) + } -ClientOnly + + Credential = $Credential + Ensure = 'Present' + } + + Mock -CommandName Get-Label -MockWith { + return @{ + Name = 'TestLabel' + Comment = 'This is a test label' + ToolTip = 'Test tool tip' + DisplayName = 'Test label' + ParentId = 'MyLabel' + Priority = '2' + Settings = '[LabelStatus, Enabled]' + LocaleSettings = '{"LocaleKey":"DisplayName","Settings":[{"Key":"en-us","Value":"English Display Names"}]}' + Conditions = '{"And":[{"Or":[{"Key":"CCSI","Value":"cb353f78-2b72-4c3c-8827-92ebe4f69fdf","Properties":null,"Settings":[{"Key":"mincount","Value":"1"},{"Key":"maxconfidence","Value":"100"},{"Key":"rulepackage","Value":"00000000-0000-0000-0000-000000000000"},{"Key":"name","Value":"ABA Routing Number"},{"Key":"groupname","Value":"Group1"},{"Key":"minconfidence","Value":"85"},{"Key":"maxcount","Value":"-1"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"confidencelevel","Value":"High"},{"Key":"autoapplytype","Value":"Recommend"}]},{"Key":"ContentMatchesModule","Value":"ba38aa0f-8c86-4c73-87db-95147a0f4420","Properties":null,"Settings":[{"Key":"name","Value":"Legal Affairs"},{"Key":"groupname","Value":"Group1"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"autoapplytype","Value":"Recommend"}]}]},{"And":[{"Key":"CCSI","Value":"50b8b56b-4ef8-44c2-a924-03374f5831ce","Properties":null,"Settings":[{"Key":"mincount","Value":"10"},{"Key":"maxconfidence","Value":"100"},{"Key":"rulepackage","Value":"00000000-0000-0000-0000-000000000004"},{"Key":"name","Value":"All Full Names"},{"Key":"groupname","Value":"Group2"},{"Key":"minconfidence","Value":"85"},{"Key":"maxcount","Value":"100"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"confidencelevel","Value":"High"},{"Key":"autoapplytype","Value":"Recommend"}]},{"Key":"ContentMatchesModule","Value":"ba38aa0f-8c86-4c73-87db-95147a0f4420","Properties":null,"Settings":[{"Key":"name","Value":"Legal Affairs"},{"Key":"groupname","Value":"Group2"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"autoapplytype","Value":"Recommend"}]}]}]}' + } + } -ParameterFilter { $Identity -eq 'TestLabel' } + + Mock -CommandName Get-Label -MockWith { + return @{ + Name = 'MyLabel' + } + } -ParameterFilter { $Identity -eq 'MyLabel' } + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + Context -Name 'Label should not exist' -Fixture { BeforeAll { $testParams = @{ diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 36fb0879a9..ed4b425814 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -64126,6 +64126,31 @@ function Get-DlpComplianceRule $IncludeExecutionRuleGuids ) } +function Get-DlpSensitiveInformationType +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $IncludeElements, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IncludeDetails, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $Organization, + + [Parameter()] + [System.Object] + $Capability + ) +} function Get-FilePlanPropertyAuthority { [CmdletBinding()] From 62131ed9ebb99226f4047f1e52564bed332143f8 Mon Sep 17 00:00:00 2001 From: Yorick Kuijs Date: Wed, 18 Sep 2024 13:09:41 +0200 Subject: [PATCH 215/465] Fixes SCAutoSensitivityLabelRule - Setting error #4641 --- CHANGELOG.md | 4 ++++ .../MSFT_SCAutoSensitivityLabelRule.psm1 | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b23aceaae2..0ebe8dd70d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,10 @@ * IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10 * Add missing `AccessTokens` parameter to `Export-TargetResource` FIXES [#5034](https://github.com/microsoft/Microsoft365DSC/issues/5034) +* SCAutoSensitivityLabelRule + * Fixed issue with incorrectly applying HeaderMatchesPatterns, even when + parameter wasn't specified. + FIXES [#4641](https://github.com/microsoft/Microsoft365DSC/issues/4641) * SCRoleGroup * Fixes an issue with creation without specifying Displayname * Fixes an issue with Drifts because of returned Role format diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCAutoSensitivityLabelRule/MSFT_SCAutoSensitivityLabelRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCAutoSensitivityLabelRule/MSFT_SCAutoSensitivityLabelRule.psm1 index edabc166c2..22ef5eca5a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCAutoSensitivityLabelRule/MSFT_SCAutoSensitivityLabelRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCAutoSensitivityLabelRule/MSFT_SCAutoSensitivityLabelRule.psm1 @@ -631,9 +631,9 @@ function Set-TargetResource $CurrentRule = Get-TargetResource @PSBoundParameters - $HeaderMatchesPatternsValue = @{} if ($null -ne $HeaderMatchesPatterns -and $null -ne $HeaderMatchesPatterns.Name) { + $HeaderMatchesPatternsValue = @{} $HeaderMatchesPatternsValue.Add($HeaderMatchesPatterns.Name, $HeaderMatchesPatterns.Values) } if (('Present' -eq $Ensure) -and ('Absent' -eq $CurrentRule.Ensure)) From dca7c8fa8b839e05b03ae1433bbb070bf737845a Mon Sep 17 00:00:00 2001 From: Yorick Kuijs Date: Wed, 18 Sep 2024 08:55:42 +0200 Subject: [PATCH 216/465] Fixing PSDesiredStateConfiguration v1.1 mentioned as Dependency #5051 --- CHANGELOG.md | 1 + Modules/Microsoft365DSC/Dependencies/Manifest.psd1 | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0390105429..176db8abf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ * Added dependencies on Az.Accounts, Az.Resources and Az.SecurityInsights * Updated DSCParser to version 2.0.0.9. * Updated MSCloudLoginAssistant to version 1.1.25. + * Removed unnecessary dependency PSDesiredStateConfiguration v1.1 # 1.24.904.1 diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 1b2afb7550..b68b4486f9 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -108,11 +108,6 @@ ModuleName = 'PnP.PowerShell' RequiredVersion = '1.12.0' }, - @{ - ModuleName = 'PSDesiredStateConfiguration' - RequiredVersion = '1.1' - PowerShellCore = $false - }, @{ ModuleName = 'PSDesiredStateConfiguration' RequiredVersion = '2.0.7' From d0aa150a2ad0421ddf172f29d4a491d4adeb5d4d Mon Sep 17 00:00:00 2001 From: Yorick Kuijs Date: Wed, 18 Sep 2024 08:56:26 +0200 Subject: [PATCH 217/465] Fixing unit test output --- ...365DSC.IntuneDeviceCompliancePolicyWindows10.Tests.ps1 | 3 +++ ...DSC.IntuneDeviceManagementComplianceSettings.Tests.ps1 | 3 +++ .../Microsoft365DSC.SCRoleGroupMember.Tests.ps1 | 8 +++++--- .../Microsoft365DSC.SPOSharingSettings.Tests.ps1 | 3 +++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceCompliancePolicyWindows10.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceCompliancePolicyWindows10.Tests.ps1 index e2694a7aa2..aeb1f9982d 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceCompliancePolicyWindows10.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceCompliancePolicyWindows10.Tests.ps1 @@ -56,6 +56,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { } + + Mock -CommandName Write-Verbose -MockWith { + } $Script:exportedInstances =$null $Script:ExportMode = $false } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceManagementComplianceSettings.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceManagementComplianceSettings.Tests.ps1 index 7bf483c06c..d074c4be78 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceManagementComplianceSettings.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceManagementComplianceSettings.Tests.ps1 @@ -38,6 +38,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { } + + Mock -CommandName Write-Verbose -MockWith { + } $Script:exportedInstances =$null $Script:ExportMode = $false } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCRoleGroupMember.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCRoleGroupMember.Tests.ps1 index 7da44936c3..a9b7311eb3 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCRoleGroupMember.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCRoleGroupMember.Tests.ps1 @@ -169,9 +169,11 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } Mock -CommandName Get-RoleGroupMember -MockWith { - return @{ - Name = @('Group1','User1','User2') - } + return @( + [PSCustomObject]@{Name = 'Group1' }, + [PSCustomObject]@{Name = 'User1' }, + [PSCustomObject]@{Name = 'User2' } + ) } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SPOSharingSettings.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SPOSharingSettings.Tests.ps1 index 3cf66e0d06..2c48f1841d 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SPOSharingSettings.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SPOSharingSettings.Tests.ps1 @@ -38,6 +38,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { } + + Mock -CommandName Write-Warning -MockWith { + } $Script:exportedInstances =$null $Script:ExportMode = $false } From b3897b014b89e04c6d0319158b8bdd334c7155de Mon Sep 17 00:00:00 2001 From: Yorick Kuijs Date: Wed, 18 Sep 2024 13:06:48 +0200 Subject: [PATCH 218/465] Implementing [SCSensitityLabel] Auto Labeling missing in export #3784 --- CHANGELOG.md | 3 + .../MSFT_SCSensitivityLabel.psm1 | 625 +++++++++++++++++- .../MSFT_SCSensitivityLabel.schema.mof | 32 + .../Resources/SCSensitivityLabel/2-Update.ps1 | 146 ++++ ...crosoft365DSC.SCSensitivityLabel.Tests.ps1 | 194 +++++- Tests/Unit/Stubs/Microsoft365.psm1 | 25 + 6 files changed, 1010 insertions(+), 15 deletions(-) create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCSensitivityLabel/2-Update.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 176db8abf3..45cec11ff8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,9 @@ * Fixes an issue with creation without specifying Displayname * Fixes an issue with Drifts because of returned Role format FIXES [#5036](https://github.com/microsoft/Microsoft365DSC/issues/5036) +* SCSensitivityLabel + * Added support for Auto Labeling settings + FIXES [#3784](https://github.com/microsoft/Microsoft365DSC/issues/3784) * SentinelSetting * Initial release. * SPOAccessControlSettings diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.psm1 index 056f92cf9f..badac1d9d5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.psm1 @@ -1,3 +1,84 @@ +$allTrainableClassifiers = @( + [PSCustomObject]@{ Name = "Actuary reports"; Id = "b27df2ee-fd14-4ce9-b02f-4070a5d68132" } + [PSCustomObject]@{ Name = "Agreements"; Id = "7f12e403-5335-4da8-a91e-6c2210b7a2b1" } + [PSCustomObject]@{ Name = "Asset Management"; Id = "716fb550-90cd-493b-b29b-ceed41ee8a6f" } + [PSCustomObject]@{ Name = "Bank statement"; Id = "f426bd16-e42e-4397-824b-f17dedc5bb1c" } + [PSCustomObject]@{ Name = "Budget"; Id = "6f207592-f71e-4b4f-8c07-ebc4bd4965b9" } + [PSCustomObject]@{ Name = "Business Context"; Id = "08b772df-bf93-457f-be23-b5cbf02005fd" } + [PSCustomObject]@{ Name = "Business plan"; Id = "693f8221-ae4e-4612-80f5-746efee167c3" } + [PSCustomObject]@{ Name = "Completion Certificates"; Id = "b2580781-286b-4ad2-ab47-84e84ff331e5" } + [PSCustomObject]@{ Name = "Compliance policies"; Id = "fdad8089-651b-4877-8b66-be105b2e57da" } + [PSCustomObject]@{ Name = "Construction specifications"; Id = "bfde18ef-b4b9-4f30-9965-ef8d00861a2c" } + [PSCustomObject]@{ Name = "Control System and SCADA files"; Id = "59f1f471-687d-453b-a73e-0b0e9f350812" } + [PSCustomObject]@{ Name = "Corporate Sabotage"; Id = "d88960c3-6101-43d9-9250-8c43c71d638a" } + [PSCustomObject]@{ Name = "Credit Report"; Id = "07ce7d30-690a-4a1c-a331-8df9c944f1ab" } + [PSCustomObject]@{ Name = "Customer Complaints"; Id = "8137d8fc-fb7a-40db-9009-284f962fde96" } + [PSCustomObject]@{ Name = "Customer Files"; Id = "fdff9df2-03ba-4372-be97-82c0d2515118" } + [PSCustomObject]@{ Name = "Discrimination"; Id = "a65c4ab6-a155-11eb-921c-6c0b84aa8ea5" } + [PSCustomObject]@{ Name = "Employee disciplinary action files"; Id = "769d56c1-e737-4fc1-8673-8c99bbe24a07" } + [PSCustomObject]@{ Name = "Employee Insurance files"; Id = "fa982a9f-9454-4885-a2bf-94a155df2f33" } + [PSCustomObject]@{ Name = "Employee Pension Records"; Id = "f9ae0bbc-a1e0-4b7e-a96a-eb60b26b4434" } + [PSCustomObject]@{ Name = "Employee Stocks and Financial Bond Records"; Id = "a67b2b59-c5f0-4c66-a6c4-ca6973adfd94" } + [PSCustomObject]@{ Name = "Employment Agreement"; Id = "2a2baab7-b82c-4166-bbe4-55f9d3fd1129" } + [PSCustomObject]@{ Name = "Enterprise Risk Management"; Id = "eed09aae-6f32-47c7-9c99-9d17bad48783" } + [PSCustomObject]@{ Name = "Environmental permits and clearances"; Id = "1b7d3e51-0ecf-41bd-9794-966c94a889ba" } + [PSCustomObject]@{ Name = "Facility Permits"; Id = "914c5379-9d05-47cb-98f0-f5a2be059b5a" } + [PSCustomObject]@{ Name = "factory Incident Investigation reports"; Id = "86186144-d507-4603-bac7-50b56ba05c70" } + [PSCustomObject]@{ Name = "Finance"; Id = "1771481d-a337-4dbf-8e64-af8da0cc3ee9" } + [PSCustomObject]@{ Name = "Finance policies and procedures"; Id = "6556c5eb-0819-4618-ba2e-59925925655e" } + [PSCustomObject]@{ Name = "Financial Audit Reports"; Id = "b04b2a4e-22f8-4024-8adc-e2caaad1c2e2" } + [PSCustomObject]@{ Name = "Financial statement"; Id = "c31bfef9-8045-4a35-88a3-74b8681615c2" } + [PSCustomObject]@{ Name = "Freight Documents"; Id = "785917ed-db01-43c7-8153-8a6fc393efa3" } + [PSCustomObject]@{ Name = "Garnishment"; Id = "65e827c3-f8e8-4bc8-b08c-c31e3132b832" } + [PSCustomObject]@{ Name = "Gifts \u0026 entertainment"; Id = "3b3d817a-9190-465b-af2d-9e856f894059" } + [PSCustomObject]@{ Name = "Health/Medical forms"; Id = "7cc60f30-9e96-4d51-b26f-3d7a9df56338" } + [PSCustomObject]@{ Name = "Healthcare"; Id = "dcbada08-65bf-4561-b140-25d8fee4d143" } + [PSCustomObject]@{ Name = "HR"; Id = "11631f87-7ffe-4052-b173-abda16b231f3" } + [PSCustomObject]@{ Name = "Invoice"; Id = "bf7df7c3-fce4-4ffd-ab90-26f6463f3a00" } + [PSCustomObject]@{ Name = "IP"; Id = "495fad07-d6e4-4da4-9c64-5b9b109a5f59" } + [PSCustomObject]@{ Name = "IT"; Id = "77a140be-c29f-4155-9dc4-c3e247e47560" } + [PSCustomObject]@{ Name = "IT Infra and Network Security Documents"; Id = "bc55de38-cb72-43e6-952f-8422f584f229" } + [PSCustomObject]@{ Name = "Lease Deeds"; Id = "841f54ad-3e31-4ddd-aea0-e7f0cd6b3d18" } + [PSCustomObject]@{ Name = "Legal Affairs"; Id = "ba38aa0f-8c86-4c73-87db-95147a0f4420" } + [PSCustomObject]@{ Name = "Legal Agreements"; Id = "bee9cefb-88bd-410f-ab3e-67cab21cef46" } + [PSCustomObject]@{ Name = "Letter of Credits"; Id = "fd85acd5-59dd-49b2-a4c3-df7075885a82" } + [PSCustomObject]@{ Name = "License agreement"; Id = "b399eb17-c9c4-4205-951b-43f38eb8dffe" } + [PSCustomObject]@{ Name = "Loan agreements and offer letters"; Id = "5771fa57-34a1-48b3-93df-778b304daa54" } + [PSCustomObject]@{ Name = "M&A Files"; Id = "eeffbf7c-fd04-40ef-a156-b37bf61832f7" } + [PSCustomObject]@{ Name = "Manufacturing batch records"; Id = "834b2353-509a-4605-b4f1-fc2172a0d97c" } + [PSCustomObject]@{ Name = "Marketing Collaterals"; Id = "fcaa6d2a-601c-4bdc-947e-af1178a646ac" } + [PSCustomObject]@{ Name = "Meeting notes"; Id = "e7ff9a9e-4689-4192-b927-e6c6bdf099fc" } + [PSCustomObject]@{ Name = "Money laundering"; Id = "adbbb20e-b175-46e7-8ba2-cf3f3179d0ed" } + [PSCustomObject]@{ Name = "MoU Files (Memorandum of understanding)"; Id = "cb37c277-4b88-49c6-81fb-2eeca8c52bb9" } + [PSCustomObject]@{ Name = "Network Design files"; Id = "12587d70-9596-4c21-b09f-f1abe9d6ca13" } + [PSCustomObject]@{ Name = "Non disclosure agreement"; Id = "8dfd10db-0c72-4be4-a4f2-f615fe7aeb1c" } + [PSCustomObject]@{ Name = "OSHA records"; Id = "b11b771e-7dd1-4434-873a-d648a16e969e" } + [PSCustomObject]@{ Name = "Paystub"; Id = "31c11384-2d64-4635-9335-018295c64268" } + [PSCustomObject]@{ Name = "Personal Financial Information"; Id = "6901c616-5857-432f-b3da-f5234fa1d342" } + [PSCustomObject]@{ Name = "Procurement"; Id = "8fa64a47-6e77-4b4c-91a5-0f67525cebf5" } + [PSCustomObject]@{ Name = "Profanity"; Id = "4b0aa61d-37dc-4596-a1f1-fc5a5b21d56b" } + [PSCustomObject]@{ Name = "Project documents"; Id = "e062df90-816c-47ca-8913-db647510d3b5" } + [PSCustomObject]@{ Name = "Quality assurance files"; Id = "97b1e0d3-7788-4dd4-bb18-48ea77796743" } + [PSCustomObject]@{ Name = "Quotation"; Id = "3882e681-c437-42d8-ac75-1f9b7481fe13" } + [PSCustomObject]@{ Name = "Regulatory Collusion"; Id = "911b7815-6883-4022-a882-9cbe9462f114" } + [PSCustomObject]@{ Name = "Resume"; Id = "14b2da41-0427-47e9-a11b-c924e1d05689" } + [PSCustomObject]@{ Name = "Safety Records"; Id = "938fb100-5b1f-4bbb-aba7-73d9c89d086f" } + [PSCustomObject]@{ Name = "Sales and revenue"; Id = "9d6b864d-28c6-4be3-a9d0-cd40434a847f" } + [PSCustomObject]@{ Name = "Software Product Development Files"; Id = "813aa6d8-0727-48d8-acb7-06e1819ee339" } + [PSCustomObject]@{ Name = "Source code"; Id = "8aef6743-61aa-44b9-9ae5-3bb3d77df535" } + [PSCustomObject]@{ Name = "Standard Operating Procedures and Manuals"; Id = "32f23ad4-2ca1-4495-8048-8dc567891644" } + [PSCustomObject]@{ Name = "Statement of Accounts"; Id = "fe3676a6-0f5d-4990-bb46-9b2b31d7746a" } + [PSCustomObject]@{ Name = "Statement of Work"; Id = "611c95f9-b1ef-4253-8b36-d8ae19d02fb0" } + [PSCustomObject]@{ Name = "Stock manipulation"; Id = "1140cd79-ad87-4043-a562-c768acacc6ba" } + [PSCustomObject]@{ Name = "Strategic planning documents"; Id = "9332b317-2ca4-413a-b983-92a1bd88c6f3" } + [PSCustomObject]@{ Name = "Targeted Harassment"; Id = "a02ddb8e-3c93-44ac-87c1-2f682b1cb78e" } + [PSCustomObject]@{ Name = "Tax"; Id = "9722b51a-f920-4a81-8390-b188a0692840" } + [PSCustomObject]@{ Name = "Threat"; Id = "ef2edb64-6982-4648-b0ad-c0d8a861501b" } + [PSCustomObject]@{ Name = "Unauthorized disclosure"; Id = "839aecf8-c67b-4270-8aaf-378127b23b7f" } + [PSCustomObject]@{ Name = "Wire transfer"; Id = "05fc5ed0-58ef-4306-b65c-11b0a43895c2" } + [PSCustomObject]@{ Name = "Work Schedules"; Id = "25bb9d2d-a5b5-45b1-882e-b2581a183873" } +) + function Get-TargetResource { [CmdletBinding()] @@ -187,6 +268,10 @@ function Get-TargetResource [System.String] $SiteAndGroupExternalSharingControlType, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $AutoLabelingSettings, + [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -447,6 +532,101 @@ function Get-TargetResource $siteAndGroupBlockAccess = [Boolean]::Parse($entry.Value) } + # Auto Labelling Conditions + $getConditions = $null + if ([System.String]::IsNullOrEmpty($label.Conditions) -eq $false) + { + $currConditions = $label.Conditions | ConvertFrom-Json + + $getConditions = @{ + Groups = @() + Operator = '' + } + + $operator = $currConditions.PSObject.Properties.Name + $getConditions.Operator = $operator + + $autoApplyType = '' + $policyTip = '' + $groups = foreach ($group in $currConditions.$($operator)) + { + $grpObject = @{ + Name = '' + Operator = '' + } + + $grpOperator = $group.PSObject.Properties.Name + $grpObject.Operator = $grpOperator + + $grpName = '' + [array]$sensitiveInformationTypes = foreach ($item in $group.$grpOperator | Where-Object { $_.Key -eq 'CCSI'}) + { + if ([String]::IsNullOrEmpty($grpName)) + { + $grpName = ($item.Settings | Where-Object { $_.Key -eq 'groupname' }).Value + } + + if ([String]::IsNullOrEmpty($policyTip)) + { + $policyTip = ($item.Settings | Where-Object { $_.Key -eq 'policytip' }).Value + } + + if ([String]::IsNullOrEmpty($autoApplyType)) + { + $autoApplyType = ($item.Settings | Where-Object { $_.Key -eq 'autoapplytype' }).Value + } + + $settingsObject = @{ + name = ($item.Settings | Where-Object { $_.Key -eq 'name' }).Value + confidencelevel = ($item.Settings | Where-Object { $_.Key -eq 'confidencelevel' }).Value + mincount = ($item.Settings | Where-Object { $_.Key -eq 'mincount' }).Value + maxcount = ($item.Settings | Where-Object { $_.Key -eq 'maxcount' }).Value + } + + if ($null -ne ($item.Settings | Where-Object { $_.Key -eq 'classifiertype' })) + { + $settingsObject.classifiertype = ($item.Settings | Where-Object { $_.Key -eq 'classifiertype' }).Value + } + + # return the settings object as output to the sensitiveInformationTypes array + $settingsObject + } + + [array]$trainableClassifiers = foreach ($item in $group.$grpOperator | Where-Object { $_.Key -eq 'ContentMatchesModule'}) + { + if ([String]::IsNullOrEmpty($grpName)) + { + $grpName = ($item.Settings | Where-Object { $_.Key -eq 'groupname' }).Value + } + + @{ + name = ($item.Settings | Where-Object { $_.Key -eq 'name' }).Value + id = $item.Value + } + } + + $grpObject.Name = $grpName + $grpObject.SensitiveInformationType = $sensitiveInformationTypes + $grpObject.TrainableClassifier = $trainableClassifiers + + # return the group object as output to the groups array + $grpObject + } + $getConditions.Groups = $groups + if ([System.String]::IsNullOrEmpty($policyTip) -eq $false) + { + $getConditions.PolicyTip = $policyTip + } + if ([System.String]::IsNullOrEmpty($autoApplyType) -eq $false) + { + $getConditions.AutoApplyType = $autoApplyType + } + else + { + $getConditions.AutoApplyType = 'Automatic' + } + } + $result = @{ Name = $label.Name Comment = $label.Comment @@ -500,9 +680,9 @@ function Get-TargetResource SiteAndGroupProtectionEnabled = $siteAndGroupEnabledValue SiteAndGroupExternalSharingControlType = ($protectsite | Where-Object { $_.Key -eq 'externalsharingcontroltype' }).Value AccessTokens = $AccessTokens + AutoLabelingSettings = $getConditions } - Write-Verbose -Message "Get-TargetResource Result: `n $(Convert-M365DscHashtableToString -Hashtable $result)" return $result } } @@ -706,6 +886,10 @@ function Set-TargetResource [System.String] $SiteAndGroupExternalSharingControlType, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $AutoLabelingSettings, + [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -770,6 +954,139 @@ function Set-TargetResource Write-Warning -Message "You have specified EncryptionDoNotForward, EncryptionEncryptOnly or EncryptionPromptUser, but EncryptionProtectionType isn't set to UserDefined." } + if ('Present' -eq $Ensure -and $PSBoundParameters.ContainsKey('AutoLabelingSettings')) + { + Write-Verbose 'Generating required JSON string for AutoLabelingSettings' + + Write-Verbose 'Retrieving all existing Sensitive Information Types' + $existingSITs = Get-DlpSensitiveInformationType | Select-Object -Property Name,Id, RulePackId + + # Convert the AutoLabelingSettings to the correct JSON format, ready to be inserted into the label cmdlets + $autoLabelingSettingsHT = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $AutoLabelingSettings + + Write-Verbose 'Processing all setting groups' + [array]$grps = foreach ($group in $autoLabelingSettingsHT.Groups) + { + $groupCollection = @() + Write-Verbose 'Processing all Sensitive Information Types' + foreach ($sit in $group.SensitiveInformationType) + { + $currentSIT = $existingSITs | Where-Object { $_.Name -eq $sit.Name } + if ($null -eq $currentSIT) + { + throw "[ERROR] Provided Sensitive Information Type $($sit.Name) doesn't exist." + } + + [array]$settingsCollection = foreach ($setting in ($sit.Keys | Where-Object { $_ -ne 'id' })) + { + @{ + Key = $setting + Value = $sit[$setting] + } + } + $settingsCollection += @{ + Key = "rulepackage" + Value = $currentSIT.RulePackId + } + $settingsCollection += @{ + Key = "groupname" + Value = $group.Name + } + + if ($autoLabelingSettingsHT.ContainsKey("PolicyTip")) + { + $settingsCollection += @{ + Key = "policytip" + Value = $autoLabelingSettingsHT.PolicyTip + } + } + + if ($autoLabelingSettingsHT.ContainsKey("AutoApplyType") -and $autoLabelingSettingsHT.AutoApplyType -eq 'Recommend') + { + $settingsCollection += @{ + Key = "autoapplytype" + Value = $autoLabelingSettingsHT.AutoApplyType + } + } + + $groupCollection += @{ + Key = 'CCSI' + Value = $currentSIT.Id + Properties = $null + Settings = $settingsCollection + } + } + + Write-Verbose 'Processing all Trainable Classifiers' + foreach ($trainableClassifier in $group.TrainableClassifier) + { + $currentTrainableClassifier = $allTrainableClassifiers | Where-Object { $_.Name -eq $trainableClassifier.name } + if ($null -ne $currentTrainableClassifier) + { + if ([String]::IsNullOrEmpty($trainableClassifier.id) -eq $false -and ` + $trainableClassifier.id -ne $currentTrainableClassifier.Id) + { + Write-Verbose ("[WARNING] Provided ID ($($trainableClassifier.id)) does not match the known " + ` + "ID ($($currentTrainableClassifier.id)) for trainable classifier '$($trainableClassifier.name)'.") + } + $requiredId = $currentTrainableClassifier.Id + } + else + { + if ([String]::IsNullOrEmpty($trainableClassifier.id)) + { + throw "[ERROR] Trainable classifier $($trainableClassifier.name) isn't a default classifier and no ID was provided." + } + $requiredId = $trainableClassifier.id + } + + [array]$settingsCollection = foreach ($key in ($trainableClassifier.Keys | Where-Object { $_ -ne 'id' })) + { + @{ + Key = $key + Value = $trainableClassifier[$key] + } + } + $settingsCollection += @{ + Key = "groupname" + Value = $group.Name + } + + if ($autoLabelingSettingsHT.ContainsKey("PolicyTip")) + { + $settingsCollection += @{ + Key = "policytip" + Value = $autoLabelingSettingsHT.PolicyTip + } + } + + if ($autoLabelingSettingsHT.ContainsKey("AutoApplyType") -and $autoLabelingSettingsHT.AutoApplyType -eq 'Recommend') + { + $settingsCollection += @{ + Key = "autoapplytype" + Value = $autoLabelingSettingsHT.AutoApplyType + } + } + + $groupCollection += @{ + Key = 'ContentMatchesModule' + Value = $requiredId + Properties = $null + Settings = $settingsCollection + } + } + + @{ + $group.Operator = $groupCollection + } + } + + $desiredAutoLabelingSettings = @{ + $autoLabelingSettingsHT.Operator = $grps + } + Write-Verbose 'Completed generating required JSON string for AutoLabelingSettings' + } + if (('Present' -eq $Ensure) -and ('Absent' -eq $label.Ensure)) { Write-Verbose -Message "Label {$Name} doesn't already exist, creating it from the Set-TargetResource function." @@ -793,6 +1110,12 @@ function Set-TargetResource $CreationParams.Remove('SiteAndGroupExternalSharingControlType') } + if ($PSBoundParameters.ContainsKey('AutoLabelingSettings') -and $null -ne $desiredAutoLabelingSettings) + { + $CreationParams.Conditions = $desiredAutoLabelingSettings | ConvertTo-Json -Depth 20 + $CreationParams.Remove('AutoLabelingSettings') + } + $CreationParams.Remove('Priority') | Out-Null # Remove authentication parameters @@ -810,19 +1133,25 @@ function Set-TargetResource try { Write-Verbose -Message "Creating Label {$Name}" - New-Label @CreationParams + New-Label @CreationParams -ErrorAction Stop ## Can't set priority until label created if ($PSBoundParameters.ContainsKey('Priority')) { Start-Sleep 5 Write-Verbose -Message "Updating the priority for newly created label {$Name}" - Set-label -Identity $Name -priority $Priority + Set-label -Identity $Name -priority $Priority -ErrorAction Stop } } catch { - Write-Warning "New-Label is not available in tenant $($Credential.UserName.Split('@')[1]): $_" + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + throw $_ } } elseif (('Present' -eq $Ensure) -and ('Present' -eq $label.Ensure)) @@ -848,6 +1177,12 @@ function Set-TargetResource $SetParams.Remove('SiteAndGroupExternalSharingControlType') } + if ($PSBoundParameters.ContainsKey('AutoLabelingSettings') -and $null -ne $desiredAutoLabelingSettings) + { + $SetParams.Conditions = $desiredAutoLabelingSettings | ConvertTo-Json -Depth 20 + $SetParams.Remove('AutoLabelingSettings') + } + #Remove unused parameters for Set-Label cmdlet $SetParams.Remove('Name') | Out-Null @@ -865,11 +1200,17 @@ function Set-TargetResource try { - Set-Label @SetParams -Identity $Name + Set-Label @SetParams -Identity $Name -ErrorAction Stop } catch { - Write-Warning "Set-Label is not available in tenant $($Credential.UserName.Split('@')[1]): $_" + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + throw $_ } } elseif (('Absent' -eq $Ensure) -and ('Present' -eq $label.Ensure)) @@ -879,12 +1220,18 @@ function Set-TargetResource try { - Remove-Label -Identity $Name -Confirm:$false - Remove-Label -Identity $Name -Confirm:$false -forcedeletion:$true + Remove-Label -Identity $Name -Confirm:$false -ErrorAction Stop + Remove-Label -Identity $Name -Confirm:$false -forcedeletion:$true -ErrorAction Stop } catch { - Write-Warning "Remove-Label is not available in tenant $($Credential.UserName.Split('@')[1]): $_" + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + throw $_ } } } @@ -1078,6 +1425,10 @@ function Test-TargetResource [System.String] $SiteAndGroupExternalSharingControlType, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $AutoLabelingSettings, + [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -1127,6 +1478,7 @@ function Test-TargetResource $ValuesToCheck = $PSBoundParameters $ValuesToCheck.Remove('AdvancedSettings') | Out-Null $ValuesToCheck.Remove('LocaleSettings') | Out-Null + $ValuesToCheck.Remove('AutoLabelingSettings') | Out-Null if ($null -ne $AdvancedSettings -and $null -ne $CurrentValues.AdvancedSettings) { @@ -1148,6 +1500,20 @@ function Test-TargetResource } } + if ($null -ne $AutoLabelingSettings -and $null -ne $CurrentValues.AutoLabelingSettings) + { + Write-Verbose -Message 'Testing AutoLabelingSettings' + + # Convert the AutoLabelingSettings to the correct JSON format, ready to be inserted into the label cmdlets + $autoLabelingSettingsHT = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $AutoLabelingSettings + + $autoLabelSettingsSame = Test-AutoLabelingSettings -CurrentProperty $CurrentValues.AutoLabelingSettings -DesiredProperty $autoLabelingSettingsHT + if ($false -eq $autoLabelSettingsSame) + { + return $false + } + } + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` -DesiredValues $PSBoundParameters ` @@ -1241,6 +1607,10 @@ function Export-TargetResource { $Results.LocaleSettings = ConvertTo-LocaleSettingsString -LocaleSettings $Results.LocaleSettings } + if ($null -ne $Results.AutoLabelingSettings) + { + $Results.AutoLabelingSettings = ConvertTo-AutoLabelingSettingsString -AutoLabelingSettings $Results.AutoLabelingSettings + } $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` -Results $Results $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` @@ -1256,6 +1626,10 @@ function Export-TargetResource { $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'LocaleSettings' } + if ($null -ne $Results.AutoLabelingSettings) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'AutoLabelingSettings' + } Write-Host $Global:M365DSCEmojiGreenCheckMark $dscContent += $currentDSCBlock @@ -1566,7 +1940,160 @@ function Test-LocaleSettings } } + if ($foundSettings -eq $false) + { + New-M365DSCLogEntry -Message "LocaleSettings for label $Name do not match: $($driftedSetting -join ', ')" ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } + Write-Verbose -Message "Test LocaleSettings returns $foundSettings" + + return $foundSettings +} + +function Test-AutoLabelingSettings +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter (Mandatory = $true)] + [System.Object] + $DesiredProperty, + + [Parameter (Mandatory = $true)] + [System.Object] + $CurrentProperty + ) + + $foundSettings = $true + $driftedSetting = New-Object System.Collections.ArrayList + + if ($DesiredProperty.Operator -ne $CurrentProperty.Operator) + { + $null = $driftedSetting.Add("Parameter 'Operator' does not match. Current: '$($CurrentProperty.Operator)'. Desired: '$($DesiredProperty.Operator)'.") + $foundSettings = $false + } + + if ($DesiredProperty.AutoApplyType -ne $CurrentProperty.AutoApplyType) + { + $null = $driftedSetting.Add("Parameter 'AutoApplyType' does not match. Current: '$($CurrentProperty.AutoApplyType)'. Desired: '$($DesiredProperty.AutoApplyType)'.") + $foundSettings = $false + } + + if ($DesiredProperty.ContainsKey('PolicyTip') -and $DesiredProperty.PolicyTip -ne $CurrentProperty.PolicyTip) + { + $null = $driftedSetting.Add("Parameter 'PolicyTip' does not match. Current: '$($CurrentProperty.PolicyTip)'. Desired: '$($DesiredProperty.PolicyTip)'.") + $foundSettings = $false + } + + foreach ($group in $DesiredProperty.Groups) + { + $currentGroup = $CurrentProperty.Groups | Where-Object { $_.Name -eq $group.Name } + if ($null -eq $currentGroup) + { + $null = $driftedSetting.Add("Group '$($group.Name)' not found in the current settings.") + $foundSettings = $false + continue + } + + if ($group.Operator -ne $currentGroup.Operator) + { + $null = $driftedSetting.Add("Parameter 'Groups\$($group.Name)\Operator' does not match. Current: '$($currentGroup.Operator)'. Desired: '$($group.Operator)'.") + $foundSettings = $false + } + + foreach ($sensitiveinfotype in $group.SensitiveInformationType) + { + $currentSensitiveInfoType = $currentGroup.SensitiveInformationType | Where-Object { $_.name -eq $sensitiveinfotype.name } + if ($null -eq $currentSensitiveInfoType) + { + $null = $driftedSetting.Add("Sensitive Information Type '$($sensitiveinfotype.name)' not found in the current settings for group '$($group.Name)'.") + $foundSettings = $false + continue + } + + if ($sensitiveinfotype.ContainsKey('confidencelevel') -and $sensitiveinfotype.confidencelevel -ne $currentSensitiveInfoType.confidencelevel) + { + $null = $driftedSetting.Add("Parameter 'confidencelevel' does not match for Sensitive Information Type '$($sensitiveinfotype.name)' in group '$($group.Name)'. Current: '$($currentSensitiveInfoType.confidencelevel)'. Desired: '$($sensitiveinfotype.confidencelevel)'.") + $foundSettings = $false + } + + + if ($sensitiveinfotype.ContainsKey('classifiertype') -and $sensitiveinfotype.classifiertype -ne $currentSensitiveInfoType.classifiertype) + { + $null = $driftedSetting.Add("Parameter 'classifiertype' does not match for Sensitive Information Type '$($sensitiveinfotype.name)' in group '$($group.Name)'. Current: '$($currentSensitiveInfoType.classifiertype)'. Desired: '$($sensitiveinfotype.classifiertype)'.") + $foundSettings = $false + } + + if ($sensitiveinfotype.ContainsKey('mincount') -and $sensitiveinfotype.mincount -ne $currentSensitiveInfoType.mincount) + { + $null = $driftedSetting.Add("Parameter 'mincount' does not match for Sensitive Information Type '$($sensitiveinfotype.name)' in group '$($group.Name)'. Current: '$($currentSensitiveInfoType.mincount)'. Desired: '$($sensitiveinfotype.mincount)'.") + $foundSettings = $false + } + + if ($sensitiveinfotype.ContainsKey('maxcount') -and $sensitiveinfotype.maxcount -ne $currentSensitiveInfoType.maxcount) + { + $null = $driftedSetting.Add("Parameter 'maxcount' does not match for Sensitive Information Type '$($sensitiveinfotype.name)' in group '$($group.Name)'. Current: '$($currentSensitiveInfoType.maxcount)'. Desired: '$($sensitiveinfotype.maxcount)'.") + $foundSettings = $false + } + } + foreach ($trainableClassifier in $group.TrainableClassifier) + { + $currentTrainableClassifier = $currentGroup.trainableClassifier | Where-Object { $_.name -eq $trainableClassifier.name } + if ($null -eq $currentTrainableClassifier) + { + $null = $driftedSetting.Add("Trainable Classifier '$($trainableClassifier.name)' not found in the current settings for group '$($group.Name)'.") + $foundSettings = $false + continue + } + } + } + + foreach ($group in $CurrentProperty.Groups) + { + $desiredGroup = $DesiredProperty.Groups | Where-Object { $_.Name -eq $group.Name } + if ($null -eq $desiredGroup) + { + $null = $driftedSetting.Add("Group '$($group.Name)' not found in the desired settings.") + $foundSettings = $false + continue + } + + foreach ($sensitiveinfotype in $group.SensitiveInformationType) + { + $desiredSensitiveInfoType = $desiredGroup.SensitiveInformationType | Where-Object { $_.name -eq $sensitiveinfotype.name } + if ($null -eq $desiredSensitiveInfoType) + { + $null = $driftedSetting.Add("Sensitive Information Type '$($sensitiveinfotype.name)' not found in the desired settings for group '$($group.Name)'.") + $foundSettings = $false + continue + } + } + foreach ($trainableClassifier in $group.TrainableClassifier) + { + $desiredTrainableClassifier = $desiredGroup.trainableClassifier | Where-Object { $_.name -eq $trainableClassifier.name } + if ($null -eq $desiredTrainableClassifier) + { + $null = $driftedSetting.Add("Trainable Classifier '$($trainableClassifier.name)' not found in the desired settings for group '$($group.Name)'.") + $foundSettings = $false + continue + } + } + } + + if ($foundSettings -eq $false) + { + New-M365DSCLogEntry -Message "AutoLabelingSettings for label $Name do not match: `r`n- $($driftedSetting -join '`r`n- ')" ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } + + Write-Verbose -Message "Test AutoLabelingSettings returns $foundSettings" + return $foundSettings } @@ -1625,4 +2152,84 @@ function ConvertTo-LocaleSettingsString return $StringContent } +function ConvertTo-AutoLabelingSettingsString +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter(Mandatory = $true)] + $AutoLabelingSettings + ) + + $StringContent = "" + foreach ($autoLabelingSetting in $AutoLabelingSettings) + { + $StringContent += " MSFT_SCSLAutoLabelingSettings`r`n" + $StringContent += " {`r`n" + $StringContent += " Operator = '$($autoLabelingSetting.Operator)'`r`n" + if ($autoLabelingSetting.ContainsKey('PolicyTip')) + { + $StringContent += " PolicyTip = '$($autoLabelingSetting.PolicyTip.Replace("'", "''"))'`r`n" + } + $StringContent += " AutoApplyType = '$($autoLabelingSetting.AutoApplyType)'`r`n" + $StringContent += " Groups = @(`r`n" + foreach ($Group in $autoLabelingSetting.Groups) + { + $StringContent += " MSFT_SCSLSensitiveInformationGroup`r`n" + $StringContent += " {`r`n" + $StringContent += " Name = '$($Group.Name.Replace("'", "''"))'`r`n" + $StringContent += " Operator = '$($Group.Operator)'`r`n" + if ($Group.ContainsKey('SensitiveInformationType')) + { + $StringContent += " SensitiveInformationType = @(`r`n" + foreach ($sensitiveInformationType in $Group.SensitiveInformationType) + { + $StringContent += " MSFT_SCSLSensitiveInformationType`r`n" + $StringContent += " {`r`n" + $StringContent += " name = '$($sensitiveInformationType.name.Replace("'", "''"))'`r`n" + if ($sensitiveInformationType.ContainsKey('confidencelevel')) + { + $StringContent += " confidencelevel = '$($sensitiveInformationType.confidencelevel)'`r`n" + } + if ($sensitiveInformationType.ContainsKey('classifiertype')) + { + $StringContent += " classifiertype = '$($sensitiveInformationType.classifiertype)'`r`n" + } + if ($sensitiveInformationType.ContainsKey('mincount')) + { + $StringContent += " mincount = '$($sensitiveInformationType.mincount)'`r`n" + } + if ($sensitiveInformationType.ContainsKey('maxcount')) + { + $StringContent += " maxcount = '$($sensitiveInformationType.maxcount)'`r`n" + } + $StringContent += " }`r`n" + } + $StringContent += " )`r`n" + } + if ($Group.ContainsKey('TrainableClassifier')) + { + $StringContent += " TrainableClassifier = @(`r`n" + foreach ($trainableClassifier in $Group.TrainableClassifier) + { + $StringContent += " MSFT_SCSLTrainableClassifiers`r`n" + $StringContent += " {`r`n" + $StringContent += " name = '$($trainableClassifier.name.Replace("'", "''"))'`r`n" + if ($trainableClassifier.ContainsKey('id')) + { + $StringContent += " id = '$($trainableClassifier.id)'`r`n" + } + $StringContent += " }`r`n" + } + $StringContent += " )`r`n" + } + $StringContent += " }`r`n" + } + $StringContent += " )`r`n" + $StringContent += " }`r`n" + } + return $StringContent +} + Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.schema.mof index 1cedd8011b..4653fd23be 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.schema.mof @@ -1,4 +1,35 @@ [ClassVersion("1.0.0")] +class MSFT_SCSLSensitiveInformationType +{ + [Required, Description("Name of the Sensitive Information Type")] String name; + [Write, Description("Confidence level value for the Sensitive Information"),ValueMap{"Low","Medium","High"}, Values{"Low","Medium","High"}] String confidencelevel; + [Write, Description("Type of Classifier value for the Sensitive Information")] String classifiertype; + [Write, Description("Minimum Count value for the Sensitive Information")] String mincount; + [Write, Description("Maximum Count value for the Sensitive Information")] String maxcount; +}; +[ClassVersion("1.0.0")] +class MSFT_SCSLTrainableClassifiers +{ + [Required, Description("Name of the Trainable Classifier")] String name; + [Write, Description("Id of the Trainable Classifier")] String id; +}; +[ClassVersion("1.0.0")] +class MSFT_SCSLSensitiveInformationGroup +{ + [Write, Description("Sensitive Information Content Types"),EmbeddedInstance("MSFT_SCSLSensitiveInformationType")] String SensitiveInformationType[]; + [Write, Description("Trainable Classifiers"),EmbeddedInstance("MSFT_SCSLTrainableClassifiers")] String TrainableClassifier[]; + [Required, Description("Name of the group")] String Name; + [Required, Description("How to process the Sensitive Information Types and Trainable Classifiers"),ValueMap{"And","Or"}, Values{"And","Or"}] String Operator; +}; +[ClassVersion("1.0.0")] +class MSFT_SCSLAutoLabelingSettings +{ + [Required, Description("Groups of sensitive information types."),EmbeddedInstance("MSFT_SCSLSensitiveInformationGroup")] String Groups[]; + [Required, Description("How to process the various groups"),ValueMap{"And","Or"}, Values{"And","Or"}] String Operator; + [Write, Description("Display this message to users when the label is applied")] String PolicyTip; + [Required, Description("Specifies what to do when content matches the conditions"),ValueMap{"Automatic","Recommend"}, Values{"Automatic","Recommend"}] String AutoApplyType; +}; +[ClassVersion("1.0.0")] class MSFT_SCLabelSetting { [Write, Description("Advanced settings key.")] String Key; @@ -57,6 +88,7 @@ class MSFT_SCSensitivityLabel : OMI_BaseResource [Write, Description("The SiteAndGroupProtectionEnabled parameter enables or disables the Site and Group Protection action for the labels.")] Boolean SiteAndGroupProtectionEnabled; [Write, Description("The SiteAndGroupProtectionPrivacy parameter specifies the privacy level for the label."), ValueMap{"Public","Private","Unspecified"}, Values{"Public","Private","Unspecified"}] String SiteAndGroupProtectionPrivacy; [Write, Description("The SiteAndGroupExternalSharingControlType parameter specifies the external user sharing setting for the label."), ValueMap{"ExternalUserAndGuestSharing","ExternalUserSharingOnly","ExistingExternalUserSharingOnly","Disabled"}, Values{"ExternalUserAndGuestSharing","ExternalUserSharingOnly","ExistingExternalUserSharingOnly","Disabled"}] String SiteAndGroupExternalSharingControlType; + [Write, Description("The AutoLabelingSettings parameter specifies the conditions for label to be automatically applied to files and emails."), EmbeddedInstance("MSFT_SCSLAutoLabelingSettings")] String AutoLabelingSettings; [Write, Description("Credentials of the Exchange Global 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; diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCSensitivityLabel/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCSensitivityLabel/2-Update.ps1 new file mode 100644 index 0000000000..374d2e371c --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCSensitivityLabel/2-Update.ps1 @@ -0,0 +1,146 @@ +<# +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 + { + SCSensitivityLabel 'ConfigureSensitivityLabel' + { + Name = 'DemoLabel' + Comment = 'Demo Label comment' + ToolTip = 'Demo tool tip' + DisplayName = 'Demo Label' + ApplyContentMarkingFooterAlignment = 'Center' + ApplyContentMarkingFooterEnabled = $true + ApplyContentMarkingFooterFontColor = '#FF0000' + ApplyContentMarkingFooterFontSize = 10 + ApplyContentMarkingFooterMargin = 5 + ApplyContentMarkingFooterText = 'Demo footer text' + ApplyContentMarkingHeaderAlignment = 'Center' + ApplyContentMarkingHeaderEnabled = $true + ApplyContentMarkingHeaderFontColor = '#FF0000' + ApplyContentMarkingHeaderFontSize = 10 + ApplyContentMarkingHeaderMargin = 5 + ApplyContentMarkingHeaderText = 'demo header text' + ApplyWaterMarkingEnabled = $true + ApplyWaterMarkingFontColor = '#FF0000' + ApplyWaterMarkingFontSize = 10 + ApplyWaterMarkingLayout = 'Diagonal' + ApplyWaterMarkingText = 'demo watermark' + SiteAndGroupProtectionAllowAccessToGuestUsers = $true + SiteAndGroupProtectionAllowEmailFromGuestUsers = $true + SiteAndGroupProtectionAllowFullAccess = $true + SiteAndGroupProtectionAllowLimitedAccess = $true + SiteAndGroupProtectionBlockAccess = $true + SiteAndGroupProtectionEnabled = $true + SiteAndGroupProtectionPrivacy = 'Private' + LocaleSettings = @( + MSFT_SCLabelLocaleSettings + { + LocaleKey = 'DisplayName' + LabelSettings = @( + MSFT_SCLabelSetting + { + Key = 'en-us' + Value = 'English Display Names' + } + MSFT_SCLabelSetting + { + Key = 'fr-fr' + Value = "Nom da'ffichage francais" + } + ) + } + MSFT_SCLabelLocaleSettings + { + LocaleKey = 'StopColor' + LabelSettings = @( + MSFT_SCLabelSetting + { + Key = 'en-us' + Value = 'RedGreen' + } + MSFT_SCLabelSetting + { + Key = 'fr-fr' + Value = 'Rouge' + } + ) + } + ) + AdvancedSettings = @( + MSFT_SCLabelSetting + { + Key = 'AllowedLevel' + Value = @('Sensitive', 'Classified') + } + MSFT_SCLabelSetting + { + Key = 'LabelStatus' + Value = 'Enabled' + } + ) + AutoLabelingSettings = MSFT_SCSLAutoLabelingSettings + { + Operator = 'And' + AutoApplyType = 'Recommend' + PolicyTip = 'My Perfect Test Tip!' + Groups = @( + MSFT_SCSLSensitiveInformationGroup + { + Name = 'Group1' + Operator = 'Or' + SensitiveInformationType = @( + MSFT_SCSLSensitiveInformationType + { + name = 'ABA Routing Number' + confidencelevel = 'High' + maxcount = -1 + mincount = 1 + } + ) + TrainableClassifier = @( + MSFT_SCSLTrainableClassifiers + { + name = 'Legal Affairs' + } + ) + } + MSFT_SCSLSensitiveInformationGroup + { + Name = 'Group2' + Operator = 'And' + SensitiveInformationType = @( + MSFT_SCSLSensitiveInformationType + { + name = 'All Full Names' + confidencelevel = 'High' + maxcount = 100 + mincount = 10 + } + ) + TrainableClassifier = @( + MSFT_SCSLTrainableClassifiers + { + name = 'Threat' + } + ) + } + ) + } + ParentId = 'Personal' + Ensure = 'Present' + Credential = $Credscredential + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCSensitivityLabel.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCSensitivityLabel.Tests.ps1 index 8aff682552..4a9fbac0d0 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCSensitivityLabel.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCSensitivityLabel.Tests.ps1 @@ -55,6 +55,13 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Start-Sleep -MockWith { } + Mock -CommandName Get-DlpSensitiveInformationType -MockWith { + return @( + [PSCustomObject]@{Name = 'ABA Routing Number'; Id = 'cb353f78-2b72-4c3c-8827-92ebe4f69fdf'; RulePackId = '00000000-0000-0000-0000-000000000000' }, + [PSCustomObject]@{Name = 'All Full Names'; Id = '50b8b56b-4ef8-44c2-a924-03374f5831ce'; RulePackId = '00000000-0000-0000-0000-000000000004' } + ) + } + # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { } @@ -82,6 +89,47 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Value = 'English DisplayName' } -ClientOnly) } -ClientOnly) + AutoLabelingSettings = New-CimInstance -ClassName MSFT_SCSLAutoLabelingSettings -Property @{ + Operator = 'And' + AutoApplyType = 'Recommend' + PolicyTip = 'My Perfect Test Tip!' + Groups = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationGroup -Property @{ + Name = 'Group1' + Operator = 'Or' + SensitiveInformationType = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationType -Property @{ + name = 'ABA Routing Number' + confidencelevel = 'High' + mincount = 1 + maxcount = -1 + } -ClientOnly + ) + TrainableClassifier = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLTrainableClassifiers -Property @{ + name = 'Legal Affairs' + } -ClientOnly + ) + } -ClientOnly + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationGroup -Property @{ + Name = 'Group2' + Operator = 'And' + SensitiveInformationType = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationType -Property @{ + name = 'All Full Names' + confidencelevel = 'High' + mincount = 10 + maxcount = 100 + } -ClientOnly + ) + TrainableClassifier = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLTrainableClassifiers -Property @{ + name = 'Legal Affairs' + } -ClientOnly + ) + } -ClientOnly + ) + } -ClientOnly Credential = $Credential Ensure = 'Present' } @@ -104,7 +152,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } - Context -Name 'Label already exists' -Fixture { + Context -Name 'Label already exists, but is incorrectly configured' -Fixture { BeforeAll { $testParams = @{ Name = 'TestLabel' @@ -126,6 +174,48 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } -ClientOnly) } -ClientOnly) + AutoLabelingSettings = New-CimInstance -ClassName MSFT_SCSLAutoLabelingSettings -Property @{ + Operator = 'And' + AutoApplyType = 'Recommend' + PolicyTip = 'My Perfect Test Tip!' + Groups = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationGroup -Property @{ + Name = 'Group1' + Operator = 'Or' + SensitiveInformationType = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationType -Property @{ + name = 'ABA Routing Number' + confidencelevel = 'High' + mincount = 1 + maxcount = -1 + } -ClientOnly + ) + TrainableClassifier = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLTrainableClassifiers -Property @{ + name = 'Legal Affairs' + } -ClientOnly + ) + } -ClientOnly + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationGroup -Property @{ + Name = 'Group2' + Operator = 'And' + SensitiveInformationType = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationType -Property @{ + name = 'All Full Names' + confidencelevel = 'High' + mincount = 1 + maxcount = 100 + } -ClientOnly + ) + TrainableClassifier = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLTrainableClassifiers -Property @{ + name = 'Legal Affairs' + } -ClientOnly + ) + } -ClientOnly + ) + } -ClientOnly + Credential = $Credential Ensure = 'Present' } @@ -138,11 +228,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { DisplayName = 'Test label' ParentId = 'MyLabel' Priority = '2' - Settings = '{"Key": "LabelStatus", - "Value": "Enabled"}' - LocaleSettings = '{"LocaleKey":"DisplayName", - "LabelSettings":[ - {"Key":"en-us","Value":"English Display Names"}]}' + Settings = '[LabelStatus, Enabled]' + LocaleSettings = '{"LocaleKey":"DisplayName","Settings":[{"Key":"en-us","Value":"English Display Names"}]}' + Conditions = '{"And":[{"Or":[{"Key":"CCSI","Value":"cb353f78-2b72-4c3c-8827-92ebe4f69fdf","Properties":null,"Settings":[{"Key":"mincount","Value":"1"},{"Key":"maxconfidence","Value":"100"},{"Key":"rulepackage","Value":"00000000-0000-0000-0000-000000000000"},{"Key":"name","Value":"ABA Routing Number"},{"Key":"groupname","Value":"Group1"},{"Key":"minconfidence","Value":"85"},{"Key":"maxcount","Value":"-1"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"confidencelevel","Value":"High"},{"Key":"autoapplytype","Value":"Recommend"}]},{"Key":"ContentMatchesModule","Value":"ba38aa0f-8c86-4c73-87db-95147a0f4420","Properties":null,"Settings":[{"Key":"name","Value":"Legal Affairs"},{"Key":"groupname","Value":"Group1"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"autoapplytype","Value":"Recommend"}]}]},{"And":[{"Key":"CCSI","Value":"50b8b56b-4ef8-44c2-a924-03374f5831ce","Properties":null,"Settings":[{"Key":"mincount","Value":"10"},{"Key":"maxconfidence","Value":"100"},{"Key":"rulepackage","Value":"00000000-0000-0000-0000-000000000004"},{"Key":"name","Value":"All Full Names"},{"Key":"groupname","Value":"Group2"},{"Key":"minconfidence","Value":"85"},{"Key":"maxcount","Value":"100"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"confidencelevel","Value":"High"},{"Key":"autoapplytype","Value":"Recommend"}]},{"Key":"ContentMatchesModule","Value":"ba38aa0f-8c86-4c73-87db-95147a0f4420","Properties":null,"Settings":[{"Key":"name","Value":"Legal Affairs"},{"Key":"groupname","Value":"Group2"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"autoapplytype","Value":"Recommend"}]}]}]}' } } } @@ -160,6 +248,100 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } + Context -Name 'Label already exists and is correctly configured' -Fixture { + BeforeAll { + $testParams = @{ + Name = 'TestLabel' + Comment = 'This is a test label' + ToolTip = 'Test tool tip' + DisplayName = 'Test label' + ParentId = 'MyLabel' + + AdvancedSettings = (New-CimInstance -ClassName MSFT_SCLabelSetting -Property @{ + Key = 'LabelStatus' + Value = 'Enabled' + } -ClientOnly) + + LocaleSettings = (New-CimInstance -ClassName MSFT_SCLabelLocaleSettings -Property @{ + LocaleKey = 'DisplayName' + LabelSettings = (New-CimInstance -ClassName MSFT_SCLabelSetting -Property @{ + Key = 'en-us' + Value = 'English Display Names' + } -ClientOnly) + } -ClientOnly) + + AutoLabelingSettings = New-CimInstance -ClassName MSFT_SCSLAutoLabelingSettings -Property @{ + Operator = 'And' + AutoApplyType = 'Recommend' + PolicyTip = 'My Perfect Test Tip!' + Groups = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationGroup -Property @{ + Name = 'Group1' + Operator = 'Or' + SensitiveInformationType = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationType -Property @{ + name = 'ABA Routing Number' + confidencelevel = 'High' + mincount = 1 + maxcount = -1 + } -ClientOnly + ) + TrainableClassifier = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLTrainableClassifiers -Property @{ + name = 'Legal Affairs' + } -ClientOnly + ) + } -ClientOnly + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationGroup -Property @{ + Name = 'Group2' + Operator = 'And' + SensitiveInformationType = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLSensitiveInformationType -Property @{ + name = 'All Full Names' + confidencelevel = 'High' + mincount = 10 + maxcount = 100 + } -ClientOnly + ) + TrainableClassifier = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_SCSLTrainableClassifiers -Property @{ + name = 'Legal Affairs' + } -ClientOnly + ) + } -ClientOnly + ) + } -ClientOnly + + Credential = $Credential + Ensure = 'Present' + } + + Mock -CommandName Get-Label -MockWith { + return @{ + Name = 'TestLabel' + Comment = 'This is a test label' + ToolTip = 'Test tool tip' + DisplayName = 'Test label' + ParentId = 'MyLabel' + Priority = '2' + Settings = '[LabelStatus, Enabled]' + LocaleSettings = '{"LocaleKey":"DisplayName","Settings":[{"Key":"en-us","Value":"English Display Names"}]}' + Conditions = '{"And":[{"Or":[{"Key":"CCSI","Value":"cb353f78-2b72-4c3c-8827-92ebe4f69fdf","Properties":null,"Settings":[{"Key":"mincount","Value":"1"},{"Key":"maxconfidence","Value":"100"},{"Key":"rulepackage","Value":"00000000-0000-0000-0000-000000000000"},{"Key":"name","Value":"ABA Routing Number"},{"Key":"groupname","Value":"Group1"},{"Key":"minconfidence","Value":"85"},{"Key":"maxcount","Value":"-1"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"confidencelevel","Value":"High"},{"Key":"autoapplytype","Value":"Recommend"}]},{"Key":"ContentMatchesModule","Value":"ba38aa0f-8c86-4c73-87db-95147a0f4420","Properties":null,"Settings":[{"Key":"name","Value":"Legal Affairs"},{"Key":"groupname","Value":"Group1"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"autoapplytype","Value":"Recommend"}]}]},{"And":[{"Key":"CCSI","Value":"50b8b56b-4ef8-44c2-a924-03374f5831ce","Properties":null,"Settings":[{"Key":"mincount","Value":"10"},{"Key":"maxconfidence","Value":"100"},{"Key":"rulepackage","Value":"00000000-0000-0000-0000-000000000004"},{"Key":"name","Value":"All Full Names"},{"Key":"groupname","Value":"Group2"},{"Key":"minconfidence","Value":"85"},{"Key":"maxcount","Value":"100"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"confidencelevel","Value":"High"},{"Key":"autoapplytype","Value":"Recommend"}]},{"Key":"ContentMatchesModule","Value":"ba38aa0f-8c86-4c73-87db-95147a0f4420","Properties":null,"Settings":[{"Key":"name","Value":"Legal Affairs"},{"Key":"groupname","Value":"Group2"},{"Key":"policytip","Value":"My Perfect Test Tip!"},{"Key":"autoapplytype","Value":"Recommend"}]}]}]}' + } + } -ParameterFilter { $Identity -eq 'TestLabel' } + + Mock -CommandName Get-Label -MockWith { + return @{ + Name = 'MyLabel' + } + } -ParameterFilter { $Identity -eq 'MyLabel' } + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + Context -Name 'Label should not exist' -Fixture { BeforeAll { $testParams = @{ diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 36fb0879a9..ed4b425814 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -64126,6 +64126,31 @@ function Get-DlpComplianceRule $IncludeExecutionRuleGuids ) } +function Get-DlpSensitiveInformationType +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $IncludeElements, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IncludeDetails, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $Organization, + + [Parameter()] + [System.Object] + $Capability + ) +} function Get-FilePlanPropertyAuthority { [CmdletBinding()] From 3181d64b9e4696ba128580adf70864836833c0f8 Mon Sep 17 00:00:00 2001 From: Yorick Kuijs Date: Wed, 18 Sep 2024 13:09:41 +0200 Subject: [PATCH 219/465] Fixes SCAutoSensitivityLabelRule - Setting error #4641 --- CHANGELOG.md | 4 ++++ .../MSFT_SCAutoSensitivityLabelRule.psm1 | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45cec11ff8..6490acb01b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,10 @@ * IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10 * Add missing `AccessTokens` parameter to `Export-TargetResource` FIXES [#5034](https://github.com/microsoft/Microsoft365DSC/issues/5034) +* SCAutoSensitivityLabelRule + * Fixed issue with incorrectly applying HeaderMatchesPatterns, even when + parameter wasn't specified. + FIXES [#4641](https://github.com/microsoft/Microsoft365DSC/issues/4641) * SCRoleGroup * Fixes an issue with creation without specifying Displayname * Fixes an issue with Drifts because of returned Role format diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCAutoSensitivityLabelRule/MSFT_SCAutoSensitivityLabelRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCAutoSensitivityLabelRule/MSFT_SCAutoSensitivityLabelRule.psm1 index edabc166c2..22ef5eca5a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCAutoSensitivityLabelRule/MSFT_SCAutoSensitivityLabelRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCAutoSensitivityLabelRule/MSFT_SCAutoSensitivityLabelRule.psm1 @@ -631,9 +631,9 @@ function Set-TargetResource $CurrentRule = Get-TargetResource @PSBoundParameters - $HeaderMatchesPatternsValue = @{} if ($null -ne $HeaderMatchesPatterns -and $null -ne $HeaderMatchesPatterns.Name) { + $HeaderMatchesPatternsValue = @{} $HeaderMatchesPatternsValue.Add($HeaderMatchesPatterns.Name, $HeaderMatchesPatterns.Values) } if (('Present' -eq $Ensure) -and ('Absent' -eq $CurrentRule.Ensure)) From c308b66316162131ddad1c4161d6abaf7ce8f707 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Wed, 18 Sep 2024 17:02:57 +0530 Subject: [PATCH 220/465] minor fix --- .../DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 0d220f65cf..eb16df2b5b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -192,7 +192,7 @@ function Get-TargetResource $myIdTokenClaim.Add('Name', $currentIdTokenClaim.Name) $myIdTokenClaim.Add('Source', $currentIdTokenClaim.Source) - $currentIdTokenClaim += $myIdTokenClaim + $complexIdTokenClaims += $myIdTokenClaim } $complexOptionalClaims.Add('IdToken',$complexIdTokenClaims) From 3f5b08db548f15984b81b7fe5d558b8e494ca7b9 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 18 Sep 2024 22:08:38 -0400 Subject: [PATCH 221/465] Fixes for Unit Tests --- .../MSFT_SCInsiderRiskEntityList.psm1 | 288 +++++++++++++++--- .../MSFT_SCInsiderRiskEntityList.schema.mof | 9 +- .../MSFT_SCInsiderRiskEntityList/readme.md | 2 +- .../settings.json | 22 +- .../SCInsiderRiskEntityList/1-Create.ps1 | 14 +- .../SCInsiderRiskEntityList/2-Update.ps1 | 14 +- .../SCInsiderRiskEntityList/3-Remove.ps1 | 14 +- .../Modules/M365DSCReport.psm1 | 9 +- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 49 ++- ...ft365DSC.SCInsiderRiskEntityList.Tests.ps1 | 115 +++++-- Tests/Unit/Stubs/Microsoft365.psm1 | 92 ++++++ .../Microsoft365DSC.ResourceName.Tests.ps1 | 1 + 12 files changed, 533 insertions(+), 96 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 index 8ab587b2aa..a0d5e92ed3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.psm1 @@ -41,7 +41,7 @@ function Get-TargetResource $SensitiveInformationTypes, [Parameter()] - [System.Management.Infrastructure.CimInstance[]] + [Microsoft.Management.Infrastructure.CimInstance[]] $Sites, [Parameter()] @@ -62,7 +62,7 @@ function Get-TargetResource [Parameter()] [System.String[]] - $ExcludedFilePathGroup, + $ExcludedFilePathGroups, [Parameter()] [System.String[]] @@ -209,7 +209,12 @@ function Get-TargetResource foreach ($entity in $instance.Entities) { $entity = ConvertFrom-Json $entity - $SiteValues += $entity.Url + $site = @{ + Url = $entity.Url + Name = $entity.Name + Guid = $entity.Guid + } + $SiteValues += $site } } @@ -220,7 +225,7 @@ function Get-TargetResource foreach ($entity in $instance.Entities) { $entity = ConvertFrom-Json $entity - $SiteValues += $entity.Url + $TrainableClassifierValues += $entity.Guid } } @@ -233,7 +238,7 @@ function Get-TargetResource { $entity = ConvertFrom-Json $entity $group = Get-InsiderRiskEntityList -Identity $entity.GroupId - $excludedKeywordGroupValue += $group.DisplayName + $excludedKeywordGroupValue += $group.Name } } @@ -246,7 +251,7 @@ function Get-TargetResource { $entity = ConvertFrom-Json $entity $group = Get-InsiderRiskEntityList -Identity $entity.GroupId - $exceptionKeywordGroupValue += $group.DisplayName + $exceptionKeywordGroupValue += $group.Name } } @@ -259,7 +264,7 @@ function Get-TargetResource { $entity = ConvertFrom-Json $entity $group = Get-InsiderRiskEntityList -Identity $entity.GroupId - $excludedClassifierGroupValue += $group.DisplayName + $excludedClassifierGroupValue += $group.Name } } @@ -272,12 +277,12 @@ function Get-TargetResource { $entity = ConvertFrom-Json $entity $group = Get-InsiderRiskEntityList -Identity $entity.GroupId - $excludedDomainGroupValue += $group.DisplayName + $excludedDomainGroupValue += $group.Name } } # Global Exclusions - Excluded File Path Groups - $excludedFilePathGroupValue = @() + $ExcludedFilePathGroupsValue = @() if ($instance.Name -eq 'IrmXSGFilePaths') { $entities = $instance.Entities @@ -285,7 +290,7 @@ function Get-TargetResource { $entity = ConvertFrom-Json $entity $group = Get-InsiderRiskEntityList -Identity $entity.GroupId - $excludedFilePathGroupValue += $group.DisplayName + $ExcludedFilePathGroupsValue += $group.Name } } @@ -298,7 +303,7 @@ function Get-TargetResource { $entity = ConvertFrom-Json $entity $group = Get-InsiderRiskEntityList -Identity $entity.GroupId - $excludedSiteGroupValue += $group.DisplayName + $excludedSiteGroupValue += $group.Name } } @@ -311,7 +316,7 @@ function Get-TargetResource { $entity = ConvertFrom-Json $entity $group = Get-InsiderRiskEntityList -Identity $entity.GroupId - $excludedSITGroupValue += $group.DisplayName + $excludedSITGroupValue += $group.Name } } @@ -324,7 +329,7 @@ function Get-TargetResource { $entity = ConvertFrom-Json $entity $group = Get-InsiderRiskEntityList -Identity $entity.GroupId - $excludedFileTypeGroupValue += $group.DisplayName + $excludedFileTypeGroupValue += $group.Name } } @@ -339,12 +344,12 @@ function Get-TargetResource Keywords = $KeywordValues SensitiveInformationTypes = $SITValues Sites = $SiteValues - #TrainableClassifiers = + TrainableClassifiers = $TrainableClassifierValues ExcludedKeyworkGroups = $excludedKeywordGroupValue ExceptionKeyworkGroups = $exceptionKeywordGroupValue ExcludedClassifierGroups = $excludedClassifierGroupValue ExcludedDomainGroups = $excludedDomainGroupValue - ExcludedFilePathGroup = $excludedFilePathGroupValue + ExcludedFilePathGroups = $ExcludedFilePathGroupsValue ExcludedSiteGroups = $excludedSiteGroupValue ExcludedSensitiveInformationTypeGroups = $excludedSITGroupValue ExcludedFileTypeGroups = $excludedFileTypeGroupValue @@ -412,7 +417,7 @@ function Set-TargetResource $SensitiveInformationTypes, [Parameter()] - [System.Management.Infrastructure.CimInstance[]] + [Microsoft.Management.Infrastructure.CimInstance[]] $Sites, [Parameter()] @@ -433,7 +438,7 @@ function Set-TargetResource [Parameter()] [System.String[]] - $ExcludedFilePathGroup, + $ExcludedFilePathGroups, [Parameter()] [System.String[]] @@ -481,7 +486,6 @@ function Set-TargetResource $AccessTokens ) - Write-Verbose -Message "Start Set-TargetResource" #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -496,8 +500,6 @@ function Set-TargetResource $currentInstance = Get-TargetResource @PSBoundParameters - $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters - # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { @@ -577,21 +579,39 @@ function Set-TargetResource $value = @() foreach ($site in $Sites) { - $value += "{`"Url`":`"$($site.Url)`";`"Name`":`"$($site.Name)`";`"Guid`":`"$($site.Guid)`"}" + $value += "{`"Url`":`"$($site.Url.ToString())`",`"Name`":`"$($site.Name.ToString())`",`"Guid`":`"$((New-GUID).ToString())`"}" } - Write-Verbose -Message "Creating new Site Group {$Name} with values {$($value -join ',')}" + Write-Verbose -Message "Creating new Site Group {$Name} with values {$($value)}" New-InsiderRiskEntityList -Type 'CustomSiteLists' ` -Name $Name ` -DisplayName $DisplayName ` -Description $Description ` -Entities $value | Out-Null } + elseif ($ListType -eq 'CustomMLClassifierTypeLists') + { + $value = @() + foreach ($clasifier in $TrainableClassifiers) + { + $value += "{`"Guid`":`"$($classifier)`"}" + } + Write-Verbose -Message "Creating new Trainable classifier Group {$Name} with values {$($value)}" + New-InsiderRiskEntityList -Type 'CustomMLClassifierTypeLists' ` + -Name $Name ` + -DisplayName $DisplayName ` + -Description $Description ` + -Entities $value | Out-Null + } + else + { + throw "Couldn't not identify operation to perform on {$Name}" + } } # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { # Update Domain Group - if ($ListType -eq 'CustomDomainLists') + if ($ListType -eq 'CustomDomainLists' -or $Name -eq 'IrmWhitelistDomains') { $entitiesToAdd = @() $entitiesToRemove = @() @@ -621,7 +641,8 @@ function Set-TargetResource -RemoveEntities $entitiesToRemove | Out-Null } # Update File Path Group - elseif ($ListType -eq 'CustomFilePathRegexLists') + elseif ($ListType -eq 'CustomFilePathRegexLists' -or $Name -eq 'IrmCustomExWinFilePaths' -or ` + $Name -eq 'IrmDsbldSysExWinFilePaths') { $entitiesToAdd = @() $entitiesToRemove = @() @@ -677,7 +698,7 @@ function Set-TargetResource -RemoveEntities $entitiesToRemove | Out-Null } # Update Keywords Group - elseif ($ListType -eq 'CustomKeywordLists') + elseif ($ListType -eq 'CustomKeywordLists' -or $Name -eq 'IrmExcludedKeywords' -or $Name -eq 'IrmNotExcludedKeywords') { $entitiesToAdd = @() $entitiesToRemove = @() @@ -705,7 +726,8 @@ function Set-TargetResource -RemoveEntities $entitiesToRemove | Out-Null } # Update SIT Group - elseif ($ListType -eq 'CustomSensitiveInformationTypeLists') + elseif ($ListType -eq 'CustomSensitiveInformationTypeLists' -or $Name -eq 'IrmCustomExSensitiveTypes ' -or ` + $Name -eq 'IrmDsbldSysExSensitiveTypes') { $entitiesToAdd = @() $entitiesToRemove = @() @@ -733,8 +755,9 @@ function Set-TargetResource -RemoveEntities $entitiesToRemove | Out-Null } # Update Sites Group - elseif ($ListType -eq 'CustomSiteLists') + elseif ($ListType -eq 'CustomSiteLists' -or $Name -eq 'IrmExcludedSites') { + Write-Verbose -Message "Calculating the difference in the Site list." $entitiesToAdd = @() $entitiesToRemove = @() $differences = Compare-Object -ReferenceObject $currentInstance.Sites.Url -DifferenceObject $Sites.Url @@ -743,12 +766,46 @@ function Set-TargetResource if ($diff.SideIndicator -eq '=>') { $entry = $Sites | Where-Object -FilterScript {$_.Url -eq $diff.InputObject} - $entitiesToAdd += "{`"Url`":`"$($entry.Url)`";`"Name`":`"$($entry.Name)`";`"Guid`":`"$($entry.Guid)`"}" + $guid = $entry.Guid + if ([System.String]::IsNullOrEmpty($guid)) + { + $guid = (New-Guid).ToString() + } + $entitiesToAdd += "{`"Url`":`"$($entry.Url)`",`"Name`":`"$($entry.Name)`",`"Guid`":`"$($guid)`"}" } else { $entry = $currentInstance.Sites | Where-Object -FilterScript {$_.Url -eq $diff.InputObject} - $entitiesToRemove += "{`"Url`":`"$($entry.Url)`";`"Name`":`"$($entry.Name)`";`"Guid`":`"$($entry.Guid)`"}" + $entitiesToRemove += "{`"Url`":`"$($entry.Url)`",`"Name`":`"$($entry.Name)`",`"Guid`":`"$($entry.Guid)`"}" + } + } + + Write-Verbose -Message "Updating Sites Group {$Name}" + Write-Verbose -Message "Adding entities: $($entitiesToAdd -join ',')" + Write-Verbose -Message "Removing entities: $($entitiesToRemove -join ',')" + + Set-InsiderRiskEntityList -Identity $Name ` + -DisplayName $DisplayName ` + -Description $Description ` + -AddEntities $entitiesToAdd ` + -RemoveEntities $entitiesToRemove | Out-Null + } + # Update Trainable Classifiers Group + elseif ($ListType -eq 'CustomMLClassifierTypeLists' -or $Name -eq 'IrmCustomExMLClassifiers' -or ` + $Name -eq 'IrmDsbldSysExMLClassifiers') + { + $entitiesToAdd = @() + $entitiesToRemove = @() + $differences = Compare-Object -ReferenceObject $currentInstance.Sites.Url -DifferenceObject $Sites.Url + foreach ($diff in $differences) + { + if ($diff.SideIndicator -eq '=>') + { + $entitiesToAdd += "{`"Guid`":`"$($diff.InputObject)`"}" + } + else + { + $entitiesToRemove += "{`"Guid`":`"$($diff.InputObject)`"}" } } @@ -762,12 +819,62 @@ function Set-TargetResource -AddEntities $entitiesToAdd ` -RemoveEntities $entitiesToRemove | Out-Null } + + <################## Group Exclusions #############> + if ($null -ne $ExcludedDomainGroups -and $ExcludedDomainGroups.Length -gt 0) + { + Set-M365DSCSCInsiderRiskExclusionGroup -CurrentValues $currentInstance.ExcludedDomainGroups ` + -DesiredValues $ExcludedDomainGroups ` + -Name 'IrmXSGDomains' + } + elseif ($null -ne $ExcludedFilePathGroups -and $ExcludedFilePathGroups.Length -gt 0) + { + Set-M365DSCSCInsiderRiskExclusionGroup -CurrentValues $currentInstance.ExcludedFilePathGroups ` + -DesiredValues $ExcludedFilePathGroups ` + -Name 'IrmXSGFilePaths' + } + elseif ($null -ne $ExcludedFileTypeGroups -and $ExcludedFileTypeGroups.Length -gt 0) + { + Set-M365DSCSCInsiderRiskExclusionGroup -CurrentValues $currentInstance.ExcludedFileTypeGroups ` + -DesiredValues $ExcludedFileTypeGroups ` + -Name 'IrmXSGFiletypes' + } + elseif ($null -ne $ExceptionKeyworkGroups -and $ExceptionKeyworkGroups.Length -gt 0) + { + Set-M365DSCSCInsiderRiskExclusionGroup -CurrentValues $currentInstance.ExceptionKeyworkGroups ` + -DesiredValues $ExceptionKeyworkGroups ` + -Name 'IrmXSGExcludedKeywords ' + } + elseif ($null -ne $ExcludedKeyworkGroups -and $ExcludedKeyworkGroups.Length -gt 0) + { + Set-M365DSCSCInsiderRiskExclusionGroup -CurrentValues $currentInstance.ExcludedKeyworkGroups ` + -DesiredValues $ExcludedKeyworkGroups ` + -Name 'IrmXSGExcludedKeywords ' + } + elseif ($null -ne $ExcludedSensitiveInformationTypeGroups -and $ExcludedSensitiveInformationTypeGroups.Length -gt 0) + { + Set-M365DSCSCInsiderRiskExclusionGroup -CurrentValues $currentInstance.ExcludedSensitiveInformationTypeGroups ` + -DesiredValues $ExcludedSensitiveInformationTypeGroups ` + -Name 'IrmXSGSensitiveInfoTypes ' + } + elseif ($null -ne $ExcludedSiteGroups -and $ExcludedSiteGroups.Length -gt 0) + { + Set-M365DSCSCInsiderRiskExclusionGroup -CurrentValues $currentInstance.ExcludedSiteGroups ` + -DesiredValues $ExcludedSiteGroups ` + -Name 'IrmXSGSites ' + } + elseif ($null -ne $ExcludedClassifierGroups -and $ExcludedClassifierGroups.Length -gt 0) + { + Set-M365DSCSCInsiderRiskExclusionGroup -CurrentValues $currentInstance.ExcludedClassifierGroups ` + -DesiredValues $ExcludedClassifierGroups ` + -Name 'IrmXSGMLClassifierTypes ' + } } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - ##TODO - Replace by the Remove cmdlet for the resource - Remove-cmdlet @SetParameters + Write-Verbose -Message "Removing group {$Name}" + Remove-InsiderRiskEntityList -Identity $Name -ForceDeletion } } @@ -814,7 +921,7 @@ function Test-TargetResource $SensitiveInformationTypes, [Parameter()] - [System.Management.Infrastructure.CimInstance[]] + [Microsoft.Management.Infrastructure.CimInstance[]] $Sites, [Parameter()] @@ -835,7 +942,7 @@ function Test-TargetResource [Parameter()] [System.String[]] - $ExcludedFilePathGroup, + $ExcludedFilePathGroups, [Parameter()] [System.String[]] @@ -897,7 +1004,6 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() - $ValuesToCheck.Remove('Name') | Out-Null Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" @@ -1007,6 +1113,19 @@ function Export-TargetResource } $Results = Get-TargetResource @Params + + if ($null -ne $Results.Domains -and $Results.Domains.Length -gt 0 -and ` + ($Results.ListType -eq 'CustomDomainLists' -or $Results.ListType -eq 'DomainLists')) + { + $Results.Domains = ConvertTo-M365DSCSCInsiderRiskDomainToString -Domains $Results.Domains + } + + if ($null -ne $Results.Sites -and $Results.Sites.Length -gt 0 -and ` + ($Results.ListType -eq 'CustomSiteLists' -or $Results.ListType -eq 'SiteLists')) + { + $Results.Sites = ConvertTo-M365DSCSCInsiderRiskSiteToString -Sites $Results.Sites + } + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` -Results $Results @@ -1015,6 +1134,19 @@ function Export-TargetResource -ModulePath $PSScriptRoot ` -Results $Results ` -Credential $Credential + + if ($null -ne $Results.Domains -and ` + ($Results.ListType -eq 'CustomDomainLists' -or $Results.ListType -eq 'DomainLists')) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Domains' -IsCIMArray $true + } + + if ($null -ne $Results.Sites -and ` + ($Results.ListType -eq 'CustomSiteLists' -or $Results.ListType -eq 'SiteLists')) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Sites' -IsCIMArray $true + } + $dscContent += $currentDSCBlock Save-M365DSCPartialExport -Content $currentDSCBlock ` -FileName $Global:PartialExportFileName @@ -1037,4 +1169,92 @@ function Export-TargetResource } } +function ConvertTo-M365DSCSCInsiderRiskDomainToString +{ + [CmdletBinding()] + [OutputType([System.String])] + param( + [Parameter(Mandatory=$true)] + [System.Object[]] + $Domains + ) + + $content = "@(" + foreach ($domain in $Domains) + { + $content += "MSFT_SCInsiderRiskEntityListDomain`r`n" + $content += "{`r`n" + $content += " Dmn = '$($domain.Dmn)'`r`n" + $content += " isMLSubDmn = `$$($domain.isMLSubDmn)`r`n" + $content += "}`r`n" + } + $content += ")" + return $content +} + +function ConvertTo-M365DSCSCInsiderRiskSiteToString +{ + [CmdletBinding()] + [OutputType([System.String])] + param( + [Parameter(Mandatory=$true)] + [System.Object[]] + $Sites + ) + + $content = "@(" + foreach ($site in $Sites) + { + $content += "MSFT_SCInsiderRiskEntityListSite`r`n" + $content += "{`r`n" + $content += " Url = '$($site.Url)'`r`n" + $content += " Name = '$($site.Name)'`r`n" + $content += " Guid = '$($site.Guid)'`r`n" + $content += "}`r`n" + } + $content += ")" + return $content +} + +function Set-M365DSCSCInsiderRiskExclusionGroup +{ + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [System.String[]] + $CurrentValues, + + [Parameter(Mandatory = $true)] + [System.String[]] + $DesiredValues, + + [Parameter(Mandatory = $true)] + [System.String] + $Name + ) + + $entitiesToAdd = @() + $entitiesToRemove = @() + $differences = Compare-Object -ReferenceObject $CurrentValues -DifferenceObject $DesiredValues + foreach ($diff in $differences) + { + if ($diff.SideIndicator -eq '=>') + { + $entitiesToAdd += "{`"GroupId`":`"$($diff.InputObject)`"}" + } + else + { + $entitiesToRemove += "{`"GroupId`":`"$($diff.InputObject)`"}" + } + } + + Write-Verbose -Message "Updating Group Exclusions for {$Name}" + Write-Verbose -Message "Adding entities: $($entitiesToAdd -join ',')" + Write-Verbose -Message "Removing entities: $($entitiesToRemove -join ',')" + + Set-InsiderRiskEntityList -Identity $Name ` + -AddEntities $entitiesToAdd ` + -RemoveEntities $entitiesToRemove | Out-Null +} + Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof index 7aec32fdc3..dbf3fcf00f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof @@ -3,14 +3,13 @@ class MSFT_SCInsiderRiskEntityListDomain { [Required, Description("Domain name.")] String Dmn; [Write, Description("Defines if the entry should include multi-level subdomains or not.")] Boolean isMLSubDmn; - [Write, Description("Type of the Sensitive Information label")] String type; }; [ClassVersion("1.0.0")] class MSFT_SCInsiderRiskEntityListSite { - [Required, Description("Url of the site.")] String SiteUrl; - [Write, Description("Name of the site.")] String SiteName; - [Write, Description("Unique identifier of the site.")] String SiteGuid; + [Required, Description("Url of the site.")] String Url; + [Write, Description("Name of the site.")] String Name; + [Write, Description("Unique identifier of the site.")] String Guid; }; [ClassVersion("1.0.0.0"), FriendlyName("SCInsiderRiskEntityList")] class MSFT_SCInsiderRiskEntityList : OMI_BaseResource @@ -29,7 +28,7 @@ class MSFT_SCInsiderRiskEntityList : OMI_BaseResource [Write, Description("")] String ExceptionKeyworkGroups[]; [Write, Description("")] String ExcludedClassifierGroups[]; [Write, Description("")] String ExcludedDomainGroups[]; - [Write, Description("")] String ExcludedFilePathGroup[]; + [Write, Description("")] String ExcludedFilePathGroups[]; [Write, Description("")] String ExcludedFileTypeGroups[]; [Write, Description("")] String ExcludedKeyworkGroups[]; [Write, Description("")] String ExcludedSensitiveInformationTypeGroups[]; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/readme.md index 1a24877790..75a6e455f5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/readme.md @@ -3,4 +3,4 @@ ## Description -##TODO - Provide a short description of what the resource is set to configure. +Configures settings for Insider Risk in Purview. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/settings.json index c44468a9df..98c729187d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/settings.json @@ -1,13 +1,9 @@ { "resourceName": "SCInsiderRiskEntityList", - "description": "Description of what the resource is about.", + "description": "Configures settings for Insider Risk in Purview.", "roles": { - "read": [ - "Role" - ], - "update": [ - "Role" - ] + "read": [], + "update": [] }, "permissions": { "graph": { @@ -16,16 +12,8 @@ "update": [] }, "application": { - "read": [ - { - "name": "Permission for Monitoring and Export" - } - ], - "update": [ - { - "name": "Permission for deploying" - } - ] + "read": [], + "update": [] } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/1-Create.ps1 index b516274848..b1d724763e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/1-Create.ps1 @@ -21,6 +21,18 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + SCInsiderRiskEntityList "SCInsiderRiskEntityList-MyFileType" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Description = "Test file type"; + DisplayName = "MyFileType"; + Ensure = "Present"; + FileTypes = @(".exe",".cmd",".bat"); + Keywords = @(); + ListType = "CustomFileTypeLists"; + Name = "MyFileTypeList"; + TenantId = $OrganizationName; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/2-Update.ps1 index b516274848..c230194a30 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/2-Update.ps1 @@ -21,6 +21,18 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + SCInsiderRiskEntityList "SCInsiderRiskEntityList-MyFileType" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Description = "Test file type"; + DisplayName = "MyFileType"; + Ensure = "Present"; + FileTypes = @(".exe",".txt",".bat"); # Drfit + Keywords = @(); + ListType = "CustomFileTypeLists"; + Name = "MyFileTypeList"; + TenantId = $OrganizationName; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/3-Remove.ps1 index b516274848..cf49044588 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskEntityList/3-Remove.ps1 @@ -21,6 +21,18 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + SCInsiderRiskEntityList "SCInsiderRiskEntityList-MyFileType" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Description = "Test file type"; + DisplayName = "MyFileType"; + Ensure = "Absent"; + FileTypes = @(".exe",".cmd",".bat"); + Keywords = @(); + ListType = "CustomFileTypeLists"; + Name = "MyFileTypeList"; + TenantId = $OrganizationName; + } } } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 index e10606ca0c..c7209dbf4d 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 @@ -1169,7 +1169,7 @@ function Compare-M365DSCConfigurations This function gets the key parameter for the specified CIMInstance .Functionality -Internal, Hidden +Public #> function Get-M365DSCCIMInstanceKey { @@ -1223,6 +1223,10 @@ function Get-M365DSCCIMInstanceKey { $primaryKey = 'dataType' } + elseif ($CIMInstance.ContainsKey("Dmn")) + { + $primaryKey = 'Dmn' + } return $primaryKey } @@ -1931,5 +1935,6 @@ function Initialize-M365DSCReporting Export-ModuleMember -Function @( 'Compare-M365DSCConfigurations', 'New-M365DSCDeltaReport', - 'New-M365DSCReportFromConfiguration' + 'New-M365DSCReportFromConfiguration', + 'Get-M365DSCCIMInstanceKey' ) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index ac59719bcf..d2baffcc43 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -462,7 +462,7 @@ function Compare-PSCustomObjectArrays Desired = $DesiredEntry.$KeyProperty Current = $null } - $DriftedProperties += $DesiredEntry + $DriftedProperties += $result } else { @@ -496,6 +496,53 @@ function Compare-PSCustomObjectArrays } } + foreach ($currentEntry in $currentValues) + { + $KeyProperty = Get-M365DSCCIMInstanceKey -CIMInstance $currentEntry + + $EquivalentEntryInDesired = $DesiredValues | Where-Object -FilterScript { $_.$KeyProperty -eq $currentEntry.$KeyProperty } + if ($null -eq $EquivalentEntryInDesired) + { + $result = @{ + Property = $currentEntry + PropertyName = $KeyProperty + Desired = $currentEntry.$KeyProperty + Current = $null + } + $DriftedProperties += $result + } + else + { + foreach ($property in $Properties) + { + $propertyName = $property.Name + + if ((-not [System.String]::IsNullOrEmpty($currentEntry.$PropertyName) -and -not [System.String]::IsNullOrEmpty($EquivalentEntryInDesired.$PropertyName)) -and ` + $currentEntry.$PropertyName -ne $EquivalentEntryInDesired.$PropertyName) + { + $drift = $true + if ($currentEntry.$PropertyName.GetType().Name -eq 'String' -and $currentEntry.$PropertyName.Contains('$OrganizationName')) + { + if ($currentEntry.$PropertyName.Split('@')[0] -eq $EquivalentEntryInDesired.$PropertyName.Split('@')[0]) + { + $drift = $false + } + } + if ($drift) + { + $result = @{ + Property = $currentEntry + PropertyName = $PropertyName + Desired = $currentEntry.$PropertyName + Current = $EquivalentEntryInDesired.$PropertyName + } + $DriftedProperties += $result + } + } + } + } + } + return $DriftedProperties } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskEntityList.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskEntityList.Tests.ps1 index 20857e0393..8fb7fa383d 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskEntityList.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskEntityList.Tests.ps1 @@ -35,7 +35,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets + Mock -CommandName Set-InsiderRiskEntityList -MockWith { + } + + Mock -CommandName New-InsiderRiskEntityList -MockWith { + } + + Mock -CommandName Remove-InsiderRiskEntityList -MockWith { + } # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { @@ -47,13 +54,16 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + Description = "Test Description"; + DisplayName = "TestFileTypeList"; + Ensure = "Present"; + FileTypes = @(".exe",".cmd",".bat"); + ListType = "CustomFileTypeLists"; + Name = "TestName"; + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-InsiderRiskEntityList -MockWith { return $null } } @@ -65,23 +75,34 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should create a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one - Should -Invoke -CommandName New-Cmdlet -Exactly 1 + Set-TargetResource @testParams + Should -Invoke -CommandName New-InsiderRiskEntityList -Exactly 1 } } Context -Name "The instance exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Absent' - Credential = $Credential; + Description = "Test Description"; + DisplayName = "TestFileTypeList"; + Ensure = "Absent"; + FileTypes = @(".exe",".cmd",".bat"); + ListType = "CustomFileTypeLists"; + Name = "TestName"; + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-InsiderRiskEntityList -MockWith { return @{ - + ListType = 'CustomFileTypeLists' + Name = 'TestName'; + DisplayName = "TestFileTypeList"; + Description = "Test Description"; + Entities = @( + '{"Ext":".exe"}', + '{"Ext":".cmd"}', + '{"Ext":".bat"}' + ) } } } @@ -93,23 +114,34 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should remove the instance from the Set method' { - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-InsiderRiskEntityList -Exactly 1 } } Context -Name "The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + Description = "Test Description"; + DisplayName = "TestFileTypeList"; + Ensure = "Present"; + FileTypes = @(".exe",".cmd",".bat"); + ListType = "CustomFileTypeLists"; + Name = "TestName"; + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-InsiderRiskEntityList -MockWith { return @{ - + ListType = 'CustomFileTypeLists' + Name = 'TestName'; + DisplayName = "TestFileTypeList"; + Description = "Test Description"; + Entities = @( + '{"Ext":".exe"}', + '{"Ext":".cmd"}', + '{"Ext":".bat"}' + ) } } } @@ -122,15 +154,26 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + Description = "Test Description"; + DisplayName = "TestFileTypeList"; + Ensure = "Present"; + FileTypes = @(".exe",".cmd",".bat"); + ListType = "CustomFileTypeLists"; + Name = "TestName"; + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-InsiderRiskEntityList -MockWith { return @{ - + ListType = 'CustomFileTypeLists' + Name = 'TestName'; + DisplayName = "TestFileTypeList"; + Description = "Test Description"; + Entities = @( + '{"Ext":".exe"}', + '{"Ext":".txt"}', #drift + '{"Ext":".bat"}' + ) } } } @@ -145,8 +188,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the Set method' { Set-TargetResource @testParams - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + Should -Invoke -CommandName Set-InsiderRiskEntityList -Exactly 1 } } @@ -158,10 +200,17 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-InsiderRiskEntityList -MockWith { return @{ - + ListType = 'CustomFileTypeLists' + Name = 'TestName'; + DisplayName = "TestFileTypeList"; + Description = "Test Description"; + Entities = @( + '{"Ext":".exe"}', + '{"Ext":".cmd"}', + '{"Ext":".bat"}' + ) } } } diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 36fb0879a9..b9278ef7cc 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -70030,6 +70030,98 @@ function Set-SupervisoryReviewPolicy $SamplingRate ) } +function Set-InsiderRiskEntityList +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.Object[]] + $Entities, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.Object[]] + $AddEntities, + + [Parameter()] + [System.Object[]] + $RemoveEntities + ) +} + +function New-InsiderRiskEntityList +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.Object[]] + $Entities, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Type + ) +} + +function Remove-InsiderRiskEntityList +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ForceDeletion + ) +} + +function Get-InsiderRiskEntityList +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Type + ) +} + function Set-SupervisoryReviewPolicyV2 { [CmdletBinding()] diff --git a/dev-package/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 b/dev-package/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 index 20857e0393..f3ddc7d594 100644 --- a/dev-package/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 +++ b/dev-package/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 @@ -66,6 +66,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should create a new instance from the Set method' { ##TODO - Replace the New-Cmdlet by the appropriate one + Set-TargetResource @testParams Should -Invoke -CommandName New-Cmdlet -Exactly 1 } } From 029e0fd6047132abd35f28088f5f3e10ae37bd98 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 18 Sep 2024 22:30:41 -0400 Subject: [PATCH 222/465] Update MSFT_SCInsiderRiskEntityList.schema.mof --- .../MSFT_SCInsiderRiskEntityList.schema.mof | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof index dbf3fcf00f..4c2bba503b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof @@ -14,25 +14,25 @@ class MSFT_SCInsiderRiskEntityListSite [ClassVersion("1.0.0.0"), FriendlyName("SCInsiderRiskEntityList")] class MSFT_SCInsiderRiskEntityList : OMI_BaseResource { - [Key, Description("")] String Name; - [Required, Description("")] String ListType; - [Write, Description("")] String Description; - [Write, Description("")] String DisplayName; - [Write, Description(""), EmbeddedInstance("MSFT_SCInsiderRiskEntityListDomain")] String Domains[]; - [Write, Description("")] String FilePaths[]; - [Write, Description("")] String FileTypes[]; - [Write, Description("")] String Keywords[]; - [Write, Description("")] String SensitiveInformationTypes[]; - [Write, Description(""), EmbeddedInstance("MSFT_SCInsiderRiskEntityListSite")] String Sites[]; - [Write, Description("")] String TrainableClassifiers[]; - [Write, Description("")] String ExceptionKeyworkGroups[]; - [Write, Description("")] String ExcludedClassifierGroups[]; - [Write, Description("")] String ExcludedDomainGroups[]; - [Write, Description("")] String ExcludedFilePathGroups[]; - [Write, Description("")] String ExcludedFileTypeGroups[]; - [Write, Description("")] String ExcludedKeyworkGroups[]; - [Write, Description("")] String ExcludedSensitiveInformationTypeGroups[]; - [Write, Description("")] String ExcludedSiteGroups[]; + [Key, Description("The name of the group or setting.")] String Name; + [Required, Description("The setting type.")] String ListType; + [Write, DescriptionDescription for the group or setting. String Description; + [Write, Description("The display name of the group or setting.")] String DisplayName; + [Write, Description("List of domains"), EmbeddedInstance("MSFT_SCInsiderRiskEntityListDomain")] String Domains[]; + [Write, Description("List of file paths.")] String FilePaths[]; + [Write, Description("List of file types")] String FileTypes[]; + [Write, Description("List of keywords")] String Keywords[]; + [Write, Description("List of sensitive information types.")] String SensitiveInformationTypes[]; + [Write, Description("List of sites."), EmbeddedInstance("MSFT_SCInsiderRiskEntityListSite")] String Sites[]; + [Write, Description("List of trainable classifiers.")] String TrainableClassifiers[]; + [Write, Description("List of keywords for exception.")] String ExceptionKeyworkGroups[]; + [Write, Description("List of excluded trainable classifiers.")] String ExcludedClassifierGroups[]; + [Write, Description("List of excluded domains.")] String ExcludedDomainGroups[]; + [Write, Description("List of excluded file paths.")] String ExcludedFilePathGroups[]; + [Write, Description("List of excluded file types.")] String ExcludedFileTypeGroups[]; + [Write, Description("List of excluded keywords.")] String ExcludedKeyworkGroups[]; + [Write, Description("List of excluded sensitive information types.")] String ExcludedSensitiveInformationTypeGroups[]; + [Write, Description("List of excluded sites.")] String ExcludedSiteGroups[]; [Write, Description("Specify if this entity should exist or not."), 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 232aee04fa1872fca0457c5bb5ffe3f01f3e95f9 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 18 Sep 2024 22:41:46 -0400 Subject: [PATCH 223/465] Update MSFT_SCInsiderRiskEntityList.schema.mof --- .../MSFT_SCInsiderRiskEntityList.schema.mof | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof index 4c2bba503b..020a45d679 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskEntityList/MSFT_SCInsiderRiskEntityList.schema.mof @@ -16,12 +16,12 @@ class MSFT_SCInsiderRiskEntityList : OMI_BaseResource { [Key, Description("The name of the group or setting.")] String Name; [Required, Description("The setting type.")] String ListType; - [Write, DescriptionDescription for the group or setting. String Description; + [Write, Description("Description for the group or setting.")] String Description; [Write, Description("The display name of the group or setting.")] String DisplayName; [Write, Description("List of domains"), EmbeddedInstance("MSFT_SCInsiderRiskEntityListDomain")] String Domains[]; [Write, Description("List of file paths.")] String FilePaths[]; - [Write, Description("List of file types")] String FileTypes[]; - [Write, Description("List of keywords")] String Keywords[]; + [Write, Description("List of file types.")] String FileTypes[]; + [Write, Description("List of keywords.")] String Keywords[]; [Write, Description("List of sensitive information types.")] String SensitiveInformationTypes[]; [Write, Description("List of sites."), EmbeddedInstance("MSFT_SCInsiderRiskEntityListSite")] String Sites[]; [Write, Description("List of trainable classifiers.")] String TrainableClassifiers[]; From 9d3a481475e63954657da839bc8ba81b99812d05 Mon Sep 17 00:00:00 2001 From: sasistla Date: Thu, 19 Sep 2024 15:24:53 +0530 Subject: [PATCH 224/465] Update 2-Update.ps1 --- .../Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 index 59e7cd4060..bb4c462947 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOEmailTenantSettings/2-Update.ps1 @@ -28,7 +28,6 @@ Configuration Example Identity = $TenantId; IsValid = $True; ObjectState = "Unchanged" - Ensure = "Present"; Name = "Default" TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint From 4d6880486756be376cbea1b65468a615328448fa Mon Sep 17 00:00:00 2001 From: kasaxena5 Date: Thu, 19 Sep 2024 16:11:03 +0530 Subject: [PATCH 225/465] minor fixes --- .../MSFT_AADApplication.psm1 | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index eb16df2b5b..60b9b976f8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -61,7 +61,7 @@ function Get-TargetResource $Owners, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] + [Microsoft.Management.Infrastructure.CimInstance] $OptionalClaims, [Parameter()] @@ -357,7 +357,7 @@ function Set-TargetResource $Owners, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] + [Microsoft.Management.Infrastructure.CimInstance] $OptionalClaims, [Parameter()] @@ -511,6 +511,16 @@ function Set-TargetResource $currentParameters.Remove('LogoutURL') | Out-Null $currentParameters.Remove('Homepage') | Out-Null + + $keys = (([Hashtable]$currentParameters).clone()).Keys + foreach ($key in $keys) + { + if ($null -ne $currentParameters.$key -and $currentParameters.$key.getType().Name -like '*cimInstance*') + { + $currentParameters.$key = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $currentParameters.$key + } + } + $skipToUpdate = $false $AppIdValue = $null if ($Ensure -eq 'Present' -and $currentAADApp.Ensure -eq 'Absent') @@ -799,7 +809,7 @@ function Test-TargetResource $Owners, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] + [Microsoft.Management.Infrastructure.CimInstance] $OptionalClaims, [Parameter()] @@ -889,10 +899,28 @@ function Test-TargetResource Write-Verbose -Message 'No Permissions exist for the current Azure AD App and no permissions were specified' } } + + + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($source.getType().Name -like '*CimInstance*' -and $target -ne 'Permissions') + { + $source = Get-M365DSCDRGComplexTypeToHashtable -ComplexObject $source + + $cimtestResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + $ValuesToCheck.Remove($key) | Out-Null + } + } + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" - $ValuesToCheck = $PSBoundParameters $ValuesToCheck.Remove('ObjectId') | Out-Null $ValuesToCheck.Remove('AppId') | Out-Null $ValuesToCheck.Remove('Permissions') | Out-Null @@ -905,7 +933,7 @@ function Test-TargetResource Write-Verbose -Message "Test-TargetResource returned $TestResult" - return $TestResult + return $TestResult -and $cimtestResult } function Export-TargetResource From c585798bc0beae1b371f9769f3fcbace28ed1573 Mon Sep 17 00:00:00 2001 From: kasaxena5 Date: Thu, 19 Sep 2024 16:42:26 +0530 Subject: [PATCH 226/465] minor fixes --- .../MSFT_AADApplication.psm1 | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 60b9b976f8..efc49ff2fa 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -910,10 +910,16 @@ function Test-TargetResource { $source = Get-M365DSCDRGComplexTypeToHashtable -ComplexObject $source - $cimtestResult = Compare-M365DSCComplexObject ` + $testResult = Compare-M365DSCComplexObject ` -Source ($source) ` -Target ($target) + if (-Not $testResult) + { + $testResult = $false + break + } + $ValuesToCheck.Remove($key) | Out-Null } } @@ -925,15 +931,18 @@ function Test-TargetResource $ValuesToCheck.Remove('AppId') | Out-Null $ValuesToCheck.Remove('Permissions') | Out-Null - $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` - -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` - -ValuesToCheck $ValuesToCheck.Keys ` - -IncludedDrifts $driftedParams + if($testResult) + { + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys ` + -IncludedDrifts $driftedParams + } Write-Verbose -Message "Test-TargetResource returned $TestResult" - return $TestResult -and $cimtestResult + return $TestResult } function Export-TargetResource From 0a59d7fd31c9c2331734d9cae3d3c6b8c8ab060f Mon Sep 17 00:00:00 2001 From: kasaxena5 Date: Thu, 19 Sep 2024 16:50:20 +0530 Subject: [PATCH 227/465] Added description --- .../MSFT_AADApplication.schema.mof | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof index 7b2d7e504d..78d7ed2509 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof @@ -10,17 +10,17 @@ class MSFT_AADApplicationPermission [ClassVersion("1.0.0")] class MSFT_MicrosoftGraphOptionalClaim { - [Write, Description("")] Boolean Essential; - [Write, Description("")] String Name; - [Write, Description("")] String Source; + [Write, Description("If the value is true, the claim specified by the client is necessary to ensure a smooth authorization experience for the specific task requested by the end user.")] Boolean Essential; + [Write, Description("The name of the optional claim.")] String Name; + [Write, Description("The source (directory object) of the claim. There are predefined claims and user-defined claims from extension properties.")] String Source; }; [ClassVersion("1.0.0")] class MSFT_AADApplicationOptionalClaims { - [Write, Description(""), EmbeddedInstance("MSFT_MicrosoftGraphOptionalClaim")] String AccessToken[]; - [Write, Description(""), EmbeddedInstance("MSFT_MicrosoftGraphOptionalClaim")] String IdToken[]; - [Write, Description(""), EmbeddedInstance("MSFT_MicrosoftGraphOptionalClaim")] String Saml2Token[]; + [Write, Description("The optional claims returned in the JWT access token."), EmbeddedInstance("MSFT_MicrosoftGraphOptionalClaim")] String AccessToken[]; + [Write, Description("The optional claims returned in the JWT ID token."), EmbeddedInstance("MSFT_MicrosoftGraphOptionalClaim")] String IdToken[]; + [Write, Description("The optional claims returned in the SAML token."), EmbeddedInstance("MSFT_MicrosoftGraphOptionalClaim")] String Saml2Token[]; }; [ClassVersion("1.0.0.0"), FriendlyName("AADApplication")] @@ -41,7 +41,7 @@ class MSFT_AADApplication : OMI_BaseResource [Write, Description("Specifies the URLs that user tokens are sent to for sign in, or the redirect URIs that OAuth 2.0 authorization codes and access tokens are sent to.")] String ReplyURLs[]; [Write, Description("UPN or ObjectID values of the app's owners.")] String Owners[]; [Write, Description("Specify if the Azure AD App should exist or not."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; - [Write, Description(""), EmbeddedInstance("MSFT_AADApplicationOptionalClaims")] string OptionalClaims; + [Write, Description("Optional claims are used to configure additional information which is returned in one or more tokens."), EmbeddedInstance("MSFT_AADApplicationOptionalClaims")] string OptionalClaims; [Write, Description("Credentials for the Microsoft Graph delegated permissions."), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Secret of the Azure Active Directory application to authenticate with."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; From 84e8d2b2baef7e4e78407fc3d7f86ca8a28de32b Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 19 Sep 2024 07:39:19 -0400 Subject: [PATCH 228/465] Fixed Unit Tests --- .../Modules/M365DSCReport.psm1 | 8 ++++ .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 45 ++++++++++++++----- ...oft365DSC.SPOUserProfileProperty.Tests.ps1 | 6 ++- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 index c7209dbf4d..2545a03b39 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 @@ -1227,6 +1227,14 @@ function Get-M365DSCCIMInstanceKey { $primaryKey = 'Dmn' } + elseif ($CIMInstance.ContainsKey('EmergencyDialString')) + { + $primaryKey = 'EmergencyDialString' + } + else + { + $primaryKey = $CIMInstance.Keys[0] + } return $primaryKey } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index d2baffcc43..d899a833d1 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -498,15 +498,24 @@ function Compare-PSCustomObjectArrays foreach ($currentEntry in $currentValues) { - $KeyProperty = Get-M365DSCCIMInstanceKey -CIMInstance $currentEntry + if ($currentEntry.GetType().Name -eq 'PSCustomObject') + { + $fixedEntry = @{} + $currentEntry.psobject.properties | Foreach { $fixedEntry[$_.Name] = $_.Value } + } + else + { + $fixedEntry = $currentEntry + } + $KeyProperty = Get-M365DSCCIMInstanceKey -CIMInstance $fixedEntry - $EquivalentEntryInDesired = $DesiredValues | Where-Object -FilterScript { $_.$KeyProperty -eq $currentEntry.$KeyProperty } + $EquivalentEntryInDesired = $DesiredValues | Where-Object -FilterScript { $_.$KeyProperty -eq $fixedEntry.$KeyProperty } if ($null -eq $EquivalentEntryInDesired) { $result = @{ - Property = $currentEntry + Property = $fixedEntry PropertyName = $KeyProperty - Desired = $currentEntry.$KeyProperty + Desired = $fixedEntry.$KeyProperty Current = $null } $DriftedProperties += $result @@ -517,13 +526,13 @@ function Compare-PSCustomObjectArrays { $propertyName = $property.Name - if ((-not [System.String]::IsNullOrEmpty($currentEntry.$PropertyName) -and -not [System.String]::IsNullOrEmpty($EquivalentEntryInDesired.$PropertyName)) -and ` - $currentEntry.$PropertyName -ne $EquivalentEntryInDesired.$PropertyName) + if ((-not [System.String]::IsNullOrEmpty($fixedEntry.$PropertyName) -and -not [System.String]::IsNullOrEmpty($EquivalentEntryInDesired.$PropertyName)) -and ` + $fixedEntry.$PropertyName -ne $EquivalentEntryInDesired.$PropertyName) { $drift = $true - if ($currentEntry.$PropertyName.GetType().Name -eq 'String' -and $currentEntry.$PropertyName.Contains('$OrganizationName')) + if ($fixedEntry.$PropertyName.GetType().Name -eq 'String' -and $fixedEntry.$PropertyName.Contains('$OrganizationName')) { - if ($currentEntry.$PropertyName.Split('@')[0] -eq $EquivalentEntryInDesired.$PropertyName.Split('@')[0]) + if ($fixedEntry.$PropertyName.Split('@')[0] -eq $EquivalentEntryInDesired.$PropertyName.Split('@')[0]) { $drift = $false } @@ -531,9 +540,9 @@ function Compare-PSCustomObjectArrays if ($drift) { $result = @{ - Property = $currentEntry + Property = $fixedEntry PropertyName = $PropertyName - Desired = $currentEntry.$PropertyName + Desired = $fixedEntry.$PropertyName Current = $EquivalentEntryInDesired.$PropertyName } $DriftedProperties += $result @@ -747,8 +756,20 @@ function Test-M365DSCParameterState } $AllDesiredValuesAsArray += [PSCustomObject]$currentEntry } - $arrayCompare = Compare-PSCustomObjectArrays -CurrentValues $CurrentValues.$fieldName ` - -DesiredValues $AllDesiredValuesAsArray + try + { + $arrayCompare = $null + if ($CurrentValues.$fieldName.GetType().Name -ne 'CimInstance' -and ` + $CurrentValues.$fieldName.GetType().Name -ne 'CimInstance[]') + { + $arrayCompare = Compare-PSCustomObjectArrays -CurrentValues $CurrentValues.$fieldName ` + -DesiredValues $AllDesiredValuesAsArray + } + } + catch + { + Write-Verbose -Message $_ + } if ($null -ne $arrayCompare) { diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SPOUserProfileProperty.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SPOUserProfileProperty.Tests.ps1 index 64b8e2e90c..d082a08989 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SPOUserProfileProperty.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SPOUserProfileProperty.Tests.ps1 @@ -101,7 +101,11 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-PnPUserProfileProperty -MockWith { return @{ AccountName = 'john.smith@contoso.com' - UserProfileProperties = @{'MyOldKey' = 'MyValue' } + UserProfileProperties = @( + @{ + MyOldKey = 'MyValue' + } + ) } } } From 13334d30cd75b865815421b613f84aaf8970be51 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 19 Sep 2024 11:51:44 +0000 Subject: [PATCH 229/465] Updated Resources and Cmdlet documentation pages --- .../SCInsiderRiskEntityList.md | 208 ++++++++++++++++++ .../cmdlets/Get-M365DSCCIMInstanceKey.md | 18 ++ 2 files changed, 226 insertions(+) create mode 100644 docs/docs/resources/security-compliance/SCInsiderRiskEntityList.md create mode 100644 docs/docs/user-guide/cmdlets/Get-M365DSCCIMInstanceKey.md diff --git a/docs/docs/resources/security-compliance/SCInsiderRiskEntityList.md b/docs/docs/resources/security-compliance/SCInsiderRiskEntityList.md new file mode 100644 index 0000000000..4c0e22601d --- /dev/null +++ b/docs/docs/resources/security-compliance/SCInsiderRiskEntityList.md @@ -0,0 +1,208 @@ +# SCInsiderRiskEntityList + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Name** | Key | String | The name of the group or setting. | | +| **ListType** | Required | String | The setting type. | | +| **Description** | Write | String | Description for the group or setting. | | +| **DisplayName** | Write | String | The display name of the group or setting. | | +| **Domains** | Write | MSFT_SCInsiderRiskEntityListDomain[] | List of domains | | +| **FilePaths** | Write | StringArray[] | List of file paths. | | +| **FileTypes** | Write | StringArray[] | List of file types. | | +| **Keywords** | Write | StringArray[] | List of keywords. | | +| **SensitiveInformationTypes** | Write | StringArray[] | List of sensitive information types. | | +| **Sites** | Write | MSFT_SCInsiderRiskEntityListSite[] | List of sites. | | +| **TrainableClassifiers** | Write | StringArray[] | List of trainable classifiers. | | +| **ExceptionKeyworkGroups** | Write | StringArray[] | List of keywords for exception. | | +| **ExcludedClassifierGroups** | Write | StringArray[] | List of excluded trainable classifiers. | | +| **ExcludedDomainGroups** | Write | StringArray[] | List of excluded domains. | | +| **ExcludedFilePathGroups** | Write | StringArray[] | List of excluded file paths. | | +| **ExcludedFileTypeGroups** | Write | StringArray[] | List of excluded file types. | | +| **ExcludedKeyworkGroups** | Write | StringArray[] | List of excluded keywords. | | +| **ExcludedSensitiveInformationTypeGroups** | Write | StringArray[] | List of excluded sensitive information types. | | +| **ExcludedSiteGroups** | Write | StringArray[] | List of excluded sites. | | +| **Ensure** | Write | String | Specify if this entity should exist or not. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_SCInsiderRiskEntityListDomain + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Dmn** | Required | String | Domain name. | | +| **isMLSubDmn** | Write | Boolean | Defines if the entry should include multi-level subdomains or not. | | + +### MSFT_SCInsiderRiskEntityListSite + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Url** | Required | String | Url of the site. | | +| **Name** | Write | String | Name of the site. | | +| **Guid** | Write | String | Unique identifier of the site. | | + + +## Description + +Configures settings for Insider Risk in Purview. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCInsiderRiskEntityList "SCInsiderRiskEntityList-MyFileType" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Description = "Test file type"; + DisplayName = "MyFileType"; + Ensure = "Present"; + FileTypes = @(".exe",".cmd",".bat"); + Keywords = @(); + ListType = "CustomFileTypeLists"; + Name = "MyFileTypeList"; + TenantId = $OrganizationName; + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCInsiderRiskEntityList "SCInsiderRiskEntityList-MyFileType" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Description = "Test file type"; + DisplayName = "MyFileType"; + Ensure = "Present"; + FileTypes = @(".exe",".txt",".bat"); # Drfit + Keywords = @(); + ListType = "CustomFileTypeLists"; + Name = "MyFileTypeList"; + TenantId = $OrganizationName; + } + } +} +``` + +### Example 3 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCInsiderRiskEntityList "SCInsiderRiskEntityList-MyFileType" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Description = "Test file type"; + DisplayName = "MyFileType"; + Ensure = "Absent"; + FileTypes = @(".exe",".cmd",".bat"); + Keywords = @(); + ListType = "CustomFileTypeLists"; + Name = "MyFileTypeList"; + TenantId = $OrganizationName; + } + } +} +``` + diff --git a/docs/docs/user-guide/cmdlets/Get-M365DSCCIMInstanceKey.md b/docs/docs/user-guide/cmdlets/Get-M365DSCCIMInstanceKey.md new file mode 100644 index 0000000000..f4b2a95b4d --- /dev/null +++ b/docs/docs/user-guide/cmdlets/Get-M365DSCCIMInstanceKey.md @@ -0,0 +1,18 @@ +# Get-M365DSCCIMInstanceKey + +## Description + +This function gets the key parameter for the specified CIMInstance + +## Output + +This function outputs information as the following type: +**System.String** + +## Parameters + +| Parameter | Required | DataType | Default Value | Allowed Values | Description | +| --- | --- | --- | --- | --- | --- | +| CIMInstance | True | Hashtable | | | | + + From 30e267d5db9f32f5cdb7ec4ad9e92edea69c90e0 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 19 Sep 2024 11:53:38 +0000 Subject: [PATCH 230/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index a1e5c97de8..699d440d56 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -38814,6 +38814,176 @@ } ] }, + { + "ClassName": "MSFT_SCInsiderRiskEntityListDomain", + "Parameters": [ + { + "CIMType": "String", + "Name": "Dmn", + "Option": "Required" + }, + { + "CIMType": "Boolean", + "Name": "isMLSubDmn", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_SCInsiderRiskEntityListSite", + "Parameters": [ + { + "CIMType": "String", + "Name": "Url", + "Option": "Required" + }, + { + "CIMType": "String", + "Name": "Name", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Guid", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_SCInsiderRiskEntityList", + "Parameters": [ + { + "CIMType": "String", + "Name": "Name", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "ListType", + "Option": "Required" + }, + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Write" + }, + { + "CIMType": "MSFT_SCInsiderRiskEntityListDomain[]", + "Name": "Domains", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "FilePaths", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "FileTypes", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "Keywords", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "SensitiveInformationTypes", + "Option": "Write" + }, + { + "CIMType": "MSFT_SCInsiderRiskEntityListSite[]", + "Name": "Sites", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "TrainableClassifiers", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ExceptionKeyworkGroups", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ExcludedClassifierGroups", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ExcludedDomainGroups", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ExcludedFilePathGroups", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ExcludedFileTypeGroups", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ExcludedKeyworkGroups", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ExcludedSensitiveInformationTypeGroups", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ExcludedSiteGroups", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_SCLabelSetting", "Parameters": [ From 00fde30e0185e2c4ed265cc485687a4eed4a856e Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Thu, 19 Sep 2024 16:44:32 +0200 Subject: [PATCH 231/465] Add WinRM requirement to prerequisite instructions --- docs/docs/user-guide/get-started/prerequisites.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/docs/user-guide/get-started/prerequisites.md b/docs/docs/user-guide/get-started/prerequisites.md index 0ff30b9b23..243cd7322f 100644 --- a/docs/docs/user-guide/get-started/prerequisites.md +++ b/docs/docs/user-guide/get-started/prerequisites.md @@ -6,6 +6,10 @@ For Microsoft365DSC to function, you need to arrange the following components: Microsoft365DSC is supported for PowerShell version 5.1 and 7.3+. For additional details on how to leverage it with PowerShell 7, please refer to our [PowerShell 7+ Guide for Microsoft365DSC](https://microsoft365dsc.com/user-guide/get-started/powershell7-support/). +### Windows Remote Management (WinRM) + +Microsoft365DSC uses the Local Configuration Manager (LCM). This requires PowerShell Remoting to be enabled. Please run either `winrm quickconfig -force` or `Enable-PSRemoting -Force -SkipNetworkProfileCheck` to enable it. + ### Tooling To get the best experience running Microsoft365DSC cmdlets, it is recommended that you use the Windows Terminal. All screenshots provided in this article are using the Windows Terminal. This tool allows you to quickly switch between PowerShell versions and provide better support for icons and symbols that are used throughout Microsoft365DSC’s experience. From 148e7cd300bb717ddfcf86c4fb6ea9115482fecb Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 19 Sep 2024 17:14:26 +0000 Subject: [PATCH 232/465] Updated Resources and Cmdlet documentation pages --- .../exchange/EXOAtpProtectionPolicyRule.md | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 docs/docs/resources/exchange/EXOAtpProtectionPolicyRule.md diff --git a/docs/docs/resources/exchange/EXOAtpProtectionPolicyRule.md b/docs/docs/resources/exchange/EXOAtpProtectionPolicyRule.md new file mode 100644 index 0000000000..59c88250cd --- /dev/null +++ b/docs/docs/resources/exchange/EXOAtpProtectionPolicyRule.md @@ -0,0 +1,174 @@ +# EXOAtpProtectionPolicyRule + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Identity** | Key | String | Identifier for the rule | | +| **Enabled** | Write | Boolean | Specifies whether the rule is enabled | | +| **Comments** | Write | String | Informative comments for the rule, such as what the rule is used for or how it has changed over time. The length of the comment can't exceed 1024 characters. | | +| **ExceptIfRecipientDomainIs** | Write | StringArray[] | Specifies an exception that looks for recipients with email addresses in the specified domains. | | +| **ExceptIfSentTo** | Write | StringArray[] | Specifies an exception that looks for recipients in messages. You can use any value that uniquely identifies the recipient | | +| **ExceptIfSentToMemberOf** | Write | StringArray[] | Specifies an exception that looks for messages sent to members of groups. You can use any value that uniquely identifies the group. | | +| **Name** | Write | String | Unique name for the rule. The maximum length is 64 characters. | | +| **Priority** | Write | UInt32 | Specifies a priority value for the rule that determines the order of rule processing. A lower integer value indicates a higher priority, the value 0 is the highest priority, and rules can't have the same priority value. | | +| **RecipientDomainIs** | Write | StringArray[] | Specifies a condition that looks for recipients with email addresses in the specified domains. | | +| **SafeAttachmentPolicy** | Write | String | Specifies the existing Safe Attachments policy that's associated with the preset security policy. | | +| **SafeLinksPolicy** | Write | String | Specifies the existing Safe Links policy that's associated with the preset security policy. | | +| **SentTo** | Write | StringArray[] | Specifies a condition that looks for recipients in messages. You can use any value that uniquely identifies the recipient. | | +| **SentToMemberOf** | Write | StringArray[] | Specifies a condition that looks for messages sent to members of distribution groups, dynamic distribution groups, or mail-enabled security groups. | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Manage ATP Protection policy rules that are associated with Microsoft Defender for Office 365 protections in preset security policies. + +## Permissions + +### Exchange + +To authenticate with Microsoft Exchange, this resource required the following permissions: + +#### Roles + +- Transport Hygiene, Security Admin, View-Only Configuration, Security Reader + +#### Role Groups + +- Organization Management + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOATPProtectionPolicyRule "EXOATPProtectionPolicyRule-Strict Preset Security Policy" + { + Comments = "Built-in Strict Preset Security Policy"; + Enabled = $False; + Identity = "Strict Preset Security Policy"; + Name = "Strict Preset Security Policy"; + Priority = 0; + SafeAttachmentPolicy = "Strict Preset Security Policy1725468967835"; + SafeLinksPolicy = "Strict Preset Security Policy1725468969412"; + Ensure = "Present" + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOATPProtectionPolicyRule "EXOATPProtectionPolicyRule-Strict Preset Security Policy" + { + Comments = "Built-in Strict Preset Security Policy with comments"; # Changed value + Enabled = $True; # Changed value + Identity = "Strict Preset Security Policy"; + Name = "Strict Preset Security Policy"; + Priority = 0; + SafeAttachmentPolicy = "Strict Preset Security Policy1725468967835"; + SafeLinksPolicy = "Strict Preset Security Policy1725468969412"; + Ensure = "Present" + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + +### Example 3 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOATPProtectionPolicyRule "EXOATPProtectionPolicyRule-Strict Preset Security Policy" + { + Comments = "Built-in Strict Preset Security Policy"; + Enabled = $False; + Identity = "Strict Preset Security Policy"; + Name = "Strict Preset Security Policy"; + Priority = 0; + SafeAttachmentPolicy = "Strict Preset Security Policy1725468967835"; + SafeLinksPolicy = "Strict Preset Security Policy1725468969412"; + Ensure = "Absent" + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + From b9a1b122d57af424ee1c17795b1a675166bebfee Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 19 Sep 2024 17:16:09 +0000 Subject: [PATCH 233/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 699d440d56..239087b5ff 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -6239,6 +6239,111 @@ } ] }, + { + "ClassName": "MSFT_EXOAtpProtectionPolicyRule", + "Parameters": [ + { + "CIMType": "String", + "Name": "Identity", + "Option": "Key" + }, + { + "CIMType": "Boolean", + "Name": "Enabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Comments", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ExceptIfRecipientDomainIs", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ExceptIfSentTo", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ExceptIfSentToMemberOf", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Name", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "Priority", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "RecipientDomainIs", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SafeAttachmentPolicy", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SafeLinksPolicy", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "SentTo", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "SentToMemberOf", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOAuthenticationPolicy", "Parameters": [ From 4b671c43315533c9960338320310f6011b329178 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 19 Sep 2024 17:18:00 +0000 Subject: [PATCH 234/465] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index d96a63f694..907e37db8e 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -129,6 +129,20 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOATPProtectionPolicyRule 'EXOATPProtectionPolicyRule-Strict Preset Security Policy' + { + Comments = "Built-in Strict Preset Security Policy"; + Enabled = $False; + Identity = "Strict Preset Security Policy"; + Name = "Strict Preset Security Policy"; + Priority = 0; + SafeAttachmentPolicy = "Strict Preset Security Policy1725468967835"; + SafeLinksPolicy = "Strict Preset Security Policy1725468969412"; + Ensure = "Present" + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } EXOAuthenticationPolicy 'ConfigureAuthenticationPolicy' { Identity = "Block Basic Auth" From 5e066597bf10b185ca85002f88e5f6bf40574b27 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 19 Sep 2024 17:18:28 +0000 Subject: [PATCH 235/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index b1c89d5d9f..200455c0ad 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -147,6 +147,20 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOATPProtectionPolicyRule 'EXOATPProtectionPolicyRule-Strict Preset Security Policy' + { + Comments = "Built-in Strict Preset Security Policy with comments"; # Changed value + Enabled = $True; # Changed value + Identity = "Strict Preset Security Policy"; + Name = "Strict Preset Security Policy"; + Priority = 0; + SafeAttachmentPolicy = "Strict Preset Security Policy1725468967835"; + SafeLinksPolicy = "Strict Preset Security Policy1725468969412"; + Ensure = "Present" + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } EXOAuthenticationPolicy 'ConfigureAuthenticationPolicy' { Identity = "Block Basic Auth" From af28151061c9c2c2e4a8de7d03df3c33d84a993c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 19 Sep 2024 17:19:03 +0000 Subject: [PATCH 236/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Remove.Tests.ps1 | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 index 9561195d84..065fa1f57d 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 @@ -115,6 +115,20 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOATPProtectionPolicyRule 'EXOATPProtectionPolicyRule-Strict Preset Security Policy' + { + Comments = "Built-in Strict Preset Security Policy"; + Enabled = $False; + Identity = "Strict Preset Security Policy"; + Name = "Strict Preset Security Policy"; + Priority = 0; + SafeAttachmentPolicy = "Strict Preset Security Policy1725468967835"; + SafeLinksPolicy = "Strict Preset Security Policy1725468969412"; + Ensure = "Absent" + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } EXOAuthenticationPolicy 'ConfigureAuthenticationPolicy' { Identity = "Block Basic Auth" From aa6466fe0fa5f1cfdbdbf537de46593407445959 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 19 Sep 2024 15:36:34 -0400 Subject: [PATCH 237/465] ADOPermissionGroup - Initial Release --- .../MSFT_ADOPermissionGroup.psm1 | 596 ++++++++++++++++++ .../MSFT_ADOPermissionGroup.schema.mof | 19 + .../MSFT_ADOPermissionGroup/readme.md | 6 + .../MSFT_ADOPermissionGroup/settings.json | 20 + .../Resources/ADOPermissionGroup/1-Create.ps1 | 38 ++ .../Resources/ADOPermissionGroup/2-Update.ps1 | 38 ++ .../Resources/ADOPermissionGroup/3-Remove.ps1 | 38 ++ .../M365DSCAzureDevOPSHelper.psm1 | 8 +- ...crosoft365DSC.ADOPermissionGroup.Tests.ps1 | 290 +++++++++ 9 files changed, 1051 insertions(+), 2 deletions(-) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroup/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroup/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroup/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOPermissionGroup.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.psm1 new file mode 100644 index 0000000000..ede45030e4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.psm1 @@ -0,0 +1,596 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $OrganizationName, + + [Parameter(Mandatory = $true)] + [System.String] + $PrincipalName, + + [Parameter()] + [System.String] + $Descriptor, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [ValidateSet('Project', 'Organization')] + [System.String] + $Level, + + [Parameter()] + [System.String[]] + $Members, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'AzureDevOPS' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + if (-not [System.String]::IsNullOrEmpty($Descriptor)) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.descriptor -eq $Descriptor} + } + + if ($null -eq $instance) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.principalName -eq $PrincipalName} + } + } + else + { + $uri = "https://vssps.dev.azure.com/$OrganizationName/_apis/graph/groups?api-version=7.1-preview.1" + $allInstances = (Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri).value + if (-not [System.String]::IsNullOrEmpty($Descriptor)) + { + $instance = $allInstances | Where-Object -FilterScript {$_.descriptor -eq $Descriptor} + } + if ($null -eq $instance) + { + $instance = $allInstances | Where-Object -FilterScript {$_.principalName -eq $PrincipalName} + } + } + if ($null -eq $instance) + { + return $nullResult + } + + # Level + $LevelValue = 'Project' + if ($instance.domain.StartsWith('vstfs:///Framework/IdentityDomain/')) + { + $LevelValue = 'Organization' + } + + # Membership + $MembersValue = @() + $uri = "https://vsaex.dev.azure.com/$($OrganizationName)/_apis/GroupEntitlements/$($instance.originId)/members?api-version=7.1" + $membership = (Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri).members + + foreach ($member in $membership) + { + $MembersValue += $member.user.principalName + } + + $results = @{ + OrganizationName = $OrganizationName + PrincipalName = $instance.principalName + Description = $instance.description + DisplayName = $instance.displayName + Descriptor = $instance.descriptor + Level = $LevelValue + Id = $instance.originId + Members = $MembersValue + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $OrganizationName, + + [Parameter(Mandatory = $true)] + [System.String] + $PrincipalName, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Descriptor, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [ValidateSet('Project', 'Organization')] + [System.String] + $Level, + + [Parameter()] + [System.String[]] + $Members, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + New-M365DSCConnection -Workload 'AzureDevOPS' ` + -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 + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + $newGroup = $null + if ($Level -eq 'Organization') + { + $uri = "https://vssps.dev.azure.com/$OrganizationName/_apis/graph/groups?api-version=7.1-preview.1" + $body = '{"displayName": "' + $DisplayName + '","description": "' + $Description + '"}' + $newGroup = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri -Method POST -Body $body -ContentType 'application/json' + } + elseif ($Level -eq 'Project') + { + $projectName = $PrincipalName.Split(']')[0] + $projectName = $projectName.Substring(1, $projectName.Length -1) + $uri = "https://dev.azure.com/$($OrganizationName)/_apis/projects/$($ProjectName)?api-version=7.1" + $response = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri + $projectId = $response.id + + $uri = "https://vssps.dev.azure.com/$($OrganizationName)/_apis/graph/descriptors/$($projectId)?api-version=7.1-preview.1" + $response = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri + $scope = $response.value + + $uri = "https://vssps.dev.azure.com/$($OrganizationName)/_apis/graph/groups?scopeDescriptor=$($scope)&api-version=7.1-preview.1" + $body = '{"displayName": "' + $DisplayName + '","description": "' + $Description + '"}' + $newGroup = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri -Method POST -Body $body -ContentType 'application/json' + } + + Write-Host "NEWGROUP::: $($newGroup | fl * | Out-String)" + foreach ($member in $Members) + { + Write-Verbose -Message "Adding Member {$member} to group ${$PrincipalName}" + Set-M365DSCADOPermissionGroupMember -OrganizationName $OrganizationName ` + -GroupId $newGroup.originId ` + -PrincipalName $member + } + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + if ($Description -ne $currentInstance.Description) + { + Write-Verbose -Message "Updating group {$PrincipalName} description to {$Description}" + $uri = "https://vssps.dev.azure.com/$($OrganizationName)/_apis/graph/groups/$($currentInstance.Descriptor)?api-version=7.1-preview.1" + $body = '[{"op": "replace", "path": "/description", "from": null, "value": "' + $Description + '"}]' + } + + $membershipChanges = Compare-Object -ReferenceObject $currentInstance.Members -DifferenceObject $Members + foreach ($diff in $membershipChanges) + { + if ($diff.SideIndicator -eq '=>') + { + Write-Verbose -Message "Adding Member {$($diff.InputObject)} to group ${$PrincipalName}" + Set-M365DSCADOPermissionGroupMember -OrganizationName $OrganizationName ` + -GroupId $currentInstance.Id ` + -PrincipalName $diff.InputObject ` + -Method 'PUT' + } + else + { + Write-Verbose -Message "Removing Member {$($diff.InputObject)} to group ${$PrincipalName}" + Set-M365DSCADOPermissionGroupMember -OrganizationName $OrganizationName ` + -GroupId $currentInstance.Id ` + -PrincipalName $diff.InputObject ` + -Method 'DELETE' + } + } + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing group {$principalName} with Descriptor {$($currentInstance.Descriptor)}" + $uri = "https://vssps.dev.azure.com/$($OrganizationName)/_apis/graph/groups/$($currentInstance.Descriptor)?api-version=7.1-preview.1" + Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri -Method 'DELETE' -ContentType 'application/json' | Out-Null + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $OrganizationName, + + [Parameter(Mandatory = $true)] + [System.String] + $PrincipalName, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Descriptor, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [ValidateSet('Project', 'Organization')] + [System.String] + $Level, + + [Parameter()] + [System.String[]] + $Members, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace workload + $ConnectionMode = New-M365DSCConnection -Workload 'AzureDevOPS' ` + -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 + { + $Script:ExportMode = $true + + $profile = Invoke-M365DSCAzureDevOPSWebRequest -Uri 'https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=5.1' + $accounts = Invoke-M365DSCAzureDevOPSWebRequest -Uri "https://app.vssps.visualstudio.com/_apis/accounts?api-version=7.1-preview.1&memberId=$($profile.id)" + + $i = 1 + $dscContent = '' + if ($accounts.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($account in $accounts) + { + $organization = $account.Value.accountName + $uri = "https://vssps.dev.azure.com/$organization/_apis/graph/groups?api-version=7.1-preview.1" + + [array] $Script:exportedInstances = (Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri).Value + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.principalName + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + OrganizationName = $Organization + PrincipalName = $config.principalName + Descriptor = $config.descriptor + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + if (-not $config.principalName.StartsWith("[TEAM FOUNDATION]")) + { + $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 '' + } +} + +function Set-M365DSCADOPermissionGroupMember +{ + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [System.String] + $OrganizationName, + + [Parameter(Mandatory = $true)] + [System.String] + $GroupId, + + [Parameter(Mandatory = $true)] + [System.String] + $PrincipalName, + + [Parameter()] + [System.String] + $Method = 'Put' + ) + if ($null -eq $Script:allUsers) + { + $uri = "https://vsaex.dev.azure.com/$($OrganizationName)/_apis/userentitlements?api-version=7.2-preview.4" + $Script:allUsers = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri + } + $user = $Script:allUsers.items | Where-Object -FilterScript {$_.user.principalName -eq $PrincipalName} + $UserId = $user.id + $uri = "https://vsaex.dev.azure.com/$($OrganizationName)/_apis/GroupEntitlements/$($GroupId)/members/$($UserId)?api-version=5.0-preview.1" + Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri -Method $Method | Out-Null +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.schema.mof new file mode 100644 index 0000000000..43ef224474 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.schema.mof @@ -0,0 +1,19 @@ +[ClassVersion("1.0.0.0"), FriendlyName("ADOPermissionGroup")] +class MSFT_ADOPermissionGroup : OMI_BaseResource +{ + [Key, Description("The name of the Azure DevOPS Organization.")] String OrganizationName; + [Key, Description("Principal name to identify the group.")] String PrincipalName; + [Write, Description("Display name for the group.")] String DisplayName; + [Write, Description("Description of the group.")] String Description; + [Write, Description("List of principal names of the members of the group.")] String Members[]; + [Write, Description("Unique identifier for the group.")] String Id; + [Write, Description("Unique descriptor for the group.")] String Descriptor; + [Write, Description("Determines at what level in the hierarchy the group exists. Valid values are Project or Organization."), ValueMap{"Organization", "Project"}, Values{"Organization", "Project"}] String Level; + [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/readme.md new file mode 100644 index 0000000000..d460ee4d90 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/readme.md @@ -0,0 +1,6 @@ + +# ADOPermissionGroup + +## Description + +Manages Azure DevOPS permission groups. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/settings.json new file mode 100644 index 0000000000..9157b5dcfc --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/settings.json @@ -0,0 +1,20 @@ +{ + "resourceName": "ADOPermissionGroup", + "description": "Manages Azure DevOPS permission groups.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroup/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroup/1-Create.ps1 new file mode 100644 index 0000000000..053c8b5b43 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroup/1-Create.ps1 @@ -0,0 +1,38 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + ADOPermissionGroup "TestPermissionGroup" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Description = "My Description"; + DisplayName = "TestGroup"; + Ensure = "Present"; + Level = "Organization"; + Members = @("AdeleV@$TenantId"); + OrganizationName = "O365DSC-Dev"; + PrincipalName = "[O365DSC-DEV]\TestGroup"; + TenantId = $TenantId; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroup/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroup/2-Update.ps1 new file mode 100644 index 0000000000..f4bf481b12 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroup/2-Update.ps1 @@ -0,0 +1,38 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + ADOPermissionGroup "TestPermissionGroup" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Description = "My Description"; + DisplayName = "TestGroup"; + Ensure = "Present"; + Level = "Organization"; + Members = @("AdeleV@$TenantId", "admin@$TenantId"); #Drift + OrganizationName = "O365DSC-Dev"; + PrincipalName = "[O365DSC-DEV]\TestGroup"; + TenantId = $TenantId; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroup/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroup/3-Remove.ps1 new file mode 100644 index 0000000000..57f2071f19 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/ADOPermissionGroup/3-Remove.ps1 @@ -0,0 +1,38 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + ADOPermissionGroup "TestPermissionGroup" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Description = "My Description"; + DisplayName = "TestGroup"; + Ensure = "Absent"; + Level = "Organization"; + Members = @("AdeleV@$TenantId"); + OrganizationName = "O365DSC-Dev"; + PrincipalName = "[O365DSC-DEV]\TestGroup"; + TenantId = $TenantId; + } + } +} diff --git a/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 b/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 index 19f3105cf7..92375e9444 100644 --- a/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 +++ b/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1 @@ -13,12 +13,16 @@ function Invoke-M365DSCAzureDevOPSWebRequest [Parameter()] [System.String] - $Body + $Body, + + [Parameter()] + [System.String] + $ContentType = 'application/json-patch+json' ) $headers = @{ Authorization = $global:MsCloudLoginConnectionProfile.AzureDevOPS.AccessToken - 'Content-Type' = 'application/json-patch+json' + 'Content-Type' = $ContentType } $params = @{ diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOPermissionGroup.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOPermissionGroup.Tests.ps1 new file mode 100644 index 0000000000..eab6c2dfc5 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ADOPermissionGroup.Tests.ps1 @@ -0,0 +1,290 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Description = "Test Description"; + DisplayName = "TestGroup"; + Level = "Organization"; + Members = @("john.smith@contoso.com"); + OrganizationName = "TestOrg"; + PrincipalName = "[TestOrg]\TestGroup"; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Invoke-M365DSCAzureDevOPSWebRequest -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 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Description = "Test Description"; + DisplayName = "TestGroup"; + Level = "Organization"; + Members = @("john.smith@contoso.com"); + OrganizationName = "TestOrg"; + PrincipalName = "[TestOrg]\TestGroup"; + Ensure = 'Absent' + Credential = $Credential; + } + + Mock -CommandName Invoke-M365DSCAzureDevOPSWebRequest -MockWith { + if ($Script:count -eq 0) + { + $Script:count++ + return @{ + Value = @{ + PrincipalName = '[TestOrg]\TestGroup' + Domain = 'vstfs:///Framework/IdentityDomain/' + OriginId = '12345-12345-12345-12345-12345' + } + } + } + elseif ($Script:count -eq 1) + { + $Script:count++ + return @{ + Members = @( + @{ + User = @{ + principalName = "john.smith@contoso.com" + } + } + ) + } + } + } + } + It 'Should return Values from the Get method' { + $Script:count = 0 + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + It 'Should return false from the Test method' { + $Script:count = 0 + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should remove the instance from the Set method' { + Set-TargetResource @testParams + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Description = "Test Description"; + DisplayName = "TestGroup"; + Level = "Organization"; + Members = @("john.smith@contoso.com"); + OrganizationName = "TestOrg"; + PrincipalName = "[TestOrg]\TestGroup"; + Ensure = 'Present' + Credential = $Credential; + } + + $Script:count = 0 + Mock -CommandName Invoke-M365DSCAzureDevOPSWebRequest -MockWith { + if ($Script:count -eq 0) + { + $Script:count++ + return @{ + Value = @{ + PrincipalName = '[TestOrg]\TestGroup' + Domain = 'vstfs:///Framework/IdentityDomain/' + OriginId = '12345-12345-12345-12345-12345' + Description = 'Test Description' + DisplayName = 'TestGroup' + } + } + } + elseif ($Script:count -eq 1) + { + $Script:count++ + return @{ + Members = @( + @{ + User = @{ + principalName = "john.smith@contoso.com" + } + } + ) + } + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Description = "Test Description"; + DisplayName = "TestGroup"; + Level = "Organization"; + Members = @("john.smith@contoso.com"); + OrganizationName = "TestOrg"; + PrincipalName = "[TestOrg]\TestGroup"; + Ensure = 'Present' + Credential = $Credential; + } + + $Script:count = 0 + Mock -CommandName Invoke-M365DSCAzureDevOPSWebRequest -MockWith { + if ($Script:count -eq 0) + { + $Script:count++ + return @{ + Value = @{ + PrincipalName = '[TestOrg]\TestGroup' + Domain = 'vstfs:///Framework/IdentityDomain/' + OriginId = '12345-12345-12345-12345-12345' + Description = 'Test Description' + DisplayName = 'TestGroup' + } + } + } + elseif ($Script:count -eq 1) + { + $Script:count++ + return @{ + Members = @( + @{ + User = @{ + principalName = "bob.houle@contoso.com" # 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 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + $Script:count = 0 + Mock -CommandName Invoke-M365DSCAzureDevOPSWebRequest -MockWith { + if ($Script:count -eq 0) + { + $Script:count++ + return @{ + id = '12345-12345-12345-12345-12346' + } + } + elseif ($Script:count -eq 1) + { + $Script:count++ + return @( + @{ + Value = @{ + accountName = 'MyOrg' + } + } + ) + } + elseif ($Script:count -eq 2) + { + $Script:count++ + return @{ + Value = @{ + PrincipalName = '[TestOrg]\TestGroup' + Domain = 'vstfs:///Framework/IdentityDomain/' + OriginId = '12345-12345-12345-12345-12345' + Description = 'Test Description' + DisplayName = 'TestGroup' + } + } + } + elseif ($Script:count -eq 3) + { + $Script:count++ + return @{ + Members = @( + @{ + User = @{ + principalName = "john.smith@contoso.com" + } + } + ) + } + } + } + } + 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 66930b7a8d59e3a6f6fdb0bf42a3bb212beee891 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 19 Sep 2024 15:37:35 -0400 Subject: [PATCH 238/465] Update CHANGELOG.md --- CHANGELOG.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b25d25321c..a2fc9290a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ * Initial release * ADOOrganizationOwner * Initial release. -* ADOOrganizationOwner +* ADOPermissionGroup * Initial release. * ADOSecurityPolicy * Initial release. @@ -22,8 +22,6 @@ * Initial Release. * EXOManagementScope * Initial Release. -* EXOManagementScope - * Initial Release. * EXORetenionPolicy * Initial Release. * EXOPhishSimOverrideRule From 5d47b69dd86f9edd562af3d9e7056cdb8a89b326 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 19 Sep 2024 19:58:58 +0000 Subject: [PATCH 239/465] Updated Resources and Cmdlet documentation pages --- .../resources/azure-ad/ADOPermissionGroup.md | 178 ++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 docs/docs/resources/azure-ad/ADOPermissionGroup.md diff --git a/docs/docs/resources/azure-ad/ADOPermissionGroup.md b/docs/docs/resources/azure-ad/ADOPermissionGroup.md new file mode 100644 index 0000000000..f05b158e0d --- /dev/null +++ b/docs/docs/resources/azure-ad/ADOPermissionGroup.md @@ -0,0 +1,178 @@ +# ADOPermissionGroup + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **OrganizationName** | Key | String | The name of the Azure DevOPS Organization. | | +| **PrincipalName** | Key | String | Principal name to identify the group. | | +| **DisplayName** | Write | String | Display name for the group. | | +| **Description** | Write | String | Description of the group. | | +| **Members** | Write | StringArray[] | List of principal names of the members of the group. | | +| **Id** | Write | String | Unique identifier for the group. | | +| **Descriptor** | Write | String | Unique descriptor for the group. | | +| **Level** | Write | String | Determines at what level in the hierarchy the group exists. Valid values are Project or Organization. | `Organization`, `Project` | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Manages Azure DevOPS permission groups. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + ADOPermissionGroup "TestPermissionGroup" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Description = "My Description"; + DisplayName = "TestGroup"; + Ensure = "Present"; + Level = "Organization"; + Members = @("AdeleV@$TenantId"); + OrganizationName = "O365DSC-Dev"; + PrincipalName = "[O365DSC-DEV]\TestGroup"; + TenantId = $TenantId; + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + ADOPermissionGroup "TestPermissionGroup" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Description = "My Description"; + DisplayName = "TestGroup"; + Ensure = "Present"; + Level = "Organization"; + Members = @("AdeleV@$TenantId", "admin@$TenantId"); #Drift + OrganizationName = "O365DSC-Dev"; + PrincipalName = "[O365DSC-DEV]\TestGroup"; + TenantId = $TenantId; + } + } +} +``` + +### Example 3 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + ADOPermissionGroup "TestPermissionGroup" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Description = "My Description"; + DisplayName = "TestGroup"; + Ensure = "Absent"; + Level = "Organization"; + Members = @("AdeleV@$TenantId"); + OrganizationName = "O365DSC-Dev"; + PrincipalName = "[O365DSC-DEV]\TestGroup"; + TenantId = $TenantId; + } + } +} +``` + From 73d969390b6ba246212afda667c6db95caa6f172 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 19 Sep 2024 20:01:16 +0000 Subject: [PATCH 240/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 239087b5ff..7a8f7aec70 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -5199,6 +5199,86 @@ } ] }, + { + "ClassName": "MSFT_ADOPermissionGroup", + "Parameters": [ + { + "CIMType": "String", + "Name": "OrganizationName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "PrincipalName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "Members", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Descriptor", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Level", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_ADOSecurityPolicy", "Parameters": [ From 04f7136e907a9b78e482e96f4f74b1ec27fa3911 Mon Sep 17 00:00:00 2001 From: Peter Richards Date: Thu, 19 Sep 2024 15:24:59 -0700 Subject: [PATCH 241/465] Implement support for DmarcQuarantineAction and DmarcRejectAction on EXOAntiPhishPolicy --- .../MSFT_EXOAntiPhishPolicy.psm1 | 32 +++++++++++++++++++ .../MSFT_EXOAntiPhishPolicy.schema.mof | 2 ++ .../Resources/EXOAntiPhishPolicy/1-Create.ps1 | 2 ++ .../Resources/EXOAntiPhishPolicy/2-Update.ps1 | 2 ++ .../Resources/EXOAntiPhishPolicy/3-Remove.ps1 | 2 ++ .../M365DSCIntegration.EXO.Create.Tests.ps1 | 2 ++ .../M365DSCIntegration.EXO.Remove.Tests.ps1 | 4 ++- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 2 ++ 8 files changed, 47 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.psm1 index d849dc40ff..2fab25e233 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.psm1 @@ -151,6 +151,16 @@ function Get-TargetResource [System.String] $TargetedUserQuarantineTag, + [Parameter()] + [System.String] + [ValidateSet('MoveToJmf', 'Quarantine')] + $DmarcQuarantineAction, + + [Parameter()] + [System.String] + [ValidateSet('Quarantine', 'Reject')] + $DmarcRejectAction, + [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -277,6 +287,8 @@ function Get-TargetResource TargetedUserProtectionAction = $TargetedUserProtectionActionValue TargetedUsersToProtect = $AntiPhishPolicy.TargetedUsersToProtect TargetedUserQuarantineTag = $AntiPhishPolicy.TargetedUserQuarantineTag + DmarcQuarantineAction = $AntiPhishPolicy.DmarcQuarantineAction + DmarcRejectAction = $AntiPhishPolicy.DmarcRejectAction Credential = $Credential Ensure = 'Present' ApplicationId = $ApplicationId @@ -457,6 +469,16 @@ function Set-TargetResource [System.String] $TargetedUserQuarantineTag, + [Parameter()] + [System.String] + [ValidateSet('MoveToJmf', 'Quarantine')] + $DmarcQuarantineAction, + + [Parameter()] + [System.String] + [ValidateSet('Quarantine', 'Reject')] + $DmarcRejectAction, + [Parameter()] [System.Management.Automation.PSCredential] $Credential, @@ -694,6 +716,16 @@ function Test-TargetResource [System.String] $TargetedUserQuarantineTag, + [Parameter()] + [System.String] + [ValidateSet('MoveToJmf', 'Quarantine')] + $DmarcQuarantineAction, + + [Parameter()] + [System.String] + [ValidateSet('Quarantine', 'Reject')] + $DmarcRejectAction, + [Parameter()] [System.Management.Automation.PSCredential] $Credential, diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.schema.mof index 42d4410650..39594f64e1 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAntiPhishPolicy/MSFT_EXOAntiPhishPolicy.schema.mof @@ -36,6 +36,8 @@ class MSFT_EXOAntiPhishPolicy : OMI_BaseResource [Write, Description("The TargetedUserActionRecipients parameter specifies the replacement or additional recipients for detected user impersonation messages when the TargetedUserProtectionAction parameter is set to the value Redirect or BccMessage. A valid value for this parameter is an email address. You can specify multiple email addresses separated by commas.")] String TargetedUserActionRecipients[]; [Write, Description("The TargetedUsersToProtect parameter specifies the users that are included in user impersonation protection when the EnableTargetedUserProtection parameter is set to $true.")] String TargetedUsersToProtect[]; [Write, Description("The TargetedUserQuarantineTag specifies the quarantine policy that's used on messages that are quarantined by user impersonation protection.")] String TargetedUserQuarantineTag; + [Write, Description("The DmarcQuarantineAction parameter specifies the action to take when a message fails DMARC checks and the sender's DMARC policy is p=quarantine"), ValueMap{"MoveToJmf","Quarantine"}, Values{"MoveToJmf","Quarantine"}] String DmarcQuarantineAction; + [Write, Description("The DmarcRejectAction parameter specifies the action to take when a message fails DMARC checks and the sender's DMARC policy is p=reject."), ValueMap{"Quarantine","Reject"}, Values{"Quarantine","Reject"}] String DmarcRejectAction; [Write, Description("Credentials of the Exchange Global 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; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishPolicy/1-Create.ps1 index a65fc01916..2166373c7b 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishPolicy/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishPolicy/1-Create.ps1 @@ -45,6 +45,8 @@ Configuration Example EnableUnusualCharactersSafetyTips = $null TargetedUserActionRecipients = $null Ensure = "Present" + DmarcQuarantineAction = "Quarantine" + DmarcRejectAction = "Reject" ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishPolicy/2-Update.ps1 index b5fa497a46..5a606beeaa 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishPolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishPolicy/2-Update.ps1 @@ -45,6 +45,8 @@ Configuration Example EnableUnusualCharactersSafetyTips = $null TargetedUserActionRecipients = $null Ensure = "Present" + DmarcQuarantineAction = "Quarantine" + DmarcRejectAction = "Reject" ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishPolicy/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishPolicy/3-Remove.ps1 index b5fa497a46..7bf9e68c43 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishPolicy/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishPolicy/3-Remove.ps1 @@ -44,6 +44,8 @@ Configuration Example EnableOrganizationDomainsProtection = $null EnableUnusualCharactersSafetyTips = $null TargetedUserActionRecipients = $null + DmarcQuarantineAction = "Quarantine" + DmarcRejectAction = "Reject" Ensure = "Present" ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index 907e37db8e..5d5ded4159 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -101,6 +101,8 @@ EnableOrganizationDomainsProtection = $null EnableUnusualCharactersSafetyTips = $null TargetedUserActionRecipients = $null + DmarcQuarantineAction = "Quarantine" + DmarcRejectAction = "Reject" Ensure = "Present" ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 index 065fa1f57d..a1e535e007 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 @@ -92,6 +92,8 @@ EnableOrganizationDomainsProtection = $null EnableUnusualCharactersSafetyTips = $null TargetedUserActionRecipients = $null + DmarcQuarantineAction = "Quarantine" + DmarcRejectAction = "Reject" Ensure = "Present" ApplicationId = $ApplicationId TenantId = $TenantId @@ -469,7 +471,7 @@ } EXORecipientPermission 'AddSendAs' { - + Identity = 'AdeleV@$Domain' Trustee = "admin@$TenantId" Ensure = 'Absent' diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index 200455c0ad..8b40016f2e 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -101,6 +101,8 @@ EnableOrganizationDomainsProtection = $null EnableUnusualCharactersSafetyTips = $null TargetedUserActionRecipients = $null + DmarcQuarantineAction = "Quarantine" + DmarcRejectAction = "Reject" Ensure = "Present" ApplicationId = $ApplicationId TenantId = $TenantId From e0b9483d8bb352aba866325ed294024574f9821d Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 20 Sep 2024 04:46:36 +0000 Subject: [PATCH 242/465] Updated Resources and Cmdlet documentation pages --- .../exchange/EXOEmailTenantSettings.md | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 docs/docs/resources/exchange/EXOEmailTenantSettings.md diff --git a/docs/docs/resources/exchange/EXOEmailTenantSettings.md b/docs/docs/resources/exchange/EXOEmailTenantSettings.md new file mode 100644 index 0000000000..0de767d147 --- /dev/null +++ b/docs/docs/resources/exchange/EXOEmailTenantSettings.md @@ -0,0 +1,83 @@ +# EXOEmailTenantSettings + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **IsSingleInstance** | Key | String | Only valid value is 'Yes'. | `Yes` | +| **Identity** | Write | String | Identity which indicates the organization name. | | +| **EnablePriorityAccountProtection** | Write | Boolean | Specifies whether priority account protection is enabled. | | +| **IsValid** | Write | Boolean | Specifies whether the migration configuration is valid. | | +| **ObjectState** | Write | String | Specifies the state of the object. | | +| **Name** | Write | String | Specifies the name of the object. | | +| **Credential** | Write | PSCredential | Credentials of the Exchange Global Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **CertificatePath** | Write | String | Path to certificate used in service principal usually a PFX file. | | +| **CertificatePassword** | Write | PSCredential | Username can be made up to anything but password will be used for CertificatePassword | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +EXOEmailTenantSettings + +## Description + +This resource allows users to manage email tenant settings. + +## Permissions + +### Exchange + +To authenticate with Microsoft Exchange, this resource required the following permissions: + +#### Roles + +- Organization Management, Security Reader + +#### Role Groups + +- Organization Management, Security Administrator + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOEmailTenantSettings "EXOEmailTenantSettings-Test" + { + IsSingleInstance = "Yes" + EnablePriorityAccountProtection = $True; + Identity = $TenantId; + IsValid = $True; + ObjectState = "Unchanged" + Name = "Default" + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationId = $ApplicationId + } + } +} +``` + From 5b1e1f5f3c78ee187621ee5f4a9c80322ff8939f Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 20 Sep 2024 04:48:34 +0000 Subject: [PATCH 243/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 7a8f7aec70..3c139d61a7 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -7994,6 +7994,81 @@ } ] }, + { + "ClassName": "MSFT_EXOEmailTenantSettings", + "Parameters": [ + { + "CIMType": "String", + "Name": "IsSingleInstance", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Identity", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EnablePriorityAccountProtection", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsValid", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ObjectState", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Name", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificatePath", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "CertificatePassword", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOEOPProtectionPolicyRule", "Parameters": [ From 581d15723d077abc1b7a20ea2c25afb5086536aa Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 20 Sep 2024 04:49:22 +0000 Subject: [PATCH 244/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index 200455c0ad..964a5ffcdf 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -370,6 +370,18 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOEmailTenantSettings 'EXOEmailTenantSettings-Test' + { + IsSingleInstance = "Yes" + EnablePriorityAccountProtection = $True; + Identity = $TenantId; + IsValid = $True; + ObjectState = "Unchanged" + Name = "Default" + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ApplicationId = $ApplicationId + } EXOFocusedInbox 'EXOFocusedInbox-Test' { Ensure = "Present"; From f4a3e94c0e125df37f24b1e17e3a5c64d55de252 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Fri, 20 Sep 2024 16:59:38 +0530 Subject: [PATCH 245/465] Added App Roles --- .../MSFT_AADApplication.psm1 | 51 +++++++++++++++++++ .../MSFT_AADApplication.schema.mof | 14 +++++ 2 files changed, 65 insertions(+) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index efc49ff2fa..8462e221b1 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -60,6 +60,10 @@ function Get-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $AppRoles, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $OptionalClaims, @@ -168,6 +172,24 @@ function Get-TargetResource { Write-Verbose -Message 'An instance of Azure AD App was retrieved.' + + $complexAppRoles = @() + foreach ($currentappRoles in $AADApp.appRoles) + { + $myappRoles = @{} + $myappRoles.Add('AllowedMemberTypes', $currentappRoles.allowedMemberTypes) + $myappRoles.Add('Description', $currentappRoles.description) + $myappRoles.Add('DisplayName', $currentappRoles.displayName) + $myappRoles.Add('Id', $currentappRoles.id) + $myappRoles.Add('IsEnabled', $currentappRoles.isEnabled) + $myappRoles.Add('Origin', $currentappRoles.origin) + $myappRoles.Add('Value', $currentappRoles.value) + if ($myappRoles.values.Where({$null -ne $_}).Count -gt 0) + { + $complexAppRoles += $myappRoles + } + } + $complexOptionalClaims = @{} $complexAccessTokenClaims = @() foreach ($currentAccessTokenClaim in $AADApp.OptionalClaims.AccessToken) @@ -261,6 +283,7 @@ function Get-TargetResource Owners = $OwnersValues ObjectId = $AADApp.Id AppId = $AADApp.AppId + AppRoles = $complexAppRoles OptionalClaims = $complexOptionalClaims Permissions = $permissionsObj Ensure = 'Present' @@ -356,6 +379,10 @@ function Set-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $AppRoles, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $OptionalClaims, @@ -808,6 +835,10 @@ function Test-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $AppRoles, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $OptionalClaims, @@ -1039,6 +1070,22 @@ function Export-TargetResource $Results.Permissions = Get-M365DSCAzureADAppPermissionsAsString $Results.Permissions } + + if ($null -ne $Results.AppRoles) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.AppRoles ` + -CIMInstanceName 'MicrosoftGraphappRole' + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.AppRoles = $complexTypeStringResult + } + else + { + $Results.Remove('AppRoles') | Out-Null + } + } + if($null -ne $Results.OptionalClaims) { $complexMapping = @( @@ -1089,6 +1136,10 @@ function Export-TargetResource -ParameterName 'Permissions' } + if ($Results.AppRoles) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "AppRoles" -IsCIMArray:$True + } if ($Results.OptionalClaims) { diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof index 78d7ed2509..51bff12ec7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof @@ -7,6 +7,19 @@ class MSFT_AADApplicationPermission [Write, Description("Represented whether or not the Admin consent been granted on the app.")] Boolean AdminConsentGranted; }; + +[ClassVersion("1.0.0")] +class MSFT_MicrosoftGraphAppRole +{ + [Write, Description("Specifies whether this app role can be assigned to users and groups (by setting to 'User'), to other application's (by setting to 'Application', or both (by setting to 'User', 'Application'). App roles supporting assignment to other applications' service principals are also known as application permissions. The 'Application' value is only supported for app roles defined on application entities.")] String AllowedMemberTypes[]; + [Write, Description("The description for the app role. This is displayed when the app role is being assigned and, if the app role functions as an application permission, during consent experiences.")] String Description; + [Write, Description("Display name for the permission that appears in the app role assignment and consent experiences.")] String DisplayName; + [Write, Description("Unique role identifier inside the appRoles collection. When creating a new app role, a new GUID identifier must be provided.")] String Id; + [Write, Description("When creating or updating an app role, this must be set to true (which is the default). To delete a role, this must first be set to false. At that point, in a subsequent call, this role may be removed.")] Boolean IsEnabled; + [Write, Description("Specifies if the app role is defined on the application object or on the servicePrincipal entity. Must not be included in any POST or PATCH requests. Read-only.")] String Origin; + [Write, Description("Specifies the value to include in the roles claim in ID tokens and access tokens authenticating an assigned user or service principal. Must not exceed 120 characters in length. Allowed characters are : ! # $ % & ' ( ) * + , - . / : = + _ } , and characters in the ranges 0-9, A-Z and a-z. Any other character, including the space character, aren't allowed. May not begin with ..")] String Value; +}; + [ClassVersion("1.0.0")] class MSFT_MicrosoftGraphOptionalClaim { @@ -36,6 +49,7 @@ class MSFT_AADApplication : OMI_BaseResource [Write, Description("User-defined URI(s) that uniquely identify a Web application within its Azure AD tenant, or within a verified custom domain.")] string IdentifierUris[]; [Write, Description("Specifies the fallback application type as public client, such as an installed application running on a mobile device. The default value is false, which means the fallback application type is confidential client such as web app. There are certain scenarios where Microsoft Entra ID cannot determine the client application type (for example, ROPC flow where it is configured without specifying a redirect URI). In those cases, Microsoft Entra ID will interpret the application type based on the value of this property.")] Boolean IsFallbackPublicClient; [Write, Description("Client applications that are tied to this resource application.")] string KnownClientApplications[]; + [Write, Description("The collection of roles defined for the application. With app role assignments, these roles can be assigned to users, groups, or service principals associated with other applications. Not nullable."), EmbeddedInstance("MSFT_MicrosoftGraphappRole")] String AppRoles[]; [Write, Description("The logout url for this application.")] string LogoutURL; [Write, Description("Specifies whether this application is a public client (such as an installed application running on a mobile device). Default is false.")] Boolean PublicClient; [Write, Description("Specifies the URLs that user tokens are sent to for sign in, or the redirect URIs that OAuth 2.0 authorization codes and access tokens are sent to.")] String ReplyURLs[]; From 6b790ba5ea545cde63fc35fc25f258c2ee6d4c02 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 20 Sep 2024 17:45:15 +0000 Subject: [PATCH 246/465] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/exchange/EXOAntiPhishPolicy.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/docs/resources/exchange/EXOAntiPhishPolicy.md b/docs/docs/resources/exchange/EXOAntiPhishPolicy.md index d0859b5a13..5c09c05326 100644 --- a/docs/docs/resources/exchange/EXOAntiPhishPolicy.md +++ b/docs/docs/resources/exchange/EXOAntiPhishPolicy.md @@ -39,6 +39,8 @@ | **TargetedUserActionRecipients** | Write | StringArray[] | The TargetedUserActionRecipients parameter specifies the replacement or additional recipients for detected user impersonation messages when the TargetedUserProtectionAction parameter is set to the value Redirect or BccMessage. A valid value for this parameter is an email address. You can specify multiple email addresses separated by commas. | | | **TargetedUsersToProtect** | Write | StringArray[] | The TargetedUsersToProtect parameter specifies the users that are included in user impersonation protection when the EnableTargetedUserProtection parameter is set to $true. | | | **TargetedUserQuarantineTag** | Write | String | The TargetedUserQuarantineTag specifies the quarantine policy that's used on messages that are quarantined by user impersonation protection. | | +| **DmarcQuarantineAction** | Write | String | The DmarcQuarantineAction parameter specifies the action to take when a message fails DMARC checks and the sender's DMARC policy is p=quarantine | `MoveToJmf`, `Quarantine` | +| **DmarcRejectAction** | Write | String | The DmarcRejectAction parameter specifies the action to take when a message fails DMARC checks and the sender's DMARC policy is p=reject. | `Quarantine`, `Reject` | | **Credential** | Write | PSCredential | Credentials of the Exchange Global Admin | | | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | @@ -117,6 +119,8 @@ Configuration Example EnableUnusualCharactersSafetyTips = $null TargetedUserActionRecipients = $null Ensure = "Present" + DmarcQuarantineAction = "Quarantine" + DmarcRejectAction = "Reject" ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint @@ -173,6 +177,8 @@ Configuration Example EnableUnusualCharactersSafetyTips = $null TargetedUserActionRecipients = $null Ensure = "Present" + DmarcQuarantineAction = "Quarantine" + DmarcRejectAction = "Reject" ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint @@ -228,6 +234,8 @@ Configuration Example EnableOrganizationDomainsProtection = $null EnableUnusualCharactersSafetyTips = $null TargetedUserActionRecipients = $null + DmarcQuarantineAction = "Quarantine" + DmarcRejectAction = "Reject" Ensure = "Present" ApplicationId = $ApplicationId TenantId = $TenantId From 4f7ca1a78ff5d06af75ce8e820270d1b7b2ac96d Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 20 Sep 2024 17:47:07 +0000 Subject: [PATCH 247/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 3c139d61a7..7acf32a9b7 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -5972,6 +5972,16 @@ "Name": "TargetedUserQuarantineTag", "Option": "Write" }, + { + "CIMType": "String", + "Name": "DmarcQuarantineAction", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DmarcRejectAction", + "Option": "Write" + }, { "CIMType": "MSFT_Credential", "Name": "Credential", From 83252db2ae4d5507e1b15be84338c41c0a0e6de1 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 20 Sep 2024 17:47:22 +0000 Subject: [PATCH 248/465] Updated {Create} EXO Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index 5d5ded4159..e6ed079a01 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -101,9 +101,9 @@ EnableOrganizationDomainsProtection = $null EnableUnusualCharactersSafetyTips = $null TargetedUserActionRecipients = $null + Ensure = "Present" DmarcQuarantineAction = "Quarantine" DmarcRejectAction = "Reject" - Ensure = "Present" ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint From a7ad97826b9c87921b3641c1e2bb1322d656839a Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 20 Sep 2024 17:47:49 +0000 Subject: [PATCH 249/465] Updated {Update} EXO Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index edc270afb6..4b112d0d83 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -101,9 +101,9 @@ EnableOrganizationDomainsProtection = $null EnableUnusualCharactersSafetyTips = $null TargetedUserActionRecipients = $null + Ensure = "Present" DmarcQuarantineAction = "Quarantine" DmarcRejectAction = "Reject" - Ensure = "Present" ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint From e5f347a74305f3e763ef65d854b5d98845d19cd9 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 20 Sep 2024 17:48:11 +0000 Subject: [PATCH 250/465] Updated {Update} EXO Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 index a1e535e007..d309331b25 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 @@ -471,7 +471,7 @@ } EXORecipientPermission 'AddSendAs' { - + Identity = 'AdeleV@$Domain' Trustee = "admin@$TenantId" Ensure = 'Absent' From c5de2da5d7fe1f5b57a90bfc102bf2f262c2e114 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 20 Sep 2024 14:10:21 -0400 Subject: [PATCH 251/465] Updated DSCPArser --- CHANGELOG.md | 1 + Modules/Microsoft365DSC/Dependencies/Manifest.psd1 | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea8a75523f..4bf8282a0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ * SPOAccessControlSettings * Added support for property EnableRestrictedAccessControl. * DEPENDENCIES + * Updated DSCParser to version 2.0.0.10. * Updated Microsoft.Graph to version 2.23.0. * Added dependencies on Az.Accounts, Az.Resources and Az.SecurityInsights * Updated DSCParser to version 2.0.0.9. diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 1b2afb7550..85952adab5 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -14,7 +14,7 @@ }, @{ ModuleName = 'DSCParser' - RequiredVersion = '2.0.0.9' + RequiredVersion = '2.0.0.10' }, @{ ModuleName = 'ExchangeOnlineManagement' From f2af9e48eb77fed51dc8c7654a4dcaec204180b9 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 23 Sep 2024 10:13:23 +0530 Subject: [PATCH 252/465] Added App Roles and Password Credentials --- .../MSFT_AADApplication.psm1 | 142 ++++++------------ .../MSFT_AADApplication.schema.mof | 27 ++-- 2 files changed, 56 insertions(+), 113 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 8462e221b1..3589a90260 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -62,11 +62,11 @@ function Get-TargetResource [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] - $AppRoles, + $PasswordCredentials, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance] - $OptionalClaims, + [Microsoft.Management.Infrastructure.CimInstance[]] + $AppRoles, [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] @@ -172,6 +172,26 @@ function Get-TargetResource { Write-Verbose -Message 'An instance of Azure AD App was retrieved.' + $complexPasswordCredentials = @() + foreach ($currentpasswordCredentials in $AADApp.passwordCredentials) + { + $mypasswordCredentials = @{} + $mypasswordCredentials.Add('DisplayName', $currentpasswordCredentials.displayName) + if ($null -ne $currentpasswordCredentials.endDateTime) + { + $mypasswordCredentials.Add('EndDateTime', ([DateTimeOffset]$currentpasswordCredentials.endDateTime).ToString('o')) + } + $mypasswordCredentials.Add('Hint', $currentpasswordCredentials.hint) + $mypasswordCredentials.Add('KeyId', $currentpasswordCredentials.keyId) + if ($null -ne $currentpasswordCredentials.startDateTime) + { + $mypasswordCredentials.Add('StartDateTime', ([DateTimeOffset]$currentpasswordCredentials.startDateTime).ToString('o')) + } + if ($mypasswordCredentials.values.Where({$null -ne $_}).Count -gt 0) + { + $complexPasswordCredentials += $mypasswordCredentials + } + } $complexAppRoles = @() foreach ($currentappRoles in $AADApp.appRoles) @@ -190,52 +210,6 @@ function Get-TargetResource } } - $complexOptionalClaims = @{} - $complexAccessTokenClaims = @() - foreach ($currentAccessTokenClaim in $AADApp.OptionalClaims.AccessToken) - { - $myAccessTokenClaim = @{} - $myAccessTokenClaim.Add('Essential', $currentAccessTokenClaim.Essential) - - $myAccessTokenClaim.Add('Name', $currentAccessTokenClaim.Name) - - $myAccessTokenClaim.Add('Source', $currentAccessTokenClaim.Source) - $complexAccessTokenClaims += $myAccessTokenClaim - } - $complexOptionalClaims.Add('AccessToken',$complexAccessTokenClaims) - - - $complexIdTokenClaims = @() - foreach ($currentIdTokenClaim in $AADApp.OptionalClaims.IdToken) - { - $myIdTokenClaim = @{} - $myIdTokenClaim.Add('Essential', $currentIdTokenClaim.Essential) - - $myIdTokenClaim.Add('Name', $currentIdTokenClaim.Name) - - $myIdTokenClaim.Add('Source', $currentIdTokenClaim.Source) - $complexIdTokenClaims += $myIdTokenClaim - } - $complexOptionalClaims.Add('IdToken',$complexIdTokenClaims) - - $complexSaml2TokenClaims = @() - foreach ($currentSaml2TokenClaim in $AADApp.OptionalClaims.Saml2Token) - { - $mySaml2TokenClaim = @{} - $mySaml2TokenClaim.Add('Essential', $currentSaml2TokenClaim.Essential) - - $mySaml2TokenClaim.Add('Name', $currentSaml2TokenClaim.Name) - - $mySaml2TokenClaim.Add('Source', $currentSaml2TokenClaim.Source) - $complexSaml2TokenClaims += $mySaml2TokenClaim - } - $complexOptionalClaims.Add('Saml2Token',$complexSaml2TokenClaims) - - if ($complexOptionalClaims.values.Where({$null -ne $_}).count -eq 0) - { - $complexOptionalClaims = $null - } - $permissionsObj = Get-M365DSCAzureADAppPermissions -App $AADApp $isPublicClient = $false if (-not [System.String]::IsNullOrEmpty($AADApp.PublicClient) -and $AADApp.PublicClient -eq $true) @@ -283,8 +257,8 @@ function Get-TargetResource Owners = $OwnersValues ObjectId = $AADApp.Id AppId = $AADApp.AppId + PasswordCredentials = $complexPasswordCredentials AppRoles = $complexAppRoles - OptionalClaims = $complexOptionalClaims Permissions = $permissionsObj Ensure = 'Present' Credential = $Credential @@ -381,11 +355,11 @@ function Set-TargetResource [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] - $AppRoles, + $PasswordCredentials, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance] - $OptionalClaims, + [Microsoft.Management.Infrastructure.CimInstance[]] + $AppRoles, [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] @@ -837,11 +811,11 @@ function Test-TargetResource [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] - $AppRoles, + $PasswordCredentials, [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance] - $OptionalClaims, + [Microsoft.Management.Infrastructure.CimInstance[]] + $AppRoles, [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] @@ -1070,60 +1044,36 @@ function Export-TargetResource $Results.Permissions = Get-M365DSCAzureADAppPermissionsAsString $Results.Permissions } - - if ($null -ne $Results.AppRoles) + if ($null -ne $Results.PasswordCredentials) { $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` - -ComplexObject $Results.AppRoles ` - -CIMInstanceName 'MicrosoftGraphappRole' + -ComplexObject $Results.PasswordCredentials ` + -CIMInstanceName 'MicrosoftGraphpasswordCredential' if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) { - $Results.AppRoles = $complexTypeStringResult + $Results.PasswordCredentials = $complexTypeStringResult } else { - $Results.Remove('AppRoles') | Out-Null + $Results.Remove('PasswordCredentials') | Out-Null } } - if($null -ne $Results.OptionalClaims) + if ($null -ne $Results.AppRoles) { - $complexMapping = @( - @{ - Name = 'OptionalClaims' - CimInstanceName = 'AADApplicationOptionalClaims' - IsRequired = $False - } - @{ - Name = 'AccessToken' - CimInstanceName = 'MicrosoftGraphOptionalClaim' - IsRequired = $False - } - @{ - Name = 'IdToken' - CimInstanceName = 'MicrosoftGraphOptionalClaim' - IsRequired = $False - } - @{ - Name = 'Saml2Token' - CimInstanceName = 'MicrosoftGraphOptionalClaim' - IsRequired = $False - } - ) $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` - -ComplexObject $Results.OptionalClaims` - -CIMInstanceName 'AADApplicationOptionalClaims' ` - -ComplexTypeMapping $complexMapping - - if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + -ComplexObject $Results.AppRoles ` + -CIMInstanceName 'MicrosoftGraphappRole' + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) { - $Results.OptionalClaims = $complexTypeStringResult + $Results.AppRoles = $complexTypeStringResult } else { - $Results.Remove('OptionalClaims') | Out-Null + $Results.Remove('AppRoles') | Out-Null } } + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` -ConnectionMode $ConnectionMode ` -ModulePath $PSScriptRoot ` @@ -1136,14 +1086,14 @@ function Export-TargetResource -ParameterName 'Permissions' } - if ($Results.AppRoles) + if ($Results.PasswordCredentials) { - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "AppRoles" -IsCIMArray:$True + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "PasswordCredentials" -IsCIMArray:$True } - if ($Results.OptionalClaims) + if ($Results.AppRoles) { - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "OptionalClaims" -isCIMArray:$False + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "AppRoles" -IsCIMArray:$True } $dscContent.Append($currentDSCBlock) | Out-Null diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof index 51bff12ec7..b2764d65fa 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof @@ -7,6 +7,15 @@ class MSFT_AADApplicationPermission [Write, Description("Represented whether or not the Admin consent been granted on the app.")] Boolean AdminConsentGranted; }; +[ClassVersion("1.0.0")] +class MSFT_MicrosoftGraphPasswordCredential +{ + [Write, Description("Friendly name for the password. Optional.")] String DisplayName; + [Write, Description("The date and time at which the password expires represented using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z. Optional.")] String EndDateTime; + [Write, Description("Contains the first three characters of the password. Read-only.")] String Hint; + [Write, Description("The unique identifier for the password.")] String KeyId; + [Write, Description("The date and time at which the password becomes valid. The Timestamp type represents date and time information using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z. Optional.")] String StartDateTime; +}; [ClassVersion("1.0.0")] class MSFT_MicrosoftGraphAppRole @@ -20,22 +29,6 @@ class MSFT_MicrosoftGraphAppRole [Write, Description("Specifies the value to include in the roles claim in ID tokens and access tokens authenticating an assigned user or service principal. Must not exceed 120 characters in length. Allowed characters are : ! # $ % & ' ( ) * + , - . / : = + _ } , and characters in the ranges 0-9, A-Z and a-z. Any other character, including the space character, aren't allowed. May not begin with ..")] String Value; }; -[ClassVersion("1.0.0")] -class MSFT_MicrosoftGraphOptionalClaim -{ - [Write, Description("If the value is true, the claim specified by the client is necessary to ensure a smooth authorization experience for the specific task requested by the end user.")] Boolean Essential; - [Write, Description("The name of the optional claim.")] String Name; - [Write, Description("The source (directory object) of the claim. There are predefined claims and user-defined claims from extension properties.")] String Source; -}; - -[ClassVersion("1.0.0")] -class MSFT_AADApplicationOptionalClaims -{ - [Write, Description("The optional claims returned in the JWT access token."), EmbeddedInstance("MSFT_MicrosoftGraphOptionalClaim")] String AccessToken[]; - [Write, Description("The optional claims returned in the JWT ID token."), EmbeddedInstance("MSFT_MicrosoftGraphOptionalClaim")] String IdToken[]; - [Write, Description("The optional claims returned in the SAML token."), EmbeddedInstance("MSFT_MicrosoftGraphOptionalClaim")] String Saml2Token[]; -}; - [ClassVersion("1.0.0.0"), FriendlyName("AADApplication")] class MSFT_AADApplication : OMI_BaseResource { @@ -49,13 +42,13 @@ class MSFT_AADApplication : OMI_BaseResource [Write, Description("User-defined URI(s) that uniquely identify a Web application within its Azure AD tenant, or within a verified custom domain.")] string IdentifierUris[]; [Write, Description("Specifies the fallback application type as public client, such as an installed application running on a mobile device. The default value is false, which means the fallback application type is confidential client such as web app. There are certain scenarios where Microsoft Entra ID cannot determine the client application type (for example, ROPC flow where it is configured without specifying a redirect URI). In those cases, Microsoft Entra ID will interpret the application type based on the value of this property.")] Boolean IsFallbackPublicClient; [Write, Description("Client applications that are tied to this resource application.")] string KnownClientApplications[]; + [Write, Description("The collection of password credentials associated with the application. Not nullable."), EmbeddedInstance("MSFT_MicrosoftGraphpasswordCredential")] String PasswordCredentials[]; [Write, Description("The collection of roles defined for the application. With app role assignments, these roles can be assigned to users, groups, or service principals associated with other applications. Not nullable."), EmbeddedInstance("MSFT_MicrosoftGraphappRole")] String AppRoles[]; [Write, Description("The logout url for this application.")] string LogoutURL; [Write, Description("Specifies whether this application is a public client (such as an installed application running on a mobile device). Default is false.")] Boolean PublicClient; [Write, Description("Specifies the URLs that user tokens are sent to for sign in, or the redirect URIs that OAuth 2.0 authorization codes and access tokens are sent to.")] String ReplyURLs[]; [Write, Description("UPN or ObjectID values of the app's owners.")] String Owners[]; [Write, Description("Specify if the Azure AD App should exist or not."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; - [Write, Description("Optional claims are used to configure additional information which is returned in one or more tokens."), EmbeddedInstance("MSFT_AADApplicationOptionalClaims")] string OptionalClaims; [Write, Description("Credentials for the Microsoft Graph delegated permissions."), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Secret of the Azure Active Directory application to authenticate with."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; From c3730778bb1c42a0a3aab538c4bbfbd881ee7b46 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 23 Sep 2024 11:24:37 +0530 Subject: [PATCH 253/465] minor fix --- .../MSFT_AADApplication.psm1 | 37 +++---------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 3589a90260..ead62c2afa 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -905,30 +905,6 @@ function Test-TargetResource } } - - $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() - foreach ($key in $PSBoundParameters.Keys) - { - $source = $PSBoundParameters.$key - $target = $CurrentValues.$key - if ($source.getType().Name -like '*CimInstance*' -and $target -ne 'Permissions') - { - $source = Get-M365DSCDRGComplexTypeToHashtable -ComplexObject $source - - $testResult = Compare-M365DSCComplexObject ` - -Source ($source) ` - -Target ($target) - - if (-Not $testResult) - { - $testResult = $false - break - } - - $ValuesToCheck.Remove($key) | Out-Null - } - } - Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" @@ -936,14 +912,11 @@ function Test-TargetResource $ValuesToCheck.Remove('AppId') | Out-Null $ValuesToCheck.Remove('Permissions') | Out-Null - if($testResult) - { - $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` - -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` - -ValuesToCheck $ValuesToCheck.Keys ` - -IncludedDrifts $driftedParams - } + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys ` + -IncludedDrifts $driftedParams Write-Verbose -Message "Test-TargetResource returned $TestResult" From d9b4d1b19edf5a407024c3208e5304e3aef9dec1 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 23 Sep 2024 11:45:28 +0530 Subject: [PATCH 254/465] mistake --- .../DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index ead62c2afa..0698d0c7f5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -908,6 +908,7 @@ function Test-TargetResource Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + $ValuesToCheck = $PSBoundParameters $ValuesToCheck.Remove('ObjectId') | Out-Null $ValuesToCheck.Remove('AppId') | Out-Null $ValuesToCheck.Remove('Permissions') | Out-Null From 8db0f0db4da70fffcd5dd0dd00847bd27e5e9c23 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 23 Sep 2024 15:16:37 +0530 Subject: [PATCH 255/465] Added Key Credentials --- .../MSFT_AADApplication.psm1 | 56 +++++++++++++++++++ .../MSFT_AADApplication.schema.mof | 14 +++++ 2 files changed, 70 insertions(+) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 0698d0c7f5..6ed5685d08 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -60,6 +60,10 @@ function Get-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $KeyCredentials, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $PasswordCredentials, @@ -172,6 +176,29 @@ function Get-TargetResource { Write-Verbose -Message 'An instance of Azure AD App was retrieved.' + $complexKeyCredentials = @() + foreach ($currentkeyCredentials in $AADApp.keyCredentials) + { + $mykeyCredentials = @{} + $mykeyCredentials.Add('CustomKeyIdentifier', $currentkeyCredentials.customKeyIdentifier) + $mykeyCredentials.Add('DisplayName', $currentkeyCredentials.displayName) + if ($null -ne $currentkeyCredentials.endDateTime) + { + $mykeyCredentials.Add('EndDateTime', ([DateTimeOffset]$currentkeyCredentials.endDateTime).ToString('o')) + } + $mykeyCredentials.Add('KeyId', $currentkeyCredentials.keyId) + if ($null -ne $currentkeyCredentials.startDateTime) + { + $mykeyCredentials.Add('StartDateTime', ([DateTimeOffset]$currentkeyCredentials.startDateTime).ToString('o')) + } + $mykeyCredentials.Add('Type', $currentkeyCredentials.type) + $mykeyCredentials.Add('Usage', $currentkeyCredentials.usage) + if ($mykeyCredentials.values.Where({$null -ne $_}).Count -gt 0) + { + $complexKeyCredentials += $mykeyCredentials + } + } + $complexPasswordCredentials = @() foreach ($currentpasswordCredentials in $AADApp.passwordCredentials) { @@ -257,6 +284,7 @@ function Get-TargetResource Owners = $OwnersValues ObjectId = $AADApp.Id AppId = $AADApp.AppId + KeyCredentials = $complexKeyCredentials PasswordCredentials = $complexPasswordCredentials AppRoles = $complexAppRoles Permissions = $permissionsObj @@ -353,6 +381,10 @@ function Set-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $KeyCredentials, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $PasswordCredentials, @@ -809,6 +841,10 @@ function Test-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $KeyCredentials, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $PasswordCredentials, @@ -1018,6 +1054,21 @@ function Export-TargetResource $Results.Permissions = Get-M365DSCAzureADAppPermissionsAsString $Results.Permissions } + if ($null -ne $Results.KeyCredentials) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.KeyCredentials ` + -CIMInstanceName 'MicrosoftGraphkeyCredential' + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.KeyCredentials = $complexTypeStringResult + } + else + { + $Results.Remove('KeyCredentials') | Out-Null + } + } + if ($null -ne $Results.PasswordCredentials) { $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` @@ -1060,6 +1111,11 @@ function Export-TargetResource -ParameterName 'Permissions' } + if ($Results.KeyCredentials) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "KeyCredentials" -IsCIMArray:$True + } + if ($Results.PasswordCredentials) { $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "PasswordCredentials" -IsCIMArray:$True diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof index b2764d65fa..7bfee43b55 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof @@ -7,6 +7,19 @@ class MSFT_AADApplicationPermission [Write, Description("Represented whether or not the Admin consent been granted on the app.")] Boolean AdminConsentGranted; }; + +[ClassVersion("1.0.0")] +class MSFT_MicrosoftGraphKeyCredential +{ + [Write, Description("A 40-character binary type that can be used to identify the credential. Optional. When not provided in the payload, defaults to the thumbprint of the certificate.")] String CustomKeyIdentifier; + [Write, Description("Friendly name for the key. Optional.")] String DisplayName; + [Write, Description("The date and time at which the credential expires. The DateTimeOffset type represents date and time information using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z.")] String EndDateTime; + [Write, Description("The unique identifier (GUID) for the key.")] String KeyId; + [Write, Description("The date and time at which the credential becomes valid.The Timestamp type represents date and time information using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z.")] String StartDateTime; + [Write, Description("The type of key credential for example, Symmetric, AsymmetricX509Cert.")] String Type; + [Write, Description("A string that describes the purpose for which the key can be used for example, Verify.")] String Usage; +}; + [ClassVersion("1.0.0")] class MSFT_MicrosoftGraphPasswordCredential { @@ -43,6 +56,7 @@ class MSFT_AADApplication : OMI_BaseResource [Write, Description("Specifies the fallback application type as public client, such as an installed application running on a mobile device. The default value is false, which means the fallback application type is confidential client such as web app. There are certain scenarios where Microsoft Entra ID cannot determine the client application type (for example, ROPC flow where it is configured without specifying a redirect URI). In those cases, Microsoft Entra ID will interpret the application type based on the value of this property.")] Boolean IsFallbackPublicClient; [Write, Description("Client applications that are tied to this resource application.")] string KnownClientApplications[]; [Write, Description("The collection of password credentials associated with the application. Not nullable."), EmbeddedInstance("MSFT_MicrosoftGraphpasswordCredential")] String PasswordCredentials[]; + [Write, Description("The collection of key credentials associated with the application. Not nullable. Supports $filter (eq, not, ge, le)."), EmbeddedInstance("MSFT_MicrosoftGraphkeyCredential")] String KeyCredentials[]; [Write, Description("The collection of roles defined for the application. With app role assignments, these roles can be assigned to users, groups, or service principals associated with other applications. Not nullable."), EmbeddedInstance("MSFT_MicrosoftGraphappRole")] String AppRoles[]; [Write, Description("The logout url for this application.")] string LogoutURL; [Write, Description("Specifies whether this application is a public client (such as an installed application running on a mobile device). Default is false.")] Boolean PublicClient; From a072c56dd91a758b8c8a9ae5fb1110fec08f1f95 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Mon, 23 Sep 2024 16:15:34 +0530 Subject: [PATCH 256/465] minor --- .../MSFT_EXOMailboxFolderPermission.psm1 | 29 +++++++++++++++---- ...MSFT_EXOMailboxFolderPermission.schema.mof | 4 +-- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 3 ++ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 index 3575ea8ce3..3da7404ef3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 @@ -97,7 +97,7 @@ function Get-TargetResource $results = @{ Identity = $Identity - UserPermissions = [Array]$permissionsObj + UserPermissions = [Array]$permissionsObj Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -319,6 +319,25 @@ function Test-TargetResource # } # } + # foreach($value in $ValuesToCheck.UserPermissions) { + # if ($value.SharingPermissionFlags -ne "None" -and $value.SharingPermissionFlags -ne "Delegate" -and $value.SharingPermissionFlags -ne "CanViewPrivateItems") + # { + # $value.Remove('SharingPermissionFlags') | Out-Null + # } + # } + + for ($i = 0; $i -lt $ValuesToCheck.UserPermissions.Count; $i++) { + # $value = $ValuesToCheck.UserPermissions[$i] + + Write-Host "$i : Target Values: $ValuesToCheck.UserPermissions[$i]" + Write-Host "$i : Target Values: $CurrentValues.UserPermissions[$i]" + # if ($value.SharingPermissionFlags -ne "None" -and $value.SharingPermissionFlags -ne "Delegate" -and $value.SharingPermissionFlags -ne "CanViewPrivateItems") { + # # Update the value in place + # $ValuesToCheck.UserPermissions[$i].Remove('SharingPermissionFlags') | Out-Null + # Write-Verbose $ValuesToCheck.UserPermissions[$i] + # } + } + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" @@ -389,12 +408,10 @@ function Export-TargetResource try { Write-Host "`r`n" -NoNewline - Write-Host " |---Getting the mailbox folders on behalf of the current admin" -NoNewline + Write-Host " |---Getting only the mailbox folders for the current admin" -NoNewline [Array]$mailboxFolders = Get-MailboxFolder -Recurse - Write-Host "`r`n" -NoNewline - if ($mailboxes.Length -eq 0) { Write-Host $Global:M365DSCEmojiGreenCheckMark @@ -412,7 +429,7 @@ function Export-TargetResource $Params = @{ Identity = $mailboxFolder.Identity - UserPermissions = $null + UserPermissions = $null Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId @@ -492,4 +509,4 @@ function Get-M365DSCEXOUserPermissionsList return $StringContent } -Export-ModuleMember -Function * +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.schema.mof index 6867096ccc..90ba203151 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.schema.mof @@ -1,8 +1,8 @@ [ClassVersion("1.0.0")] class MSFT_EXOMailboxFolderUserPermission { - [Required, Description("The AccessRights parameter specifies the permissions that you want to add for the user on the mailbox folder.")] String AccessRights[]; - [Required, Description("The User parameter specifies who gets the permissions on the mailbox folder.")] String User; + [Write, Description("The AccessRights parameter specifies the permissions that you want to add for the user on the mailbox folder.")] String AccessRights[]; + [Write, Description("The User parameter specifies who gets the permissions on the mailbox folder.")] String User; [Write, Description("The SharingPermissionFlags parameter assigns calendar delegate permissions. This parameter only applies to calendar folders and can only be used when the AccessRights parameter value is Editor. Valid values are: None, Delegate, CanViewPrivateItems")] String SharingPermissionFlags; }; diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 7fad40386a..490ba44942 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -236,9 +236,12 @@ function Convert-M365DscCIMInstanceToString $CIMInstance ) + Write-Host $CIMInstance + Write-Host "entering for loop*******************************************" $str = '{' foreach ($prop in $CIMInstance.CimInstanceProperties) { + Write-Host $prop.Name if ($str -notmatch '{$') { $str += '; ' From d5a8cbcc0c545ef15f9c1d823a1285413154fcdf Mon Sep 17 00:00:00 2001 From: Matan Shabtay Date: Mon, 23 Sep 2024 14:10:18 +0300 Subject: [PATCH 257/465] Adding MdcSubscriptionDefenderPlan --- CHANGELOG.md | 3 +- .../MSFT_MdcSubscriptionDefenderPlan.psm1 | 475 ++++++++++++++++++ ...SFT_MdcSubscriptionDefenderPlan.schema.mof | 18 + .../readme.md | 12 + .../settings.json | 20 + .../MdcSubscriptionDefenderPlan/2-Update.ps1 | 37 ++ ...5DSC.MdcSubscriptionDefenderPlan.Tests.ps1 | 176 +++++++ 7 files changed, 740 insertions(+), 1 deletion(-) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/MdcSubscriptionDefenderPlan/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.MdcSubscriptionDefenderPlan.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bf8282a0c..c1f55085e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Change log for Microsoft365DSC # UNRELEASED - +* MdcSubscriptionDefenderPlan + * Initial release * AADPasswordRuleSettings * Initial release * ADOOrganizationOwner diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.psm1 new file mode 100644 index 0000000000..bcb06d6007 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.psm1 @@ -0,0 +1,475 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $SubscriptionName, + + [Parameter(Mandatory = $true)] + [System.String] + $PlanName, + + [Parameter()] + [System.String] + $SubscriptionId, + + [Parameter()] + [ValidateSet('Free', 'Standard')] + [System.String] + $PricingTier, + + [Parameter()] + [System.String] + $SubPlanName, + + [Parameter()] + [System.String] + $Extensions, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'Azure' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + if (-not [System.String]::IsNullOrEmpty($SubscriptionId)) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.SubscriptionId -eq $SubscriptionId -and $_.Name -eq $PlanName} + } + elseif ($null -eq $instance -and -not [System.String]::IsNullOrEmpty($SubscriptionName)) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.SubscriptionName -eq $SubscriptionName -and $_.Name -eq $PlanName} + } + } + else + { + $subscriptionId = $SubscriptionId + if ([System.String]::IsNullOrEmpty($subscriptionId)) + { + $subscription = Get-AzSubscription -SubscriptionName $SubscriptionName + + if($subscription -ne $null) + { + $subscriptionId = $subscription.Id + } + } + + + if($subscriptionId -ne $null) + { + Set-AzContext -Subscription $subscriptionId -ErrorAction Stop + $instance = Get-AzSecurityPricing -Name $PlanName -ErrorAction Stop + $azContext = Get-AzContext + Add-Member -InputObject $instance -NotePropertyName "SubscriptionName" -NotePropertyValue $azContext.Subscription.Name + Add-Member -InputObject $instance -NotePropertyName "SubscriptionId" -NotePropertyValue $azContext.Subscription.Id + } + + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + SubscriptionId = $instance.SubscriptionId + SubscriptionName = $instance.SubscriptionName + PlanName = $PlanName + PricingTier = $instance.PricingTier + SubPlanName = $instance.SubPlan + Extensions = $instance.Extensions + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $SubscriptionName, + + [Parameter(Mandatory = $true)] + [System.String] + $PlanName, + + [Parameter()] + [System.String] + $SubscriptionId, + + [Parameter()] + [ValidateSet('Free', 'Standard')] + [System.String] + $PricingTier, + + [Parameter()] + [System.String] + $SubPlanName, + + [Parameter()] + [System.String] + $Extensions, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + throw "It's not possible to create Microsoft Defender for Cloud bundles" + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Set-AzContext -Subscription $currentInstance.SubscriptionId -ErrorAction Stop + if($Extensions) + { + Set-AzSecurityPricing -Name $PlanName -PricingTier $PricingTier -SubPlan $SubPlanName -Extension $Extensions -ErrorAction Stop + } + else + { + Set-AzSecurityPricing -Name $PlanName -PricingTier $PricingTier -SubPlan $SubPlanName -ErrorAction Stop + } + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + throw "It's not possible to delete Microsoft Defender for Cloud bundles" + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $SubscriptionName, + + [Parameter(Mandatory = $true)] + [System.String] + $PlanName, + + [Parameter()] + [System.String] + $SubscriptionId, + + [Parameter()] + [ValidateSet('Free', 'Standard')] + [System.String] + $PricingTier, + + [Parameter()] + [System.String] + $SubPlanName, + + [Parameter()] + [System.String] + $Extensions, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'Azure' ` + -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 + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-SubscriptionsDefenderPlansFromArg -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + SubscriptionName = $config.SubscriptionName + SubscriptionId = $config.SubscriptionId + PlanName = $config.PlanName + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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 '' + } +} + + +function Get-SubscriptionsDefenderPlansFromArg +{ + $results = @() + $argQuery=@' +securityresources | where type == "microsoft.security/pricings" | project Id=id, PlanName=name, SubscriptionId=subscriptionId, SubPlan=tostring(properties.subPlan), PricingTier=tostring(properties.pricingTier), Extensions=tostring(properties.extensions) +| join kind=inner (resourcecontainers | where type == "microsoft.resources/subscriptions" | project SubscriptionName = name, SubscriptionId = subscriptionId) on SubscriptionId | project-away SubscriptionId1 +'@ + $queryResult = Search-AzGraph -Query $argQuery -First 1000 -UseTenantScope -ErrorAction Stop + $results+=$queryResult.Data + + while($queryResult.SkipToken -ne $null) + { + $queryResult = Search-AzGraph -Query $argQuery -First 1000 -UseTenantScope -SkipToken $queryResult.SkipToken -ErrorAction Stop + $results+=$queryResult.Data + } + + return $results +} + + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.schema.mof new file mode 100644 index 0000000000..ace2e3f567 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.schema.mof @@ -0,0 +1,18 @@ +[ClassVersion("1.0.0.0"), FriendlyName("MdcSubscriptionDefenderPlan")] +class MSFT_MdcSubscriptionDefenderPlan : OMI_BaseResource +{ + [Key, Description("The display name of the subscription.")] String SubscriptionName; + [Key, Description("The Defender plan name, for the list all of possible Defender plans refer to Defender for Cloud documentation")] String PlanName; + [Write, ("The unique identifier of the Azure subscription.")] String SubscriptionId; + [Write, Description("The pricing tier ('Standard' or 'Free')")] String PricingTier; + [Write, Description("The Defender sub plan name, for the list all of possible sub plans refer to Defender for Cloud documentation")] String SubPlanName; + [Write, Description("The extensions offered under the plan, for more information refer to Defender for Cloud documentation")] String Extensions; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] 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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/readme.md new file mode 100644 index 0000000000..6cd90a1442 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/readme.md @@ -0,0 +1,12 @@ + +# MdcSubscriptionDefenderPlan + +## Description + +Enables or disables Microsoft Defender plans for a subscription in Microsoft Defender for Cloud. +For more information about the available Defender plans, sub plans and plan extensions refer to Defender for Cloud onboarding API documentation. +https://learn.microsoft.com/en-us/rest/api/defenderforcloud/pricings/update?view=rest-defenderforcloud-2024-01-01&tabs=HTTP + + +To have all security features enabled during plan enablement, make sure to assign the required Azure RBAC permissions to the application running this module. +For more information about the required permissions refer to the documentation https://learn.microsoft.com/en-us/azure/defender-for-cloud/permissions. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/settings.json new file mode 100644 index 0000000000..3b429806ed --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/settings.json @@ -0,0 +1,20 @@ +{ + "resourceName": "MdcSubscriptionDefenderPlan", + "description": "Enables or disables Microsoft Defender plans for a subscription in Microsoft Defender for Cloud.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/MdcSubscriptionDefenderPlan/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/MdcSubscriptionDefenderPlan/2-Update.ps1 new file mode 100644 index 0000000000..00f0025e55 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/MdcSubscriptionDefenderPlan/2-Update.ps1 @@ -0,0 +1,37 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + MdcSubscriptionDefenderPlan 'TestSubscription' + { + SubscriptionName = 'MyTestSubscription' + PlanName = 'VirtualMachines' + SubPlanName = 'P2' + PricingTier = 'Standard' + SubscriptionId = 'd620d94d-916d-4dd9-9de5-179292873e20' + Enabled = $true + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.MdcSubscriptionDefenderPlan.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.MdcSubscriptionDefenderPlan.Tests.ps1 new file mode 100644 index 0000000000..83ebbe1e43 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.MdcSubscriptionDefenderPlan.Tests.ps1 @@ -0,0 +1,176 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length - 1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return 'Credentials' + } + + Mock -CommandName Set-AzSecurityPricing -MockWith { + } + + Mock -CommandName Set-AzContext -MockWith { + } + + # 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 instance exists and values are already in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + SubscriptionName = 'MySubscription' + PlanName = 'VirtualMachines' + SubPlanName = 'P2' + PricingTier = 'Standard' + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName Get-AzSubscription -MockWith { + return @{ + Id = '2974ccf2-1e67-4b74-a102-2d921b595a89' + Name = 'MySubscription' + } + } + + Mock -CommandName Get-AzContext -MockWith { + return @{ + Subscription = @{ + Id = '2974ccf2-1e67-4b74-a102-2d921b595a89' + Name = 'MySubscription' + } + } + } + + Mock -CommandName Get-AzSecurityPricing -MockWith { + return @{ + Name = 'VirtualMachines' + SubPlan = 'P2' + PricingTier = 'Standard' + Extensions = $null + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name 'The instance exists and values are NOT in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + SubscriptionName = 'MySubscription' + PlanName = 'VirtualMachines' + SubPlanName = 'P2' + PricingTier = 'Standard' + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName Get-AzSubscription -MockWith { + return @{ + Id = '2974ccf2-1e67-4b74-a102-2d921b595a89' + Name = 'MySubscription' + } + } + + Mock -CommandName Get-AzContext -MockWith { + return @{ + Subscription = @{ + Id = '2974ccf2-1e67-4b74-a102-2d921b595a89' + Name = 'MySubscription' + } + } + } + + Mock -CommandName Get-AzSecurityPricing -MockWith { + return @{ + Name = 'VirtualMachines' + PricingTier = 'Free' # Drift + SubPlan = $null + Extensions = $null + } + } + } + + 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-AzSecurityPricing -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Search-AzGraph -MockWith { + return @{ + Data = @( + @{ + SubscriptionId = '2974ccf2-1e67-4b74-a102-2d921b595a89' + SubscriptionName = 'MySubscription' + PlanName = 'VirtualMachines' + SubPlanName = 'P2' + PricingTier = 'Standard' + Extensions = $null + } + ) + } + } + } + + 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 bb53aaca49d041c6252242c97944768c07674886 Mon Sep 17 00:00:00 2001 From: Matan Shabtay Date: Mon, 23 Sep 2024 14:46:22 +0300 Subject: [PATCH 258/465] updated stubs --- .../MdcSubscriptionDefenderPlan/2-Update.ps1 | 1 - Tests/Unit/Stubs/Microsoft365.psm1 | 71 +++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/MdcSubscriptionDefenderPlan/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/MdcSubscriptionDefenderPlan/2-Update.ps1 index 00f0025e55..89955f7891 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/MdcSubscriptionDefenderPlan/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/MdcSubscriptionDefenderPlan/2-Update.ps1 @@ -28,7 +28,6 @@ Configuration Example SubPlanName = 'P2' PricingTier = 'Standard' SubscriptionId = 'd620d94d-916d-4dd9-9de5-179292873e20' - Enabled = $true ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 625bc887df..1cbd830f9e 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -67,6 +67,77 @@ function Get-AzSubscription ) } +function Get-AzSecurityPricing +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Name + ) +} + +function Set-AzSecurityPricing +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $PricingTier, + + [Parameter()] + [System.String] + $SubPlan, + + [Parameter()] + [System.String] + $Extension + ) +} + +function Get-AzContext +{ + [CmdletBinding()] + param() +} + +function Set-AzContext +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Subscription + ) +} + +function Search-AzGraph +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Query, + + [Parameter()] + [System.Int32] + $First, + + [Parameter()] + [System.String] + $SkipToken, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $UseTenantScope + ) +} + + function Enable-ATPProtectionPolicyRule { [CmdletBinding()] From 541e6983f877fd0c27bd3ab741fd062abf9008b0 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 23 Sep 2024 18:13:33 +0530 Subject: [PATCH 259/465] Added AuthenticationBehaviours --- .../MSFT_AADApplication.psm1 | 61 +++++++++++++++++++ .../MSFT_AADApplication.schema.mof | 8 +++ .../Dependencies/Manifest.psd1 | 4 ++ 3 files changed, 73 insertions(+) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 6ed5685d08..c06ecbe8f9 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -60,6 +60,10 @@ function Get-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $AuthenticationBehaviors, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $KeyCredentials, @@ -176,6 +180,22 @@ function Get-TargetResource { Write-Verbose -Message 'An instance of Azure AD App was retrieved.' + + if($AuthenticationBehaviors) + { + $AADBetaApp= Get-MgBetaApplication -ApplicationId $Id -ErrorAction SilentlyContinue + + $complexAuthenticationBehaviors = @{} + $complexAuthenticationBehaviors.Add('BlockAzureADGraphAccess', $AADBetaApp.authenticationBehaviors.blockAzureADGraphAccess) + $complexAuthenticationBehaviors.Add('RemoveUnverifiedEmailClaim', $AADBetaApp.authenticationBehaviors.removeUnverifiedEmailClaim) + $complexAuthenticationBehaviors.Add('RequireClientServicePrincipal', $AADBetaApp.authenticationBehaviors.requireClientServicePrincipal) + if ($complexAuthenticationBehaviors.values.Where({$null -ne $_}).Count -eq 0) + { + $complexAuthenticationBehaviors = $null + } + } + + $complexKeyCredentials = @() foreach ($currentkeyCredentials in $AADApp.keyCredentials) { @@ -269,6 +289,7 @@ function Get-TargetResource { $IsFallbackPublicClientValue = $AADApp.IsFallbackPublicClient } + $result = @{ DisplayName = $AADApp.DisplayName AvailableToOtherTenants = $AvailableToOtherTenantsValue @@ -284,6 +305,7 @@ function Get-TargetResource Owners = $OwnersValues ObjectId = $AADApp.Id AppId = $AADApp.AppId + AuthenticationBehaviors = $complexAuthenticationBehaviors KeyCredentials = $complexKeyCredentials PasswordCredentials = $complexPasswordCredentials AppRoles = $complexAppRoles @@ -381,6 +403,10 @@ function Set-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $AuthenticationBehaviors, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $KeyCredentials, @@ -494,6 +520,7 @@ function Set-TargetResource # App should exist but it doesn't $needToUpdatePermissions = $false + $needToUpdateAuthenticationBehaviors = $false $currentParameters.Remove('AppId') | Out-Null $currentParameters.Remove('Permissions') | Out-Null @@ -598,6 +625,7 @@ function Set-TargetResource $currentAADApp = New-MgApplication @currentParameters Write-Verbose -Message "Azure AD Application {$DisplayName} was successfully created" $needToUpdatePermissions = $true + $needToUpdateAuthenticationBehaviors = $true $tries = 1 $appEntity = $null @@ -624,6 +652,7 @@ function Set-TargetResource Update-MgApplication @currentParameters $currentAADApp.Add('ID', $AppIdValue) $needToUpdatePermissions = $true + $needToUpdateAuthenticationBehaviors = $true } # App exists but should not elseif ($Ensure -eq 'Absent' -and $currentAADApp.Ensure -eq 'Present') @@ -777,6 +806,14 @@ function Set-TargetResource Update-MgApplication -ApplicationId ($currentAADApp.Id) ` -RequiredResourceAccess $allRequiredAccess | Out-Null } + + if($needToUpdateAuthenticationBehaviors -and $AuthenticationBehaviors) + { + Write-Verbose -Message "Updating for Azure AD Application {$($currentAADApp.DisplayName)} with AuthenticationBehaviors:`r`n$($AuthenticationBehaviors| Out-String)" + Write-Verbose -Message "Current App Id: $($currentAADApp.AppId)" + + Update-MgBetaApplication -ApplicationId ($currentAADApp.Id) -AuthenticationBehaviors $AuthenticationBehaviors | Out-Null + } } function Test-TargetResource @@ -841,6 +878,10 @@ function Test-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $AuthenticationBehaviors, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $KeyCredentials, @@ -1054,6 +1095,21 @@ function Export-TargetResource $Results.Permissions = Get-M365DSCAzureADAppPermissionsAsString $Results.Permissions } + if ($null -ne $Results.AuthenticationBehaviors) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.AuthenticationBehaviors ` + -CIMInstanceName 'MicrosoftGraphauthenticationBehaviors' + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.AuthenticationBehaviors = $complexTypeStringResult + } + else + { + $Results.Remove('AuthenticationBehaviors') | Out-Null + } + } + if ($null -ne $Results.KeyCredentials) { $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` @@ -1111,6 +1167,11 @@ function Export-TargetResource -ParameterName 'Permissions' } + if ($Results.AuthenticationBehaviors) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "AuthenticationBehaviors" -IsCIMArray:$False + } + if ($Results.KeyCredentials) { $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "KeyCredentials" -IsCIMArray:$True diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof index 7bfee43b55..5c341a898e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof @@ -7,6 +7,13 @@ class MSFT_AADApplicationPermission [Write, Description("Represented whether or not the Admin consent been granted on the app.")] Boolean AdminConsentGranted; }; +[ClassVersion("1.0.0")] +class MSFT_MicrosoftGraphAuthenticationBehaviors +{ + [Write, Description("If false, allows the app to have extended access to Azure AD Graph until June 30, 2025 when Azure AD Graph is fully retired. For more information on Azure AD retirement updates, see June 2024 update on Azure AD Graph API retirement.")] Boolean BlockAzureADGraphAccess; + [Write, Description("If true, removes the email claim from tokens sent to an application when the email address's domain can't be verified.")] Boolean RemoveUnverifiedEmailClaim; + [Write, Description("If true, requires multitenant applications to have a service principal in the resource tenant as part of authorization checks before they're granted access tokens. This property is only modifiable for multitenant resource applications that rely on access from clients without a service principal and had this behavior as set to false by Microsoft. Tenant administrators should respond to security advisories sent through Azure Health Service events and the Microsoft 365 message center.")] Boolean RequireClientServicePrincipal; +}; [ClassVersion("1.0.0")] class MSFT_MicrosoftGraphKeyCredential @@ -55,6 +62,7 @@ class MSFT_AADApplication : OMI_BaseResource [Write, Description("User-defined URI(s) that uniquely identify a Web application within its Azure AD tenant, or within a verified custom domain.")] string IdentifierUris[]; [Write, Description("Specifies the fallback application type as public client, such as an installed application running on a mobile device. The default value is false, which means the fallback application type is confidential client such as web app. There are certain scenarios where Microsoft Entra ID cannot determine the client application type (for example, ROPC flow where it is configured without specifying a redirect URI). In those cases, Microsoft Entra ID will interpret the application type based on the value of this property.")] Boolean IsFallbackPublicClient; [Write, Description("Client applications that are tied to this resource application.")] string KnownClientApplications[]; + [Write, Description("The collection of breaking change behaviors related to token issuance that are configured for the application. Authentication behaviors are unset by default (null) and must be explicitly enabled or disabled. Nullable. Returned only on $select. For more information about authentication behaviors, see Manage application authenticationBehaviors to avoid unverified use of email claims for user identification or authorization."), EmbeddedInstance("MSFT_MicrosoftGraphauthenticationBehaviors")] String AuthenticationBehaviors; [Write, Description("The collection of password credentials associated with the application. Not nullable."), EmbeddedInstance("MSFT_MicrosoftGraphpasswordCredential")] String PasswordCredentials[]; [Write, Description("The collection of key credentials associated with the application. Not nullable. Supports $filter (eq, not, ge, le)."), EmbeddedInstance("MSFT_MicrosoftGraphkeyCredential")] String KeyCredentials[]; [Write, Description("The collection of roles defined for the application. With app role assignments, these roles can be assigned to users, groups, or service principals associated with other applications. Not nullable."), EmbeddedInstance("MSFT_MicrosoftGraphappRole")] String AppRoles[]; diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 85952adab5..359a525fa3 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -24,6 +24,10 @@ ModuleName = 'Microsoft.Graph.Applications' RequiredVersion = '2.23.0' }, + @{ + ModuleName = 'Microsoft.Graph.Beta.Applications' + Requiredversion = '2.23.0' + }, @{ ModuleName = 'Microsoft.Graph.Authentication' RequiredVersion = '2.23.0' From 3c5597c33f381e785fa0554cad1b0b97832bfbca Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 23 Sep 2024 18:33:33 +0530 Subject: [PATCH 260/465] minor fix --- .../DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index c06ecbe8f9..f22d4a27e4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -183,7 +183,7 @@ function Get-TargetResource if($AuthenticationBehaviors) { - $AADBetaApp= Get-MgBetaApplication -ApplicationId $Id -ErrorAction SilentlyContinue + $AADBetaApp= Get-MgBetaApplication -Property "id,displayName,appId,authenticationBehaviors" -ApplicationId $Id -ErrorAction SilentlyContinue $complexAuthenticationBehaviors = @{} $complexAuthenticationBehaviors.Add('BlockAzureADGraphAccess', $AADBetaApp.authenticationBehaviors.blockAzureADGraphAccess) From 0fa970fd2e8a0f3ed5a33f9b40d6c56cea262029 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 23 Sep 2024 22:06:49 +0530 Subject: [PATCH 261/465] fixes --- .../MSFT_AADApplication.psm1 | 49 +++++++++++++++---- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index f22d4a27e4..5d5b25809f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -181,18 +181,24 @@ function Get-TargetResource Write-Verbose -Message 'An instance of Azure AD App was retrieved.' - if($AuthenticationBehaviors) - { - $AADBetaApp= Get-MgBetaApplication -Property "id,displayName,appId,authenticationBehaviors" -ApplicationId $Id -ErrorAction SilentlyContinue + $AADBetaApp= Get-MgBetaApplication -Property "id,displayName,appId,authenticationBehaviors" -ApplicationId $Id -ErrorAction SilentlyContinue - $complexAuthenticationBehaviors = @{} + $complexAuthenticationBehaviors = @{} + if ($null -ne $AADBetaApp.authenticationBehaviors.blockAzureADGraphAccess) + { $complexAuthenticationBehaviors.Add('BlockAzureADGraphAccess', $AADBetaApp.authenticationBehaviors.blockAzureADGraphAccess) + } + if ($null -ne $AADBetaApp.authenticationBehaviors.removeUnverifiedEmailClaim) + { $complexAuthenticationBehaviors.Add('RemoveUnverifiedEmailClaim', $AADBetaApp.authenticationBehaviors.removeUnverifiedEmailClaim) + } + if ($null -ne $AADBetaApp.authenticationBehaviors.requireClientServicePrincipal) + { $complexAuthenticationBehaviors.Add('RequireClientServicePrincipal', $AADBetaApp.authenticationBehaviors.requireClientServicePrincipal) - if ($complexAuthenticationBehaviors.values.Where({$null -ne $_}).Count -eq 0) - { - $complexAuthenticationBehaviors = $null - } + } + if ($complexAuthenticationBehaviors.values.Where({$null -ne $_}).Count -eq 0) + { + $complexAuthenticationBehaviors = $null } @@ -523,6 +529,7 @@ function Set-TargetResource $needToUpdateAuthenticationBehaviors = $false $currentParameters.Remove('AppId') | Out-Null $currentParameters.Remove('Permissions') | Out-Null + $currentParameters.Remove('AuthenticationBehaviors)') | Out-Null if ($currentParameters.AvailableToOtherTenants) { @@ -990,11 +997,35 @@ function Test-TargetResource $ValuesToCheck.Remove('AppId') | Out-Null $ValuesToCheck.Remove('Permissions') | Out-Null - $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($source.getType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-Not $testResult) + { + $testResult = $false + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } + + if($TestResult) + { + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` -DesiredValues $PSBoundParameters ` -ValuesToCheck $ValuesToCheck.Keys ` -IncludedDrifts $driftedParams + } Write-Verbose -Message "Test-TargetResource returned $TestResult" From 066b976e6da32963759e4ea865d9874594c4c5f8 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 23 Sep 2024 22:14:56 +0530 Subject: [PATCH 262/465] fix --- .../DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 5d5b25809f..ab04c0b2af 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -181,7 +181,7 @@ function Get-TargetResource Write-Verbose -Message 'An instance of Azure AD App was retrieved.' - $AADBetaApp= Get-MgBetaApplication -Property "id,displayName,appId,authenticationBehaviors" -ApplicationId $Id -ErrorAction SilentlyContinue + $AADBetaApp= Get-MgBetaApplication -Property "id,displayName,appId,authenticationBehaviors" -ApplicationId $ObjectID -ErrorAction SilentlyContinue $complexAuthenticationBehaviors = @{} if ($null -ne $AADBetaApp.authenticationBehaviors.blockAzureADGraphAccess) From d57b6e252d0025b045db3a354a1c4784555b9227 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 23 Sep 2024 12:46:01 -0400 Subject: [PATCH 263/465] Initial --- .../MSFT_SCInsiderRiskPolicy.psm1 | 450 ++++++++++++++++++ .../MSFT_SCInsiderRiskPolicy.schema.mof | 14 + .../MSFT_SCInsiderRiskPolicy/readme.md | 6 + .../MSFT_SCInsiderRiskPolicy/settings.json | 32 ++ .../SCInsiderRiskPolicy/1-Create.ps1 | 26 + .../SCInsiderRiskPolicy/2-Update.ps1 | 26 + .../SCInsiderRiskPolicy/3-Remove.ps1 | 26 + ...rosoft365DSC.SCInsiderRiskPolicy.Tests.ps1 | 177 +++++++ 8 files changed, 757 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskPolicy.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 new file mode 100644 index 0000000000..40a7943a85 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 @@ -0,0 +1,450 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $IsSingleInstance = 'Yes', + + [Parameter()] + [System.Boolean] + $DLPUserRiskSync, + + [Parameter()] + [System.Boolean] + $OptInIRMDataExport, + + [Parameter()] + [System.Boolean] + $RaiseAuditAlert, + + ##TODO - Add the list of Parameters + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace the workload by the one associated to your resource + New-M365DSCConnection -Workload 'Workload' ` + -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 + { + $instance = Get-InsiderRiskPolicy -ErrorAction Stop + $tenantSettings = ConvertFrom-Json $instance.TenantSettings + + $results = @{ + IsSingleInstance = 'Yes' + DLPUserRiskSync = [Boolean]$tenantSettings.FeatureSettings.DLPUserRiskSync + OptInIRMDataExport = [Boolean]$tenantSettings.FeatureSettings.OptInIRMDataExport + RaiseAuditAlert = [Boolean]$tenantSettings.FeatureSettings.RaiseAuditAlert + FileVolCutoffLimits = $tenantSettings.IntelligentDetections.FileVolCutoffLimits + AlertVolume = $tenantSettings.IntelligentDetections.AlertVolume + AnomalyDetections = [Boolean]$tenantSettings.Indicators.AnomalyDetections + CopyToPersonalCloud = [Boolean]$tenantSettings.Indicators. + CopyToUSB = [Boolean]$tenantSettings.Indicators. + CumulativeExfiltrationDetector = [Boolean]$tenantSettings.Indicators. + EmailExternal = [Boolean]$tenantSettings.Indicators. + EmployeeAccessedEmployeePatientData = [Boolean]$tenantSettings.Indicators. + EmployeeAccessedFamilyData = [Boolean]$tenantSettings.Indicators. + EmployeeAccessedHighVolumePatientData = [Boolean]$tenantSettings.Indicators. + EmployeeAccessedNeighbourData = [Boolean]$tenantSettings.Indicators. + EmployeeAccessedRestrictedData = [Boolean]$tenantSettings.Indicators. + EpoBrowseToChildAbuseSites = [Boolean]$tenantSettings.Indicators. + EpoBrowseToCriminalActivitySites = [Boolean]$tenantSettings.Indicators. + EpoBrowseToCultSites = [Boolean]$tenantSettings.Indicators. + EpoBrowseToGamblingSites = [Boolean]$tenantSettings.Indicators. + EpoBrowseToHackingSites = [Boolean]$tenantSettings.Indicators. + EpoBrowseToHateIntoleranceSites = [Boolean]$tenantSettings.Indicators. + EpoBrowseToIllegalSoftwareSites = [Boolean]$tenantSettings.Indicators. + EpoBrowseToKeyloggerSites = [Boolean]$tenantSettings.Indicators. + EpoBrowseToLlmSites = [Boolean]$tenantSettings.Indicators. + EpoBrowseToMalwareSites = [Boolean]$tenantSettings.Indicators. + EpoBrowseToPhishingSites = [Boolean]$tenantSettings.Indicators. + EpoBrowseToPornographySites = [Boolean]$tenantSettings.Indicators. + EpoBrowseToUnallowedDomain = [Boolean]$tenantSettings.Indicators. + EpoBrowseToViolenceSites = [Boolean]$tenantSettings.Indicators. + EpoCopyToClipboardFromSensitiveFile = [Boolean]$tenantSettings.Indicators. + EpoCopyToNetworkShare = [Boolean]$tenantSettings.Indicators. + EpoFileArchived = [Boolean]$tenantSettings.Indicators. + EpoFileCopiedToRemoteDesktopSession = [Boolean]$tenantSettings.Indicators. + EpoFileDeleted = [Boolean]$tenantSettings.Indicators. + EpoFileDownloadedFromBlacklistedDomain = [Boolean]$tenantSettings.Indicators. + EpoFileDownloadedFromEnterpriseDomain = [Boolean]$tenantSettings.Indicators. + EpoFileRenamed = [Boolean]$tenantSettings.Indicators. + EpoFileStagedToCentralLocation = [Boolean]$tenantSettings.Indicators. + EpoHiddenFileCreated = [Boolean]$tenantSettings.Indicators. + EpoRemovableMediaMount = [Boolean]$tenantSettings.Indicators. + EpoSensitiveFileRead = [Boolean]$tenantSettings.Indicators. + Mcas3rdPartyAppDownload = [Boolean]$tenantSettings.Indicators. + Mcas3rdPartyAppFileDelete = [Boolean]$tenantSettings.Indicators. + Mcas3rdPartyAppFileSharing = [Boolean]$tenantSettings.Indicators. + McasActivityFromInfrequentCountry = [Boolean]$tenantSettings.Indicators. + McasImpossibleTravel = [Boolean]$tenantSettings.Indicators. + McasMultipleFailedLogins = [Boolean]$tenantSettings.Indicators. + McasMultipleStorageDeletion = [Boolean]$tenantSettings.Indicators. + McasMultipleVMCreation = [Boolean]$tenantSettings.Indicators. + McasMultipleVMDeletion = [Boolean]$tenantSettings.Indicators. + McasSuspiciousAdminActivities = [Boolean]$tenantSettings.Indicators. + McasSuspiciousCloudCreation = [Boolean]$tenantSettings.Indicators. + McasSuspiciousCloudTrailLoggingChange = [Boolean]$tenantSettings.Indicators. + McasTerminatedEmployeeActivity = [Boolean]$tenantSettings.Indicators. + OdbDownload = [Boolean]$tenantSettings.Indicators. + OdbSyncDownload = [Boolean]$tenantSettings.Indicators. + PeerCumulativeExfiltrationDetector = [Boolean]$tenantSettings.Indicators. + PhysicalAccess = [Boolean]$tenantSettings.Indicators. + PotentialHighImpactUser = [Boolean]$tenantSettings.Indicators. + Print = [Boolean]$tenantSettings.Indicators. + PriorityUserGroupMember = [Boolean]$tenantSettings.Indicators. + SecurityAlertDefenseEvasion = [Boolean]$tenantSettings.Indicators. + SecurityAlertUnwantedSoftware = [Boolean]$tenantSettings.Indicators. + SpoAccessRequest = [Boolean]$tenantSettings.Indicators. + SpoApprovedAccess = [Boolean]$tenantSettings.Indicators. + SpoDownload = [Boolean]$tenantSettings.Indicators. + SpoDownloadV2 = [Boolean]$tenantSettings.Indicators. + SpoFileAccessed = [Boolean]$tenantSettings.Indicators. + SpoFileDeleted = [Boolean]$tenantSettings.Indicators.SpoFileDeleted + SpoFileDeletedFromFirstStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFileDeletedFromFirstStageRecycleBin + SpoFileDeletedFromSecondStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFileDeletedFromSecondStageRecycleBin + SpoFileLabelDowngraded = [Boolean]$tenantSettings.Indicators.SpoFileLabelDowngraded + SpoFileLabelRemoved = [Boolean]$tenantSettings.Indicators.SpoFileLabelRemoved + SpoFileSharing = [Boolean]$tenantSettings.Indicators.SpoFileSharing + SpoFolderDeleted = [Boolean]$tenantSettings.Indicators.SpoFolderDeleted + SpoFolderDeletedFromFirstStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFolderDeletedFromFirstStageRecycleBin + SpoFolderDeletedFromSecondStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFolderDeletedFromSecondStageRecycleBin + SpoFolderSharing = [Boolean]$tenantSettings.Indicators.SpoFolderSharing + SpoSiteExternalUserAdded = [Boolean]$tenantSettings.Indicators.SpoSiteExternalUserAdded + SpoSiteInternalUserAdded = [Boolean]$tenantSettings.Indicators.SpoSiteInternalUserAdded + SpoSiteLabelRemoved = [Boolean]$tenantSettings.Indicators.SpoSiteLabelRemoved + SpoSiteSharing = [Boolean]$tenantSettings.Indicators.SpoSiteSharing + SpoSyncDownload = [Boolean]$tenantSettings.Indicators.SpoSyncDownload + TeamsChannelFileSharedExternal = [Boolean]$tenantSettings.Indicators.TeamsChannelFileSharedExternal + TeamsChannelMemberAddedExternal = [Boolean]$tenantSettings.Indicators.TeamsChannelMemberAddedExternal + TeamsChatFileSharedExternal = [Boolean]$tenantSettings.Indicators.TeamsChatFileSharedExternal + TeamsFileDownload = [Boolean]$tenantSettings.Indicators.TeamsFileDownload + TeamsFolderSharedExternal = [Boolean]$tenantSettings.Indicators.TeamsFolderSharedExternal + TeamsMemberAddedExternal = [Boolean]$tenantSettings.Indicators.TeamsMemberAddedExternal + TeamsSensitiveMessage = [Boolean]$tenantSettings.Indicators.TeamsSensitiveMessage + UserHistory = [Boolean]$tenantSettings.Indicators.UserHistory + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + ##TODO - Replace by the New cmdlet for the resource + New-Cmdlet @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Update/Set cmdlet for the resource + Set-cmdlet @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Remove cmdlet for the resource + Remove-cmdlet @SetParameters + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace workload + $ConnectionMode = New-M365DSCConnection -Workload 'Workload' ` + -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 + { + $Script:ExportMode = $true + ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances + [array] $Script:exportedInstances = Get-Cmdlet -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + ##TODO - Specify the Primary Key + #PrimaryKey = $config.PrimaryKey + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof new file mode 100644 index 0000000000..be6b06c877 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof @@ -0,0 +1,14 @@ +[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] +class MSFT_ResourceName : OMI_BaseResource +{ + [Key, Description("")] String PrimaryKey; + [Write, Description("")] String OtherProperties; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] 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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/readme.md new file mode 100644 index 0000000000..32e0e7fb27 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/readme.md @@ -0,0 +1,6 @@ + +# ResourceName + +## Description + +##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/settings.json new file mode 100644 index 0000000000..edf14b05e4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "ResourceName", + "description": "Description of what the resource is about.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/1-Create.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/1-Create.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/2-Update.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/3-Remove.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/3-Remove.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskPolicy.Tests.ps1 new file mode 100644 index 0000000000..f3ddc7d594 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskPolicy.Tests.ps1 @@ -0,0 +1,177 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -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 a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Set-TargetResource @testParams + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 remove the instance from the Set method' { + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + 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 + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 9ceb88029be2ebed829db44f36b1af78531a321d Mon Sep 17 00:00:00 2001 From: Matan Shabtay Date: Mon, 23 Sep 2024 19:48:06 +0300 Subject: [PATCH 264/465] Fixing the mof file --- .../MSFT_MdcSubscriptionDefenderPlan.schema.mof | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.schema.mof index ace2e3f567..3abb93040c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.schema.mof @@ -3,7 +3,7 @@ class MSFT_MdcSubscriptionDefenderPlan : OMI_BaseResource { [Key, Description("The display name of the subscription.")] String SubscriptionName; [Key, Description("The Defender plan name, for the list all of possible Defender plans refer to Defender for Cloud documentation")] String PlanName; - [Write, ("The unique identifier of the Azure subscription.")] String SubscriptionId; + [Write, Description("The unique identifier of the Azure subscription.")] String SubscriptionId; [Write, Description("The pricing tier ('Standard' or 'Free')")] String PricingTier; [Write, Description("The Defender sub plan name, for the list all of possible sub plans refer to Defender for Cloud documentation")] String SubPlanName; [Write, Description("The extensions offered under the plan, for more information refer to Defender for Cloud documentation")] String Extensions; @@ -16,3 +16,4 @@ class MSFT_MdcSubscriptionDefenderPlan : OMI_BaseResource [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; [Write, Description("Access token used for authentication.")] String AccessTokens[]; }; + From f0e5c60645fce3d2c90e2e4fddbf7df5767f637e Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 23 Sep 2024 22:19:53 +0530 Subject: [PATCH 265/465] fix --- .../DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index ab04c0b2af..62fe42656e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -992,7 +992,7 @@ function Test-TargetResource Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" - $ValuesToCheck = $PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() $ValuesToCheck.Remove('ObjectId') | Out-Null $ValuesToCheck.Remove('AppId') | Out-Null $ValuesToCheck.Remove('Permissions') | Out-Null From fcc5e91386254c2b6a7680f81b9e08e122aedcf5 Mon Sep 17 00:00:00 2001 From: kasaxena5 Date: Tue, 24 Sep 2024 10:50:33 +0530 Subject: [PATCH 266/465] fixes --- .../MSFT_AADApplication.psm1 | 43 ++++++------------- 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index ab04c0b2af..5a9a60d5d0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -529,7 +529,7 @@ function Set-TargetResource $needToUpdateAuthenticationBehaviors = $false $currentParameters.Remove('AppId') | Out-Null $currentParameters.Remove('Permissions') | Out-Null - $currentParameters.Remove('AuthenticationBehaviors)') | Out-Null + $currentParameters.Remove('AuthenticationBehaviors') | Out-Null if ($currentParameters.AvailableToOtherTenants) { @@ -819,7 +819,13 @@ function Set-TargetResource Write-Verbose -Message "Updating for Azure AD Application {$($currentAADApp.DisplayName)} with AuthenticationBehaviors:`r`n$($AuthenticationBehaviors| Out-String)" Write-Verbose -Message "Current App Id: $($currentAADApp.AppId)" - Update-MgBetaApplication -ApplicationId ($currentAADApp.Id) -AuthenticationBehaviors $AuthenticationBehaviors | Out-Null + $IAuthenticationBehaviors = @{ + blockAzureADGraphAccess = $AuthenticationBehaviors.blockAzureADGraphAccess + removeUnverifiedEmailClaim = $AuthenticationBehaviors.removeUnverifiedEmailClaim + requireClientServicePrincipal = $AuthenticationBehaviors.requireClientServicePrincipal + } + + Update-MgBetaApplication -ApplicationId ($currentAADApp.Id) -AuthenticationBehaviors $IAuthenticationBehaviors | Out-Null } } @@ -997,35 +1003,12 @@ function Test-TargetResource $ValuesToCheck.Remove('AppId') | Out-Null $ValuesToCheck.Remove('Permissions') | Out-Null - #Compare Cim instances - foreach ($key in $PSBoundParameters.Keys) - { - $source = $PSBoundParameters.$key - $target = $CurrentValues.$key - if ($source.getType().Name -like '*CimInstance*') - { - $testResult = Compare-M365DSCComplexObject ` - -Source ($source) ` - -Target ($target) - - if (-Not $testResult) - { - $testResult = $false - break - } - - $ValuesToCheck.Remove($key) | Out-Null - } - } - if($TestResult) - { - $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` - -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` - -ValuesToCheck $ValuesToCheck.Keys ` - -IncludedDrifts $driftedParams - } + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys ` + -IncludedDrifts $driftedParams Write-Verbose -Message "Test-TargetResource returned $TestResult" From 18dd1ed2ff20bfdb6cfa0f79deaef45b31a8e8a1 Mon Sep 17 00:00:00 2001 From: kasaxena5 Date: Tue, 24 Sep 2024 16:49:46 +0530 Subject: [PATCH 267/465] Fix --- .../MSFT_AADApplication.psm1 | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 9cb04c35cc..b0296818a5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -995,10 +995,34 @@ function Test-TargetResource } } + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + + $testTargetResource = $true + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*' -and $source -notlike '*Permission*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-not $testResult) + { + $testTargetResource = $false + } + else { + $ValuesToCheck.Remove($key) | Out-Null + } + } + } + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" - $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() $ValuesToCheck.Remove('ObjectId') | Out-Null $ValuesToCheck.Remove('AppId') | Out-Null $ValuesToCheck.Remove('Permissions') | Out-Null @@ -1010,9 +1034,15 @@ function Test-TargetResource -ValuesToCheck $ValuesToCheck.Keys ` -IncludedDrifts $driftedParams - Write-Verbose -Message "Test-TargetResource returned $TestResult" + if(-not $TestResult) + { + $testTargetResource = $false + } + + + Write-Verbose -Message "Test-TargetResource returned $testTargetResource" - return $TestResult + return $testTargetResource } function Export-TargetResource From 01756e827925ff6d1b6e74fa2c823021b6044c7f Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 24 Sep 2024 14:21:52 +0000 Subject: [PATCH 268/465] Updated Resources and Cmdlet documentation pages --- .../intune/MdcSubscriptionDefenderPlan.md | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 docs/docs/resources/intune/MdcSubscriptionDefenderPlan.md diff --git a/docs/docs/resources/intune/MdcSubscriptionDefenderPlan.md b/docs/docs/resources/intune/MdcSubscriptionDefenderPlan.md new file mode 100644 index 0000000000..aeca74d777 --- /dev/null +++ b/docs/docs/resources/intune/MdcSubscriptionDefenderPlan.md @@ -0,0 +1,98 @@ +# MdcSubscriptionDefenderPlan + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **SubscriptionName** | Key | String | The display name of the subscription. | | +| **PlanName** | Key | String | The Defender plan name, for the list all of possible Defender plans refer to Defender for Cloud documentation | | +| **SubscriptionId** | Write | String | The unique identifier of the Azure subscription. | | +| **PricingTier** | Write | String | The pricing tier ('Standard' or 'Free') | | +| **SubPlanName** | Write | String | The Defender sub plan name, for the list all of possible sub plans refer to Defender for Cloud documentation | | +| **Extensions** | Write | String | The extensions offered under the plan, for more information refer to Defender for Cloud documentation | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Enables or disables Microsoft Defender plans for a subscription in Microsoft Defender for Cloud. +For more information about the available Defender plans, sub plans and plan extensions refer to Defender for Cloud onboarding API documentation. +https://learn.microsoft.com/en-us/rest/api/defenderforcloud/pricings/update?view=rest-defenderforcloud-2024-01-01&tabs=HTTP + + +To have all security features enabled during plan enablement, make sure to assign the required Azure RBAC permissions to the application running this module. +For more information about the required permissions refer to the documentation https://learn.microsoft.com/en-us/azure/defender-for-cloud/permissions. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + MdcSubscriptionDefenderPlan 'TestSubscription' + { + SubscriptionName = 'MyTestSubscription' + PlanName = 'VirtualMachines' + SubPlanName = 'P2' + PricingTier = 'Standard' + SubscriptionId = 'd620d94d-916d-4dd9-9de5-179292873e20' + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + From 5169f2244c7ef52cf69d7575f6284803cdca47ce Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 24 Sep 2024 14:24:26 +0000 Subject: [PATCH 269/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 7acf32a9b7..9eca5b6007 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -35974,6 +35974,76 @@ } ] }, + { + "ClassName": "MSFT_MdcSubscriptionDefenderPlan", + "Parameters": [ + { + "CIMType": "String", + "Name": "SubscriptionName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "PlanName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "SubscriptionId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PricingTier", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SubPlanName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Extensions", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_O365AdminAuditLogConfig", "Parameters": [ From 51b7a4e385765501de04f1d40601ca3907871283 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 24 Sep 2024 12:14:29 -0400 Subject: [PATCH 270/465] Updates --- .../MSFT_SCInsiderRiskPolicy.psm1 | 2205 +++++++++++++++-- .../MSFT_SCInsiderRiskPolicy.schema.mof | 148 +- 2 files changed, 2127 insertions(+), 226 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 index 40a7943a85..1285bc70ea 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 @@ -6,7 +6,7 @@ function Get-TargetResource ( [Parameter(Mandatory = $true)] [System.String] - $IsSingleInstance = 'Yes', + $Name, [Parameter()] [System.Boolean] @@ -20,261 +20,2027 @@ function Get-TargetResource [System.Boolean] $RaiseAuditAlert, - ##TODO - Add the list of Parameters + [Parameter()] + [System.String] + $FileVolCutoffLimits, + + [Parameter()] + [System.String] + $AlertVolume, + + [Parameter()] + [System.Boolean] + $AnomalyDetections, + + [Parameter()] + [System.Boolean] + $CopyToPersonalCloud, + + [Parameter()] + [System.Boolean] + $CopyToUSB, + + [Parameter()] + [System.Boolean] + $CumulativeExfiltrationDetector, + + [Parameter()] + [System.Boolean] + $EmailExternal, + + [Parameter()] + [System.Boolean] + $EmployeeAccessedEmployeePatientData, + + [Parameter()] + [System.Boolean] + $EmployeeAccessedFamilyData, + + [Parameter()] + [System.Boolean] + $EmployeeAccessedHighVolumePatientData, + + [Parameter()] + [System.Boolean] + $EmployeeAccessedNeighbourData, + + [Parameter()] + [System.Boolean] + $EmployeeAccessedRestrictedData, + + [Parameter()] + [System.Boolean] + $EpoBrowseToChildAbuseSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToCriminalActivitySites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToCultSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToGamblingSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToHackingSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToHateIntoleranceSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToIllegalSoftwareSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToKeyloggerSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToLlmSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToMalwareSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToPhishingSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToPornographySites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToUnallowedDomain, + + [Parameter()] + [System.Boolean] + $EpoBrowseToViolenceSites, + + [Parameter()] + [System.Boolean] + $EpoCopyToClipboardFromSensitiveFile, + + [Parameter()] + [System.Boolean] + $EpoCopyToNetworkShare, + + [Parameter()] + [System.Boolean] + $EpoFileArchived, + + [Parameter()] + [System.Boolean] + $EpoFileCopiedToRemoteDesktopSession, + + [Parameter()] + [System.Boolean] + $EpoFileDeleted, + + [Parameter()] + [System.Boolean] + $EpoFileDownloadedFromBlacklistedDomain, + + [Parameter()] + [System.Boolean] + $EpoFileDownloadedFromEnterpriseDomain, + + [Parameter()] + [System.Boolean] + $EpoFileRenamed, + + [Parameter()] + [System.Boolean] + $EpoFileStagedToCentralLocation, + + [Parameter()] + [System.Boolean] + $EpoHiddenFileCreated, + + [Parameter()] + [System.Boolean] + $EpoRemovableMediaMount, + + [Parameter()] + [System.Boolean] + $EpoSensitiveFileRead, + + [Parameter()] + [System.Boolean] + $Mcas3rdPartyAppDownload, + + [Parameter()] + [System.Boolean] + $Mcas3rdPartyAppFileDelete, + + [Parameter()] + [System.Boolean] + $Mcas3rdPartyAppFileSharing, + + [Parameter()] + [System.Boolean] + $McasActivityFromInfrequentCountry, + + [Parameter()] + [System.Boolean] + $McasImpossibleTravel, + + [Parameter()] + [System.Boolean] + $McasMultipleFailedLogins, + + [Parameter()] + [System.Boolean] + $McasMultipleStorageDeletion, + + [Parameter()] + [System.Boolean] + $McasMultipleVMCreation, + + [Parameter()] + [System.Boolean] + $McasMultipleVMDeletion, + + [Parameter()] + [System.Boolean] + $McasSuspiciousAdminActivities, + + [Parameter()] + [System.Boolean] + $McasSuspiciousCloudCreation, + + [Parameter()] + [System.Boolean] + $McasSuspiciousCloudTrailLoggingChange, + + [Parameter()] + [System.Boolean] + $McasTerminatedEmployeeActivity, + + [Parameter()] + [System.Boolean] + $OdbDownload, + + [Parameter()] + [System.Boolean] + $OdbSyncDownload, + + [Parameter()] + [System.Boolean] + $PeerCumulativeExfiltrationDetector, + + [Parameter()] + [System.Boolean] + $PhysicalAccess, + + [Parameter()] + [System.Boolean] + $PotentialHighImpactUser, + + [Parameter()] + [System.Boolean] + $Print, + + [Parameter()] + [System.Boolean] + $PriorityUserGroupMember, + + [Parameter()] + [System.Boolean] + $SecurityAlertDefenseEvasion, + + [Parameter()] + [System.Boolean] + $SecurityAlertUnwantedSoftware, + + [Parameter()] + [System.Boolean] + $SpoAccessRequest, + + [Parameter()] + [System.Boolean] + $SpoApprovedAccess, + + [Parameter()] + [System.Boolean] + $SpoDownload, + + [Parameter()] + [System.Boolean] + $SpoDownloadV2, + + [Parameter()] + [System.Boolean] + $SpoFileAccessed, + + [Parameter()] + [System.Boolean] + $SpoFileDeleted, + + [Parameter()] + [System.Boolean] + $SpoFileDeletedFromFirstStageRecycleBin, + + [Parameter()] + [System.Boolean] + $SpoFileDeletedFromSecondStageRecycleBin, + + [Parameter()] + [System.Boolean] + $SpoFileLabelDowngraded, + + [Parameter()] + [System.Boolean] + $SpoFileLabelRemoved, + + [Parameter()] + [System.Boolean] + $SpoFileSharing, + + [Parameter()] + [System.Boolean] + $SpoFolderDeleted, + + [Parameter()] + [System.Boolean] + $SpoFolderDeletedFromFirstStageRecycleBin, + + [Parameter()] + [System.Boolean] + $SpoFolderDeletedFromSecondStageRecycleBin, + + [Parameter()] + [System.Boolean] + $SpoFolderSharing, + + [Parameter()] + [System.Boolean] + $SpoSiteExternalUserAdded, + + [Parameter()] + [System.Boolean] + $SpoSiteInternalUserAdded, + + [Parameter()] + [System.Boolean] + $SpoSiteLabelRemoved, + + [Parameter()] + [System.Boolean] + $SpoSiteSharing, + + [Parameter()] + [System.Boolean] + $SpoSyncDownload, + + [Parameter()] + [System.Boolean] + $TeamsChannelFileSharedExternal, + + [Parameter()] + [System.Boolean] + $TeamsChannelMemberAddedExternal, + + [Parameter()] + [System.Boolean] + $TeamsChatFileSharedExternal, + + [Parameter()] + [System.Boolean] + $TeamsFileDownload, + + [Parameter()] + [System.Boolean] + $TeamsFolderSharedExternal, + + [Parameter()] + [System.Boolean] + $TeamsMemberAddedExternal, + + [Parameter()] + [System.Boolean] + $TeamsSensitiveMessage, + + [Parameter()] + [System.Boolean] + $UserHistory, + + [Parameter()] + [System.Boolean] + $AWSS3BlockPublicAccessDisabled, + + [Parameter()] + [System.Boolean] + $AWSS3BucketDeleted, + + [Parameter()] + [System.Boolean] + $AWSS3PublicAccessEnabled, + + [Parameter()] + [System.Boolean] + $AWSS3ServerLoggingDisabled, + + [Parameter()] + [System.Boolean] + $AzureElevateAccessToAllSubscriptions, + + [Parameter()] + [System.Boolean] + $AzureResourceThreatProtectionSettingsUpdated, + + [Parameter()] + [System.Boolean] + $AzureSQLServerAuditingSettingsUpdated, + + [Parameter()] + [System.Boolean] + $AzureSQLServerFirewallRuleDeleted, + + [Parameter()] + [System.Boolean] + $AzureSQLServerFirewallRuleUpdated, + + [Parameter()] + [System.Boolean] + $AzureStorageAccountOrContainerDeleted, + + [Parameter()] + [System.Boolean] + $BoxContentAccess, + + [Parameter()] + [System.Boolean] + $BoxContentDelete, + + [Parameter()] + [System.Boolean] + $BoxContentDownload, + + [Parameter()] + [System.Boolean] + $BoxContentExternallyShared, + + [Parameter()] + [System.Boolean] + $CCFinancialRegulatoryRiskyTextSent, + + [Parameter()] + [System.Boolean] + $CCInappropriateContentSent, + + [Parameter()] + [System.Boolean] + $CCInappropriateImagesSent, + + [Parameter()] + [System.Boolean] + $DropboxContentAccess, + + [Parameter()] + [System.Boolean] + $DropboxContentDelete, + + [Parameter()] + [System.Boolean] + $DropboxContentDownload, + + [Parameter()] + [System.Boolean] + $DropboxContentExternallyShared, + + [Parameter()] + [System.Boolean] + $GoogleDriveContentAccess, + + [Parameter()] + [System.Boolean] + $GoogleDriveContentDelete, + + [Parameter()] + [System.Boolean] + $GoogleDriveContentExternallyShared, + + [Parameter()] + [System.Boolean] + $PowerBIDashboardsDeleted, + + [Parameter()] + [System.Boolean] + $PowerBIReportsDeleted, + + [Parameter()] + [System.Boolean] + $PowerBIReportsDownloaded, + + [Parameter()] + [System.Boolean] + $PowerBIReportsExported, + + [Parameter()] + [System.Boolean] + $PowerBIReportsViewed, + + [Parameter()] + [System.Boolean] + $PowerBISemanticModelsDeleted, + + [Parameter()] + [System.Boolean] + $PowerBISensitivityLabelDowngradedForArtifacts, + + [Parameter()] + [System.Boolean] + $PowerBISensitivityLabelRemovedFromArtifacts, + + [Parameter()] + [System.String] + $HistoricTimeSpan, + + [Parameter()] + [System.String] + $InScopeTimeSpan, + + [Parameter()] + [System.Boolean] + $EnableTeam, + + [Parameter()] + [System.Boolean] + $AnalyticsNewInsightEnabled, + + [Parameter()] + [System.Boolean] + $AnalyticsTurnedOffEnabled, + + [Parameter()] + [System.Boolean] + $HighSeverityAlertsEnabled, + + [Parameter()] + [System.String[]] + $HighSeverityAlertsRoleGroups, + + [Parameter()] + [System.Boolean] + $PoliciesHealthEnabled, + + [Parameter()] + [System.String[]] + $PoliciesHealthRoleGroups, + + [Parameter()] + [System.Boolean] + $NotificationDetailsEnabled, + + [Parameter()] + [System.String[]] + $NotificationDetailsRoleGroups, + + [Parameter()] + [System.Boolean] + $ClipDeletionEnabled, + + [Parameter()] + [System.Boolean] + $SessionRecordingEnabled, + + [Parameter()] + [System.Boolean] + $RecordingTimeframePreEventInSec, + + [Parameter()] + [System.Boolean] + $RecordingTimeframePostEventInSec, + + [Parameter()] + [System.Boolean] + $BandwidthCapInMb, + + [Parameter()] + [System.Boolean] + $OfflineRecordingStorageLimitInMb, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + 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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Name -eq $Name} + } + else + { + $instance = Get-InsiderRiskPolicy -Identity $Name + } + + $results = @{ + Name = $instance.Name + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + if (-not [System.String]::IsNullOrEmpty($instance.SessionRecordingSettings)) + { + $SessionRecordingSettings = ConvertFrom-Json $instance.SessionRecordingSettings + $forensicSettingsHash = @{ + ClipDeletionEnabled = [Boolean]$SessionRecordingSettings.ClipDeletionEnabled + SessionRecordingEnabled = [Boolean]$SessionRecordingSettings.Enabled + RecordingTimeframePreEventInSec = $SessionRecordingSettings.RecordingTimeframePreEventInSec + RecordingTimeframePostEventInSec = $SessionRecordingSettings.RecordingTimeframePostEventInSec + BandwidthCapInMb = $SessionRecordingSettings.BandwidthCapInMb + OfflineRecordingStorageLimitInMb = $SessionRecordingSettings.OfflineRecordingStorageLimitInMb + } + $results += $forensicSettingsHash + } + + if (-not [System.String]::IsNullOrEmpty($instance.TenantSettings)) + { + $tenantSettings = ConvertFrom-Json $instance.TenantSettings[0] + $tenantSettingsHash = @{ + DLPUserRiskSync = [Boolean]$tenantSettings.FeatureSettings.DLPUserRiskSync + OptInIRMDataExport = [Boolean]$tenantSettings.FeatureSettings.OptInIRMDataExport + RaiseAuditAlert = [Boolean]$tenantSettings.FeatureSettings.RaiseAuditAlert + FileVolCutoffLimits = $tenantSettings.IntelligentDetections.FileVolCutoffLimits + AlertVolume = $tenantSettings.IntelligentDetections.AlertVolume + AnomalyDetections = [Boolean]$tenantSettings.Indicators.AnomalyDetections + CopyToPersonalCloud = [Boolean]$tenantSettings.Indicators.CopyToPersonalCloud + CopyToUSB = [Boolean]$tenantSettings.Indicators.CopyToUSB + CumulativeExfiltrationDetector = [Boolean]$tenantSettings.Indicators.CumulativeExfiltrationDetector + EmailExternal = [Boolean]$tenantSettings.Indicators.EmailExternal + EmployeeAccessedEmployeePatientData = [Boolean]$tenantSettings.Indicators.EmployeeAccessedEmployeePatientData + EmployeeAccessedFamilyData = [Boolean]$tenantSettings.Indicators.EmployeeAccessedFamilyData + EmployeeAccessedHighVolumePatientData = [Boolean]$tenantSettings.Indicators.EmployeeAccessedHighVolumePatientData + EmployeeAccessedNeighbourData = [Boolean]$tenantSettings.Indicators.EmployeeAccessedNeighbourData + EmployeeAccessedRestrictedData = [Boolean]$tenantSettings.Indicators.EmployeeAccessedRestrictedData + EpoBrowseToChildAbuseSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToChildAbuseSites + EpoBrowseToCriminalActivitySites = [Boolean]$tenantSettings.Indicators.EpoBrowseToCriminalActivitySites + EpoBrowseToCultSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToCultSites + EpoBrowseToGamblingSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToGamblingSites + EpoBrowseToHackingSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToHackingSites + EpoBrowseToHateIntoleranceSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToHateIntoleranceSites + EpoBrowseToIllegalSoftwareSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToIllegalSoftwareSites + EpoBrowseToKeyloggerSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToKeyloggerSites + EpoBrowseToLlmSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToLlmSites + EpoBrowseToMalwareSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToMalwareSites + EpoBrowseToPhishingSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToPhishingSites + EpoBrowseToPornographySites = [Boolean]$tenantSettings.Indicators.EpoBrowseToPornographySites + EpoBrowseToUnallowedDomain = [Boolean]$tenantSettings.Indicators.EpoBrowseToUnallowedDomain + EpoBrowseToViolenceSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToViolenceSites + EpoCopyToClipboardFromSensitiveFile = [Boolean]$tenantSettings.Indicators.EpoCopyToClipboardFromSensitiveFile + EpoCopyToNetworkShare = [Boolean]$tenantSettings.Indicators.EpoCopyToNetworkShare + EpoFileArchived = [Boolean]$tenantSettings.Indicators.EpoFileArchived + EpoFileCopiedToRemoteDesktopSession = [Boolean]$tenantSettings.Indicators.EpoFileCopiedToRemoteDesktopSession + EpoFileDeleted = [Boolean]$tenantSettings.Indicators.EpoFileDeleted + EpoFileDownloadedFromBlacklistedDomain = [Boolean]$tenantSettings.Indicators.EpoFileDownloadedFromBlacklistedDomain + EpoFileDownloadedFromEnterpriseDomain = [Boolean]$tenantSettings.Indicators.EpoFileDownloadedFromEnterpriseDomain + EpoFileRenamed = [Boolean]$tenantSettings.Indicators.EpoFileRenamed + EpoFileStagedToCentralLocation = [Boolean]$tenantSettings.Indicators.EpoFileStagedToCentralLocation + EpoHiddenFileCreated = [Boolean]$tenantSettings.Indicators.EpoHiddenFileCreated + EpoRemovableMediaMount = [Boolean]$tenantSettings.Indicators.EpoRemovableMediaMount + EpoSensitiveFileRead = [Boolean]$tenantSettings.Indicators.EpoSensitiveFileRead + Mcas3rdPartyAppDownload = [Boolean]$tenantSettings.Indicators.Mcas3rdPartyAppDownload + Mcas3rdPartyAppFileDelete = [Boolean]$tenantSettings.Indicators.Mcas3rdPartyAppFileDelete + Mcas3rdPartyAppFileSharing = [Boolean]$tenantSettings.Indicators.Mcas3rdPartyAppFileSharing + McasActivityFromInfrequentCountry = [Boolean]$tenantSettings.Indicators.McasActivityFromInfrequentCountry + McasImpossibleTravel = [Boolean]$tenantSettings.Indicators.McasImpossibleTravel + McasMultipleFailedLogins = [Boolean]$tenantSettings.Indicators.McasMultipleFailedLogins + McasMultipleStorageDeletion = [Boolean]$tenantSettings.Indicators.McasMultipleStorageDeletion + McasMultipleVMCreation = [Boolean]$tenantSettings.Indicators.McasMultipleVMCreation + McasMultipleVMDeletion = [Boolean]$tenantSettings.Indicators.McasMultipleVMDeletion + McasSuspiciousAdminActivities = [Boolean]$tenantSettings.Indicators.McasSuspiciousAdminActivities + McasSuspiciousCloudCreation = [Boolean]$tenantSettings.Indicators.McasSuspiciousCloudCreation + McasSuspiciousCloudTrailLoggingChange = [Boolean]$tenantSettings.Indicators.McasSuspiciousCloudTrailLoggingChange + McasTerminatedEmployeeActivity = [Boolean]$tenantSettings.Indicators.McasTerminatedEmployeeActivity + OdbDownload = [Boolean]$tenantSettings.Indicators.OdbDownload + OdbSyncDownload = [Boolean]$tenantSettings.Indicators.OdbSyncDownload + PeerCumulativeExfiltrationDetector = [Boolean]$tenantSettings.Indicators.PeerCumulativeExfiltrationDetector + PhysicalAccess = [Boolean]$tenantSettings.Indicators.PhysicalAccess + PotentialHighImpactUser = [Boolean]$tenantSettings.Indicators.PotentialHighImpactUser + Print = [Boolean]$tenantSettings.Indicators.Print + PriorityUserGroupMember = [Boolean]$tenantSettings.Indicators.PriorityUserGroupMember + SecurityAlertDefenseEvasion = [Boolean]$tenantSettings.Indicators.SecurityAlertDefenseEvasion + SecurityAlertUnwantedSoftware = [Boolean]$tenantSettings.Indicators.SecurityAlertUnwantedSoftware + SpoAccessRequest = [Boolean]$tenantSettings.Indicators.SpoAccessRequest + SpoApprovedAccess = [Boolean]$tenantSettings.Indicators.SpoApprovedAccess + SpoDownload = [Boolean]$tenantSettings.Indicators.SpoDownload + SpoDownloadV2 = [Boolean]$tenantSettings.Indicators.SpoDownloadV2 + SpoFileAccessed = [Boolean]$tenantSettings.Indicators.SpoFileAccessed + SpoFileDeleted = [Boolean]$tenantSettings.Indicators.SpoFileDeleted + SpoFileDeletedFromFirstStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFileDeletedFromFirstStageRecycleBin + SpoFileDeletedFromSecondStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFileDeletedFromSecondStageRecycleBin + SpoFileLabelDowngraded = [Boolean]$tenantSettings.Indicators.SpoFileLabelDowngraded + SpoFileLabelRemoved = [Boolean]$tenantSettings.Indicators.SpoFileLabelRemoved + SpoFileSharing = [Boolean]$tenantSettings.Indicators.SpoFileSharing + SpoFolderDeleted = [Boolean]$tenantSettings.Indicators.SpoFolderDeleted + SpoFolderDeletedFromFirstStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFolderDeletedFromFirstStageRecycleBin + SpoFolderDeletedFromSecondStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFolderDeletedFromSecondStageRecycleBin + SpoFolderSharing = [Boolean]$tenantSettings.Indicators.SpoFolderSharing + SpoSiteExternalUserAdded = [Boolean]$tenantSettings.Indicators.SpoSiteExternalUserAdded + SpoSiteInternalUserAdded = [Boolean]$tenantSettings.Indicators.SpoSiteInternalUserAdded + SpoSiteLabelRemoved = [Boolean]$tenantSettings.Indicators.SpoSiteLabelRemoved + SpoSiteSharing = [Boolean]$tenantSettings.Indicators.SpoSiteSharing + SpoSyncDownload = [Boolean]$tenantSettings.Indicators.SpoSyncDownload + TeamsChannelFileSharedExternal = [Boolean]$tenantSettings.Indicators.TeamsChannelFileSharedExternal + TeamsChannelMemberAddedExternal = [Boolean]$tenantSettings.Indicators.TeamsChannelMemberAddedExternal + TeamsChatFileSharedExternal = [Boolean]$tenantSettings.Indicators.TeamsChatFileSharedExternal + TeamsFileDownload = [Boolean]$tenantSettings.Indicators.TeamsFileDownload + TeamsFolderSharedExternal = [Boolean]$tenantSettings.Indicators.TeamsFolderSharedExternal + TeamsMemberAddedExternal = [Boolean]$tenantSettings.Indicators.TeamsMemberAddedExternal + TeamsSensitiveMessage = [Boolean]$tenantSettings.Indicators.TeamsSensitiveMessage + UserHistory = [Boolean]$tenantSettings.Indicators.UserHistory + AWSS3BlockPublicAccessDisabled = [Boolean]$tenantSettings.ExtensibleIndicators.AWSS3BlockPublicAccessDisabled + AWSS3BucketDeleted = [Boolean]$tenantSettings.ExtensibleIndicators.AWSS3BucketDeleted + AWSS3PublicAccessEnabled = [Boolean]$tenantSettings.ExtensibleIndicators.AWSS3PublicAccessEnabled + AWSS3ServerLoggingDisabled = [Boolean]$tenantSettings.ExtensibleIndicators.AWSS3ServerLoggingDisabled + AzureElevateAccessToAllSubscriptions = [Boolean]$tenantSettings.ExtensibleIndicators.AzureElevateAccessToAllSubscriptions + AzureResourceThreatProtectionSettingsUpdated = [Boolean]$tenantSettings.ExtensibleIndicators.AzureResourceThreatProtectionSettingsUpdated + AzureSQLServerAuditingSettingsUpdated = [Boolean]$tenantSettings.ExtensibleIndicators.AzureSQLServerAuditingSettingsUpdated + AzureSQLServerFirewallRuleDeleted = [Boolean]$tenantSettings.ExtensibleIndicators.AzureSQLServerFirewallRuleDeleted + AzureSQLServerFirewallRuleUpdated = [Boolean]$tenantSettings.ExtensibleIndicators.AzureSQLServerFirewallRuleUpdated + AzureStorageAccountOrContainerDeleted = [Boolean]$tenantSettings.ExtensibleIndicators.AzureStorageAccountOrContainerDeleted + BoxContentAccess = [Boolean]$tenantSettings.ExtensibleIndicators.BoxContentAccess + BoxContentDelete = [Boolean]$tenantSettings.ExtensibleIndicators.BoxContentDelete + BoxContentDownload = [Boolean]$tenantSettings.ExtensibleIndicators.BoxContentDownload + BoxContentExternallyShared = [Boolean]$tenantSettings.ExtensibleIndicators.BoxContentExternallyShared + CCFinancialRegulatoryRiskyTextSent = [Boolean]$tenantSettings.ExtensibleIndicators.CCFinancialRegulatoryRiskyTextSent + CCInappropriateContentSent = [Boolean]$tenantSettings.ExtensibleIndicators.CCInappropriateContentSent + CCInappropriateImagesSent = [Boolean]$tenantSettings.ExtensibleIndicators.CCInappropriateImagesSent + DropboxContentAccess = [Boolean]$tenantSettings.ExtensibleIndicators.DropboxContentAccess + DropboxContentDelete = [Boolean]$tenantSettings.ExtensibleIndicators.DropboxContentDelete + DropboxContentDownload = [Boolean]$tenantSettings.ExtensibleIndicators.DropboxContentDownload + DropboxContentExternallyShared = [Boolean]$tenantSettings.ExtensibleIndicators.DropboxContentExternallyShared + GoogleDriveContentAccess = [Boolean]$tenantSettings.ExtensibleIndicators.GoogleDriveContentAccess + GoogleDriveContentDelete = [Boolean]$tenantSettings.ExtensibleIndicators.GoogleDriveContentDelete + GoogleDriveContentExternallyShared = [Boolean]$tenantSettings.ExtensibleIndicators.GoogleDriveContentExternallyShared + PowerBIDashboardsDeleted = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBIDashboardsDeleted + PowerBIReportsDeleted = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBIReportsDeleted + PowerBIReportsDownloaded = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBIReportsDownloaded + PowerBIReportsExported = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBIReportsExported + PowerBIReportsViewed = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBIReportsViewed + PowerBISemanticModelsDeleted = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBISemanticModelsDeleted + PowerBISensitivityLabelDowngradedForArtifacts = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBISensitivityLabelDowngradedForArtifacts + PowerBISensitivityLabelRemovedFromArtifacts = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBISensitivityLabelRemovedFromArtifacts + HistoricTimeSpan = $tenantSettings.TimeSpan.HistoricTimeSpan + InScopeTimeSpan = $tenantSettings.TimeSpan.InScopeTimeSpan + EnableTeam = [Boolean]$tenantSettings.FeatureSettings.EnableTeam + } + + $AnalyticsNewInsight = $tenantSettings.NotificationPreferences | Where-Object -FilterScript {$_.NotificationType -eq 'AnalyticsNewInsight'} + if ($null -ne $AnalyticsNewInsight) + { + $tenantSettingsHash.Add('AnalyticsNewInsightEnabled', [Boolean]$AnalyticsNewInsight.Enabled) + } + + $AnalyticsTurnedOff = $tenantSettings.NotificationPreferences | Where-Object -FilterScript {$_.NotificationType -eq 'AnalyticsTurnedOff'} + if ($null -ne $AnalyticsTurnedOff) + { + $tenantSettingsHash.Add('AnalyticsTurnedOffEnabled', [Boolean]$AnalyticsTurnedOff.Enabled) + } + + $highSeverityAlerts = $tenantSettings.NotificationPreferences | Where-Object -FilterScript {$_.NotificationType -eq 'HighSeverityAlerts'} + if ($null -ne $highSeverityAlerts) + { + $tenantSettingsHash.Add('HighSeverityAlertsEnabled', [Boolean]$highSeverityAlerts.Enabled) + $tenantSettingsHash.Add('HighSeverityAlertsRoleGroups', [Array]$highSeverityAlerts.RoleGroups) + } + + $policiesHealth = $tenantSettings.NotificationPreferences | Where-Object -FilterScript {$_.NotificationType -eq 'PoliciesHealth'} + if ($null -ne $policiesHealth) + { + $tenantSettingsHash.Add('PoliciesHealthEnabled', [Boolean]$policiesHealth.Enabled) + $tenantSettingsHash.Add('PoliciesHealthRoleGroups', [Array]$policiesHealth.RoleGroups) + } + + if ($null -ne $tenantSettings.FeatureSettings.NotificationDetails) + { + $tenantSettingsHash.Add('NotificationDetailsEnabled', $true) + $tenantSettingsHash.Add('NotificationDetailsRoleGroups', [Array]$tenantSettings.FeatureSettings.NotificationDetails.RoleGroups) + } + else + { + $tenantSettingsHash.Add('NotificationDetailsEnabled', $false) + } + + $results += $tenantSettingsHash + } + + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter()] + [System.Boolean] + $DLPUserRiskSync, + + [Parameter()] + [System.Boolean] + $OptInIRMDataExport, + + [Parameter()] + [System.Boolean] + $RaiseAuditAlert, + + [Parameter()] + [System.String] + $FileVolCutoffLimits, + + [Parameter()] + [System.String] + $AlertVolume, + + [Parameter()] + [System.Boolean] + $AnomalyDetections, + + [Parameter()] + [System.Boolean] + $CopyToPersonalCloud, + + [Parameter()] + [System.Boolean] + $CopyToUSB, + + [Parameter()] + [System.Boolean] + $CumulativeExfiltrationDetector, + + [Parameter()] + [System.Boolean] + $EmailExternal, + + [Parameter()] + [System.Boolean] + $EmployeeAccessedEmployeePatientData, + + [Parameter()] + [System.Boolean] + $EmployeeAccessedFamilyData, + + [Parameter()] + [System.Boolean] + $EmployeeAccessedHighVolumePatientData, + + [Parameter()] + [System.Boolean] + $EmployeeAccessedNeighbourData, + + [Parameter()] + [System.Boolean] + $EmployeeAccessedRestrictedData, + + [Parameter()] + [System.Boolean] + $EpoBrowseToChildAbuseSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToCriminalActivitySites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToCultSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToGamblingSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToHackingSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToHateIntoleranceSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToIllegalSoftwareSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToKeyloggerSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToLlmSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToMalwareSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToPhishingSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToPornographySites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToUnallowedDomain, + + [Parameter()] + [System.Boolean] + $EpoBrowseToViolenceSites, + + [Parameter()] + [System.Boolean] + $EpoCopyToClipboardFromSensitiveFile, + + [Parameter()] + [System.Boolean] + $EpoCopyToNetworkShare, + + [Parameter()] + [System.Boolean] + $EpoFileArchived, + + [Parameter()] + [System.Boolean] + $EpoFileCopiedToRemoteDesktopSession, + + [Parameter()] + [System.Boolean] + $EpoFileDeleted, + + [Parameter()] + [System.Boolean] + $EpoFileDownloadedFromBlacklistedDomain, + + [Parameter()] + [System.Boolean] + $EpoFileDownloadedFromEnterpriseDomain, + + [Parameter()] + [System.Boolean] + $EpoFileRenamed, + + [Parameter()] + [System.Boolean] + $EpoFileStagedToCentralLocation, + + [Parameter()] + [System.Boolean] + $EpoHiddenFileCreated, + + [Parameter()] + [System.Boolean] + $EpoRemovableMediaMount, + + [Parameter()] + [System.Boolean] + $EpoSensitiveFileRead, + + [Parameter()] + [System.Boolean] + $Mcas3rdPartyAppDownload, + + [Parameter()] + [System.Boolean] + $Mcas3rdPartyAppFileDelete, + + [Parameter()] + [System.Boolean] + $Mcas3rdPartyAppFileSharing, + + [Parameter()] + [System.Boolean] + $McasActivityFromInfrequentCountry, + + [Parameter()] + [System.Boolean] + $McasImpossibleTravel, + + [Parameter()] + [System.Boolean] + $McasMultipleFailedLogins, + + [Parameter()] + [System.Boolean] + $McasMultipleStorageDeletion, + + [Parameter()] + [System.Boolean] + $McasMultipleVMCreation, + + [Parameter()] + [System.Boolean] + $McasMultipleVMDeletion, + + [Parameter()] + [System.Boolean] + $McasSuspiciousAdminActivities, + + [Parameter()] + [System.Boolean] + $McasSuspiciousCloudCreation, + + [Parameter()] + [System.Boolean] + $McasSuspiciousCloudTrailLoggingChange, + + [Parameter()] + [System.Boolean] + $McasTerminatedEmployeeActivity, + + [Parameter()] + [System.Boolean] + $OdbDownload, + + [Parameter()] + [System.Boolean] + $OdbSyncDownload, + + [Parameter()] + [System.Boolean] + $PeerCumulativeExfiltrationDetector, + + [Parameter()] + [System.Boolean] + $PhysicalAccess, + + [Parameter()] + [System.Boolean] + $PotentialHighImpactUser, + + [Parameter()] + [System.Boolean] + $Print, + + [Parameter()] + [System.Boolean] + $PriorityUserGroupMember, + + [Parameter()] + [System.Boolean] + $SecurityAlertDefenseEvasion, + + [Parameter()] + [System.Boolean] + $SecurityAlertUnwantedSoftware, + + [Parameter()] + [System.Boolean] + $SpoAccessRequest, + + [Parameter()] + [System.Boolean] + $SpoApprovedAccess, + + [Parameter()] + [System.Boolean] + $SpoDownload, + + [Parameter()] + [System.Boolean] + $SpoDownloadV2, + + [Parameter()] + [System.Boolean] + $SpoFileAccessed, + + [Parameter()] + [System.Boolean] + $SpoFileDeleted, + + [Parameter()] + [System.Boolean] + $SpoFileDeletedFromFirstStageRecycleBin, + + [Parameter()] + [System.Boolean] + $SpoFileDeletedFromSecondStageRecycleBin, + + [Parameter()] + [System.Boolean] + $SpoFileLabelDowngraded, + + [Parameter()] + [System.Boolean] + $SpoFileLabelRemoved, + + [Parameter()] + [System.Boolean] + $SpoFileSharing, + + [Parameter()] + [System.Boolean] + $SpoFolderDeleted, + + [Parameter()] + [System.Boolean] + $SpoFolderDeletedFromFirstStageRecycleBin, + + [Parameter()] + [System.Boolean] + $SpoFolderDeletedFromSecondStageRecycleBin, + + [Parameter()] + [System.Boolean] + $SpoFolderSharing, + + [Parameter()] + [System.Boolean] + $SpoSiteExternalUserAdded, + + [Parameter()] + [System.Boolean] + $SpoSiteInternalUserAdded, + + [Parameter()] + [System.Boolean] + $SpoSiteLabelRemoved, + + [Parameter()] + [System.Boolean] + $SpoSiteSharing, + + [Parameter()] + [System.Boolean] + $SpoSyncDownload, + + [Parameter()] + [System.Boolean] + $TeamsChannelFileSharedExternal, + + [Parameter()] + [System.Boolean] + $TeamsChannelMemberAddedExternal, + + [Parameter()] + [System.Boolean] + $TeamsChatFileSharedExternal, + + [Parameter()] + [System.Boolean] + $TeamsFileDownload, + + [Parameter()] + [System.Boolean] + $TeamsFolderSharedExternal, + + [Parameter()] + [System.Boolean] + $TeamsMemberAddedExternal, + + [Parameter()] + [System.Boolean] + $TeamsSensitiveMessage, + + [Parameter()] + [System.Boolean] + $UserHistory, + + [Parameter()] + [System.Boolean] + $AWSS3BlockPublicAccessDisabled, + + [Parameter()] + [System.Boolean] + $AWSS3BucketDeleted, + + [Parameter()] + [System.Boolean] + $AWSS3PublicAccessEnabled, + + [Parameter()] + [System.Boolean] + $AWSS3ServerLoggingDisabled, + + [Parameter()] + [System.Boolean] + $AzureElevateAccessToAllSubscriptions, + + [Parameter()] + [System.Boolean] + $AzureResourceThreatProtectionSettingsUpdated, + + [Parameter()] + [System.Boolean] + $AzureSQLServerAuditingSettingsUpdated, + + [Parameter()] + [System.Boolean] + $AzureSQLServerFirewallRuleDeleted, + + [Parameter()] + [System.Boolean] + $AzureSQLServerFirewallRuleUpdated, + + [Parameter()] + [System.Boolean] + $AzureStorageAccountOrContainerDeleted, + + [Parameter()] + [System.Boolean] + $BoxContentAccess, + + [Parameter()] + [System.Boolean] + $BoxContentDelete, + + [Parameter()] + [System.Boolean] + $BoxContentDownload, + + [Parameter()] + [System.Boolean] + $BoxContentExternallyShared, + + [Parameter()] + [System.Boolean] + $CCFinancialRegulatoryRiskyTextSent, + + [Parameter()] + [System.Boolean] + $CCInappropriateContentSent, + + [Parameter()] + [System.Boolean] + $CCInappropriateImagesSent, + + [Parameter()] + [System.Boolean] + $DropboxContentAccess, + + [Parameter()] + [System.Boolean] + $DropboxContentDelete, + + [Parameter()] + [System.Boolean] + $DropboxContentDownload, + + [Parameter()] + [System.Boolean] + $DropboxContentExternallyShared, + + [Parameter()] + [System.Boolean] + $GoogleDriveContentAccess, + + [Parameter()] + [System.Boolean] + $GoogleDriveContentDelete, + + [Parameter()] + [System.Boolean] + $GoogleDriveContentExternallyShared, + + [Parameter()] + [System.Boolean] + $PowerBIDashboardsDeleted, + + [Parameter()] + [System.Boolean] + $PowerBIReportsDeleted, + + [Parameter()] + [System.Boolean] + $PowerBIReportsDownloaded, + + [Parameter()] + [System.Boolean] + $PowerBIReportsExported, + + [Parameter()] + [System.Boolean] + $PowerBIReportsViewed, + + [Parameter()] + [System.Boolean] + $PowerBISemanticModelsDeleted, + + [Parameter()] + [System.Boolean] + $PowerBISensitivityLabelDowngradedForArtifacts, + + [Parameter()] + [System.Boolean] + $PowerBISensitivityLabelRemovedFromArtifacts, + + [Parameter()] + [System.String] + $HistoricTimeSpan, + + [Parameter()] + [System.String] + $InScopeTimeSpan, + + [Parameter()] + [System.Boolean] + $EnableTeam, + + [Parameter()] + [System.Boolean] + $AnalyticsNewInsightEnabled, + + [Parameter()] + [System.Boolean] + $AnalyticsTurnedOffEnabled, + + [Parameter()] + [System.Boolean] + $HighSeverityAlertsEnabled, + + [Parameter()] + [System.String[]] + $HighSeverityAlertsRoleGroups, + + [Parameter()] + [System.Boolean] + $PoliciesHealthEnabled, + + [Parameter()] + [System.String[]] + $PoliciesHealthRoleGroups, + + [Parameter()] + [System.Boolean] + $NotificationDetailsEnabled, + + [Parameter()] + [System.String[]] + $NotificationDetailsRoleGroups, + + [Parameter()] + [System.Boolean] + $ClipDeletionEnabled, + + [Parameter()] + [System.Boolean] + $SessionRecordingEnabled, + + [Parameter()] + [System.Boolean] + $RecordingTimeframePreEventInSec, + + [Parameter()] + [System.Boolean] + $RecordingTimeframePostEventInSec, + + [Parameter()] + [System.Boolean] + $BandwidthCapInMb, + + [Parameter()] + [System.Boolean] + $OfflineRecordingStorageLimitInMb, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + ##TODO - Replace by the New cmdlet for the resource + New-Cmdlet @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Update/Set cmdlet for the resource + Set-cmdlet @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Remove cmdlet for the resource + Remove-cmdlet @SetParameters + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter()] + [System.Boolean] + $DLPUserRiskSync, + + [Parameter()] + [System.Boolean] + $OptInIRMDataExport, + + [Parameter()] + [System.Boolean] + $RaiseAuditAlert, + + [Parameter()] + [System.String] + $FileVolCutoffLimits, + + [Parameter()] + [System.String] + $AlertVolume, + + [Parameter()] + [System.Boolean] + $AnomalyDetections, + + [Parameter()] + [System.Boolean] + $CopyToPersonalCloud, + + [Parameter()] + [System.Boolean] + $CopyToUSB, + + [Parameter()] + [System.Boolean] + $CumulativeExfiltrationDetector, + + [Parameter()] + [System.Boolean] + $EmailExternal, + + [Parameter()] + [System.Boolean] + $EmployeeAccessedEmployeePatientData, + + [Parameter()] + [System.Boolean] + $EmployeeAccessedFamilyData, + + [Parameter()] + [System.Boolean] + $EmployeeAccessedHighVolumePatientData, + + [Parameter()] + [System.Boolean] + $EmployeeAccessedNeighbourData, + + [Parameter()] + [System.Boolean] + $EmployeeAccessedRestrictedData, + + [Parameter()] + [System.Boolean] + $EpoBrowseToChildAbuseSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToCriminalActivitySites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToCultSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToGamblingSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToHackingSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToHateIntoleranceSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToIllegalSoftwareSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToKeyloggerSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToLlmSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToMalwareSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToPhishingSites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToPornographySites, + + [Parameter()] + [System.Boolean] + $EpoBrowseToUnallowedDomain, + + [Parameter()] + [System.Boolean] + $EpoBrowseToViolenceSites, + + [Parameter()] + [System.Boolean] + $EpoCopyToClipboardFromSensitiveFile, + + [Parameter()] + [System.Boolean] + $EpoCopyToNetworkShare, + + [Parameter()] + [System.Boolean] + $EpoFileArchived, + + [Parameter()] + [System.Boolean] + $EpoFileCopiedToRemoteDesktopSession, + + [Parameter()] + [System.Boolean] + $EpoFileDeleted, + + [Parameter()] + [System.Boolean] + $EpoFileDownloadedFromBlacklistedDomain, + + [Parameter()] + [System.Boolean] + $EpoFileDownloadedFromEnterpriseDomain, + + [Parameter()] + [System.Boolean] + $EpoFileRenamed, + + [Parameter()] + [System.Boolean] + $EpoFileStagedToCentralLocation, + + [Parameter()] + [System.Boolean] + $EpoHiddenFileCreated, + + [Parameter()] + [System.Boolean] + $EpoRemovableMediaMount, + + [Parameter()] + [System.Boolean] + $EpoSensitiveFileRead, + + [Parameter()] + [System.Boolean] + $Mcas3rdPartyAppDownload, + + [Parameter()] + [System.Boolean] + $Mcas3rdPartyAppFileDelete, + + [Parameter()] + [System.Boolean] + $Mcas3rdPartyAppFileSharing, + + [Parameter()] + [System.Boolean] + $McasActivityFromInfrequentCountry, + + [Parameter()] + [System.Boolean] + $McasImpossibleTravel, + + [Parameter()] + [System.Boolean] + $McasMultipleFailedLogins, + + [Parameter()] + [System.Boolean] + $McasMultipleStorageDeletion, + + [Parameter()] + [System.Boolean] + $McasMultipleVMCreation, + + [Parameter()] + [System.Boolean] + $McasMultipleVMDeletion, + + [Parameter()] + [System.Boolean] + $McasSuspiciousAdminActivities, + + [Parameter()] + [System.Boolean] + $McasSuspiciousCloudCreation, + + [Parameter()] + [System.Boolean] + $McasSuspiciousCloudTrailLoggingChange, + + [Parameter()] + [System.Boolean] + $McasTerminatedEmployeeActivity, + + [Parameter()] + [System.Boolean] + $OdbDownload, + + [Parameter()] + [System.Boolean] + $OdbSyncDownload, + + [Parameter()] + [System.Boolean] + $PeerCumulativeExfiltrationDetector, + + [Parameter()] + [System.Boolean] + $PhysicalAccess, + + [Parameter()] + [System.Boolean] + $PotentialHighImpactUser, + + [Parameter()] + [System.Boolean] + $Print, + + [Parameter()] + [System.Boolean] + $PriorityUserGroupMember, + + [Parameter()] + [System.Boolean] + $SecurityAlertDefenseEvasion, + + [Parameter()] + [System.Boolean] + $SecurityAlertUnwantedSoftware, + + [Parameter()] + [System.Boolean] + $SpoAccessRequest, + + [Parameter()] + [System.Boolean] + $SpoApprovedAccess, + + [Parameter()] + [System.Boolean] + $SpoDownload, + + [Parameter()] + [System.Boolean] + $SpoDownloadV2, + + [Parameter()] + [System.Boolean] + $SpoFileAccessed, + + [Parameter()] + [System.Boolean] + $SpoFileDeleted, + + [Parameter()] + [System.Boolean] + $SpoFileDeletedFromFirstStageRecycleBin, + + [Parameter()] + [System.Boolean] + $SpoFileDeletedFromSecondStageRecycleBin, + + [Parameter()] + [System.Boolean] + $SpoFileLabelDowngraded, + + [Parameter()] + [System.Boolean] + $SpoFileLabelRemoved, + + [Parameter()] + [System.Boolean] + $SpoFileSharing, + + [Parameter()] + [System.Boolean] + $SpoFolderDeleted, + + [Parameter()] + [System.Boolean] + $SpoFolderDeletedFromFirstStageRecycleBin, [Parameter()] - [System.Management.Automation.PSCredential] - $Credential, + [System.Boolean] + $SpoFolderDeletedFromSecondStageRecycleBin, [Parameter()] - [System.String] - $ApplicationId, + [System.Boolean] + $SpoFolderSharing, [Parameter()] - [System.String] - $TenantId, + [System.Boolean] + $SpoSiteExternalUserAdded, [Parameter()] - [System.String] - $CertificateThumbprint, + [System.Boolean] + $SpoSiteInternalUserAdded, [Parameter()] - [Switch] - $ManagedIdentity, + [System.Boolean] + $SpoSiteLabelRemoved, [Parameter()] - [System.String[]] - $AccessTokens - ) + [System.Boolean] + $SpoSiteSharing, - ##TODO - Replace the workload by the one associated to your resource - New-M365DSCConnection -Workload 'Workload' ` - -InboundParameters $PSBoundParameters | Out-Null + [Parameter()] + [System.Boolean] + $SpoSyncDownload, - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies + [Parameter()] + [System.Boolean] + $TeamsChannelFileSharedExternal, - #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 + [Parameter()] + [System.Boolean] + $TeamsChannelMemberAddedExternal, - $nullResult = $PSBoundParameters - $nullResult.Ensure = 'Absent' - try - { - $instance = Get-InsiderRiskPolicy -ErrorAction Stop - $tenantSettings = ConvertFrom-Json $instance.TenantSettings + [Parameter()] + [System.Boolean] + $TeamsChatFileSharedExternal, - $results = @{ - IsSingleInstance = 'Yes' - DLPUserRiskSync = [Boolean]$tenantSettings.FeatureSettings.DLPUserRiskSync - OptInIRMDataExport = [Boolean]$tenantSettings.FeatureSettings.OptInIRMDataExport - RaiseAuditAlert = [Boolean]$tenantSettings.FeatureSettings.RaiseAuditAlert - FileVolCutoffLimits = $tenantSettings.IntelligentDetections.FileVolCutoffLimits - AlertVolume = $tenantSettings.IntelligentDetections.AlertVolume - AnomalyDetections = [Boolean]$tenantSettings.Indicators.AnomalyDetections - CopyToPersonalCloud = [Boolean]$tenantSettings.Indicators. - CopyToUSB = [Boolean]$tenantSettings.Indicators. - CumulativeExfiltrationDetector = [Boolean]$tenantSettings.Indicators. - EmailExternal = [Boolean]$tenantSettings.Indicators. - EmployeeAccessedEmployeePatientData = [Boolean]$tenantSettings.Indicators. - EmployeeAccessedFamilyData = [Boolean]$tenantSettings.Indicators. - EmployeeAccessedHighVolumePatientData = [Boolean]$tenantSettings.Indicators. - EmployeeAccessedNeighbourData = [Boolean]$tenantSettings.Indicators. - EmployeeAccessedRestrictedData = [Boolean]$tenantSettings.Indicators. - EpoBrowseToChildAbuseSites = [Boolean]$tenantSettings.Indicators. - EpoBrowseToCriminalActivitySites = [Boolean]$tenantSettings.Indicators. - EpoBrowseToCultSites = [Boolean]$tenantSettings.Indicators. - EpoBrowseToGamblingSites = [Boolean]$tenantSettings.Indicators. - EpoBrowseToHackingSites = [Boolean]$tenantSettings.Indicators. - EpoBrowseToHateIntoleranceSites = [Boolean]$tenantSettings.Indicators. - EpoBrowseToIllegalSoftwareSites = [Boolean]$tenantSettings.Indicators. - EpoBrowseToKeyloggerSites = [Boolean]$tenantSettings.Indicators. - EpoBrowseToLlmSites = [Boolean]$tenantSettings.Indicators. - EpoBrowseToMalwareSites = [Boolean]$tenantSettings.Indicators. - EpoBrowseToPhishingSites = [Boolean]$tenantSettings.Indicators. - EpoBrowseToPornographySites = [Boolean]$tenantSettings.Indicators. - EpoBrowseToUnallowedDomain = [Boolean]$tenantSettings.Indicators. - EpoBrowseToViolenceSites = [Boolean]$tenantSettings.Indicators. - EpoCopyToClipboardFromSensitiveFile = [Boolean]$tenantSettings.Indicators. - EpoCopyToNetworkShare = [Boolean]$tenantSettings.Indicators. - EpoFileArchived = [Boolean]$tenantSettings.Indicators. - EpoFileCopiedToRemoteDesktopSession = [Boolean]$tenantSettings.Indicators. - EpoFileDeleted = [Boolean]$tenantSettings.Indicators. - EpoFileDownloadedFromBlacklistedDomain = [Boolean]$tenantSettings.Indicators. - EpoFileDownloadedFromEnterpriseDomain = [Boolean]$tenantSettings.Indicators. - EpoFileRenamed = [Boolean]$tenantSettings.Indicators. - EpoFileStagedToCentralLocation = [Boolean]$tenantSettings.Indicators. - EpoHiddenFileCreated = [Boolean]$tenantSettings.Indicators. - EpoRemovableMediaMount = [Boolean]$tenantSettings.Indicators. - EpoSensitiveFileRead = [Boolean]$tenantSettings.Indicators. - Mcas3rdPartyAppDownload = [Boolean]$tenantSettings.Indicators. - Mcas3rdPartyAppFileDelete = [Boolean]$tenantSettings.Indicators. - Mcas3rdPartyAppFileSharing = [Boolean]$tenantSettings.Indicators. - McasActivityFromInfrequentCountry = [Boolean]$tenantSettings.Indicators. - McasImpossibleTravel = [Boolean]$tenantSettings.Indicators. - McasMultipleFailedLogins = [Boolean]$tenantSettings.Indicators. - McasMultipleStorageDeletion = [Boolean]$tenantSettings.Indicators. - McasMultipleVMCreation = [Boolean]$tenantSettings.Indicators. - McasMultipleVMDeletion = [Boolean]$tenantSettings.Indicators. - McasSuspiciousAdminActivities = [Boolean]$tenantSettings.Indicators. - McasSuspiciousCloudCreation = [Boolean]$tenantSettings.Indicators. - McasSuspiciousCloudTrailLoggingChange = [Boolean]$tenantSettings.Indicators. - McasTerminatedEmployeeActivity = [Boolean]$tenantSettings.Indicators. - OdbDownload = [Boolean]$tenantSettings.Indicators. - OdbSyncDownload = [Boolean]$tenantSettings.Indicators. - PeerCumulativeExfiltrationDetector = [Boolean]$tenantSettings.Indicators. - PhysicalAccess = [Boolean]$tenantSettings.Indicators. - PotentialHighImpactUser = [Boolean]$tenantSettings.Indicators. - Print = [Boolean]$tenantSettings.Indicators. - PriorityUserGroupMember = [Boolean]$tenantSettings.Indicators. - SecurityAlertDefenseEvasion = [Boolean]$tenantSettings.Indicators. - SecurityAlertUnwantedSoftware = [Boolean]$tenantSettings.Indicators. - SpoAccessRequest = [Boolean]$tenantSettings.Indicators. - SpoApprovedAccess = [Boolean]$tenantSettings.Indicators. - SpoDownload = [Boolean]$tenantSettings.Indicators. - SpoDownloadV2 = [Boolean]$tenantSettings.Indicators. - SpoFileAccessed = [Boolean]$tenantSettings.Indicators. - SpoFileDeleted = [Boolean]$tenantSettings.Indicators.SpoFileDeleted - SpoFileDeletedFromFirstStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFileDeletedFromFirstStageRecycleBin - SpoFileDeletedFromSecondStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFileDeletedFromSecondStageRecycleBin - SpoFileLabelDowngraded = [Boolean]$tenantSettings.Indicators.SpoFileLabelDowngraded - SpoFileLabelRemoved = [Boolean]$tenantSettings.Indicators.SpoFileLabelRemoved - SpoFileSharing = [Boolean]$tenantSettings.Indicators.SpoFileSharing - SpoFolderDeleted = [Boolean]$tenantSettings.Indicators.SpoFolderDeleted - SpoFolderDeletedFromFirstStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFolderDeletedFromFirstStageRecycleBin - SpoFolderDeletedFromSecondStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFolderDeletedFromSecondStageRecycleBin - SpoFolderSharing = [Boolean]$tenantSettings.Indicators.SpoFolderSharing - SpoSiteExternalUserAdded = [Boolean]$tenantSettings.Indicators.SpoSiteExternalUserAdded - SpoSiteInternalUserAdded = [Boolean]$tenantSettings.Indicators.SpoSiteInternalUserAdded - SpoSiteLabelRemoved = [Boolean]$tenantSettings.Indicators.SpoSiteLabelRemoved - SpoSiteSharing = [Boolean]$tenantSettings.Indicators.SpoSiteSharing - SpoSyncDownload = [Boolean]$tenantSettings.Indicators.SpoSyncDownload - TeamsChannelFileSharedExternal = [Boolean]$tenantSettings.Indicators.TeamsChannelFileSharedExternal - TeamsChannelMemberAddedExternal = [Boolean]$tenantSettings.Indicators.TeamsChannelMemberAddedExternal - TeamsChatFileSharedExternal = [Boolean]$tenantSettings.Indicators.TeamsChatFileSharedExternal - TeamsFileDownload = [Boolean]$tenantSettings.Indicators.TeamsFileDownload - TeamsFolderSharedExternal = [Boolean]$tenantSettings.Indicators.TeamsFolderSharedExternal - TeamsMemberAddedExternal = [Boolean]$tenantSettings.Indicators.TeamsMemberAddedExternal - TeamsSensitiveMessage = [Boolean]$tenantSettings.Indicators.TeamsSensitiveMessage - UserHistory = [Boolean]$tenantSettings.Indicators.UserHistory - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens - } - return [System.Collections.Hashtable] $results - } - catch - { - Write-Verbose -Message $_ - New-M365DSCLogEntry -Message 'Error retrieving data:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential + [Parameter()] + [System.Boolean] + $TeamsFileDownload, - return $nullResult - } -} + [Parameter()] + [System.Boolean] + $TeamsFolderSharedExternal, -function Set-TargetResource -{ - [CmdletBinding()] - param - ( - ##TODO - Replace the PrimaryKey - [Parameter(Mandatory = $true)] - [System.String] - $PrimaryKey, + [Parameter()] + [System.Boolean] + $TeamsMemberAddedExternal, - ##TODO - Add the list of Parameters + [Parameter()] + [System.Boolean] + $TeamsSensitiveMessage, [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present', + [System.Boolean] + $UserHistory, [Parameter()] - [System.Management.Automation.PSCredential] - $Credential, + [System.Boolean] + $AWSS3BlockPublicAccessDisabled, [Parameter()] - [System.String] - $ApplicationId, + [System.Boolean] + $AWSS3BucketDeleted, + + [Parameter()] + [System.Boolean] + $AWSS3PublicAccessEnabled, + + [Parameter()] + [System.Boolean] + $AWSS3ServerLoggingDisabled, + + [Parameter()] + [System.Boolean] + $AzureElevateAccessToAllSubscriptions, + + [Parameter()] + [System.Boolean] + $AzureResourceThreatProtectionSettingsUpdated, + + [Parameter()] + [System.Boolean] + $AzureSQLServerAuditingSettingsUpdated, + + [Parameter()] + [System.Boolean] + $AzureSQLServerFirewallRuleDeleted, + + [Parameter()] + [System.Boolean] + $AzureSQLServerFirewallRuleUpdated, + + [Parameter()] + [System.Boolean] + $AzureStorageAccountOrContainerDeleted, + + [Parameter()] + [System.Boolean] + $BoxContentAccess, + + [Parameter()] + [System.Boolean] + $BoxContentDelete, + + [Parameter()] + [System.Boolean] + $BoxContentDownload, + + [Parameter()] + [System.Boolean] + $BoxContentExternallyShared, + + [Parameter()] + [System.Boolean] + $CCFinancialRegulatoryRiskyTextSent, + + [Parameter()] + [System.Boolean] + $CCInappropriateContentSent, + + [Parameter()] + [System.Boolean] + $CCInappropriateImagesSent, + + [Parameter()] + [System.Boolean] + $DropboxContentAccess, + + [Parameter()] + [System.Boolean] + $DropboxContentDelete, + + [Parameter()] + [System.Boolean] + $DropboxContentDownload, + + [Parameter()] + [System.Boolean] + $DropboxContentExternallyShared, + + [Parameter()] + [System.Boolean] + $GoogleDriveContentAccess, + + [Parameter()] + [System.Boolean] + $GoogleDriveContentDelete, + + [Parameter()] + [System.Boolean] + $GoogleDriveContentExternallyShared, + + [Parameter()] + [System.Boolean] + $PowerBIDashboardsDeleted, + + [Parameter()] + [System.Boolean] + $PowerBIReportsDeleted, + + [Parameter()] + [System.Boolean] + $PowerBIReportsDownloaded, + + [Parameter()] + [System.Boolean] + $PowerBIReportsExported, + + [Parameter()] + [System.Boolean] + $PowerBIReportsViewed, + + [Parameter()] + [System.Boolean] + $PowerBISemanticModelsDeleted, + + [Parameter()] + [System.Boolean] + $PowerBISensitivityLabelDowngradedForArtifacts, + + [Parameter()] + [System.Boolean] + $PowerBISensitivityLabelRemovedFromArtifacts, [Parameter()] [System.String] - $TenantId, + $HistoricTimeSpan, [Parameter()] [System.String] - $CertificateThumbprint, + $InScopeTimeSpan, [Parameter()] - [Switch] - $ManagedIdentity, + [System.Boolean] + $EnableTeam, + + [Parameter()] + [System.Boolean] + $AnalyticsNewInsightEnabled, + + [Parameter()] + [System.Boolean] + $AnalyticsTurnedOffEnabled, + + [Parameter()] + [System.Boolean] + $HighSeverityAlertsEnabled, [Parameter()] [System.String[]] - $AccessTokens - ) + $HighSeverityAlertsRoleGroups, - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies + [Parameter()] + [System.Boolean] + $PoliciesHealthEnabled, - #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 + [Parameter()] + [System.String[]] + $PoliciesHealthRoleGroups, - $currentInstance = Get-TargetResource @PSBoundParameters + [Parameter()] + [System.Boolean] + $NotificationDetailsEnabled, - $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + [Parameter()] + [System.String[]] + $NotificationDetailsRoleGroups, - # CREATE - if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') - { - ##TODO - Replace by the New cmdlet for the resource - New-Cmdlet @SetParameters - } - # UPDATE - elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') - { - ##TODO - Replace by the Update/Set cmdlet for the resource - Set-cmdlet @SetParameters - } - # REMOVE - elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') - { - ##TODO - Replace by the Remove cmdlet for the resource - Remove-cmdlet @SetParameters - } -} + [Parameter()] + [System.Boolean] + $ClipDeletionEnabled, -function Test-TargetResource -{ - [CmdletBinding()] - [OutputType([System.Boolean])] - param - ( - ##TODO - Replace the PrimaryKey - [Parameter(Mandatory = $true)] - [System.String] - $PrimaryKey, + [Parameter()] + [System.Boolean] + $SessionRecordingEnabled, + + [Parameter()] + [System.Boolean] + $RecordingTimeframePreEventInSec, + + [Parameter()] + [System.Boolean] + $RecordingTimeframePostEventInSec, + + [Parameter()] + [System.Boolean] + $BandwidthCapInMb, - ##TODO - Add the list of Parameters + [Parameter()] + [System.Boolean] + $OfflineRecordingStorageLimitInMb, [Parameter()] [ValidateSet('Present', 'Absent')] @@ -369,8 +2135,7 @@ function Export-TargetResource $AccessTokens ) - ##TODO - Replace workload - $ConnectionMode = New-M365DSCConnection -Workload 'Workload' ` + $ConnectionMode = New-M365DSCConnection -Workload 'SecurityComplianceCenter' ` -InboundParameters $PSBoundParameters #Ensure the proper dependencies are installed in the current environment. @@ -388,11 +2153,10 @@ function Export-TargetResource try { $Script:ExportMode = $true - ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances - [array] $Script:exportedInstances = Get-Cmdlet -ErrorAction Stop + [array] $Script:exportedInstances = Get-InsiderRiskPolicy -ErrorAction Stop - $i = 1 $dscContent = '' + $i = 1 if ($Script:exportedInstances.Length -eq 0) { Write-Host $Global:M365DSCEmojiGreenCheckMark @@ -403,11 +2167,10 @@ function Export-TargetResource } foreach ($config in $Script:exportedInstances) { - $displayedKey = $config.Id + $displayedKey = $config.Name Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline $params = @{ - ##TODO - Specify the Primary Key - #PrimaryKey = $config.PrimaryKey + Name = $config.Name Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId @@ -428,8 +2191,8 @@ function Export-TargetResource $dscContent += $currentDSCBlock Save-M365DSCPartialExport -Content $currentDSCBlock ` -FileName $Global:PartialExportFileName - $i++ Write-Host $Global:M365DSCEmojiGreenCheckMark + $i++ } return $dscContent } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof index be6b06c877..5cae80ebe7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof @@ -1,9 +1,147 @@ -[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] -class MSFT_ResourceName : OMI_BaseResource +[ClassVersion("1.0.0.0"), FriendlyName("SCInsiderRiskPolicy")] +class MSFT_SCInsiderRiskPolicy : OMI_BaseResource { - [Key, Description("")] String PrimaryKey; - [Write, Description("")] String OtherProperties; - + [Key, Description("Name of the insider risk policy.")] string Name; + [Write, Description("")] Boolean DLPUserRiskSync; + [Write, Description("")] Boolean OptInIRMDataExport; + [Write, Description("")] Boolean RaiseAuditAlert; + [Write, Description("")] String FileVolCutoffLimits; + [Write, Description("")] String AlertVolume; + [Write, Description("")] Boolean AnomalyDetections; + [Write, Description("")] Boolean CopyToPersonalCloud; + [Write, Description("")] Boolean CopyToUSB; + [Write, Description("")] Boolean CumulativeExfiltrationDetector; + [Write, Description("")] Boolean EmailExternal; + [Write, Description("")] Boolean EmployeeAccessedEmployeePatientData; + [Write, Description("")] Boolean EmployeeAccessedFamilyData; + [Write, Description("")] Boolean EmployeeAccessedHighVolumePatientData; + [Write, Description("")] Boolean EmployeeAccessedNeighbourData; + [Write, Description("")] Boolean EmployeeAccessedRestrictedData; + [Write, Description("")] Boolean EpoBrowseToChildAbuseSites; + [Write, Description("")] Boolean EpoBrowseToCriminalActivitySites; + [Write, Description("")] Boolean EpoBrowseToCultSites; + [Write, Description("")] Boolean EpoBrowseToGamblingSites; + [Write, Description("")] Boolean EpoBrowseToHackingSites; + [Write, Description("")] Boolean EpoBrowseToHateIntoleranceSites; + [Write, Description("")] Boolean EpoBrowseToIllegalSoftwareSites; + [Write, Description("")] Boolean EpoBrowseToKeyloggerSites; + [Write, Description("")] Boolean EpoBrowseToLlmSites; + [Write, Description("")] Boolean EpoBrowseToMalwareSites; + [Write, Description("")] Boolean EpoBrowseToPhishingSites; + [Write, Description("")] Boolean EpoBrowseToPornographySites; + [Write, Description("")] Boolean EpoBrowseToUnallowedDomain; + [Write, Description("")] Boolean EpoBrowseToViolenceSites; + [Write, Description("")] Boolean EpoCopyToClipboardFromSensitiveFile; + [Write, Description("")] Boolean EpoCopyToNetworkShare; + [Write, Description("")] Boolean EpoFileArchived; + [Write, Description("")] Boolean EpoFileCopiedToRemoteDesktopSession; + [Write, Description("")] Boolean EpoFileDeleted; + [Write, Description("")] Boolean EpoFileDownloadedFromBlacklistedDomain; + [Write, Description("")] Boolean EpoFileDownloadedFromEnterpriseDomain; + [Write, Description("")] Boolean EpoFileRenamed; + [Write, Description("")] Boolean EpoFileStagedToCentralLocation; + [Write, Description("")] Boolean EpoHiddenFileCreated; + [Write, Description("")] Boolean EpoRemovableMediaMount; + [Write, Description("")] Boolean EpoSensitiveFileRead; + [Write, Description("")] Boolean Mcas3rdPartyAppDownload; + [Write, Description("")] Boolean Mcas3rdPartyAppFileDelete; + [Write, Description("")] Boolean Mcas3rdPartyAppFileSharing; + [Write, Description("")] Boolean McasActivityFromInfrequentCountry; + [Write, Description("")] Boolean McasImpossibleTravel; + [Write, Description("")] Boolean McasMultipleFailedLogins; + [Write, Description("")] Boolean McasMultipleStorageDeletion; + [Write, Description("")] Boolean McasMultipleVMCreation; + [Write, Description("")] Boolean McasMultipleVMDeletion; + [Write, Description("")] Boolean McasSuspiciousAdminActivities; + [Write, Description("")] Boolean McasSuspiciousCloudCreation; + [Write, Description("")] Boolean McasSuspiciousCloudTrailLoggingChange; + [Write, Description("")] Boolean McasTerminatedEmployeeActivity; + [Write, Description("")] Boolean OdbDownload; + [Write, Description("")] Boolean OdbSyncDownload; + [Write, Description("")] Boolean PeerCumulativeExfiltrationDetector; + [Write, Description("")] Boolean PhysicalAccess; + [Write, Description("")] Boolean PotentialHighImpactUser; + [Write, Description("")] Boolean Print; + [Write, Description("")] Boolean PriorityUserGroupMember; + [Write, Description("")] Boolean SecurityAlertDefenseEvasion; + [Write, Description("")] Boolean SecurityAlertUnwantedSoftware; + [Write, Description("")] Boolean SpoAccessRequest; + [Write, Description("")] Boolean SpoApprovedAccess; + [Write, Description("")] Boolean SpoDownload; + [Write, Description("")] Boolean SpoDownloadV2; + [Write, Description("")] Boolean SpoFileAccessed; + [Write, Description("")] Boolean SpoFileDeleted; + [Write, Description("")] Boolean SpoFileDeletedFromFirstStageRecycleBin; + [Write, Description("")] Boolean SpoFileDeletedFromSecondStageRecycleBin; + [Write, Description("")] Boolean SpoFileLabelDowngraded; + [Write, Description("")] Boolean SpoFileLabelRemoved; + [Write, Description("")] Boolean SpoFileSharing; + [Write, Description("")] Boolean SpoFolderDeleted; + [Write, Description("")] Boolean SpoFolderDeletedFromFirstStageRecycleBin; + [Write, Description("")] Boolean SpoFolderDeletedFromSecondStageRecycleBin; + [Write, Description("")] Boolean SpoFolderSharing; + [Write, Description("")] Boolean SpoSiteExternalUserAdded; + [Write, Description("")] Boolean SpoSiteInternalUserAdded; + [Write, Description("")] Boolean SpoSiteLabelRemoved; + [Write, Description("")] Boolean SpoSiteSharing; + [Write, Description("")] Boolean SpoSyncDownload; + [Write, Description("")] Boolean TeamsChannelFileSharedExternal; + [Write, Description("")] Boolean TeamsChannelMemberAddedExternal; + [Write, Description("")] Boolean TeamsChatFileSharedExternal; + [Write, Description("")] Boolean TeamsFileDownload; + [Write, Description("")] Boolean TeamsFolderSharedExternal; + [Write, Description("")] Boolean TeamsMemberAddedExternal; + [Write, Description("")] Boolean TeamsSensitiveMessage; + [Write, Description("")] Boolean UserHistory; + [Write, Description("")] Boolean AWSS3BlockPublicAccessDisabled; + [Write, Description("")] Boolean AWSS3BucketDeleted; + [Write, Description("")] Boolean AWSS3PublicAccessEnabled; + [Write, Description("")] Boolean AWSS3ServerLoggingDisabled; + [Write, Description("")] Boolean AzureElevateAccessToAllSubscriptions; + [Write, Description("")] Boolean AzureResourceThreatProtectionSettingsUpdated; + [Write, Description("")] Boolean AzureSQLServerAuditingSettingsUpdated; + [Write, Description("")] Boolean AzureSQLServerFirewallRuleDeleted; + [Write, Description("")] Boolean AzureSQLServerFirewallRuleUpdated; + [Write, Description("")] Boolean AzureStorageAccountOrContainerDeleted; + [Write, Description("")] Boolean BoxContentAccess; + [Write, Description("")] Boolean BoxContentDelete; + [Write, Description("")] Boolean BoxContentDownload; + [Write, Description("")] Boolean BoxContentExternallyShared; + [Write, Description("")] Boolean CCFinancialRegulatoryRiskyTextSent; + [Write, Description("")] Boolean CCInappropriateContentSent; + [Write, Description("")] Boolean CCInappropriateImagesSent; + [Write, Description("")] Boolean DropboxContentAccess; + [Write, Description("")] Boolean DropboxContentDelete; + [Write, Description("")] Boolean DropboxContentDownload; + [Write, Description("")] Boolean DropboxContentExternallyShared; + [Write, Description("")] Boolean GoogleDriveContentAccess; + [Write, Description("")] Boolean GoogleDriveContentDelete; + [Write, Description("")] Boolean GoogleDriveContentExternallyShared; + [Write, Description("")] Boolean PowerBIDashboardsDeleted; + [Write, Description("")] Boolean PowerBIReportsDeleted; + [Write, Description("")] Boolean PowerBIReportsDownloaded; + [Write, Description("")] Boolean PowerBIReportsExported; + [Write, Description("")] Boolean PowerBIReportsViewed; + [Write, Description("")] Boolean PowerBISemanticModelsDeleted; + [Write, Description("")] Boolean PowerBISensitivityLabelDowngradedForArtifacts; + [Write, Description("")] Boolean PowerBISensitivityLabelRemovedFromArtifacts; + [Write, Description("")] String HistoricTimeSpan; + [Write, Description("")] String InScopeTimeSpan; + [Write, Description("")] Boolean EnableTeam; + [Write, Description("")] Boolean AnalyticsNewInsightEnabled; + [Write, Description("")] Boolean AnalyticsTurnedOffEnabled; + [Write, Description("")] Boolean HighSeverityAlertsEnabled; + [Write, Description("")] String HighSeverityAlertsRoleGroups[]; + [Write, Description("")] Boolean PoliciesHealthEnabled; + [Write, Description("")] String PoliciesHealthRoleGroups[]; + [Write, Description("")] Boolean NotificationDetailsEnabled; + [Write, Description("")] String NotificationDetailsRoleGroups[]; + [Write, Description("")] Boolean ClipDeletionEnabled; + [Write, Description("")] Boolean SessionRecordingEnabled; + [Write, Description("")] String RecordingTimeframePreEventInSec; + [Write, Description("")] String RecordingTimeframePostEventInSec; + [Write, Description("")] String BandwidthCapInMb; + [Write, Description("")] String OfflineRecordingStorageLimitInMb; [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] 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 f0f6913a172c090606adb3ef2437cbcbb0b88925 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 24 Sep 2024 12:21:15 -0400 Subject: [PATCH 271/465] Updates --- .../MSFT_DefenderSubscriptionPlan.psm1} | 0 .../MSFT_DefenderSubscriptionPlan.schema.mof} | 4 ++-- .../readme.md | 2 +- .../settings.json | 2 +- .../2-Update.ps1 | 0 Modules/Microsoft365DSC/Modules/M365DSCDocGenerator.psm1 | 3 +++ Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 | 4 ++-- Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 | 2 +- Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 | 4 ++++ Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 4 ++-- ...ps1 => Microsoft365DSC.DefenderSubscriptionPlan.Tests.ps1} | 0 11 files changed, 16 insertions(+), 9 deletions(-) rename Modules/Microsoft365DSC/DSCResources/{MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.psm1 => MSFT_DefenderSubscriptionPlan/MSFT_DefenderSubscriptionPlan.psm1} (100%) rename Modules/Microsoft365DSC/DSCResources/{MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.schema.mof => MSFT_DefenderSubscriptionPlan/MSFT_DefenderSubscriptionPlan.schema.mof} (92%) rename Modules/Microsoft365DSC/DSCResources/{MSFT_MdcSubscriptionDefenderPlan => MSFT_DefenderSubscriptionPlan}/readme.md (95%) rename Modules/Microsoft365DSC/DSCResources/{MSFT_MdcSubscriptionDefenderPlan => MSFT_DefenderSubscriptionPlan}/settings.json (89%) rename Modules/Microsoft365DSC/Examples/Resources/{MdcSubscriptionDefenderPlan => DefenderSubscriptionPlan}/2-Update.ps1 (100%) rename Tests/Unit/Microsoft365DSC/{Microsoft365DSC.MdcSubscriptionDefenderPlan.Tests.ps1 => Microsoft365DSC.DefenderSubscriptionPlan.Tests.ps1} (100%) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_DefenderSubscriptionPlan/MSFT_DefenderSubscriptionPlan.psm1 similarity index 100% rename from Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.psm1 rename to Modules/Microsoft365DSC/DSCResources/MSFT_DefenderSubscriptionPlan/MSFT_DefenderSubscriptionPlan.psm1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_DefenderSubscriptionPlan/MSFT_DefenderSubscriptionPlan.schema.mof similarity index 92% rename from Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.schema.mof rename to Modules/Microsoft365DSC/DSCResources/MSFT_DefenderSubscriptionPlan/MSFT_DefenderSubscriptionPlan.schema.mof index 3abb93040c..5a9df9169a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/MSFT_MdcSubscriptionDefenderPlan.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_DefenderSubscriptionPlan/MSFT_DefenderSubscriptionPlan.schema.mof @@ -1,5 +1,5 @@ -[ClassVersion("1.0.0.0"), FriendlyName("MdcSubscriptionDefenderPlan")] -class MSFT_MdcSubscriptionDefenderPlan : OMI_BaseResource +[ClassVersion("1.0.0.0"), FriendlyName("DefenderSubscriptionPlan")] +class MSFT_DefenderSubscriptionPlan : OMI_BaseResource { [Key, Description("The display name of the subscription.")] String SubscriptionName; [Key, Description("The Defender plan name, for the list all of possible Defender plans refer to Defender for Cloud documentation")] String PlanName; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_DefenderSubscriptionPlan/readme.md similarity index 95% rename from Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/readme.md rename to Modules/Microsoft365DSC/DSCResources/MSFT_DefenderSubscriptionPlan/readme.md index 6cd90a1442..915493e159 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_DefenderSubscriptionPlan/readme.md @@ -1,5 +1,5 @@ -# MdcSubscriptionDefenderPlan +# DefenderSubscriptionPlan ## Description diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_DefenderSubscriptionPlan/settings.json similarity index 89% rename from Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/settings.json rename to Modules/Microsoft365DSC/DSCResources/MSFT_DefenderSubscriptionPlan/settings.json index 3b429806ed..d0ccb20829 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_MdcSubscriptionDefenderPlan/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_DefenderSubscriptionPlan/settings.json @@ -1,5 +1,5 @@ { - "resourceName": "MdcSubscriptionDefenderPlan", + "resourceName": "DefenderSubscriptionPlan", "description": "Enables or disables Microsoft Defender plans for a subscription in Microsoft Defender for Cloud.", "roles": { "read": [], diff --git a/Modules/Microsoft365DSC/Examples/Resources/MdcSubscriptionDefenderPlan/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/DefenderSubscriptionPlan/2-Update.ps1 similarity index 100% rename from Modules/Microsoft365DSC/Examples/Resources/MdcSubscriptionDefenderPlan/2-Update.ps1 rename to Modules/Microsoft365DSC/Examples/Resources/DefenderSubscriptionPlan/2-Update.ps1 diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDocGenerator.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDocGenerator.psm1 index a140964be6..35d03c8bef 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDocGenerator.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDocGenerator.psm1 @@ -958,6 +958,9 @@ function Update-M365DSCResourceDocumentationPage 'AAD*' { $targetFolder = 'azure-ad' } + 'Defender*' + { $targetFolder = 'Defender' + } 'EXO*' { $targetFolder = 'exchange' } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 index 2545a03b39..7258cda1bd 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 @@ -382,9 +382,9 @@ function Get-IconPath { return Get-Base64EncodedImage -IconName "Intune.jpg" } - elseif ($ResourceName.StartsWith('Intune')) + elseif ($ResourceName.StartsWith('Defender')) { - return 'http://microsoft365dsc.com/Images/Intune.jpg' + return Get-Base64EncodedImage -IconName "SecurityAndCompliance.png" } return $null } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 index 2b124e6da7..c5300bf1ec 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 @@ -41,7 +41,7 @@ function Start-M365DSCConfigurationExtract $MaxProcesses = 16, [Parameter()] - [ValidateSet('AAD', 'FABRIC', 'SPO', 'EXO', 'INTUNE', 'SC', 'SENTINEL', 'OD', 'O365', 'TEAMS', 'PP', 'PLANNER')] + [ValidateSet('AAD', 'FABRIC', 'SPO', 'DEFENDER','EXO', 'INTUNE', 'SC', 'SENTINEL', 'OD', 'O365', 'TEAMS', 'PP', 'PLANNER')] [System.String[]] $Workloads, diff --git a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 index a393a98017..cd9fb23c62 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 @@ -292,6 +292,10 @@ function Add-M365DSCTelemetryEvent { $Data.Add('Workload', 'Azure Active Directory') } + elseif ($Data.Resource.StartsWith('MSFT_Intune') -or $Data.Resource.StartsWith('Defender')) + { + $Data.Add('Workload', 'Defender') + } elseif ($Data.Resource.StartsWith('MSFT_EXO') -or $Data.Resource.StartsWith('EXO')) { $Data.Add('Workload', 'Exchange Online') diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index d899a833d1..64402b9114 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1230,7 +1230,7 @@ function Export-M365DSCConfiguration $Components, [Parameter(ParameterSetName = 'Export')] - [ValidateSet('AAD', 'FABRIC', 'SPO', 'EXO', 'INTUNE', 'SC', 'OD', 'O365', 'PLANNER', 'PP', 'TEAMS')] + [ValidateSet('AAD', 'DEFENDER', 'FABRIC', 'SPO', 'EXO', 'INTUNE', 'SC', 'OD', 'O365', 'PLANNER', 'PP', 'TEAMS')] [System.String[]] $Workloads, @@ -1777,7 +1777,7 @@ function New-M365DSCConnection param ( [Parameter(Mandatory = $true)] - [ValidateSet('Azure', 'AzureDevOPS', 'ExchangeOnline', 'Fabric', 'Intune', ` + [ValidateSet('Azure', 'AzureDevOPS', 'Defender', 'ExchangeOnline', 'Fabric', 'Intune', ` 'SecurityComplianceCenter', 'PnP', 'PowerPlatforms', ` 'MicrosoftTeams', 'MicrosoftGraph', 'SharePointOnlineREST', 'Tasks')] [System.String] diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.MdcSubscriptionDefenderPlan.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.DefenderSubscriptionPlan.Tests.ps1 similarity index 100% rename from Tests/Unit/Microsoft365DSC/Microsoft365DSC.MdcSubscriptionDefenderPlan.Tests.ps1 rename to Tests/Unit/Microsoft365DSC/Microsoft365DSC.DefenderSubscriptionPlan.Tests.ps1 From 32ef5e164a3aee52143d3ea1f57c82dde1b81ac9 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 24 Sep 2024 13:10:27 -0400 Subject: [PATCH 272/465] Update 2-Update.ps1 --- .../Examples/Resources/DefenderSubscriptionPlan/2-Update.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/DefenderSubscriptionPlan/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/DefenderSubscriptionPlan/2-Update.ps1 index 89955f7891..1d13946923 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/DefenderSubscriptionPlan/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/DefenderSubscriptionPlan/2-Update.ps1 @@ -21,7 +21,7 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - MdcSubscriptionDefenderPlan 'TestSubscription' + DefenderSubscriptionPlan 'TestSubscription' { SubscriptionName = 'MyTestSubscription' PlanName = 'VirtualMachines' From 9e9214a4e641ea4745c40aa9f283a677e44d3045 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 24 Sep 2024 17:24:35 +0000 Subject: [PATCH 273/465] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/Defender | 98 +++++++++++++++++++ .../cmdlets/Export-M365DSCConfiguration.md | 2 +- 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 docs/docs/resources/Defender diff --git a/docs/docs/resources/Defender b/docs/docs/resources/Defender new file mode 100644 index 0000000000..eec42f0198 --- /dev/null +++ b/docs/docs/resources/Defender @@ -0,0 +1,98 @@ +# DefenderSubscriptionPlan + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **SubscriptionName** | Key | String | The display name of the subscription. | | +| **PlanName** | Key | String | The Defender plan name, for the list all of possible Defender plans refer to Defender for Cloud documentation | | +| **SubscriptionId** | Write | String | The unique identifier of the Azure subscription. | | +| **PricingTier** | Write | String | The pricing tier ('Standard' or 'Free') | | +| **SubPlanName** | Write | String | The Defender sub plan name, for the list all of possible sub plans refer to Defender for Cloud documentation | | +| **Extensions** | Write | String | The extensions offered under the plan, for more information refer to Defender for Cloud documentation | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Enables or disables Microsoft Defender plans for a subscription in Microsoft Defender for Cloud. +For more information about the available Defender plans, sub plans and plan extensions refer to Defender for Cloud onboarding API documentation. +https://learn.microsoft.com/en-us/rest/api/defenderforcloud/pricings/update?view=rest-defenderforcloud-2024-01-01&tabs=HTTP + + +To have all security features enabled during plan enablement, make sure to assign the required Azure RBAC permissions to the application running this module. +For more information about the required permissions refer to the documentation https://learn.microsoft.com/en-us/azure/defender-for-cloud/permissions. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + DefenderSubscriptionPlan 'TestSubscription' + { + SubscriptionName = 'MyTestSubscription' + PlanName = 'VirtualMachines' + SubPlanName = 'P2' + PricingTier = 'Standard' + SubscriptionId = 'd620d94d-916d-4dd9-9de5-179292873e20' + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} +``` + diff --git a/docs/docs/user-guide/cmdlets/Export-M365DSCConfiguration.md b/docs/docs/user-guide/cmdlets/Export-M365DSCConfiguration.md index 2bef8f6002..ee8cb34b28 100644 --- a/docs/docs/user-guide/cmdlets/Export-M365DSCConfiguration.md +++ b/docs/docs/user-guide/cmdlets/Export-M365DSCConfiguration.md @@ -17,7 +17,7 @@ This function does not generate any output. | FileName | False | String | | | Specifies the name of the file in which the exported DSC configuration should be stored. | | ConfigurationName | False | String | | | Specifies the name of the configuration that will be generated. | | Components | False | String[] | | | Specifies the components for which an export should be created. | -| Workloads | False | String[] | | AAD, FABRIC, SPO, EXO, INTUNE, SC, OD, O365, PLANNER, PP, TEAMS | Specifies the workload for which an export should be created for all resources. | +| Workloads | False | String[] | | AAD, DEFENDER, FABRIC, SPO, EXO, INTUNE, SC, OD, O365, PLANNER, PP, TEAMS | Specifies the workload for which an export should be created for all resources. | | Mode | False | String | Default | Lite, Default, Full | Specifies the mode of the export: Lite, Default or Full. | | MaxProcesses | False | Object | | | Specifies the maximum number of processes that should run simultanious. | | GenerateInfo | False | Boolean | | | Specifies if each exported resource should get a link to the Wiki article of the resource. | From c827687e8a64d856c60070f7e16ce138e2832da3 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 24 Sep 2024 17:26:26 +0000 Subject: [PATCH 274/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 140 +++++++++--------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 9eca5b6007..63fc07080b 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -5419,6 +5419,76 @@ } ] }, + { + "ClassName": "MSFT_DefenderSubscriptionPlan", + "Parameters": [ + { + "CIMType": "String", + "Name": "SubscriptionName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "PlanName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "SubscriptionId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PricingTier", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SubPlanName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Extensions", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOAcceptedDomain", "Parameters": [ @@ -35974,76 +36044,6 @@ } ] }, - { - "ClassName": "MSFT_MdcSubscriptionDefenderPlan", - "Parameters": [ - { - "CIMType": "String", - "Name": "SubscriptionName", - "Option": "Key" - }, - { - "CIMType": "String", - "Name": "PlanName", - "Option": "Key" - }, - { - "CIMType": "String", - "Name": "SubscriptionId", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "PricingTier", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "SubPlanName", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "Extensions", - "Option": "Write" - }, - { - "CIMType": "string", - "Name": "Ensure", - "Option": "Write" - }, - { - "CIMType": "MSFT_Credential", - "Name": "Credential", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "ApplicationId", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "TenantId", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "CertificateThumbprint", - "Option": "Write" - }, - { - "CIMType": "Boolean", - "Name": "ManagedIdentity", - "Option": "Write" - }, - { - "CIMType": "String[]", - "Name": "AccessTokens", - "Option": "Write" - } - ] - }, { "ClassName": "MSFT_O365AdminAuditLogConfig", "Parameters": [ From bd90633809640953188eefb20173e0d7cd56bf18 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Tue, 24 Sep 2024 23:36:48 +0200 Subject: [PATCH 275/465] Fix exception not being rethrown in exception handler --- CHANGELOG.md | 4 ++ ...neSettingCatalogCustomPolicyWindows10.psm1 | 53 +++++++++++-------- ...tingCatalogCustomPolicyWindows10.Tests.ps1 | 12 +++++ 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1f55085e4..bcb2336a49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,10 @@ * IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10 * Add missing `AccessTokens` parameter to `Export-TargetResource` FIXES [#5034](https://github.com/microsoft/Microsoft365DSC/issues/5034) +* IntuneSettingCatalogCustomPolicyWindows10 + * Update export logic to target more specific policy types. + * Prevent thrown exception to be caught by exception handler. + FIXES [#5088](https://github.com/microsoft/Microsoft365DSC/issues/5088) * SCInsiderRiskEntityList * Initial release. * SCRoleGroup diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogCustomPolicyWindows10/MSFT_IntuneSettingCatalogCustomPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogCustomPolicyWindows10/MSFT_IntuneSettingCatalogCustomPolicyWindows10.psm1 index ebebc20cb0..1f639783f1 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogCustomPolicyWindows10/MSFT_IntuneSettingCatalogCustomPolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogCustomPolicyWindows10/MSFT_IntuneSettingCatalogCustomPolicyWindows10.psm1 @@ -107,24 +107,25 @@ function Get-TargetResource { Write-Verbose -Message "Could not find an Intune Setting Catalog Custom Policy for Windows10 with Id {$Id}" - if (-Not [string]::IsNullOrEmpty($Name)) + if (-not [string]::IsNullOrEmpty($Name)) { $getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` - -Filter "Name eq '$Name' and Platforms eq 'windows10'" ` - -ErrorAction SilentlyContinue | Where-Object ` - -FilterScript {[String]::IsNullOrWhiteSpace($_.TemplateReference.TemplateId)} - if ($getValue.count -gt 1) + -Filter "Name eq '$Name' and Platforms eq 'windows10' and Technologies eq 'mdm' and TemplateReference/TemplateFamily eq 'none'" ` + -ErrorAction SilentlyContinue + + if ($getValue.Count -gt 1) { throw "Error: The displayName {$Name} is not unique in the tenant`r`nEnsure the display Name is unique for this type of resource." } - if (-not [string]::IsNullOrEmpty($getValue.id)) + + if (-not [string]::IsNullOrEmpty($getValue.Id)) { - $getValue = Get-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $getValue.id -ExpandProperty 'settings' -ErrorAction SilentlyContinue + $getValue = Get-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $getValue.Id -ExpandProperty 'settings' -ErrorAction SilentlyContinue } } } #endregion - if ([string]::IsNullOrEmpty($getValue.id)) + if ([string]::IsNullOrEmpty($getValue.Id)) { Write-Verbose -Message "Could not find an Intune Setting Catalog Custom Policy for Windows10 with Name {$Name}" return $nullResult @@ -202,6 +203,11 @@ function Get-TargetResource -TenantId $TenantId ` -Credential $Credential + if ($_.Exception.Message -like "Error: The displayName*") + { + throw $_ + } + return $nullResult } } @@ -304,17 +310,17 @@ function Set-TargetResource if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - Write-Verbose -Message "Creating an Intune Setting Catalog Custom Policy for Windows10 with Name {$DisplayName}" + Write-Verbose -Message "Creating an Intune Setting Catalog Custom Policy for Windows10 with Name {$Name}" $BoundParameters.Remove('Assignments') | Out-Null - $CreateParameters = ([Hashtable]$BoundParameters).clone() + $CreateParameters = ([Hashtable]$BoundParameters).Clone() $CreateParameters = Rename-M365DSCCimInstanceParameter -Properties $CreateParameters -KeyMapping $keyToRename $CreateParameters.Remove('Id') | Out-Null - $keys = (([Hashtable]$CreateParameters).clone()).Keys + $keys = (([Hashtable]$CreateParameters).Clone()).Keys foreach ($key in $keys) { - if ($null -ne $CreateParameters.$key -and $CreateParameters.$key.getType().Name -like '*cimInstance*') + if ($null -ne $CreateParameters.$key -and $CreateParameters.$key.GetType().Name -like '*cimInstance*') { $CreateParameters.$key = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $CreateParameters.$key } @@ -324,9 +330,9 @@ function Set-TargetResource $policy = New-MgBetaDeviceManagementConfigurationPolicy -BodyParameter $CreateParameters $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments - if ($policy.id) + if ($policy.Id) { - Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $policy.id ` + Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $policy.Id ` -Targets $assignmentsHash ` -Repository 'deviceManagement/configurationPolicies' } @@ -337,15 +343,15 @@ function Set-TargetResource Write-Verbose -Message "Updating the Intune Setting Catalog Custom Policy for Windows10 with Id {$($currentInstance.Id)}" $BoundParameters.Remove('Assignments') | Out-Null - $UpdateParameters = ([Hashtable]$BoundParameters).clone() + $UpdateParameters = ([Hashtable]$BoundParameters).Clone() $UpdateParameters = Rename-M365DSCCimInstanceParameter -Properties $UpdateParameters -KeyMapping $keyToRename $UpdateParameters.Remove('Id') | Out-Null - $keys = (([Hashtable]$UpdateParameters).clone()).Keys + $keys = (([Hashtable]$UpdateParameters).Clone()).Keys foreach ($key in $keys) { - if ($null -ne $UpdateParameters.$key -and $UpdateParameters.$key.getType().Name -like '*cimInstance*') + if ($null -ne $UpdateParameters.$key -and $UpdateParameters.$key.GetType().Name -like '*cimInstance*') { $UpdateParameters.$key = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $UpdateParameters.$key } @@ -357,7 +363,7 @@ function Set-TargetResource $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments Update-DeviceConfigurationPolicyAssignment ` - -DeviceConfigurationPolicyId $currentInstance.id ` + -DeviceConfigurationPolicyId $currentInstance.Id ` -Targets $assignmentsHash ` -Repository 'deviceManagement/configurationPolicies' #endregion @@ -462,7 +468,7 @@ function Test-TargetResource Write-Verbose -Message "Testing configuration of the Intune Setting Catalog Custom Policy for Windows10 with Id {$Id} and Name {$Name}" $CurrentValues = Get-TargetResource @PSBoundParameters - $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() if ($CurrentValues.Ensure -ne $Ensure) { @@ -476,13 +482,13 @@ function Test-TargetResource { $source = $PSBoundParameters.$key $target = $CurrentValues.$key - if ($source.getType().Name -like '*CimInstance*') + if ($source.GetType().Name -like '*CimInstance*') { $testResult = Compare-M365DSCComplexObject ` -Source ($source) ` -Target ($target) - if (-Not $testResult) + if (-not $testResult) { $testResult = $false break @@ -491,7 +497,7 @@ function Test-TargetResource } } - $ValuesToCheck.remove('Id') | Out-Null + $ValuesToCheck.Remove('Id') | Out-Null Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" @@ -567,7 +573,8 @@ function Export-TargetResource [array]$getValue = Get-MgBetaDeviceManagementConfigurationPolicy -Filter $Filter -All ` -ErrorAction Stop | Where-Object -FilterScript { ` $_.Platforms -eq 'windows10' -and - [String]::IsNullOrWhiteSpace($_.TemplateReference.TemplateId) + $_.Technologies -eq 'mdm' -and + $_.TemplateReference.TemplateFamily -eq 'none' } #endregion diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneSettingCatalogCustomPolicyWindows10.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneSettingCatalogCustomPolicyWindows10.Tests.ps1 index 9468a1b899..d8b2b14c14 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneSettingCatalogCustomPolicyWindows10.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneSettingCatalogCustomPolicyWindows10.Tests.ps1 @@ -320,6 +320,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } ) Technologies = 'mdm' + TemplateReference = @{ + TemplateFamily = 'none' + } } } } @@ -508,6 +511,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } ) Technologies = 'mdm' + TemplateReference = @{ + TemplateFamily = 'none' + } } } } @@ -689,6 +695,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } ) Technologies = 'mdm' + TemplateReference = @{ + TemplateFamily = 'none' + } } } @@ -806,6 +815,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } ) Technologies = 'mdm' + TemplateReference = @{ + TemplateFamily = 'none' + } } } } From 106e2496498b93580eb338c2d5236febb1abcc77 Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Wed, 25 Sep 2024 10:38:45 +0530 Subject: [PATCH 276/465] Added PreAuthorized Application --- .../MSFT_AADApplication.psm1 | 65 +++++++++++++++++++ .../MSFT_AADApplication.schema.mof | 14 ++++ 2 files changed, 79 insertions(+) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index b0296818a5..4a6b918f1e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -60,6 +60,10 @@ function Get-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $Api, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $AuthenticationBehaviors, @@ -201,6 +205,24 @@ function Get-TargetResource $complexAuthenticationBehaviors = $null } + $complexApi = @{} + $complexPreAuthorizedApplications = @() + foreach ($currentPreAuthorizedApplications in $AADApp.api.preAuthorizedApplications) + { + $myPreAuthorizedApplications = @{} + $myPreAuthorizedApplications.Add('AppId', $currentPreAuthorizedApplications.appId) + $myPreAuthorizedApplications.Add('PermissionIds', $currentPreAuthorizedApplications.permissionIds) + if ($myPreAuthorizedApplications.values.Where({$null -ne $_}).Count -gt 0) + { + $complexPreAuthorizedApplications += $myPreAuthorizedApplications + } + } + $complexApi.Add('PreAuthorizedApplications',$complexPreAuthorizedApplications) + if ($complexApi.values.Where({$null -ne $_}).Count -eq 0) + { + $complexApi = $null + } + $complexKeyCredentials = @() foreach ($currentkeyCredentials in $AADApp.keyCredentials) @@ -311,6 +333,7 @@ function Get-TargetResource Owners = $OwnersValues ObjectId = $AADApp.Id AppId = $AADApp.AppId + Api = $complexApi AuthenticationBehaviors = $complexAuthenticationBehaviors KeyCredentials = $complexKeyCredentials PasswordCredentials = $complexPasswordCredentials @@ -409,6 +432,10 @@ function Set-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $Api, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $AuthenticationBehaviors, @@ -891,6 +918,10 @@ function Test-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $Api, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $AuthenticationBehaviors, @@ -1139,6 +1170,35 @@ function Export-TargetResource $Results.Permissions = Get-M365DSCAzureADAppPermissionsAsString $Results.Permissions } + if ($null -ne $Results.Api) + { + $complexMapping = @( + @{ + Name = 'Api' + CimInstanceName = 'MicrosoftGraphApiApplication' + IsRequired = $False + } + @{ + Name = 'PreAuthorizedApplications' + CimInstanceName = 'MicrosoftGraphPreAuthorizedApplication' + IsRequired = $False + } + ) + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.Api ` + -CIMInstanceName 'MicrosoftGraphapiApplication' ` + -ComplexTypeMapping $complexMapping + + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.Api = $complexTypeStringResult + } + else + { + $Results.Remove('Api') | Out-Null + } + } + if ($null -ne $Results.AuthenticationBehaviors) { $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` @@ -1205,6 +1265,11 @@ function Export-TargetResource -Results $Results ` -Credential $Credential + if ($Results.Api) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "Api" -IsCIMArray:$False + } + if ($null -ne $Results.Permissions) { $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof index 5c341a898e..90582a5f0e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof @@ -7,6 +7,19 @@ class MSFT_AADApplicationPermission [Write, Description("Represented whether or not the Admin consent been granted on the app.")] Boolean AdminConsentGranted; }; +[ClassVersion("1.0.0")] +class MSFT_MicrosoftGraphPreAuthorizedApplication +{ + [Write, Description("The unique identifier for the client application.")] String AppId; + [Write, Description("The unique identifier for the scopes the client application is granted.")] String PermissionIds[]; +}; + +[ClassVersion("1.0.0")] +class MSFT_MicrosoftGraphApiApplication +{ + [Write, Description("Lists the client applications that are preauthorized with the specified delegated permissions to access this application's APIs. Users aren't required to consent to any preauthorized application (for the permissions specified). However, any other permissions not listed in preAuthorizedApplications (requested through incremental consent for example) will require user consent."), EmbeddedInstance("MSFT_MicrosoftGraphPreAuthorizedApplication")] String PreAuthorizedApplications[]; +}; + [ClassVersion("1.0.0")] class MSFT_MicrosoftGraphAuthenticationBehaviors { @@ -62,6 +75,7 @@ class MSFT_AADApplication : OMI_BaseResource [Write, Description("User-defined URI(s) that uniquely identify a Web application within its Azure AD tenant, or within a verified custom domain.")] string IdentifierUris[]; [Write, Description("Specifies the fallback application type as public client, such as an installed application running on a mobile device. The default value is false, which means the fallback application type is confidential client such as web app. There are certain scenarios where Microsoft Entra ID cannot determine the client application type (for example, ROPC flow where it is configured without specifying a redirect URI). In those cases, Microsoft Entra ID will interpret the application type based on the value of this property.")] Boolean IsFallbackPublicClient; [Write, Description("Client applications that are tied to this resource application.")] string KnownClientApplications[]; + [Write, Description("Specifies settings for an application that implements a web API."), EmbeddedInstance("MSFT_MicrosoftGraphapiApplication")] String Api; [Write, Description("The collection of breaking change behaviors related to token issuance that are configured for the application. Authentication behaviors are unset by default (null) and must be explicitly enabled or disabled. Nullable. Returned only on $select. For more information about authentication behaviors, see Manage application authenticationBehaviors to avoid unverified use of email claims for user identification or authorization."), EmbeddedInstance("MSFT_MicrosoftGraphauthenticationBehaviors")] String AuthenticationBehaviors; [Write, Description("The collection of password credentials associated with the application. Not nullable."), EmbeddedInstance("MSFT_MicrosoftGraphpasswordCredential")] String PasswordCredentials[]; [Write, Description("The collection of key credentials associated with the application. Not nullable. Supports $filter (eq, not, ge, le)."), EmbeddedInstance("MSFT_MicrosoftGraphkeyCredential")] String KeyCredentials[]; From 9476aa375e436ef357210430b9cf0accadc65d88 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 25 Sep 2024 08:29:14 -0400 Subject: [PATCH 277/465] SCDeviceConditionalAccessRule - Initial Release --- CHANGELOG.md | 2 + .../MSFT_SCDeviceConditionalAccessRule.psm1 | 1073 +++++++++++++++++ ...T_SCDeviceConditionalAccessRule.schema.mof | 63 + .../readme.md | 6 + .../settings.json | 28 + .../1-Create.ps1 | 60 + .../2-Update.ps1 | 60 + .../3-Remove.ps1 | 34 + ...SC.SCDeviceConditionalAccessRule.Tests.ps1 | 407 +++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 457 +++++++ 10 files changed, 2190 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCDeviceConditionalAccessRule/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCDeviceConditionalAccessRule/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCDeviceConditionalAccessRule/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConditionalAccessRule.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index c1f55085e4..0b538b36bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,8 @@ * IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10 * Add missing `AccessTokens` parameter to `Export-TargetResource` FIXES [#5034](https://github.com/microsoft/Microsoft365DSC/issues/5034) +* SCDeviceConditionalAccessRule + * Initial release. * SCInsiderRiskEntityList * Initial release. * SCRoleGroup diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.psm1 new file mode 100644 index 0000000000..834c470d45 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.psm1 @@ -0,0 +1,1073 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $Policy, + + [Parameter(Mandatory = $true)] + [System.String[]] + $TargetGroups, + + [Parameter()] + [System.String] + $AccountName, + + [Parameter()] + [System.String] + $AccountUserName, + + [Parameter()] + [System.Boolean] + $AllowAppStore, + + [Parameter()] + [System.Boolean] + $AllowAssistantWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowConvenienceLogon, + + [Parameter()] + [System.Boolean] + $AllowDiagnosticSubmission, + + [Parameter()] + [System.Boolean] + $AllowiCloudBackup, + + [Parameter()] + [System.Boolean] + $AllowiCloudDocSync, + + [Parameter()] + [System.Boolean] + $AllowiCloudPhotoSync, + + [Parameter()] + [System.Boolean] + $AllowJailbroken, + + [Parameter()] + [System.Boolean] + $AllowPassbookWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowScreenshot, + + [Parameter()] + [System.Boolean] + $AllowSimplePassword, + + [Parameter()] + [System.Boolean] + $AllowVideoConferencing, + + [Parameter()] + [System.Boolean] + $AllowVoiceAssistant, + + [Parameter()] + [System.Boolean] + $AllowVoiceDialing, + + [Parameter()] + [System.UInt32] + $AntiVirusSignatureStatus, + + [Parameter()] + [System.UInt32] + $AntiVirusStatus, + + [Parameter()] + [System.String] + $AppsRating, + + [Parameter()] + [System.String] + $AutoUpdateStatus, + + [Parameter()] + [System.Boolean] + $BluetoothEnabled, + + [Parameter()] + [System.Boolean] + $CameraEnabled, + + [Parameter()] + [System.String] + $EmailAddress, + + [Parameter()] + [System.Boolean] + $EnableRemovableStorage, + + [Parameter()] + [System.String] + $ExchangeActiveSyncHost, + + [Parameter()] + [System.Boolean] + $FirewallStatus, + + [Parameter()] + [System.Boolean] + $ForceAppStorePassword, + + [Parameter()] + [System.Boolean] + $ForceEncryptedBackup, + + [Parameter()] + [System.UInt32] + $MaxPasswordAttemptsBeforeWipe, + + [Parameter()] + [System.UInt32] + $MaxPasswordGracePeriod, + + [Parameter()] + [System.String] + $MoviesRating, + + [Parameter()] + [System.UInt32] + $PasswordComplexity, + + [Parameter()] + [System.UInt32] + $PasswordExpirationDays, + + [Parameter()] + [System.UInt32] + $PasswordHistoryCount, + + [Parameter()] + [System.UInt32] + $PasswordMinComplexChars, + + [Parameter()] + [System.UInt32] + $PasswordMinimumLength, + + [Parameter()] + [System.UInt32] + $PasswordQuality, + + [Parameter()] + [System.Boolean] + $PasswordRequired, + + [Parameter()] + [System.String] + $PasswordTimeout, + + [Parameter()] + [System.Boolean] + $PhoneMemoryEncrypted, + + [Parameter()] + [System.String] + $RegionRatings, + + [Parameter()] + [System.Boolean] + $RequireEmailProfile, + + [Parameter()] + [System.Boolean] + $SmartScreenEnabled, + + [Parameter()] + [System.Boolean] + $SystemSecurityTLS, + + [Parameter()] + [System.String] + $TVShowsRating, + + [Parameter()] + [System.String] + $UserAccountControlStatus, + + [Parameter()] + [System.Boolean] + $WLANEnabled, + + [Parameter()] + [System.String] + $WorkFoldersSyncUrl, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'SecurityComplianceCenter' ` + -InboundParameters $PSBoundParameters | Out-Null + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -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 + { + $policyObj = Get-DeviceConditionalAccessPolicy | Where-Object -FilterScript {$_.Name -eq $Policy} + if ($null -ne $policyObj) + { + Write-Verbose -Message "Found policy object {$Policy}" + if ($null -ne $Script:exportedInstances -and $Script:ExportMode -and $null) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Policy -eq $policyObj.ExchangeObjectId} + } + else + { + $instance = Get-DeviceConditionalAccessRule | Where-Object -FilterScript {$_.Policy -eq $policyObj.ExchangeObjectId} + } + } + if ($null -eq $instance) + { + return $nullResult + } + + $groupNames = @() + foreach ($group in $instance.TargetGroups) + { + $groupValue = '' + $entry = Get-MgGroup -GroupId $group.Guid -ErrorAction SilentlyContinue + if ($null -eq $entry) + { + $entry = Get-MgUser -UserId $group.Guid -ErrorAction SilentlyContinue + $groupValue = $entry.UserPrincipalName + } + else + { + $groupValue = $entry.DisplayName + } + + if ($null -eq $entry) + { + Write-Error -Message "Could not find group or user identified with id {$group}" + } + else + { + $groupNames += $groupValue + } + } + + $results = @{ + Name = $instance.Name + Policy = $policyObj.Name + TargetGroups = $groupNames + AccountName = $instance.AccountName + AccountUserName = $instance.AccountUserName + AllowAppStore = $instance.AllowAppStore + AllowAssistantWhileLocked = $instance.AllowAssistantWhileLocked + AllowConvenienceLogon = $instance.AllowConvenienceLogon + AllowDiagnosticSubmission = $instance.AllowDiagnosticSubmission + AllowiCloudBackup = $instance.AllowiCloudBackup + AllowiCloudDocSync = $instance.AllowiCloudDocSync + AllowiCloudPhotoSync = $instance.AllowiCloudPhotoSync + AllowJailbroken = $instance.AllowJailbroken + AllowPassbookWhileLocked = $instance.AllowPassbookWhileLocked + AllowScreenshot = $instance.AllowScreenshot + AllowSimplePassword = $instance.AllowSimplePassword + AllowVideoConferencing = $instance.AllowVideoConferencing + AllowVoiceAssistant = $instance.AllowVoiceAssistant + AllowVoiceDialing = $instance.AllowVoiceDialing + AntiVirusSignatureStatus = $instance.AntiVirusSignatureStatus + AntiVirusStatus = $instance.AntiVirusStatus + AppsRating = $instance.AppsRating + AutoUpdateStatus = $instance.AutoUpdateStatus + BluetoothEnabled = $instance.BluetoothEnabled + CameraEnabled = $instance.CameraEnabled + EmailAddress = $instance.EmailAddress + EnableRemovableStorage = $instance.EnableRemovableStorage + ExchangeActiveSyncHost = $instance.ExchangeActiveSyncHost + FirewallStatus = $instance.FirewallStatus + ForceAppStorePassword = $instance.ForceAppStorePassword + ForceEncryptedBackup = $instance.ForceEncryptedBackup + MaxPasswordAttemptsBeforeWipe = $instance.MaxPasswordAttemptsBeforeWipe + MaxPasswordGracePeriod = $instance.MaxPasswordGracePeriod + MoviesRating = $instance.MoviesRating + PasswordComplexity = $instance.PasswordComplexity + PasswordExpirationDays = $instance.PasswordExpirationDays + PasswordHistoryCount = $instance.PasswordHistoryCount + PasswordMinComplexChars = $instance.PasswordMinComplexChars + PasswordMinimumLength = $instance.PasswordMinimumLength + PasswordQuality = $instance.PasswordQuality + PasswordRequired = $instance.PasswordRequired + PasswordTimeout = $instance.PasswordTimeout + PhoneMemoryEncrypted = $instance.PhoneMemoryEncrypted + RegionRatings = $instance.RegionRatings + RequireEmailProfile = $instance.RequireEmailProfile + SmartScreenEnabled = $instance.SmartScreenEnabled + SystemSecurityTLS = $instance.SystemSecurityTLS + TVShowsRating = $instance.TVShowsRating + UserAccountControlStatus = $instance.UserAccountControlStatus + WLANEnabled = $instance.WLANEnabled + WorkFoldersSyncUrl = $instance.WorkFoldersSyncUrl + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $Policy, + + [Parameter(Mandatory = $true)] + [System.String[]] + $TargetGroups, + + [Parameter()] + [System.String] + $AccountName, + + [Parameter()] + [System.String] + $AccountUserName, + + [Parameter()] + [System.Boolean] + $AllowAppStore, + + [Parameter()] + [System.Boolean] + $AllowAssistantWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowConvenienceLogon, + + [Parameter()] + [System.Boolean] + $AllowDiagnosticSubmission, + + [Parameter()] + [System.Boolean] + $AllowiCloudBackup, + + [Parameter()] + [System.Boolean] + $AllowiCloudDocSync, + + [Parameter()] + [System.Boolean] + $AllowiCloudPhotoSync, + + [Parameter()] + [System.Boolean] + $AllowJailbroken, + + [Parameter()] + [System.Boolean] + $AllowPassbookWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowScreenshot, + + [Parameter()] + [System.Boolean] + $AllowSimplePassword, + + [Parameter()] + [System.Boolean] + $AllowVideoConferencing, + + [Parameter()] + [System.Boolean] + $AllowVoiceAssistant, + + [Parameter()] + [System.Boolean] + $AllowVoiceDialing, + + [Parameter()] + [System.UInt32] + $AntiVirusSignatureStatus, + + [Parameter()] + [System.UInt32] + $AntiVirusStatus, + + [Parameter()] + [System.String] + $AppsRating, + + [Parameter()] + [System.String] + $AutoUpdateStatus, + + [Parameter()] + [System.Boolean] + $BluetoothEnabled, + + [Parameter()] + [System.Boolean] + $CameraEnabled, + + [Parameter()] + [System.String] + $EmailAddress, + + [Parameter()] + [System.Boolean] + $EnableRemovableStorage, + + [Parameter()] + [System.String] + $ExchangeActiveSyncHost, + + [Parameter()] + [System.Boolean] + $FirewallStatus, + + [Parameter()] + [System.Boolean] + $ForceAppStorePassword, + + [Parameter()] + [System.Boolean] + $ForceEncryptedBackup, + + [Parameter()] + [System.UInt32] + $MaxPasswordAttemptsBeforeWipe, + + [Parameter()] + [System.UInt32] + $MaxPasswordGracePeriod, + + [Parameter()] + [System.String] + $MoviesRating, + + [Parameter()] + [System.UInt32] + $PasswordComplexity, + + [Parameter()] + [System.UInt32] + $PasswordExpirationDays, + + [Parameter()] + [System.UInt32] + $PasswordHistoryCount, + + [Parameter()] + [System.UInt32] + $PasswordMinComplexChars, + + [Parameter()] + [System.UInt32] + $PasswordMinimumLength, + + [Parameter()] + [System.UInt32] + $PasswordQuality, + + [Parameter()] + [System.Boolean] + $PasswordRequired, + + [Parameter()] + [System.String] + $PasswordTimeout, + + [Parameter()] + [System.Boolean] + $PhoneMemoryEncrypted, + + [Parameter()] + [System.String] + $RegionRatings, + + [Parameter()] + [System.Boolean] + $RequireEmailProfile, + + [Parameter()] + [System.Boolean] + $SmartScreenEnabled, + + [Parameter()] + [System.Boolean] + $SystemSecurityTLS, + + [Parameter()] + [System.String] + $TVShowsRating, + + [Parameter()] + [System.String] + $UserAccountControlStatus, + + [Parameter()] + [System.Boolean] + $WLANEnabled, + + [Parameter()] + [System.String] + $WorkFoldersSyncUrl, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $setParameters.Remove('Name') | Out-Null + + if ($Ensure -eq 'Present' -and $null -ne $TargetGroups) + { + $targetGroupsValue = @() + foreach ($group in $TargetGroups) + { + $groupValue = '' + $entry = Get-MgGroup -Filter "DisplayName eq '$group'" -ErrorAction SilentlyContinue + if ($null -eq $entry) + { + $entry = Get-MgUser -UserId $group -ErrorAction SilentlyContinue + $groupValue = $entry.Id + } + else + { + $groupValue = $entry.Id + } + + if ($null -eq $entry) + { + Write-Error -Message "Could not find group or user identified with id {$group}" + } + else + { + $targetGroupsValue += $groupValue + } + } + $setParameters.TargetGroups = $targetGroupsValue + } + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating new device conditional access rule {$Name}" + New-DeviceConditionalAccessRule @setParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + $setParameters.Remove('Policy') | Out-Null + $setParameters.Add('Identity', $currentInstance.Name) + Write-Verbose -Message "Updating device conditional access rule {$Name}" + Set-DeviceConditionalAccessRule @setParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing device conditional access rule {$Name}" + Remove-DeviceConditionalAccessRule -Identity $currentInstance.Name -Confirm:$false + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $Policy, + + [Parameter(Mandatory = $true)] + [System.String[]] + $TargetGroups, + + [Parameter()] + [System.String] + $AccountName, + + [Parameter()] + [System.String] + $AccountUserName, + + [Parameter()] + [System.Boolean] + $AllowAppStore, + + [Parameter()] + [System.Boolean] + $AllowAssistantWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowConvenienceLogon, + + [Parameter()] + [System.Boolean] + $AllowDiagnosticSubmission, + + [Parameter()] + [System.Boolean] + $AllowiCloudBackup, + + [Parameter()] + [System.Boolean] + $AllowiCloudDocSync, + + [Parameter()] + [System.Boolean] + $AllowiCloudPhotoSync, + + [Parameter()] + [System.Boolean] + $AllowJailbroken, + + [Parameter()] + [System.Boolean] + $AllowPassbookWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowScreenshot, + + [Parameter()] + [System.Boolean] + $AllowSimplePassword, + + [Parameter()] + [System.Boolean] + $AllowVideoConferencing, + + [Parameter()] + [System.Boolean] + $AllowVoiceAssistant, + + [Parameter()] + [System.Boolean] + $AllowVoiceDialing, + + [Parameter()] + [System.UInt32] + $AntiVirusSignatureStatus, + + [Parameter()] + [System.UInt32] + $AntiVirusStatus, + + [Parameter()] + [System.String] + $AppsRating, + + [Parameter()] + [System.String] + $AutoUpdateStatus, + + [Parameter()] + [System.Boolean] + $BluetoothEnabled, + + [Parameter()] + [System.Boolean] + $CameraEnabled, + + [Parameter()] + [System.String] + $EmailAddress, + + [Parameter()] + [System.Boolean] + $EnableRemovableStorage, + + [Parameter()] + [System.String] + $ExchangeActiveSyncHost, + + [Parameter()] + [System.Boolean] + $FirewallStatus, + + [Parameter()] + [System.Boolean] + $ForceAppStorePassword, + + [Parameter()] + [System.Boolean] + $ForceEncryptedBackup, + + [Parameter()] + [System.UInt32] + $MaxPasswordAttemptsBeforeWipe, + + [Parameter()] + [System.UInt32] + $MaxPasswordGracePeriod, + + [Parameter()] + [System.String] + $MoviesRating, + + [Parameter()] + [System.UInt32] + $PasswordComplexity, + + [Parameter()] + [System.UInt32] + $PasswordExpirationDays, + + [Parameter()] + [System.UInt32] + $PasswordHistoryCount, + + [Parameter()] + [System.UInt32] + $PasswordMinComplexChars, + + [Parameter()] + [System.UInt32] + $PasswordMinimumLength, + + [Parameter()] + [System.UInt32] + $PasswordQuality, + + [Parameter()] + [System.Boolean] + $PasswordRequired, + + [Parameter()] + [System.String] + $PasswordTimeout, + + [Parameter()] + [System.Boolean] + $PhoneMemoryEncrypted, + + [Parameter()] + [System.String] + $RegionRatings, + + [Parameter()] + [System.Boolean] + $RequireEmailProfile, + + [Parameter()] + [System.Boolean] + $SmartScreenEnabled, + + [Parameter()] + [System.Boolean] + $SystemSecurityTLS, + + [Parameter()] + [System.String] + $TVShowsRating, + + [Parameter()] + [System.String] + $UserAccountControlStatus, + + [Parameter()] + [System.Boolean] + $WLANEnabled, + + [Parameter()] + [System.String] + $WorkFoldersSyncUrl, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + $ValuesToCheck.Remove('Name') | Out-Null + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $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 + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-DeviceConditionalAccessRule -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $config.Name + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Name = $config.Name + Policy = $config.Name.Split('{')[0] + TargetGroups = $config.TargetGroups + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.schema.mof new file mode 100644 index 0000000000..30617d1cdf --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.schema.mof @@ -0,0 +1,63 @@ +[ClassVersion("1.0.0.0"), FriendlyName("SCDeviceConditionalAccessRule")] +class MSFT_SCDeviceConditionalAccessRule : OMI_BaseResource +{ + [Key, Description("")] String Name; + [Write, Description("")] String Policy; + [Write, Description("")] String TargetGroups[]; + [Write, Description("")] String AccountName; + [Write, Description("")] String AccountUserName; + [Write, Description("")] Boolean AllowAppStore; + [Write, Description("")] Boolean AllowAssistantWhileLocked; + [Write, Description("")] Boolean AllowConvenienceLogon; + [Write, Description("")] Boolean AllowDiagnosticSubmission; + [Write, Description("")] Boolean AllowiCloudBackup; + [Write, Description("")] Boolean AllowiCloudDocSync; + [Write, Description("")] Boolean AllowiCloudPhotoSync; + [Write, Description("")] Boolean AllowJailbroken; + [Write, Description("")] Boolean AllowPassbookWhileLocked; + [Write, Description("")] Boolean AllowScreenshot; + [Write, Description("")] Boolean AllowSimplePassword; + [Write, Description("")] Boolean AllowVideoConferencing; + [Write, Description("")] Boolean AllowVoiceAssistant; + [Write, Description("")] Boolean AllowVoiceDialing; + [Write, Description("")] UInt32 AntiVirusSignatureStatus; + [Write, Description("")] UInt32 AntiVirusStatus; + [Write, Description("")] String AppsRating; + [Write, Description("")] String AutoUpdateStatus; + [Write, Description("")] Boolean BluetoothEnabled; + [Write, Description("")] Boolean CameraEnabled; + [Write, Description("")] String EmailAddress; + [Write, Description("")] Boolean EnableRemovableStorage; + [Write, Description("")] String ExchangeActiveSyncHost; + [Write, Description("")] Boolean FirewallStatus; + [Write, Description("")] Boolean ForceAppStorePassword; + [Write, Description("")] Boolean ForceEncryptedBackup; + [Write, Description("")] UInt32 MaxPasswordAttemptsBeforeWipe; + [Write, Description("")] UInt32 MaxPasswordGracePeriod; + [Write, Description("")] String MoviesRating; + [Write, Description("")] UInt32 PasswordComplexity; + [Write, Description("")] UInt32 PasswordExpirationDays; + [Write, Description("")] UInt32 PasswordHistoryCount; + [Write, Description("")] UInt32 PasswordMinComplexChars; + [Write, Description("")] UInt32 PasswordMinimumLength; + [Write, Description("")] UInt32 PasswordQuality; + [Write, Description("")] Boolean PasswordRequired; + [Write, Description("")] String PasswordTimeout; + [Write, Description("")] Boolean PhoneMemoryEncrypted; + [Write, Description("")] String RegionRatings; + [Write, Description("")] Boolean RequireEmailProfile; + [Write, Description("")] Boolean SmartScreenEnabled; + [Write, Description("")] Boolean SystemSecurityTLS; + [Write, Description("")] String TVShowsRating; + [Write, Description("")] String UserAccountControlStatus; + [Write, Description("")] Boolean WLANEnabled; + [Write, Description("")] String WorkFoldersSyncUrl; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] 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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/readme.md new file mode 100644 index 0000000000..a6bdf75fdf --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/readme.md @@ -0,0 +1,6 @@ + +# SCDeviceConditionalAccessRule + +## Description + +Manages Purview Device Conditional Access rules. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/settings.json new file mode 100644 index 0000000000..dc19088d20 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/settings.json @@ -0,0 +1,28 @@ +{ + "resourceName": "SCDeviceConditionalAccessRule", + "description": "Manages Purview Device Conditional Access rules.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Group.Read.All" + } + ], + "update": [ + { + "name": "Group.Read.All" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConditionalAccessRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConditionalAccessRule/1-Create.ps1 new file mode 100644 index 0000000000..775f239937 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConditionalAccessRule/1-Create.ps1 @@ -0,0 +1,60 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCDeviceConditionalAccessRule "MyDeviceConditionalAccessRule" + { + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowJailbroken = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + ApplicationId = $ApplicationId; + BluetoothEnabled = $True; + CameraEnabled = $True; + CertificateThumbprint = $CertificateThumbprint; + EnableRemovableStorage = $True; + Ensure = "Present"; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + TenantId = $TenantId; + WLANEnabled = $True; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConditionalAccessRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConditionalAccessRule/2-Update.ps1 new file mode 100644 index 0000000000..0cbf28e67d --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConditionalAccessRule/2-Update.ps1 @@ -0,0 +1,60 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCDeviceConditionalAccessRule "MyDeviceConditionalAccessRule" + { + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowJailbroken = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + ApplicationId = $ApplicationId; + BluetoothEnabled = $True; + CameraEnabled = $True; + CertificateThumbprint = $CertificateThumbprint; + EnableRemovableStorage = $True; + Ensure = "Present"; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $True; #Drift + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + TenantId = $TenantId; + WLANEnabled = $True; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConditionalAccessRule/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConditionalAccessRule/3-Remove.ps1 new file mode 100644 index 0000000000..6d7c6f583b --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConditionalAccessRule/3-Remove.ps1 @@ -0,0 +1,34 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCDeviceConditionalAccessRule "MyDeviceConditionalAccessRule" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + Name = "MyPolicy{394b}"; + Policy = "MyPolicy"; + TenantId = $TenantId; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConditionalAccessRule.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConditionalAccessRule.Tests.ps1 new file mode 100644 index 0000000000..486829be73 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConditionalAccessRule.Tests.ps1 @@ -0,0 +1,407 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName New-DeviceConditionalAccessRule -MockWith { + } + + Mock -CommandName Set-DeviceConditionalAccessRule -MockWith { + } + + Mock -CommandName Remove-DeviceConditionalAccessRule -MockWith { + } + + Mock -Command Get-MgGroup -MockWith { + return @{ + Id = "33333-33333-33333-33333-33333" + DisplayName = 'Communications' + } + } + + Mock -CommandName Get-DeviceConditionalAccessPolicy -MockWith { + return @{ + Name = 'MyPolicy' + Id = '12345-12345-12345-12345-12345' + } + } + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowJailbroken = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + WLANEnabled = $True; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-DeviceConditionalAccessRule -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 a new instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-DeviceConditionalAccessRule -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowJailbroken = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + WLANEnabled = $True; + Ensure = 'Absent' + Credential = $Credential; + } + + Mock -CommandName Get-DeviceConditionalAccessRule -MockWith { + return @{ + Id = '11111-11111-11111-11111-11111' + Name = 'MyPolicy{394b}' + TargetGroups = @('22222-22222-22222-22222-22222') + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowJailbroken = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + WLANEnabled = $True; + } + } + } + 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 remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-DeviceConditionalAccessRule -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowJailbroken = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + WLANEnabled = $True; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-DeviceConditionalAccessRule -MockWith { + return @{ + Id = '11111-11111-11111-11111-11111' + Name = 'MyPolicy{394b}' + TargetGroups = @('22222-22222-22222-22222-22222') + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowJailbroken = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + WLANEnabled = $True; + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowJailbroken = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + WLANEnabled = $True; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-DeviceConditionalAccessRule -MockWith { + return @{ + Id = '11111-11111-11111-11111-11111' + Name = 'MyPolicy{394b}' + TargetGroups = @('22222-22222-22222-22222-22222') + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowJailbroken = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $False; #Drift + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + WLANEnabled = $True; + } + } + } + + 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-DeviceConditionalAccessRule -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-DeviceConditionalAccessRule -MockWith { + return @{ + Id = '11111-11111-11111-11111-11111' + Name = 'MyPolicy{394b}' + TargetGroups = @('22222-22222-22222-22222-22222') + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowJailbroken = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $False; #Drift + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + WLANEnabled = $True; + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 1cbd830f9e..60ca7a79e5 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -1582,6 +1582,463 @@ function Get-DeviceConditionalAccessPolicy $Identity ) } +function Get-DeviceConditionalAccessRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $CompareToWorkload, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $DomainController + ) +} +function New-DeviceConditionalAccessRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $CameraEnabled, + + [Parameter()] + [System.Object] + $EnableRemovableStorage, + + [Parameter()] + [System.Object] + $AntiVirusSignatureStatus, + + [Parameter()] + [System.Object] + $FirewallStatus, + + [Parameter()] + [System.Object] + $AllowAppStore, + + [Parameter()] + [System.Object] + $AllowAssistantWhileLocked, + + [Parameter()] + [System.Object] + $AllowiCloudBackup, + + [Parameter()] + [System.Object] + $AppsRating, + + [Parameter()] + [System.Object] + $PasswordHistoryCount, + + [Parameter()] + [System.Object] + $PasswordQuality, + + [Parameter()] + [System.Object] + $PasswordMinComplexChars, + + [Parameter()] + [System.Object] + $PhoneMemoryEncrypted, + + [Parameter()] + [System.String] + $EmailAddress, + + [Parameter()] + [System.Object] + $BluetoothEnabled, + + [Parameter()] + [System.Object] + $AllowConvenienceLogon, + + [Parameter()] + [System.Object] + $MaxPasswordGracePeriod, + + [Parameter()] + [System.Object] + $AllowiCloudDocSync, + + [Parameter()] + [System.Object] + $ForceAppStorePassword, + + [Parameter()] + [System.Object] + $Policy, + + [Parameter()] + [System.Object] + $TVShowsRating, + + [Parameter()] + [System.Object] + $AllowJailbroken, + + [Parameter()] + [System.Object] + $RequireEmailProfile, + + [Parameter()] + [System.Object] + $AllowDiagnosticSubmission, + + [Parameter()] + [System.Object] + $AutoUpdateStatus, + + [Parameter()] + [System.String] + $AccountUserName, + + [Parameter()] + [System.Object] + $WLANEnabled, + + [Parameter()] + [System.Object] + $AllowVoiceDialing, + + [Parameter()] + [System.String] + $AccountName, + + [Parameter()] + [System.Object] + $PasswordExpirationDays, + + [Parameter()] + [System.Object] + $PasswordTimeout, + + [Parameter()] + [System.Object] + $AllowiCloudPhotoSync, + + [Parameter()] + [System.Object] + $AllowSimplePassword, + + [Parameter()] + [System.Object] + $AllowPassbookWhileLocked, + + [Parameter()] + [System.Object] + $PasswordMinimumLength, + + [Parameter()] + [System.Object] + $AllowVideoConferencing, + + [Parameter()] + [System.Object] + $PasswordRequired, + + [Parameter()] + [System.Object] + $MaxPasswordAttemptsBeforeWipe, + + [Parameter()] + [System.Object] + $MoviesRating, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $DomainController, + + [Parameter()] + [System.Object] + $AntiVirusStatus, + + [Parameter()] + [System.String] + $WorkFoldersSyncUrl, + + [Parameter()] + [System.Object] + $UserAccountControlStatus, + + [Parameter()] + [System.Object] + $ForceEncryptedBackup, + + [Parameter()] + [System.String] + $ExchangeActiveSyncHost, + + [Parameter()] + [System.Object] + $AllowScreenshot, + + [Parameter()] + [System.Object] + $PasswordComplexity, + + [Parameter()] + [System.Object] + $TargetGroups, + + [Parameter()] + [System.Object] + $AllowVoiceAssistant, + + [Parameter()] + [System.Object] + $SystemSecurityTLS, + + [Parameter()] + [System.Object] + $RegionRatings, + + [Parameter()] + [System.Object] + $SmartScreenEnabled + ) +} +function Remove-DeviceConditionalAccessRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $Identity + ) +} +function Set-DeviceConditionalAccessRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $CameraEnabled, + + [Parameter()] + [System.Object] + $EnableRemovableStorage, + + [Parameter()] + [System.Object] + $AntiVirusSignatureStatus, + + [Parameter()] + [System.Object] + $FirewallStatus, + + [Parameter()] + [System.Object] + $AllowAppStore, + + [Parameter()] + [System.Object] + $AllowAssistantWhileLocked, + + [Parameter()] + [System.Object] + $AllowiCloudBackup, + + [Parameter()] + [System.Object] + $AppsRating, + + [Parameter()] + [System.Object] + $PasswordHistoryCount, + + [Parameter()] + [System.Object] + $PasswordQuality, + + [Parameter()] + [System.Object] + $PasswordMinComplexChars, + + [Parameter()] + [System.Object] + $PhoneMemoryEncrypted, + + [Parameter()] + [System.String] + $EmailAddress, + + [Parameter()] + [System.Object] + $BluetoothEnabled, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $AllowConvenienceLogon, + + [Parameter()] + [System.Object] + $MaxPasswordGracePeriod, + + [Parameter()] + [System.Object] + $AllowiCloudDocSync, + + [Parameter()] + [System.Object] + $ForceAppStorePassword, + + [Parameter()] + [System.Object] + $TVShowsRating, + + [Parameter()] + [System.Object] + $AllowJailbroken, + + [Parameter()] + [System.Object] + $RequireEmailProfile, + + [Parameter()] + [System.Object] + $AllowDiagnosticSubmission, + + [Parameter()] + [System.Object] + $AutoUpdateStatus, + + [Parameter()] + [System.String] + $AccountUserName, + + [Parameter()] + [System.Object] + $WLANEnabled, + + [Parameter()] + [System.Object] + $AllowVoiceDialing, + + [Parameter()] + [System.String] + $AccountName, + + [Parameter()] + [System.Object] + $PasswordExpirationDays, + + [Parameter()] + [System.Object] + $PasswordTimeout, + + [Parameter()] + [System.Object] + $AllowiCloudPhotoSync, + + [Parameter()] + [System.Object] + $AllowSimplePassword, + + [Parameter()] + [System.Object] + $AllowPassbookWhileLocked, + + [Parameter()] + [System.Object] + $PasswordMinimumLength, + + [Parameter()] + [System.Object] + $AllowVideoConferencing, + + [Parameter()] + [System.Object] + $PasswordRequired, + + [Parameter()] + [System.Object] + $MaxPasswordAttemptsBeforeWipe, + + [Parameter()] + [System.Object] + $MoviesRating, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $DomainController, + + [Parameter()] + [System.Object] + $AntiVirusStatus, + + [Parameter()] + [System.String] + $WorkFoldersSyncUrl, + + [Parameter()] + [System.Object] + $UserAccountControlStatus, + + [Parameter()] + [System.Object] + $ForceEncryptedBackup, + + [Parameter()] + [System.String] + $ExchangeActiveSyncHost, + + [Parameter()] + [System.Object] + $AllowScreenshot, + + [Parameter()] + [System.Object] + $PasswordComplexity, + + [Parameter()] + [System.Object] + $TargetGroups, + + [Parameter()] + [System.Object] + $AllowVoiceAssistant, + + [Parameter()] + [System.Object] + $SystemSecurityTLS, + + [Parameter()] + [System.Object] + $RegionRatings, + + [Parameter()] + [System.Object] + $SmartScreenEnabled + ) +} + function Get-DeviceConfigurationPolicy { [CmdletBinding()] From 492d5689893c3fad898b2f4f1ab911f38c5ddf21 Mon Sep 17 00:00:00 2001 From: kasaxena5 Date: Wed, 25 Sep 2024 18:48:14 +0530 Subject: [PATCH 278/465] fix --- .../MSFT_AADApplication.psm1 | 54 +++++++++++++++++-- .../MSFT_AADApplication.schema.mof | 1 + 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 4a6b918f1e..9a4196d6e3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -186,6 +186,7 @@ function Get-TargetResource $AADBetaApp= Get-MgBetaApplication -Property "id,displayName,appId,authenticationBehaviors" -ApplicationId $ObjectID -ErrorAction SilentlyContinue + $AADAppKeyCredentials = Get-MgApplication -Property "keyCredentials" -ApplicationId $ObjectID -ErrorAction SilentlyContinue $complexAuthenticationBehaviors = @{} if ($null -ne $AADBetaApp.authenticationBehaviors.blockAzureADGraphAccess) @@ -225,16 +226,17 @@ function Get-TargetResource $complexKeyCredentials = @() - foreach ($currentkeyCredentials in $AADApp.keyCredentials) + foreach ($currentkeyCredentials in $AADAppKeyCredentials.keyCredentials) { $mykeyCredentials = @{} - $mykeyCredentials.Add('CustomKeyIdentifier', $currentkeyCredentials.customKeyIdentifier) + $mykeyCredentials.Add('CustomKeyIdentifier', [convert]::ToBase64String($currentkeyCredentials.customKeyIdentifier)) $mykeyCredentials.Add('DisplayName', $currentkeyCredentials.displayName) if ($null -ne $currentkeyCredentials.endDateTime) { $mykeyCredentials.Add('EndDateTime', ([DateTimeOffset]$currentkeyCredentials.endDateTime).ToString('o')) } $mykeyCredentials.Add('KeyId', $currentkeyCredentials.keyId) + $mykeyCredentials.Add('Key', [convert]::ToBase64String($currentkeyCredentials.key)) if ($null -ne $currentkeyCredentials.startDateTime) { $mykeyCredentials.Add('StartDateTime', ([DateTimeOffset]$currentkeyCredentials.startDateTime).ToString('o')) @@ -554,9 +556,17 @@ function Set-TargetResource # App should exist but it doesn't $needToUpdatePermissions = $false $needToUpdateAuthenticationBehaviors = $false + $needToUpdateKeyCredentials = $false $currentParameters.Remove('AppId') | Out-Null $currentParameters.Remove('Permissions') | Out-Null $currentParameters.Remove('AuthenticationBehaviors') | Out-Null + $currentParameters.Remove('KeyCredentials') | Out-Null + $currentParameters.Remove('PasswordCredentials') | Out-Null + if ($PasswordCredentials) + { + Write-Warning -Message "PasswordCredentials is a readonly property and cannot be configured." + + } if ($currentParameters.AvailableToOtherTenants) { @@ -660,6 +670,7 @@ function Set-TargetResource Write-Verbose -Message "Azure AD Application {$DisplayName} was successfully created" $needToUpdatePermissions = $true $needToUpdateAuthenticationBehaviors = $true + $needToUpdateKeyCredentials = $true $tries = 1 $appEntity = $null @@ -687,6 +698,7 @@ function Set-TargetResource $currentAADApp.Add('ID', $AppIdValue) $needToUpdatePermissions = $true $needToUpdateAuthenticationBehaviors = $true + $needToUpdateKeyCredentials = $true } # App exists but should not elseif ($Ensure -eq 'Absent' -and $currentAADApp.Ensure -eq 'Present') @@ -852,7 +864,42 @@ function Set-TargetResource requireClientServicePrincipal = $AuthenticationBehaviors.requireClientServicePrincipal } - Update-MgBetaApplication -ApplicationId ($currentAADApp.Id) -AuthenticationBehaviors $IAuthenticationBehaviors | Out-Null + Update-MgBetaApplication -ApplicationId $currentAADApp.Id -AuthenticationBehaviors $IAuthenticationBehaviors | Out-Null + } + + if($needToUpdateKeyCredentials -and $KeyCredentials) + { + Write-Verbose -Message "Updating for Azure AD Application {$($currentAADApp.DisplayName)} with KeyCredentials:`r`n$($KeyCredentials| Out-String)" + Write-Verbose -Message "Current App Id: $($currentAADApp.AppId)" + + $IKeyCredentials = @() + + foreach ($KeyCredential in $KeyCredentials) + { + $IKeyCredential = @{ + DisplayName = $KeyCredential.displayName + EndDateTime = $KeyCredential.endDateTime + KeyId = $KeyCredential.keyId + Key = [System.Text.Encoding]::UTF8.GetBytes($KeyCredential.key) + StartDateTime = $KeyCredential.startDateTime + Type = $KeyCredential.type + Usage = $KeyCredential.usage + } + + $CustomKeyIdentifier = $null + if($KeyCredential.CustomKeyIdentifier -ne $null) + { + $CustomKeyIdentifier = [System.Text.Encoding]::UTF8.GetBytes($KeyCredential.customKeyIdentifier) + $IKeyCredential.Add('CustomKeyIdentifier', $CustomKeyIdentifier) + } + + Write-Verbose -Message "Updating for Azure AD Application {$($currentAADApp.DisplayName)} with KeyCredentials:`r`n$($IKeyCredential | Out-String)" + Write-Verbose -Message "Current App Id: $($currentAADApp.AppId)" + + $IKeyCredentials += $IKeyCredential + } + + Update-MgApplication -ApplicationId $currentAADApp.Id -KeyCredentials $IKeyCredentials | Out-Null } } @@ -1043,6 +1090,7 @@ function Test-TargetResource if (-not $testResult) { + Write-Verbose "TestResult returned False for $source" $testTargetResource = $false } else { diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof index 90582a5f0e..0f537deaaa 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof @@ -35,6 +35,7 @@ class MSFT_MicrosoftGraphKeyCredential [Write, Description("Friendly name for the key. Optional.")] String DisplayName; [Write, Description("The date and time at which the credential expires. The DateTimeOffset type represents date and time information using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z.")] String EndDateTime; [Write, Description("The unique identifier (GUID) for the key.")] String KeyId; + [Write, Description("The certificate's raw data in byte array converted to Base64 string.")] String Key; [Write, Description("The date and time at which the credential becomes valid.The Timestamp type represents date and time information using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z.")] String StartDateTime; [Write, Description("The type of key credential for example, Symmetric, AsymmetricX509Cert.")] String Type; [Write, Description("A string that describes the purpose for which the key can be used for example, Verify.")] String Usage; From c9940450554cb699fb7a81280654584b327cd130 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 25 Sep 2024 09:20:57 -0400 Subject: [PATCH 279/465] Update MSFT_SCDeviceConditionalAccessRule.schema.mof --- ...T_SCDeviceConditionalAccessRule.schema.mof | 102 +++++++++--------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.schema.mof index 30617d1cdf..95217fa5d0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.schema.mof @@ -1,57 +1,57 @@ [ClassVersion("1.0.0.0"), FriendlyName("SCDeviceConditionalAccessRule")] class MSFT_SCDeviceConditionalAccessRule : OMI_BaseResource { - [Key, Description("")] String Name; - [Write, Description("")] String Policy; - [Write, Description("")] String TargetGroups[]; - [Write, Description("")] String AccountName; - [Write, Description("")] String AccountUserName; - [Write, Description("")] Boolean AllowAppStore; - [Write, Description("")] Boolean AllowAssistantWhileLocked; - [Write, Description("")] Boolean AllowConvenienceLogon; - [Write, Description("")] Boolean AllowDiagnosticSubmission; - [Write, Description("")] Boolean AllowiCloudBackup; - [Write, Description("")] Boolean AllowiCloudDocSync; - [Write, Description("")] Boolean AllowiCloudPhotoSync; - [Write, Description("")] Boolean AllowJailbroken; - [Write, Description("")] Boolean AllowPassbookWhileLocked; - [Write, Description("")] Boolean AllowScreenshot; - [Write, Description("")] Boolean AllowSimplePassword; - [Write, Description("")] Boolean AllowVideoConferencing; - [Write, Description("")] Boolean AllowVoiceAssistant; - [Write, Description("")] Boolean AllowVoiceDialing; - [Write, Description("")] UInt32 AntiVirusSignatureStatus; - [Write, Description("")] UInt32 AntiVirusStatus; - [Write, Description("")] String AppsRating; - [Write, Description("")] String AutoUpdateStatus; - [Write, Description("")] Boolean BluetoothEnabled; - [Write, Description("")] Boolean CameraEnabled; - [Write, Description("")] String EmailAddress; - [Write, Description("")] Boolean EnableRemovableStorage; - [Write, Description("")] String ExchangeActiveSyncHost; - [Write, Description("")] Boolean FirewallStatus; - [Write, Description("")] Boolean ForceAppStorePassword; - [Write, Description("")] Boolean ForceEncryptedBackup; - [Write, Description("")] UInt32 MaxPasswordAttemptsBeforeWipe; - [Write, Description("")] UInt32 MaxPasswordGracePeriod; - [Write, Description("")] String MoviesRating; - [Write, Description("")] UInt32 PasswordComplexity; - [Write, Description("")] UInt32 PasswordExpirationDays; - [Write, Description("")] UInt32 PasswordHistoryCount; - [Write, Description("")] UInt32 PasswordMinComplexChars; - [Write, Description("")] UInt32 PasswordMinimumLength; - [Write, Description("")] UInt32 PasswordQuality; - [Write, Description("")] Boolean PasswordRequired; - [Write, Description("")] String PasswordTimeout; - [Write, Description("")] Boolean PhoneMemoryEncrypted; - [Write, Description("")] String RegionRatings; - [Write, Description("")] Boolean RequireEmailProfile; - [Write, Description("")] Boolean SmartScreenEnabled; - [Write, Description("")] Boolean SystemSecurityTLS; - [Write, Description("")] String TVShowsRating; - [Write, Description("")] String UserAccountControlStatus; - [Write, Description("")] Boolean WLANEnabled; - [Write, Description("")] String WorkFoldersSyncUrl; + [Key, Description("Name for the rule.")] String Name; + [Write, Description("Name of the associated policy.")] String Policy; + [Write, Description("The display names of the graoups targeted by the policy.")] String TargetGroups[]; + [Write, Description("The AccountName parameter specifies the account name.")] String AccountName; + [Write, Description("The AccountUserName parameter specifies the account user name.")] String AccountUserName; + [Write, Description("The AllowAppStore parameter specifies whether to allow access to the app store on devices.")] Boolean AllowAppStore; + [Write, Description("The AllowAssistantWhileLocked parameter specifies whether to allow the use of the voice assistant while devices are locked.")] Boolean AllowAssistantWhileLocked; + [Write, Description("The AllowConvenienceLogon parameter specifies whether to allow convenience logons on devices.")] Boolean AllowConvenienceLogon; + [Write, Description("The AllowDiagnosticSubmission parameter specifies whether to allow diagnostic submissions from devices.")] Boolean AllowDiagnosticSubmission; + [Write, Description("The AllowiCloudBackup parameter specifies whether to allow Apple iCloud Backup from devices.")] Boolean AllowiCloudBackup; + [Write, Description("The AllowiCloudDocSync parameter specifies whether to allow Apple iCloud Documents & Data sync on devices.")] Boolean AllowiCloudDocSync; + [Write, Description("The AllowiCloudPhotoSync parameter specifies whether to allow Apple iCloud Photos sync on devices.")] Boolean AllowiCloudPhotoSync; + [Write, Description("The AllowJailbroken parameter specifies whether to allow access to your organization by jailbroken or rooted devices.")] Boolean AllowJailbroken; + [Write, Description("The AllowPassbookWhileLocked parameter specifies whether to allow the use of Apple Passbook while devices are locked.")] Boolean AllowPassbookWhileLocked; + [Write, Description("The AllowScreenshot parameter specifies whether to allow screenshots on devices.")] Boolean AllowScreenshot; + [Write, Description("The AllowSimplePassword parameter specifies whether to allow simple or non-complex passwords on devices.")] Boolean AllowSimplePassword; + [Write, Description("The AllowVideoConferencing parameter specifies whether to allow video conferencing on devices. ")] Boolean AllowVideoConferencing; + [Write, Description("The AllowVoiceAssistant parameter specifies whether to allow using the voice assistant on devices.")] Boolean AllowVoiceAssistant; + [Write, Description("The AllowVoiceDialing parameter specifies whether to allow voice-activated telephone dialing.")] Boolean AllowVoiceDialing; + [Write, Description("The AntiVirusSignatureStatus parameter specifies the antivirus signature status.")] UInt32 AntiVirusSignatureStatus; + [Write, Description("The AntiVirusStatus parameter specifies the antivirus status.")] UInt32 AntiVirusStatus; + [Write, Description("The AppsRating parameter species the maximum or most restrictive rating of apps that are allowed on devices.")] String AppsRating; + [Write, Description("The AutoUpdateStatus parameter specifies the update settings for devices.")] String AutoUpdateStatus; + [Write, Description("The BluetoothEnabled parameter specifies whether to enable or disable Bluetooth on devices.")] Boolean BluetoothEnabled; + [Write, Description("The BluetoothEnabled parameter specifies whether to enable or disable Bluetooth on devices.")] Boolean CameraEnabled; + [Write, Description("The EmailAddress parameter specifies the email address.")] String EmailAddress; + [Write, Description("The EnableRemovableStorage parameter specifies whether removable storage can be used by devices.")] Boolean EnableRemovableStorage; + [Write, Description("The ExchangeActiveSyncHost parameter specifies the Exchange ActiveSync host.")] String ExchangeActiveSyncHost; + [Write, Description("The FirewallStatus parameter specifies the acceptable firewall status values on devices.")] Boolean FirewallStatus; + [Write, Description("The ForceAppStorePassword parameter specifies whether to require a password to use the app store on devices.")] Boolean ForceAppStorePassword; + [Write, Description("The ForceEncryptedBackup parameter specifies whether to force encrypted backups for devices.")] Boolean ForceEncryptedBackup; + [Write, Description("The MaxPasswordAttemptsBeforeWipe parameter specifies the number of incorrect password attempts that cause devices to be automatically wiped.")] UInt32 MaxPasswordAttemptsBeforeWipe; + [Write, Description("The MaxPasswordGracePeriod parameter specifies the length of time users are allowed to reset expired passwords on devices.")] UInt32 MaxPasswordGracePeriod; + [Write, Description("The MoviesRating parameter species the maximum or most restrictive rating of movies that are allowed on devices. You specify the country/region rating system to use with the RegionRatings parameter.")] String MoviesRating; + [Write, Description("The PasswordComplexity parameter specifies the password complexity.")] UInt32 PasswordComplexity; + [Write, Description("The PasswordExpirationDays parameter specifies the number of days that the same password can be used on devices before users are required to change their passwords.")] UInt32 PasswordExpirationDays; + [Write, Description("The PasswordHistoryCount parameter specifies the minimum number of unique new passwords that are required on devices before an old password can be reused.")] UInt32 PasswordHistoryCount; + [Write, Description("The PasswordMinComplexChars parameter specifies the minimum number of complex characters that are required for device passwords. A complex character isn't a letter.")] UInt32 PasswordMinComplexChars; + [Write, Description("The PasswordMinimumLength parameter specifies the minimum number of characters that are required for device passwords.")] UInt32 PasswordMinimumLength; + [Write, Description("The PasswordQuality parameter specifies the minimum password quality rating that's required for device passwords. Password quality is a numeric scale that indicates the security and complexity of the password. A higher quality value indicates a more secure password.")] UInt32 PasswordQuality; + [Write, Description("The PasswordRequired parameter specifies whether a password is required to access devices.")] Boolean PasswordRequired; + [Write, Description("The PasswordTimeout parameter specifies the length of time that devices can be inactive before a password is required to reactivate them.")] String PasswordTimeout; + [Write, Description("The PhoneMemoryEncrypted parameter specifies whether to encrypt the memory on devices.")] Boolean PhoneMemoryEncrypted; + [Write, Description("The RegionRatings parameter specifies the rating system (country/region) to use for movie and television ratings with the MoviesRating and TVShowsRating parameters.")] String RegionRatings; + [Write, Description("The RequireEmailProfile parameter specifies whether an email profile is required on devices.")] Boolean RequireEmailProfile; + [Write, Description("The SmartScreenEnabled parameter specifies whether to requireWindows SmartScreen on devices.")] Boolean SmartScreenEnabled; + [Write, Description("The SystemSecurityTLS parameter specifies whether TLS encryption is used on devices.")] Boolean SystemSecurityTLS; + [Write, Description("The TVShowsRating parameter species the maximum or most restrictive rating of television shows that are allowed on devices. You specify the country/region rating system to use with the RegionRatings parameter.")] String TVShowsRating; + [Write, Description("The UserAccountControlStatus parameter specifies how User Account Control messages are presented on devices.")] String UserAccountControlStatus; + [Write, Description("The WLANEnabled parameter specifies whether Wi-Fi is enabled devices.")] Boolean WLANEnabled; + [Write, Description("The WorkFoldersSyncUrl parameter specifies the URL that's used to synchronize company data on devices.")] String WorkFoldersSyncUrl; [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; From 19c6bac1bfca86604f01c9845d6d36a68625562c Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 25 Sep 2024 09:32:05 -0400 Subject: [PATCH 280/465] Update MSFT_SCDeviceConditionalAccessRule.schema.mof --- .../MSFT_SCDeviceConditionalAccessRule.schema.mof | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.schema.mof index 95217fa5d0..d70e8d9b12 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConditionalAccessRule/MSFT_SCDeviceConditionalAccessRule.schema.mof @@ -53,7 +53,7 @@ class MSFT_SCDeviceConditionalAccessRule : OMI_BaseResource [Write, Description("The WLANEnabled parameter specifies whether Wi-Fi is enabled devices.")] Boolean WLANEnabled; [Write, Description("The WorkFoldersSyncUrl parameter specifies the URL that's used to synchronize company data on devices.")] String WorkFoldersSyncUrl; - [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent", "Present"}, Values{"Absent", "Present"}] 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; From 84f9843210ad54eeb44f5fe4b7c9978889c0b421 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 25 Sep 2024 13:44:50 +0000 Subject: [PATCH 281/465] Updated Resources and Cmdlet documentation pages --- .../SCDeviceConditionalAccessRule.md | 261 ++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 docs/docs/resources/security-compliance/SCDeviceConditionalAccessRule.md diff --git a/docs/docs/resources/security-compliance/SCDeviceConditionalAccessRule.md b/docs/docs/resources/security-compliance/SCDeviceConditionalAccessRule.md new file mode 100644 index 0000000000..efbdb61253 --- /dev/null +++ b/docs/docs/resources/security-compliance/SCDeviceConditionalAccessRule.md @@ -0,0 +1,261 @@ +# SCDeviceConditionalAccessRule + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Name** | Key | String | Name for the rule. | | +| **Policy** | Write | String | Name of the associated policy. | | +| **TargetGroups** | Write | StringArray[] | The display names of the graoups targeted by the policy. | | +| **AccountName** | Write | String | The AccountName parameter specifies the account name. | | +| **AccountUserName** | Write | String | The AccountUserName parameter specifies the account user name. | | +| **AllowAppStore** | Write | Boolean | The AllowAppStore parameter specifies whether to allow access to the app store on devices. | | +| **AllowAssistantWhileLocked** | Write | Boolean | The AllowAssistantWhileLocked parameter specifies whether to allow the use of the voice assistant while devices are locked. | | +| **AllowConvenienceLogon** | Write | Boolean | The AllowConvenienceLogon parameter specifies whether to allow convenience logons on devices. | | +| **AllowDiagnosticSubmission** | Write | Boolean | The AllowDiagnosticSubmission parameter specifies whether to allow diagnostic submissions from devices. | | +| **AllowiCloudBackup** | Write | Boolean | The AllowiCloudBackup parameter specifies whether to allow Apple iCloud Backup from devices. | | +| **AllowiCloudDocSync** | Write | Boolean | The AllowiCloudDocSync parameter specifies whether to allow Apple iCloud Documents & Data sync on devices. | | +| **AllowiCloudPhotoSync** | Write | Boolean | The AllowiCloudPhotoSync parameter specifies whether to allow Apple iCloud Photos sync on devices. | | +| **AllowJailbroken** | Write | Boolean | The AllowJailbroken parameter specifies whether to allow access to your organization by jailbroken or rooted devices. | | +| **AllowPassbookWhileLocked** | Write | Boolean | The AllowPassbookWhileLocked parameter specifies whether to allow the use of Apple Passbook while devices are locked. | | +| **AllowScreenshot** | Write | Boolean | The AllowScreenshot parameter specifies whether to allow screenshots on devices. | | +| **AllowSimplePassword** | Write | Boolean | The AllowSimplePassword parameter specifies whether to allow simple or non-complex passwords on devices. | | +| **AllowVideoConferencing** | Write | Boolean | The AllowVideoConferencing parameter specifies whether to allow video conferencing on devices. | | +| **AllowVoiceAssistant** | Write | Boolean | The AllowVoiceAssistant parameter specifies whether to allow using the voice assistant on devices. | | +| **AllowVoiceDialing** | Write | Boolean | The AllowVoiceDialing parameter specifies whether to allow voice-activated telephone dialing. | | +| **AntiVirusSignatureStatus** | Write | UInt32 | The AntiVirusSignatureStatus parameter specifies the antivirus signature status. | | +| **AntiVirusStatus** | Write | UInt32 | The AntiVirusStatus parameter specifies the antivirus status. | | +| **AppsRating** | Write | String | The AppsRating parameter species the maximum or most restrictive rating of apps that are allowed on devices. | | +| **AutoUpdateStatus** | Write | String | The AutoUpdateStatus parameter specifies the update settings for devices. | | +| **BluetoothEnabled** | Write | Boolean | The BluetoothEnabled parameter specifies whether to enable or disable Bluetooth on devices. | | +| **CameraEnabled** | Write | Boolean | The BluetoothEnabled parameter specifies whether to enable or disable Bluetooth on devices. | | +| **EmailAddress** | Write | String | The EmailAddress parameter specifies the email address. | | +| **EnableRemovableStorage** | Write | Boolean | The EnableRemovableStorage parameter specifies whether removable storage can be used by devices. | | +| **ExchangeActiveSyncHost** | Write | String | The ExchangeActiveSyncHost parameter specifies the Exchange ActiveSync host. | | +| **FirewallStatus** | Write | Boolean | The FirewallStatus parameter specifies the acceptable firewall status values on devices. | | +| **ForceAppStorePassword** | Write | Boolean | The ForceAppStorePassword parameter specifies whether to require a password to use the app store on devices. | | +| **ForceEncryptedBackup** | Write | Boolean | The ForceEncryptedBackup parameter specifies whether to force encrypted backups for devices. | | +| **MaxPasswordAttemptsBeforeWipe** | Write | UInt32 | The MaxPasswordAttemptsBeforeWipe parameter specifies the number of incorrect password attempts that cause devices to be automatically wiped. | | +| **MaxPasswordGracePeriod** | Write | UInt32 | The MaxPasswordGracePeriod parameter specifies the length of time users are allowed to reset expired passwords on devices. | | +| **MoviesRating** | Write | String | The MoviesRating parameter species the maximum or most restrictive rating of movies that are allowed on devices. You specify the country/region rating system to use with the RegionRatings parameter. | | +| **PasswordComplexity** | Write | UInt32 | The PasswordComplexity parameter specifies the password complexity. | | +| **PasswordExpirationDays** | Write | UInt32 | The PasswordExpirationDays parameter specifies the number of days that the same password can be used on devices before users are required to change their passwords. | | +| **PasswordHistoryCount** | Write | UInt32 | The PasswordHistoryCount parameter specifies the minimum number of unique new passwords that are required on devices before an old password can be reused. | | +| **PasswordMinComplexChars** | Write | UInt32 | The PasswordMinComplexChars parameter specifies the minimum number of complex characters that are required for device passwords. A complex character isn't a letter. | | +| **PasswordMinimumLength** | Write | UInt32 | The PasswordMinimumLength parameter specifies the minimum number of characters that are required for device passwords. | | +| **PasswordQuality** | Write | UInt32 | The PasswordQuality parameter specifies the minimum password quality rating that's required for device passwords. Password quality is a numeric scale that indicates the security and complexity of the password. A higher quality value indicates a more secure password. | | +| **PasswordRequired** | Write | Boolean | The PasswordRequired parameter specifies whether a password is required to access devices. | | +| **PasswordTimeout** | Write | String | The PasswordTimeout parameter specifies the length of time that devices can be inactive before a password is required to reactivate them. | | +| **PhoneMemoryEncrypted** | Write | Boolean | The PhoneMemoryEncrypted parameter specifies whether to encrypt the memory on devices. | | +| **RegionRatings** | Write | String | The RegionRatings parameter specifies the rating system (country/region) to use for movie and television ratings with the MoviesRating and TVShowsRating parameters. | | +| **RequireEmailProfile** | Write | Boolean | The RequireEmailProfile parameter specifies whether an email profile is required on devices. | | +| **SmartScreenEnabled** | Write | Boolean | The SmartScreenEnabled parameter specifies whether to requireWindows SmartScreen on devices. | | +| **SystemSecurityTLS** | Write | Boolean | The SystemSecurityTLS parameter specifies whether TLS encryption is used on devices. | | +| **TVShowsRating** | Write | String | The TVShowsRating parameter species the maximum or most restrictive rating of television shows that are allowed on devices. You specify the country/region rating system to use with the RegionRatings parameter. | | +| **UserAccountControlStatus** | Write | String | The UserAccountControlStatus parameter specifies how User Account Control messages are presented on devices. | | +| **WLANEnabled** | Write | Boolean | The WLANEnabled parameter specifies whether Wi-Fi is enabled devices. | | +| **WorkFoldersSyncUrl** | Write | String | The WorkFoldersSyncUrl parameter specifies the URL that's used to synchronize company data on devices. | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Absent`, `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Manages Purview Device Conditional Access rules. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - Group.Read.All + +- **Update** + + - Group.Read.All + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCDeviceConditionalAccessRule "MyDeviceConditionalAccessRule" + { + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowJailbroken = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + ApplicationId = $ApplicationId; + BluetoothEnabled = $True; + CameraEnabled = $True; + CertificateThumbprint = $CertificateThumbprint; + EnableRemovableStorage = $True; + Ensure = "Present"; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + TenantId = $TenantId; + WLANEnabled = $True; + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCDeviceConditionalAccessRule "MyDeviceConditionalAccessRule" + { + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowJailbroken = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + ApplicationId = $ApplicationId; + BluetoothEnabled = $True; + CameraEnabled = $True; + CertificateThumbprint = $CertificateThumbprint; + EnableRemovableStorage = $True; + Ensure = "Present"; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $True; #Drift + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + TenantId = $TenantId; + WLANEnabled = $True; + } + } +} +``` + +### Example 3 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCDeviceConditionalAccessRule "MyDeviceConditionalAccessRule" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + Name = "MyPolicy{394b}"; + Policy = "MyPolicy"; + TenantId = $TenantId; + } + } +} +``` + From 4a780c0ec2a8a871717f63eceb18b496488cda7d Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 25 Sep 2024 13:46:40 +0000 Subject: [PATCH 282/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 295 ++++++++++++++++++ 1 file changed, 295 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 63fc07080b..a662fe0cfe 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -38244,6 +38244,301 @@ } ] }, + { + "ClassName": "MSFT_SCDeviceConditionalAccessRule", + "Parameters": [ + { + "CIMType": "String", + "Name": "Name", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Policy", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "TargetGroups", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AccountName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AccountUserName", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowAppStore", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowAssistantWhileLocked", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowConvenienceLogon", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowDiagnosticSubmission", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowiCloudBackup", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowiCloudDocSync", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowiCloudPhotoSync", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowJailbroken", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowPassbookWhileLocked", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowScreenshot", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowSimplePassword", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowVideoConferencing", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowVoiceAssistant", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowVoiceDialing", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AntiVirusSignatureStatus", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AntiVirusStatus", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AppsRating", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AutoUpdateStatus", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "BluetoothEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "CameraEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "EmailAddress", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EnableRemovableStorage", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ExchangeActiveSyncHost", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "FirewallStatus", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ForceAppStorePassword", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ForceEncryptedBackup", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "MaxPasswordAttemptsBeforeWipe", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "MaxPasswordGracePeriod", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MoviesRating", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "PasswordComplexity", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "PasswordExpirationDays", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "PasswordHistoryCount", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "PasswordMinComplexChars", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "PasswordMinimumLength", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "PasswordQuality", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PasswordRequired", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PasswordTimeout", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PhoneMemoryEncrypted", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "RegionRatings", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "RequireEmailProfile", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SmartScreenEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SystemSecurityTLS", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TVShowsRating", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "UserAccountControlStatus", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "WLANEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "WorkFoldersSyncUrl", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_SCDeviceConfigurationPolicy", "Parameters": [ From b72784acabe19142b2023925cf6f8b4928239375 Mon Sep 17 00:00:00 2001 From: kasaxena5 Date: Wed, 25 Sep 2024 19:48:00 +0530 Subject: [PATCH 283/465] fix --- .../MSFT_AADApplication.psm1 | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 9a4196d6e3..3dfbe3f422 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -872,9 +872,18 @@ function Set-TargetResource Write-Verbose -Message "Updating for Azure AD Application {$($currentAADApp.DisplayName)} with KeyCredentials:`r`n$($KeyCredentials| Out-String)" Write-Verbose -Message "Current App Id: $($currentAADApp.AppId)" - $IKeyCredentials = @() - - foreach ($KeyCredential in $KeyCredentials) + $CurrentKeyCredentials = (Get-MgApplication -Property "keyCredentials" -ApplicationId $ObjectID -ErrorAction SilentlyContinue).KeyCredentials + + $CurrentKeyCredentialsKeyIds = $CurrentKeyCredentials | ForEach-Object { $_.KeyId } + $DesiredKeyCredentialsKeyIds = $KeyCredentials | ForEach-Object { $_.KeyId } + + $AddKeyCredentials = $KeyCredentials | Where-Object {$_.KeyId -notin $CurrentKeyCredentialsKeyIds}; + $RemoveKeyCredentials = $CurrentKeyCredentials | Where-Object {$_.KeyId -notin $DesiredKeyCredentialsKeyIds}; + + Write-Verbose -Message "Key Credentials to be added:`r`n$($AddKeyCredentials| Out-String)" + Write-Verbose -Message "Key Credentials to be removed:`r`n$($RemoveKeyCredentials| Out-String)" + + foreach ($KeyCredential in $AddKeyCredentials) { $IKeyCredential = @{ DisplayName = $KeyCredential.displayName @@ -893,13 +902,17 @@ function Set-TargetResource $IKeyCredential.Add('CustomKeyIdentifier', $CustomKeyIdentifier) } - Write-Verbose -Message "Updating for Azure AD Application {$($currentAADApp.DisplayName)} with KeyCredentials:`r`n$($IKeyCredential | Out-String)" - Write-Verbose -Message "Current App Id: $($currentAADApp.AppId)" + Write-Verbose -Message "Adding KeyCredentials:`r`n$($KeyCredential| Out-String) to Azure AD Application {$($currentAADApp.DisplayName)} " + Add-MgApplicationKey -ApplicationId $currentAADApp.Id -KeyCredential $IKeyCredentials + } + - $IKeyCredentials += $IKeyCredential + foreach ($KeyCredential in $RemoveKeyCredentials) + { + Write-Verbose -Message "Removing KeyCredentials:`r`n$($KeyCredential| Out-String) to Azure AD Application {$($currentAADApp.DisplayName)} " + Remove-MgApplicationKey -ApplicationId $currentAADApp.Id -KeyId $KeyCredentials.KeyId } - Update-MgApplication -ApplicationId $currentAADApp.Id -KeyCredentials $IKeyCredentials | Out-Null } } From 6fb560250f116f15473594d30ef13a9eeac07c2a Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 25 Sep 2024 10:18:54 -0400 Subject: [PATCH 284/465] SCDeviceConfigurationRule - Initial Release --- CHANGELOG.md | 2 + .../MSFT_SCDeviceConfigurationRule.psm1 | 1060 +++++++++++++++++ .../MSFT_SCDeviceConfigurationRule.schema.mof | 62 + .../MSFT_SCDeviceConfigurationRule/readme.md | 6 + .../settings.json | 28 + .../SCDeviceConfigurationRule/1-Create.ps1 | 59 + .../SCDeviceConfigurationRule/2-Update.ps1 | 59 + .../SCDeviceConfigurationRule/3-Remove.ps1 | 34 + ...365DSC.SCDeviceConfigurationRule.Tests.ps1 | 399 +++++++ 9 files changed, 1709 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b538b36bd..2c6727ac84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,8 @@ FIXES [#5034](https://github.com/microsoft/Microsoft365DSC/issues/5034) * SCDeviceConditionalAccessRule * Initial release. +* SCDeviceConfigurationRule + * Initial release. * SCInsiderRiskEntityList * Initial release. * SCRoleGroup diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 new file mode 100644 index 0000000000..40c55c6307 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 @@ -0,0 +1,1060 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $Policy, + + [Parameter(Mandatory = $true)] + [System.String[]] + $TargetGroups, + + [Parameter()] + [System.String] + $AccountName, + + [Parameter()] + [System.String] + $AccountUserName, + + [Parameter()] + [System.Boolean] + $AllowAppStore, + + [Parameter()] + [System.Boolean] + $AllowAssistantWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowConvenienceLogon, + + [Parameter()] + [System.Boolean] + $AllowDiagnosticSubmission, + + [Parameter()] + [System.Boolean] + $AllowiCloudBackup, + + [Parameter()] + [System.Boolean] + $AllowiCloudDocSync, + + [Parameter()] + [System.Boolean] + $AllowiCloudPhotoSync, + + [Parameter()] + [System.Boolean] + $AllowPassbookWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowScreenshot, + + [Parameter()] + [System.Boolean] + $AllowSimplePassword, + + [Parameter()] + [System.Boolean] + $AllowVideoConferencing, + + [Parameter()] + [System.Boolean] + $AllowVoiceAssistant, + + [Parameter()] + [System.Boolean] + $AllowVoiceDialing, + + [Parameter()] + [System.UInt32] + $AntiVirusSignatureStatus, + + [Parameter()] + [System.UInt32] + $AntiVirusStatus, + + [Parameter()] + [System.String] + $AppsRating, + + [Parameter()] + [System.String] + $AutoUpdateStatus, + + [Parameter()] + [System.Boolean] + $BluetoothEnabled, + + [Parameter()] + [System.Boolean] + $CameraEnabled, + + [Parameter()] + [System.String] + $EmailAddress, + + [Parameter()] + [System.Boolean] + $EnableRemovableStorage, + + [Parameter()] + [System.String] + $ExchangeActiveSyncHost, + + [Parameter()] + [System.Boolean] + $FirewallStatus, + + [Parameter()] + [System.Boolean] + $ForceAppStorePassword, + + [Parameter()] + [System.Boolean] + $ForceEncryptedBackup, + + [Parameter()] + [System.UInt32] + $MaxPasswordAttemptsBeforeWipe, + + [Parameter()] + [System.UInt32] + $MaxPasswordGracePeriod, + + [Parameter()] + [System.String] + $MoviesRating, + + [Parameter()] + [System.UInt32] + $PasswordComplexity, + + [Parameter()] + [System.UInt32] + $PasswordExpirationDays, + + [Parameter()] + [System.UInt32] + $PasswordHistoryCount, + + [Parameter()] + [System.UInt32] + $PasswordMinComplexChars, + + [Parameter()] + [System.UInt32] + $PasswordMinimumLength, + + [Parameter()] + [System.UInt32] + $PasswordQuality, + + [Parameter()] + [System.Boolean] + $PasswordRequired, + + [Parameter()] + [System.String] + $PasswordTimeout, + + [Parameter()] + [System.Boolean] + $PhoneMemoryEncrypted, + + [Parameter()] + [System.String] + $RegionRatings, + + [Parameter()] + [System.Boolean] + $RequireEmailProfile, + + [Parameter()] + [System.Boolean] + $SmartScreenEnabled, + + [Parameter()] + [System.Boolean] + $SystemSecurityTLS, + + [Parameter()] + [System.String] + $TVShowsRating, + + [Parameter()] + [System.String] + $UserAccountControlStatus, + + [Parameter()] + [System.Boolean] + $WLANEnabled, + + [Parameter()] + [System.String] + $WorkFoldersSyncUrl, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'SecurityComplianceCenter' ` + -InboundParameters $PSBoundParameters | Out-Null + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -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 + { + $policyObj = Get-DeviceConfigurationPolicy | Where-Object -FilterScript {$_.Name -eq $Policy} + if ($null -ne $policyObj) + { + Write-Verbose -Message "Found policy object {$Policy}" + if ($null -ne $Script:exportedInstances -and $Script:ExportMode -and $null) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Policy -eq $policyObj.ExchangeObjectId} + } + else + { + $instance = Get-DeviceConfigurationRule | Where-Object -FilterScript {$_.Policy -eq $policyObj.ExchangeObjectId} + } + } + if ($null -eq $instance) + { + return $nullResult + } + + $groupNames = @() + foreach ($group in $instance.TargetGroups) + { + $groupValue = '' + $entry = Get-MgGroup -GroupId $group.Guid -ErrorAction SilentlyContinue + if ($null -eq $entry) + { + $entry = Get-MgUser -UserId $group.Guid -ErrorAction SilentlyContinue + $groupValue = $entry.UserPrincipalName + } + else + { + $groupValue = $entry.DisplayName + } + + if ($null -eq $entry) + { + Write-Error -Message "Could not find group or user identified with id {$group}" + } + else + { + $groupNames += $groupValue + } + } + + $results = @{ + Name = $instance.Name + Policy = $policyObj.Name + TargetGroups = $groupNames + AccountName = $instance.AccountName + AccountUserName = $instance.AccountUserName + AllowAppStore = $instance.AllowAppStore + AllowAssistantWhileLocked = $instance.AllowAssistantWhileLocked + AllowConvenienceLogon = $instance.AllowConvenienceLogon + AllowDiagnosticSubmission = $instance.AllowDiagnosticSubmission + AllowiCloudBackup = $instance.AllowiCloudBackup + AllowiCloudDocSync = $instance.AllowiCloudDocSync + AllowiCloudPhotoSync = $instance.AllowiCloudPhotoSync + AllowPassbookWhileLocked = $instance.AllowPassbookWhileLocked + AllowScreenshot = $instance.AllowScreenshot + AllowSimplePassword = $instance.AllowSimplePassword + AllowVideoConferencing = $instance.AllowVideoConferencing + AllowVoiceAssistant = $instance.AllowVoiceAssistant + AllowVoiceDialing = $instance.AllowVoiceDialing + AntiVirusSignatureStatus = $instance.AntiVirusSignatureStatus + AntiVirusStatus = $instance.AntiVirusStatus + AppsRating = $instance.AppsRating + AutoUpdateStatus = $instance.AutoUpdateStatus + BluetoothEnabled = $instance.BluetoothEnabled + CameraEnabled = $instance.CameraEnabled + EmailAddress = $instance.EmailAddress + EnableRemovableStorage = $instance.EnableRemovableStorage + ExchangeActiveSyncHost = $instance.ExchangeActiveSyncHost + FirewallStatus = $instance.FirewallStatus + ForceAppStorePassword = $instance.ForceAppStorePassword + ForceEncryptedBackup = $instance.ForceEncryptedBackup + MaxPasswordAttemptsBeforeWipe = $instance.MaxPasswordAttemptsBeforeWipe + MaxPasswordGracePeriod = $instance.MaxPasswordGracePeriod + MoviesRating = $instance.MoviesRating + PasswordComplexity = $instance.PasswordComplexity + PasswordExpirationDays = $instance.PasswordExpirationDays + PasswordHistoryCount = $instance.PasswordHistoryCount + PasswordMinComplexChars = $instance.PasswordMinComplexChars + PasswordMinimumLength = $instance.PasswordMinimumLength + PasswordQuality = $instance.PasswordQuality + PasswordRequired = $instance.PasswordRequired + PasswordTimeout = $instance.PasswordTimeout + PhoneMemoryEncrypted = $instance.PhoneMemoryEncrypted + RegionRatings = $instance.RegionRatings + RequireEmailProfile = $instance.RequireEmailProfile + SmartScreenEnabled = $instance.SmartScreenEnabled + SystemSecurityTLS = $instance.SystemSecurityTLS + TVShowsRating = $instance.TVShowsRating + UserAccountControlStatus = $instance.UserAccountControlStatus + WLANEnabled = $instance.WLANEnabled + WorkFoldersSyncUrl = $instance.WorkFoldersSyncUrl + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $Policy, + + [Parameter(Mandatory = $true)] + [System.String[]] + $TargetGroups, + + [Parameter()] + [System.String] + $AccountName, + + [Parameter()] + [System.String] + $AccountUserName, + + [Parameter()] + [System.Boolean] + $AllowAppStore, + + [Parameter()] + [System.Boolean] + $AllowAssistantWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowConvenienceLogon, + + [Parameter()] + [System.Boolean] + $AllowDiagnosticSubmission, + + [Parameter()] + [System.Boolean] + $AllowiCloudBackup, + + [Parameter()] + [System.Boolean] + $AllowiCloudDocSync, + + [Parameter()] + [System.Boolean] + $AllowiCloudPhotoSync, + + [Parameter()] + [System.Boolean] + $AllowPassbookWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowScreenshot, + + [Parameter()] + [System.Boolean] + $AllowSimplePassword, + + [Parameter()] + [System.Boolean] + $AllowVideoConferencing, + + [Parameter()] + [System.Boolean] + $AllowVoiceAssistant, + + [Parameter()] + [System.Boolean] + $AllowVoiceDialing, + + [Parameter()] + [System.UInt32] + $AntiVirusSignatureStatus, + + [Parameter()] + [System.UInt32] + $AntiVirusStatus, + + [Parameter()] + [System.String] + $AppsRating, + + [Parameter()] + [System.String] + $AutoUpdateStatus, + + [Parameter()] + [System.Boolean] + $BluetoothEnabled, + + [Parameter()] + [System.Boolean] + $CameraEnabled, + + [Parameter()] + [System.String] + $EmailAddress, + + [Parameter()] + [System.Boolean] + $EnableRemovableStorage, + + [Parameter()] + [System.String] + $ExchangeActiveSyncHost, + + [Parameter()] + [System.Boolean] + $FirewallStatus, + + [Parameter()] + [System.Boolean] + $ForceAppStorePassword, + + [Parameter()] + [System.Boolean] + $ForceEncryptedBackup, + + [Parameter()] + [System.UInt32] + $MaxPasswordAttemptsBeforeWipe, + + [Parameter()] + [System.UInt32] + $MaxPasswordGracePeriod, + + [Parameter()] + [System.String] + $MoviesRating, + + [Parameter()] + [System.UInt32] + $PasswordComplexity, + + [Parameter()] + [System.UInt32] + $PasswordExpirationDays, + + [Parameter()] + [System.UInt32] + $PasswordHistoryCount, + + [Parameter()] + [System.UInt32] + $PasswordMinComplexChars, + + [Parameter()] + [System.UInt32] + $PasswordMinimumLength, + + [Parameter()] + [System.UInt32] + $PasswordQuality, + + [Parameter()] + [System.Boolean] + $PasswordRequired, + + [Parameter()] + [System.String] + $PasswordTimeout, + + [Parameter()] + [System.Boolean] + $PhoneMemoryEncrypted, + + [Parameter()] + [System.String] + $RegionRatings, + + [Parameter()] + [System.Boolean] + $RequireEmailProfile, + + [Parameter()] + [System.Boolean] + $SmartScreenEnabled, + + [Parameter()] + [System.Boolean] + $SystemSecurityTLS, + + [Parameter()] + [System.String] + $TVShowsRating, + + [Parameter()] + [System.String] + $UserAccountControlStatus, + + [Parameter()] + [System.Boolean] + $WLANEnabled, + + [Parameter()] + [System.String] + $WorkFoldersSyncUrl, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $setParameters.Remove('Name') | Out-Null + + if ($Ensure -eq 'Present' -and $null -ne $TargetGroups) + { + $targetGroupsValue = @() + foreach ($group in $TargetGroups) + { + $groupValue = '' + $entry = Get-MgGroup -Filter "DisplayName eq '$group'" -ErrorAction SilentlyContinue + if ($null -eq $entry) + { + $entry = Get-MgUser -UserId $group -ErrorAction SilentlyContinue + $groupValue = $entry.Id + } + else + { + $groupValue = $entry.Id + } + + if ($null -eq $entry) + { + Write-Error -Message "Could not find group or user identified with id {$group}" + } + else + { + $targetGroupsValue += $groupValue + } + } + $setParameters.TargetGroups = $targetGroupsValue + } + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating new device configuration rule {$Name}" + New-DeviceConfigurationRule @setParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + $setParameters.Remove('Policy') | Out-Null + $setParameters.Add('Identity', $currentInstance.Name) + Write-Verbose -Message "Updating device configuration rule {$Name}" + Set-DeviceConfigurationRule @setParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing device configuration rule {$Name}" + Remove-DeviceConfigurationRuleDeviceConditionalAccessRule -Identity $currentInstance.Name -Confirm:$false + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $Policy, + + [Parameter(Mandatory = $true)] + [System.String[]] + $TargetGroups, + + [Parameter()] + [System.String] + $AccountName, + + [Parameter()] + [System.String] + $AccountUserName, + + [Parameter()] + [System.Boolean] + $AllowAppStore, + + [Parameter()] + [System.Boolean] + $AllowAssistantWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowConvenienceLogon, + + [Parameter()] + [System.Boolean] + $AllowDiagnosticSubmission, + + [Parameter()] + [System.Boolean] + $AllowiCloudBackup, + + [Parameter()] + [System.Boolean] + $AllowiCloudDocSync, + + [Parameter()] + [System.Boolean] + $AllowiCloudPhotoSync, + + [Parameter()] + [System.Boolean] + $AllowPassbookWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowScreenshot, + + [Parameter()] + [System.Boolean] + $AllowSimplePassword, + + [Parameter()] + [System.Boolean] + $AllowVideoConferencing, + + [Parameter()] + [System.Boolean] + $AllowVoiceAssistant, + + [Parameter()] + [System.Boolean] + $AllowVoiceDialing, + + [Parameter()] + [System.UInt32] + $AntiVirusSignatureStatus, + + [Parameter()] + [System.UInt32] + $AntiVirusStatus, + + [Parameter()] + [System.String] + $AppsRating, + + [Parameter()] + [System.String] + $AutoUpdateStatus, + + [Parameter()] + [System.Boolean] + $BluetoothEnabled, + + [Parameter()] + [System.Boolean] + $CameraEnabled, + + [Parameter()] + [System.String] + $EmailAddress, + + [Parameter()] + [System.Boolean] + $EnableRemovableStorage, + + [Parameter()] + [System.String] + $ExchangeActiveSyncHost, + + [Parameter()] + [System.Boolean] + $FirewallStatus, + + [Parameter()] + [System.Boolean] + $ForceAppStorePassword, + + [Parameter()] + [System.Boolean] + $ForceEncryptedBackup, + + [Parameter()] + [System.UInt32] + $MaxPasswordAttemptsBeforeWipe, + + [Parameter()] + [System.UInt32] + $MaxPasswordGracePeriod, + + [Parameter()] + [System.String] + $MoviesRating, + + [Parameter()] + [System.UInt32] + $PasswordComplexity, + + [Parameter()] + [System.UInt32] + $PasswordExpirationDays, + + [Parameter()] + [System.UInt32] + $PasswordHistoryCount, + + [Parameter()] + [System.UInt32] + $PasswordMinComplexChars, + + [Parameter()] + [System.UInt32] + $PasswordMinimumLength, + + [Parameter()] + [System.UInt32] + $PasswordQuality, + + [Parameter()] + [System.Boolean] + $PasswordRequired, + + [Parameter()] + [System.String] + $PasswordTimeout, + + [Parameter()] + [System.Boolean] + $PhoneMemoryEncrypted, + + [Parameter()] + [System.String] + $RegionRatings, + + [Parameter()] + [System.Boolean] + $RequireEmailProfile, + + [Parameter()] + [System.Boolean] + $SmartScreenEnabled, + + [Parameter()] + [System.Boolean] + $SystemSecurityTLS, + + [Parameter()] + [System.String] + $TVShowsRating, + + [Parameter()] + [System.String] + $UserAccountControlStatus, + + [Parameter()] + [System.Boolean] + $WLANEnabled, + + [Parameter()] + [System.String] + $WorkFoldersSyncUrl, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + $ValuesToCheck.Remove('Name') | Out-Null + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $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 + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-DeviceConfigurationRule -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $config.Name + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Name = $config.Name + Policy = $config.Name.Split('{')[0] + TargetGroups = $config.TargetGroups + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof new file mode 100644 index 0000000000..183b485c1a --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof @@ -0,0 +1,62 @@ +[ClassVersion("1.0.0.0"), FriendlyName("SCDeviceConfigurationRule")] +class MSFT_SCDeviceConfigurationRule : OMI_BaseResource +{ + [Key, Description("Name for the rule.")] String Name; + [Write, Description("Name of the associated policy.")] String Policy; + [Write, Description("The display names of the graoups targeted by the policy.")] String TargetGroups[]; + [Write, Description("The AccountName parameter specifies the account name.")] String AccountName; + [Write, Description("The AccountUserName parameter specifies the account user name.")] String AccountUserName; + [Write, Description("The AllowAppStore parameter specifies whether to allow access to the app store on devices.")] Boolean AllowAppStore; + [Write, Description("The AllowAssistantWhileLocked parameter specifies whether to allow the use of the voice assistant while devices are locked.")] Boolean AllowAssistantWhileLocked; + [Write, Description("The AllowConvenienceLogon parameter specifies whether to allow convenience logons on devices.")] Boolean AllowConvenienceLogon; + [Write, Description("The AllowDiagnosticSubmission parameter specifies whether to allow diagnostic submissions from devices.")] Boolean AllowDiagnosticSubmission; + [Write, Description("The AllowiCloudBackup parameter specifies whether to allow Apple iCloud Backup from devices.")] Boolean AllowiCloudBackup; + [Write, Description("The AllowiCloudDocSync parameter specifies whether to allow Apple iCloud Documents & Data sync on devices.")] Boolean AllowiCloudDocSync; + [Write, Description("The AllowiCloudPhotoSync parameter specifies whether to allow Apple iCloud Photos sync on devices.")] Boolean AllowiCloudPhotoSync; + [Write, Description("The AllowPassbookWhileLocked parameter specifies whether to allow the use of Apple Passbook while devices are locked.")] Boolean AllowPassbookWhileLocked; + [Write, Description("The AllowScreenshot parameter specifies whether to allow screenshots on devices.")] Boolean AllowScreenshot; + [Write, Description("The AllowSimplePassword parameter specifies whether to allow simple or non-complex passwords on devices.")] Boolean AllowSimplePassword; + [Write, Description("The AllowVideoConferencing parameter specifies whether to allow video conferencing on devices. ")] Boolean AllowVideoConferencing; + [Write, Description("The AllowVoiceAssistant parameter specifies whether to allow using the voice assistant on devices.")] Boolean AllowVoiceAssistant; + [Write, Description("The AllowVoiceDialing parameter specifies whether to allow voice-activated telephone dialing.")] Boolean AllowVoiceDialing; + [Write, Description("The AntiVirusSignatureStatus parameter specifies the antivirus signature status.")] UInt32 AntiVirusSignatureStatus; + [Write, Description("The AntiVirusStatus parameter specifies the antivirus status.")] UInt32 AntiVirusStatus; + [Write, Description("The AppsRating parameter species the maximum or most restrictive rating of apps that are allowed on devices.")] String AppsRating; + [Write, Description("The AutoUpdateStatus parameter specifies the update settings for devices.")] String AutoUpdateStatus; + [Write, Description("The BluetoothEnabled parameter specifies whether to enable or disable Bluetooth on devices.")] Boolean BluetoothEnabled; + [Write, Description("The BluetoothEnabled parameter specifies whether to enable or disable Bluetooth on devices.")] Boolean CameraEnabled; + [Write, Description("The EmailAddress parameter specifies the email address.")] String EmailAddress; + [Write, Description("The EnableRemovableStorage parameter specifies whether removable storage can be used by devices.")] Boolean EnableRemovableStorage; + [Write, Description("The ExchangeActiveSyncHost parameter specifies the Exchange ActiveSync host.")] String ExchangeActiveSyncHost; + [Write, Description("The FirewallStatus parameter specifies the acceptable firewall status values on devices.")] Boolean FirewallStatus; + [Write, Description("The ForceAppStorePassword parameter specifies whether to require a password to use the app store on devices.")] Boolean ForceAppStorePassword; + [Write, Description("The ForceEncryptedBackup parameter specifies whether to force encrypted backups for devices.")] Boolean ForceEncryptedBackup; + [Write, Description("The MaxPasswordAttemptsBeforeWipe parameter specifies the number of incorrect password attempts that cause devices to be automatically wiped.")] UInt32 MaxPasswordAttemptsBeforeWipe; + [Write, Description("The MaxPasswordGracePeriod parameter specifies the length of time users are allowed to reset expired passwords on devices.")] UInt32 MaxPasswordGracePeriod; + [Write, Description("The MoviesRating parameter species the maximum or most restrictive rating of movies that are allowed on devices. You specify the country/region rating system to use with the RegionRatings parameter.")] String MoviesRating; + [Write, Description("The PasswordComplexity parameter specifies the password complexity.")] UInt32 PasswordComplexity; + [Write, Description("The PasswordExpirationDays parameter specifies the number of days that the same password can be used on devices before users are required to change their passwords.")] UInt32 PasswordExpirationDays; + [Write, Description("The PasswordHistoryCount parameter specifies the minimum number of unique new passwords that are required on devices before an old password can be reused.")] UInt32 PasswordHistoryCount; + [Write, Description("The PasswordMinComplexChars parameter specifies the minimum number of complex characters that are required for device passwords. A complex character isn't a letter.")] UInt32 PasswordMinComplexChars; + [Write, Description("The PasswordMinimumLength parameter specifies the minimum number of characters that are required for device passwords.")] UInt32 PasswordMinimumLength; + [Write, Description("The PasswordQuality parameter specifies the minimum password quality rating that's required for device passwords. Password quality is a numeric scale that indicates the security and complexity of the password. A higher quality value indicates a more secure password.")] UInt32 PasswordQuality; + [Write, Description("The PasswordRequired parameter specifies whether a password is required to access devices.")] Boolean PasswordRequired; + [Write, Description("The PasswordTimeout parameter specifies the length of time that devices can be inactive before a password is required to reactivate them.")] String PasswordTimeout; + [Write, Description("The PhoneMemoryEncrypted parameter specifies whether to encrypt the memory on devices.")] Boolean PhoneMemoryEncrypted; + [Write, Description("The RegionRatings parameter specifies the rating system (country/region) to use for movie and television ratings with the MoviesRating and TVShowsRating parameters.")] String RegionRatings; + [Write, Description("The RequireEmailProfile parameter specifies whether an email profile is required on devices.")] Boolean RequireEmailProfile; + [Write, Description("The SmartScreenEnabled parameter specifies whether to requireWindows SmartScreen on devices.")] Boolean SmartScreenEnabled; + [Write, Description("The SystemSecurityTLS parameter specifies whether TLS encryption is used on devices.")] Boolean SystemSecurityTLS; + [Write, Description("The TVShowsRating parameter species the maximum or most restrictive rating of television shows that are allowed on devices. You specify the country/region rating system to use with the RegionRatings parameter.")] String TVShowsRating; + [Write, Description("The UserAccountControlStatus parameter specifies how User Account Control messages are presented on devices.")] String UserAccountControlStatus; + [Write, Description("The WLANEnabled parameter specifies whether Wi-Fi is enabled devices.")] Boolean WLANEnabled; + [Write, Description("The WorkFoldersSyncUrl parameter specifies the URL that's used to synchronize company data on devices.")] String WorkFoldersSyncUrl; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] 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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/readme.md new file mode 100644 index 0000000000..881ff87137 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/readme.md @@ -0,0 +1,6 @@ + +# SCDeviceConfigurationRule + +## Description + +This resource configures a Device Configuration Rule in Purview. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/settings.json new file mode 100644 index 0000000000..dc6636d9d2 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/settings.json @@ -0,0 +1,28 @@ +{ + "resourceName": "SCDeviceConfigurationRule", + "description": "This resource configures a Device Configuration Rule in Purview.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Group.Read.All" + } + ], + "update": [ + { + "name": "Group.Read.All" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/1-Create.ps1 new file mode 100644 index 0000000000..d9b2278f0c --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/1-Create.ps1 @@ -0,0 +1,59 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCDeviceConfigurationRule "MyDeviceConfigurationRule" + { + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + ApplicationId = $ApplicationId; + BluetoothEnabled = $True; + CameraEnabled = $True; + CertificateThumbprint = $CertificateThumbprint; + EnableRemovableStorage = $True; + Ensure = "Present"; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyDeviceConfigurationPolicy{2b18}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyDeviceConfigurationPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("All Company"); + TenantId = $TenantId; + WLANEnabled = $True; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/2-Update.ps1 new file mode 100644 index 0000000000..abcbc2eda7 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/2-Update.ps1 @@ -0,0 +1,59 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCDeviceConfigurationRule "MyDeviceConfigurationRule" + { + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $False; # Drift + AllowVoiceDialing = $True; + ApplicationId = $ApplicationId; + BluetoothEnabled = $True; + CameraEnabled = $True; + CertificateThumbprint = $CertificateThumbprint; + EnableRemovableStorage = $True; + Ensure = "Present"; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyDeviceConfigurationPolicy{2b18}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyDeviceConfigurationPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("All Company"); + TenantId = $TenantId; + WLANEnabled = $True; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/3-Remove.ps1 new file mode 100644 index 0000000000..249a846dba --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/3-Remove.ps1 @@ -0,0 +1,34 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCDeviceConfigurationRule "MyDeviceConfigurationRule" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + Name = "MyDeviceConfigurationPolicy{2b18}"; + Policy = "MyDeviceConfigurationPolicy"; + TenantId = $TenantId; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 new file mode 100644 index 0000000000..6d40bd578e --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 @@ -0,0 +1,399 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName New-DeviceConfigurationRule -MockWith { + } + + Mock -CommandName Set-DeviceConfigurationRule -MockWith { + } + + Mock -CommandName Remove-DeviceConfigurationRule -MockWith { + } + + Mock -Command Get-MgGroup -MockWith { + return @{ + Id = "33333-33333-33333-33333-33333" + DisplayName = 'Communications' + } + } + + Mock -CommandName Get-DeviceConditionalAccessPolicy -MockWith { + return @{ + Name = 'MyPolicy' + Id = '12345-12345-12345-12345-12345' + } + } + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + WLANEnabled = $True; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-DeviceConfigurationRule -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 a new instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-DeviceConfigurationRule -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + WLANEnabled = $True; + Ensure = 'Absent' + Credential = $Credential; + } + + Mock -CommandName Get-DeviceConfigurationRule -MockWith { + return @{ + Id = '11111-11111-11111-11111-11111' + Name = 'MyPolicy{394b}' + TargetGroups = @('22222-22222-22222-22222-22222') + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + WLANEnabled = $True; + } + } + } + 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 remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-DeviceConfigurationRule -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + WLANEnabled = $True; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-DeviceConfigurationRule -MockWith { + return @{ + Id = '11111-11111-11111-11111-11111' + Name = 'MyPolicy{394b}' + TargetGroups = @('22222-22222-22222-22222-22222') + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + WLANEnabled = $True; + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + WLANEnabled = $True; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-DeviceConfigurationRule -MockWith { + return @{ + Id = '11111-11111-11111-11111-11111' + Name = 'MyPolicy{394b}' + TargetGroups = @('22222-22222-22222-22222-22222') + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $False; #Drift + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + WLANEnabled = $True; + } + } + } + + 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-DeviceConfigurationRule -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-DeviceConfigurationRule -MockWith { + return @{ + Id = '11111-11111-11111-11111-11111' + Name = 'MyPolicy{394b}' + TargetGroups = @('22222-22222-22222-22222-22222') + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $False; #Drift + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + WLANEnabled = $True; + } + } + } + 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 f4a86fe9c0093b224c65b9e40d200325109c210a Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 25 Sep 2024 10:30:51 -0400 Subject: [PATCH 285/465] Update MSFT_SCDeviceConfigurationRule.schema.mof --- .../MSFT_SCDeviceConfigurationRule.schema.mof | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof index 183b485c1a..f21d833b08 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof @@ -52,7 +52,7 @@ class MSFT_SCDeviceConfigurationRule : OMI_BaseResource [Write, Description("The WLANEnabled parameter specifies whether Wi-Fi is enabled devices.")] Boolean WLANEnabled; [Write, Description("The WorkFoldersSyncUrl parameter specifies the URL that's used to synchronize company data on devices.")] String WorkFoldersSyncUrl; - [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent", "Present"}, Values{"Absent", "Present"}] 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; From 39ff34f887f784c59a7a237576a74d255ea20f4e Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 25 Sep 2024 10:53:12 -0400 Subject: [PATCH 286/465] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 449 +++++++++++++++++++++++++++++ 1 file changed, 449 insertions(+) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 60ca7a79e5..7d67c66895 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -64770,6 +64770,455 @@ function Get-DeviceConfigurationPolicy $Identity ) } +function Get-DeviceConfigurationRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $CompareToWorkload, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $DomainController + ) +} +function New-DeviceConfigurationRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $CameraEnabled, + + [Parameter()] + [System.Object] + $EnableRemovableStorage, + + [Parameter()] + [System.Object] + $AntiVirusSignatureStatus, + + [Parameter()] + [System.Object] + $FirewallStatus, + + [Parameter()] + [System.Object] + $AllowAppStore, + + [Parameter()] + [System.Object] + $AllowAssistantWhileLocked, + + [Parameter()] + [System.Object] + $AllowiCloudBackup, + + [Parameter()] + [System.Object] + $AppsRating, + + [Parameter()] + [System.Object] + $PasswordHistoryCount, + + [Parameter()] + [System.Object] + $PasswordQuality, + + [Parameter()] + [System.Object] + $PasswordMinComplexChars, + + [Parameter()] + [System.Object] + $PhoneMemoryEncrypted, + + [Parameter()] + [System.String] + $EmailAddress, + + [Parameter()] + [System.Object] + $BluetoothEnabled, + + [Parameter()] + [System.Object] + $AllowConvenienceLogon, + + [Parameter()] + [System.Object] + $MaxPasswordGracePeriod, + + [Parameter()] + [System.Object] + $AllowiCloudDocSync, + + [Parameter()] + [System.Object] + $ForceAppStorePassword, + + [Parameter()] + [System.Object] + $Policy, + + [Parameter()] + [System.Object] + $TVShowsRating, + + [Parameter()] + [System.String] + $ExchangeActiveSyncHost, + + [Parameter()] + [System.Object] + $RequireEmailProfile, + + [Parameter()] + [System.Object] + $AllowDiagnosticSubmission, + + [Parameter()] + [System.Object] + $AutoUpdateStatus, + + [Parameter()] + [System.String] + $AccountUserName, + + [Parameter()] + [System.Object] + $WLANEnabled, + + [Parameter()] + [System.Object] + $AllowVoiceDialing, + + [Parameter()] + [System.String] + $AccountName, + + [Parameter()] + [System.Object] + $PasswordExpirationDays, + + [Parameter()] + [System.Object] + $PasswordTimeout, + + [Parameter()] + [System.Object] + $AllowiCloudPhotoSync, + + [Parameter()] + [System.Object] + $AllowSimplePassword, + + [Parameter()] + [System.Object] + $AllowPassbookWhileLocked, + + [Parameter()] + [System.Object] + $PasswordMinimumLength, + + [Parameter()] + [System.Object] + $AllowVideoConferencing, + + [Parameter()] + [System.Object] + $PasswordRequired, + + [Parameter()] + [System.Object] + $MaxPasswordAttemptsBeforeWipe, + + [Parameter()] + [System.Object] + $MoviesRating, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $DomainController, + + [Parameter()] + [System.Object] + $AntiVirusStatus, + + [Parameter()] + [System.String] + $WorkFoldersSyncUrl, + + [Parameter()] + [System.Object] + $UserAccountControlStatus, + + [Parameter()] + [System.Object] + $ForceEncryptedBackup, + + [Parameter()] + [System.Object] + $AllowScreenshot, + + [Parameter()] + [System.Object] + $PasswordComplexity, + + [Parameter()] + [System.Object] + $TargetGroups, + + [Parameter()] + [System.Object] + $AllowVoiceAssistant, + + [Parameter()] + [System.Object] + $SystemSecurityTLS, + + [Parameter()] + [System.Object] + $RegionRatings, + + [Parameter()] + [System.Object] + $SmartScreenEnabled + ) +} +function Remove-DeviceConfigurationRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $Identity + ) +} +function Set-DeviceConfigurationRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $CameraEnabled, + + [Parameter()] + [System.Object] + $EnableRemovableStorage, + + [Parameter()] + [System.Object] + $AntiVirusSignatureStatus, + + [Parameter()] + [System.Object] + $FirewallStatus, + + [Parameter()] + [System.Object] + $AllowAppStore, + + [Parameter()] + [System.Object] + $AllowAssistantWhileLocked, + + [Parameter()] + [System.Object] + $AllowiCloudBackup, + + [Parameter()] + [System.Object] + $AppsRating, + + [Parameter()] + [System.Object] + $PasswordHistoryCount, + + [Parameter()] + [System.Object] + $PasswordQuality, + + [Parameter()] + [System.Object] + $PasswordMinComplexChars, + + [Parameter()] + [System.Object] + $PhoneMemoryEncrypted, + + [Parameter()] + [System.String] + $EmailAddress, + + [Parameter()] + [System.Object] + $BluetoothEnabled, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $AllowConvenienceLogon, + + [Parameter()] + [System.Object] + $MaxPasswordGracePeriod, + + [Parameter()] + [System.Object] + $AllowiCloudDocSync, + + [Parameter()] + [System.Object] + $ForceAppStorePassword, + + [Parameter()] + [System.Object] + $TVShowsRating, + + [Parameter()] + [System.String] + $ExchangeActiveSyncHost, + + [Parameter()] + [System.Object] + $RequireEmailProfile, + + [Parameter()] + [System.Object] + $AllowDiagnosticSubmission, + + [Parameter()] + [System.Object] + $AutoUpdateStatus, + + [Parameter()] + [System.String] + $AccountUserName, + + [Parameter()] + [System.Object] + $WLANEnabled, + + [Parameter()] + [System.Object] + $AllowVoiceDialing, + + [Parameter()] + [System.String] + $AccountName, + + [Parameter()] + [System.Object] + $PasswordExpirationDays, + + [Parameter()] + [System.Object] + $PasswordTimeout, + + [Parameter()] + [System.Object] + $AllowiCloudPhotoSync, + + [Parameter()] + [System.Object] + $AllowSimplePassword, + + [Parameter()] + [System.Object] + $AllowPassbookWhileLocked, + + [Parameter()] + [System.Object] + $PasswordMinimumLength, + + [Parameter()] + [System.Object] + $AllowVideoConferencing, + + [Parameter()] + [System.Object] + $PasswordRequired, + + [Parameter()] + [System.Object] + $MaxPasswordAttemptsBeforeWipe, + + [Parameter()] + [System.Object] + $MoviesRating, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $DomainController, + + [Parameter()] + [System.Object] + $AntiVirusStatus, + + [Parameter()] + [System.String] + $WorkFoldersSyncUrl, + + [Parameter()] + [System.Object] + $UserAccountControlStatus, + + [Parameter()] + [System.Object] + $ForceEncryptedBackup, + + [Parameter()] + [System.Object] + $AllowScreenshot, + + [Parameter()] + [System.Object] + $PasswordComplexity, + + [Parameter()] + [System.Object] + $TargetGroups, + + [Parameter()] + [System.Object] + $AllowVoiceAssistant, + + [Parameter()] + [System.Object] + $SystemSecurityTLS, + + [Parameter()] + [System.Object] + $RegionRatings, + + [Parameter()] + [System.Object] + $SmartScreenEnabled + ) +} + function Get-DlpCompliancePolicy { [CmdletBinding()] From 27a3a7b8b52f5beb8e461384d853a6e3d1e2c5ae Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 25 Sep 2024 11:08:47 -0400 Subject: [PATCH 287/465] updated Tests --- .../MSFT_SCDeviceConfigurationRule.psm1 | 2 +- .../Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 index 40c55c6307..97f1c316ad 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 @@ -671,7 +671,7 @@ function Set-TargetResource elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { Write-Verbose -Message "Removing device configuration rule {$Name}" - Remove-DeviceConfigurationRuleDeviceConditionalAccessRule -Identity $currentInstance.Name -Confirm:$false + Remove-DeviceConfigurationRule -Identity $currentInstance.Name -Confirm:$false } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 index 6d40bd578e..de92d8b2e6 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 @@ -51,7 +51,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } - Mock -CommandName Get-DeviceConditionalAccessPolicy -MockWith { + Mock -CommandName Get-DeviceCOnfigurationPolicy -MockWith { return @{ Name = 'MyPolicy' Id = '12345-12345-12345-12345-12345' From 433bf1d8fc7672de4c1a8de09ab583fce1396665 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 25 Sep 2024 15:27:54 +0000 Subject: [PATCH 288/465] Updated Resources and Cmdlet documentation pages --- .../SCDeviceConfigurationRule.md | 258 ++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 docs/docs/resources/security-compliance/SCDeviceConfigurationRule.md diff --git a/docs/docs/resources/security-compliance/SCDeviceConfigurationRule.md b/docs/docs/resources/security-compliance/SCDeviceConfigurationRule.md new file mode 100644 index 0000000000..4abf57485d --- /dev/null +++ b/docs/docs/resources/security-compliance/SCDeviceConfigurationRule.md @@ -0,0 +1,258 @@ +# SCDeviceConfigurationRule + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Name** | Key | String | Name for the rule. | | +| **Policy** | Write | String | Name of the associated policy. | | +| **TargetGroups** | Write | StringArray[] | The display names of the graoups targeted by the policy. | | +| **AccountName** | Write | String | The AccountName parameter specifies the account name. | | +| **AccountUserName** | Write | String | The AccountUserName parameter specifies the account user name. | | +| **AllowAppStore** | Write | Boolean | The AllowAppStore parameter specifies whether to allow access to the app store on devices. | | +| **AllowAssistantWhileLocked** | Write | Boolean | The AllowAssistantWhileLocked parameter specifies whether to allow the use of the voice assistant while devices are locked. | | +| **AllowConvenienceLogon** | Write | Boolean | The AllowConvenienceLogon parameter specifies whether to allow convenience logons on devices. | | +| **AllowDiagnosticSubmission** | Write | Boolean | The AllowDiagnosticSubmission parameter specifies whether to allow diagnostic submissions from devices. | | +| **AllowiCloudBackup** | Write | Boolean | The AllowiCloudBackup parameter specifies whether to allow Apple iCloud Backup from devices. | | +| **AllowiCloudDocSync** | Write | Boolean | The AllowiCloudDocSync parameter specifies whether to allow Apple iCloud Documents & Data sync on devices. | | +| **AllowiCloudPhotoSync** | Write | Boolean | The AllowiCloudPhotoSync parameter specifies whether to allow Apple iCloud Photos sync on devices. | | +| **AllowPassbookWhileLocked** | Write | Boolean | The AllowPassbookWhileLocked parameter specifies whether to allow the use of Apple Passbook while devices are locked. | | +| **AllowScreenshot** | Write | Boolean | The AllowScreenshot parameter specifies whether to allow screenshots on devices. | | +| **AllowSimplePassword** | Write | Boolean | The AllowSimplePassword parameter specifies whether to allow simple or non-complex passwords on devices. | | +| **AllowVideoConferencing** | Write | Boolean | The AllowVideoConferencing parameter specifies whether to allow video conferencing on devices. | | +| **AllowVoiceAssistant** | Write | Boolean | The AllowVoiceAssistant parameter specifies whether to allow using the voice assistant on devices. | | +| **AllowVoiceDialing** | Write | Boolean | The AllowVoiceDialing parameter specifies whether to allow voice-activated telephone dialing. | | +| **AntiVirusSignatureStatus** | Write | UInt32 | The AntiVirusSignatureStatus parameter specifies the antivirus signature status. | | +| **AntiVirusStatus** | Write | UInt32 | The AntiVirusStatus parameter specifies the antivirus status. | | +| **AppsRating** | Write | String | The AppsRating parameter species the maximum or most restrictive rating of apps that are allowed on devices. | | +| **AutoUpdateStatus** | Write | String | The AutoUpdateStatus parameter specifies the update settings for devices. | | +| **BluetoothEnabled** | Write | Boolean | The BluetoothEnabled parameter specifies whether to enable or disable Bluetooth on devices. | | +| **CameraEnabled** | Write | Boolean | The BluetoothEnabled parameter specifies whether to enable or disable Bluetooth on devices. | | +| **EmailAddress** | Write | String | The EmailAddress parameter specifies the email address. | | +| **EnableRemovableStorage** | Write | Boolean | The EnableRemovableStorage parameter specifies whether removable storage can be used by devices. | | +| **ExchangeActiveSyncHost** | Write | String | The ExchangeActiveSyncHost parameter specifies the Exchange ActiveSync host. | | +| **FirewallStatus** | Write | Boolean | The FirewallStatus parameter specifies the acceptable firewall status values on devices. | | +| **ForceAppStorePassword** | Write | Boolean | The ForceAppStorePassword parameter specifies whether to require a password to use the app store on devices. | | +| **ForceEncryptedBackup** | Write | Boolean | The ForceEncryptedBackup parameter specifies whether to force encrypted backups for devices. | | +| **MaxPasswordAttemptsBeforeWipe** | Write | UInt32 | The MaxPasswordAttemptsBeforeWipe parameter specifies the number of incorrect password attempts that cause devices to be automatically wiped. | | +| **MaxPasswordGracePeriod** | Write | UInt32 | The MaxPasswordGracePeriod parameter specifies the length of time users are allowed to reset expired passwords on devices. | | +| **MoviesRating** | Write | String | The MoviesRating parameter species the maximum or most restrictive rating of movies that are allowed on devices. You specify the country/region rating system to use with the RegionRatings parameter. | | +| **PasswordComplexity** | Write | UInt32 | The PasswordComplexity parameter specifies the password complexity. | | +| **PasswordExpirationDays** | Write | UInt32 | The PasswordExpirationDays parameter specifies the number of days that the same password can be used on devices before users are required to change their passwords. | | +| **PasswordHistoryCount** | Write | UInt32 | The PasswordHistoryCount parameter specifies the minimum number of unique new passwords that are required on devices before an old password can be reused. | | +| **PasswordMinComplexChars** | Write | UInt32 | The PasswordMinComplexChars parameter specifies the minimum number of complex characters that are required for device passwords. A complex character isn't a letter. | | +| **PasswordMinimumLength** | Write | UInt32 | The PasswordMinimumLength parameter specifies the minimum number of characters that are required for device passwords. | | +| **PasswordQuality** | Write | UInt32 | The PasswordQuality parameter specifies the minimum password quality rating that's required for device passwords. Password quality is a numeric scale that indicates the security and complexity of the password. A higher quality value indicates a more secure password. | | +| **PasswordRequired** | Write | Boolean | The PasswordRequired parameter specifies whether a password is required to access devices. | | +| **PasswordTimeout** | Write | String | The PasswordTimeout parameter specifies the length of time that devices can be inactive before a password is required to reactivate them. | | +| **PhoneMemoryEncrypted** | Write | Boolean | The PhoneMemoryEncrypted parameter specifies whether to encrypt the memory on devices. | | +| **RegionRatings** | Write | String | The RegionRatings parameter specifies the rating system (country/region) to use for movie and television ratings with the MoviesRating and TVShowsRating parameters. | | +| **RequireEmailProfile** | Write | Boolean | The RequireEmailProfile parameter specifies whether an email profile is required on devices. | | +| **SmartScreenEnabled** | Write | Boolean | The SmartScreenEnabled parameter specifies whether to requireWindows SmartScreen on devices. | | +| **SystemSecurityTLS** | Write | Boolean | The SystemSecurityTLS parameter specifies whether TLS encryption is used on devices. | | +| **TVShowsRating** | Write | String | The TVShowsRating parameter species the maximum or most restrictive rating of television shows that are allowed on devices. You specify the country/region rating system to use with the RegionRatings parameter. | | +| **UserAccountControlStatus** | Write | String | The UserAccountControlStatus parameter specifies how User Account Control messages are presented on devices. | | +| **WLANEnabled** | Write | Boolean | The WLANEnabled parameter specifies whether Wi-Fi is enabled devices. | | +| **WorkFoldersSyncUrl** | Write | String | The WorkFoldersSyncUrl parameter specifies the URL that's used to synchronize company data on devices. | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Absent`, `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +This resource configures a Device Configuration Rule in Purview. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - Group.Read.All + +- **Update** + + - Group.Read.All + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCDeviceConfigurationRule "MyDeviceConfigurationRule" + { + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + ApplicationId = $ApplicationId; + BluetoothEnabled = $True; + CameraEnabled = $True; + CertificateThumbprint = $CertificateThumbprint; + EnableRemovableStorage = $True; + Ensure = "Present"; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyDeviceConfigurationPolicy{2b18}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyDeviceConfigurationPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("All Company"); + TenantId = $TenantId; + WLANEnabled = $True; + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCDeviceConfigurationRule "MyDeviceConfigurationRule" + { + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $False; # Drift + AllowVoiceDialing = $True; + ApplicationId = $ApplicationId; + BluetoothEnabled = $True; + CameraEnabled = $True; + CertificateThumbprint = $CertificateThumbprint; + EnableRemovableStorage = $True; + Ensure = "Present"; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyDeviceConfigurationPolicy{2b18}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyDeviceConfigurationPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("All Company"); + TenantId = $TenantId; + WLANEnabled = $True; + } + } +} +``` + +### Example 3 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCDeviceConfigurationRule "MyDeviceConfigurationRule" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + Name = "MyDeviceConfigurationPolicy{2b18}"; + Policy = "MyDeviceConfigurationPolicy"; + TenantId = $TenantId; + } + } +} +``` + From a17111fee34cd6ecb41390517570f4fc14638d21 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 25 Sep 2024 15:29:57 +0000 Subject: [PATCH 289/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 290 ++++++++++++++++++ 1 file changed, 290 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index a662fe0cfe..5ae692f9f2 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -38599,6 +38599,296 @@ } ] }, + { + "ClassName": "MSFT_SCDeviceConfigurationRule", + "Parameters": [ + { + "CIMType": "String", + "Name": "Name", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Policy", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "TargetGroups", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AccountName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AccountUserName", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowAppStore", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowAssistantWhileLocked", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowConvenienceLogon", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowDiagnosticSubmission", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowiCloudBackup", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowiCloudDocSync", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowiCloudPhotoSync", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowPassbookWhileLocked", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowScreenshot", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowSimplePassword", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowVideoConferencing", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowVoiceAssistant", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AllowVoiceDialing", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AntiVirusSignatureStatus", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AntiVirusStatus", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AppsRating", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AutoUpdateStatus", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "BluetoothEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "CameraEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "EmailAddress", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EnableRemovableStorage", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ExchangeActiveSyncHost", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "FirewallStatus", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ForceAppStorePassword", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ForceEncryptedBackup", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "MaxPasswordAttemptsBeforeWipe", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "MaxPasswordGracePeriod", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "MoviesRating", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "PasswordComplexity", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "PasswordExpirationDays", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "PasswordHistoryCount", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "PasswordMinComplexChars", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "PasswordMinimumLength", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "PasswordQuality", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PasswordRequired", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PasswordTimeout", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PhoneMemoryEncrypted", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "RegionRatings", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "RequireEmailProfile", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SmartScreenEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SystemSecurityTLS", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TVShowsRating", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "UserAccountControlStatus", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "WLANEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "WorkFoldersSyncUrl", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_SCDLPCompliancePolicy", "Parameters": [ From 541aa428ecd2169dcc468afc679826b14cec3a15 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Wed, 25 Sep 2024 17:42:57 +0200 Subject: [PATCH 290/465] Fix O365Group workload detection --- CHANGELOG.md | 3 +++ Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c6727ac84..b244ec1562 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,9 @@ * IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10 * Add missing `AccessTokens` parameter to `Export-TargetResource` FIXES [#5034](https://github.com/microsoft/Microsoft365DSC/issues/5034) +* M365DSCUtil + * Fixes an issue where the O365Group workload was not properly detected. + FIXES [#5095](https://github.com/microsoft/Microsoft365DSC/issues/5095) * SCDeviceConditionalAccessRule * Initial release. * SCDeviceConfigurationRule diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 64402b9114..3882742237 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -4187,7 +4187,7 @@ function Get-M365DSCWorkloadsListFromResourceNames } 'O3' { - if (-not $workloads.Name -or -not $workloads.Name.Contains('MicrosoftGraph') -and $resource -eq 'O365Group') + if (-not $workloads.Name -or -not $workloads.Name.Contains('MicrosoftGraph') -and $resource.Name -eq 'O365Group') { $workloads += @{ Name = 'MicrosoftGraph' From 281997bec07e801085d858a4fea197203ccc9d8c Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 25 Sep 2024 14:17:57 -0400 Subject: [PATCH 291/465] Added support for Service Principal Owners --- .../MSFT_AADServicePrincipal.psm1 | 64 ++++++++++++++++++- .../MSFT_AADServicePrincipal.schema.mof | 1 + 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.psm1 index 2613ce6640..a32fd0d623 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.psm1 @@ -44,6 +44,10 @@ function Get-TargetResource [System.String] $LogoutUrl, + [Parameter()] + [System.String[]] + $Owners, + [Parameter()] [System.String] $PublisherName, @@ -197,6 +201,17 @@ function Get-TargetResource } } + $ownersValues = @() + $ownersInfo = Get-MgServicePrincipalOwner -ServicePrincipalId $AADServicePrincipal.Id -ErrorAction SilentlyContinue + foreach ($ownerInfo in $ownersInfo) + { + $info = Get-MgUser -UserId $ownerInfo.Id -ErrorAction SilentlyContinue + if ($null -ne $info) + { + $ownersValues += $info.UserPrincipalName + } + } + $result = @{ AppId = $AADServicePrincipal.AppId AppRoleAssignedTo = $AppRoleAssignedToValues @@ -208,6 +223,7 @@ function Get-TargetResource ErrorUrl = $AADServicePrincipal.ErrorUrl Homepage = $AADServicePrincipal.Homepage LogoutUrl = $AADServicePrincipal.LogoutUrl + Owners = $ownersValues PublisherName = $AADServicePrincipal.PublisherName ReplyURLs = $AADServicePrincipal.ReplyURLs SamlMetadataURL = $AADServicePrincipal.SamlMetadataURL @@ -285,6 +301,10 @@ function Set-TargetResource [System.String] $LogoutUrl, + [Parameter()] + [System.String[]] + $Owners, + [Parameter()] [System.String] $PublisherName, @@ -387,7 +407,18 @@ function Set-TargetResource Write-Verbose -Message 'Creating new Service Principal' Write-Verbose -Message "With Values: $(Convert-M365DscHashtableToString -Hashtable $currentParameters)" - New-MgServicePrincipal @currentParameters + $newSP = New-MgServicePrincipal @currentParameters + + # Assign Owners + foreach ($owner in $Owners) + { + $userInfo = Get-MgUser -UserId $owner + $body = @{ + '@odata.id' = "https://graph.microsoft.com/v1.0/directoryObjects/$($userInfo.Id)" + } + Write-Verbose -Message "Adding new owner {$owner}" + $newOwner = New-MgServicePrincipalOwnerByRef -ServicePrincipalId $newSP.Id -BodyParameter $body + } } # ServicePrincipal should exist and will be configured to desired state elseif ($Ensure -eq 'Present' -and $currentAADServicePrincipal.Ensure -eq 'Present') @@ -402,6 +433,7 @@ function Set-TargetResource Write-Verbose -Message "CurrentParameters: $($currentParameters | Out-String)" Write-Verbose -Message "ServicePrincipalID: $($currentAADServicePrincipal.ObjectID)" $currentParameters.Remove('AppRoleAssignedTo') | Out-Null + $currentParameters.Remove('Owners') | Out-Null Update-MgServicePrincipal -ServicePrincipalId $currentAADServicePrincipal.ObjectID @currentParameters if ($AppRoleAssignedTo) @@ -488,6 +520,32 @@ function Set-TargetResource } } } + + Write-Verbose -Message "Checking if owners need to be updated..." + + if ($null -ne $Owners) + { + $diffOwners = Compare-Object -ReferenceObject $currentAADServicePrincipal.Owners -DifferenceObject $Owners + } + foreach ($diff in $diffOwners) + { + $userInfo = Get-MgUser -UserId $diff.InputObject + if ($diff.SideIndicator -eq '=>') + { + $body = @{ + '@odata.id' = "https://graph.microsoft.com/v1.0/directoryObjects/$($userInfo.Id)" + } + Write-Verbose -Message "Adding owner {$($userInfo.Id)}" + New-MgServicePrincipalOwnerByRef -ServicePrincipalId $currentAADServicePrincipal.ObjectId ` + -BodyParameter $body | Out-Null + } + else + { + Write-Verbose -Message "Removing owner {$($userInfo.Id)}" + Remove-MgServicePrincipalOwnerByRef -ServicePrincipalId $currentAADServicePrincipal.ObjectId ` + -DirectoryObjectId $userInfo.Id | Out-Null + } + } } # ServicePrincipal exists but should not elseif ($Ensure -eq 'Absent' -and $currentAADServicePrincipal.Ensure -eq 'Present') @@ -543,6 +601,10 @@ function Test-TargetResource [System.String] $LogoutUrl, + [Parameter()] + [System.String[]] + $Owners, + [Parameter()] [System.String] $PublisherName, diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.schema.mof index 44fefb22c6..3d4c507c12 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADServicePrincipal/MSFT_AADServicePrincipal.schema.mof @@ -19,6 +19,7 @@ class MSFT_AADServicePrincipal : OMI_BaseResource [Write, Description("Specifies the homepage of the ServicePrincipal.")] String Homepage; [Write, Description("Specifies the LogoutURL of the ServicePrincipal.")] String LogoutUrl; [Write, Description("Specifies the PublisherName of the ServicePrincipal.")] String PublisherName; + [Write, Description("List of the owners of the service principal.")] String Owners[]; [Write, Description("The URLs that user tokens are sent to for sign in with the associated application, or the redirect URIs that OAuth 2.0 authorization codes and access tokens are sent to for the associated application.")] String ReplyUrls[]; [Write, Description("The URL for the SAML metadata of the ServicePrincipal.")] String SamlMetadataUrl; [Write, Description("Specifies an array of service principal names. Based on the identifierURIs collection, plus the application's appId property, these URIs are used to reference an application's service principal.")] String ServicePrincipalNames[]; From a8e773e1922024b2e4fa6a61de61681800c044dc Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 25 Sep 2024 18:31:32 +0000 Subject: [PATCH 292/465] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/azure-ad/AADServicePrincipal.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/resources/azure-ad/AADServicePrincipal.md b/docs/docs/resources/azure-ad/AADServicePrincipal.md index ea0b418f8f..8e360204df 100644 --- a/docs/docs/resources/azure-ad/AADServicePrincipal.md +++ b/docs/docs/resources/azure-ad/AADServicePrincipal.md @@ -15,6 +15,7 @@ | **Homepage** | Write | String | Specifies the homepage of the ServicePrincipal. | | | **LogoutUrl** | Write | String | Specifies the LogoutURL of the ServicePrincipal. | | | **PublisherName** | Write | String | Specifies the PublisherName of the ServicePrincipal. | | +| **Owners** | Write | StringArray[] | List of the owners of the service principal. | | | **ReplyUrls** | Write | StringArray[] | The URLs that user tokens are sent to for sign in with the associated application, or the redirect URIs that OAuth 2.0 authorization codes and access tokens are sent to for the associated application. | | | **SamlMetadataUrl** | Write | String | The URL for the SAML metadata of the ServicePrincipal. | | | **ServicePrincipalNames** | Write | StringArray[] | Specifies an array of service principal names. Based on the identifierURIs collection, plus the application's appId property, these URIs are used to reference an application's service principal. | | From 1a6ad9ccfc1c230dfcd2c6ab33f02510f31c3b92 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 25 Sep 2024 18:33:53 +0000 Subject: [PATCH 293/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 5ae692f9f2..cafe85b791 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -4722,6 +4722,11 @@ "Name": "PublisherName", "Option": "Write" }, + { + "CIMType": "String[]", + "Name": "Owners", + "Option": "Write" + }, { "CIMType": "String[]", "Name": "ReplyUrls", From 5c6ccaaee370cd89eb7fb619f0742878a4d2808e Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Thu, 26 Sep 2024 14:05:37 +0530 Subject: [PATCH 294/465] minor --- .../MSFT_EXOMailboxFolderPermission.psm1 | 102 ++++++--------- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 2 - ...5DSC.EXOMailboxFolderPermission.Tests.ps1} | 55 +++++++-- Tests/Unit/Stubs/Microsoft365.psm1 | 116 ++++++++++++++++++ 4 files changed, 197 insertions(+), 78 deletions(-) rename Tests/Unit/Microsoft365DSC/{Microsoft365DSC.ResourceName.Tests.ps1 => Microsoft365DSC.EXOMailboxFolderPermission.Tests.ps1} (74%) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 index 3da7404ef3..6e81cac535 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 @@ -50,7 +50,6 @@ function Get-TargetResource $AccessTokens ) - ##TODO - Replace the workload by the one associated to your resource New-M365DSCConnection -Workload 'ExchangeOnline' ` -InboundParameters $PSBoundParameters | Out-Null @@ -87,7 +86,7 @@ function Get-TargetResource foreach($mailboxfolderPermission in $instances){ $currentPermission = @{} - $currentPermission.Add('User', $mailboxFolderPermission.User) + $currentPermission.Add('User', $mailboxFolderPermission.User.ToString()) $currentPermission.Add('AccessRights', $mailboxFolderPermission.AccessRights) if($null -ne $mailboxFolderPermission.SharingPermissionFlags) { $currentPermission.Add('SharingPermissionFlags', $mailboxFolderPermission.SharingPermissionFlags) @@ -186,8 +185,6 @@ function Set-TargetResource $currentInstance = Get-TargetResource @PSBoundParameters $currentMailboxFolderPermissions = $currentInstance.UserPermissions - $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters - # Remove all the current existing pemrissions on this folder. # Skip removing the default and anonymous permissions, as can't be removed, and should just be directly updated. foreach($currentUserPermission in $currentMailboxFolderPermissions) { @@ -196,7 +193,6 @@ function Set-TargetResource } } - # foreach($userPermission in $UserPermissions) { if($userPermission.User.ToString().ToLower() -eq "default" -or $userPermission.User.ToString().ToLower() -eq "anonymous"){ if ($userPermission.SharingPermissionFlags -eq ""){ @@ -215,24 +211,6 @@ function Set-TargetResource } } } - - # # CREATE - # if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') - # { - # Add-MailboxFolderPermission @SetParameters - # } - # # UPDATE - # elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') - # { - # Set-MailboxFolderPermission @SetParameters - # } - # # REMOVE - # elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') - # { - # $instanceParams.Remove('AccessTokens') | Out-Null - # $instanceParams.Remove('SharingPermissionFlags') | Out-Null - # Remove-MailboxFolderPermission @SetParameters -Confirm:$false - # } } function Test-TargetResource @@ -299,56 +277,52 @@ function Test-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion + $testTargetResource = $true $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() - # foreach($value in $ValuesToCheck.UserPermissions) { - # Write-Host $value - # Write-Host $value.SharingPermissionFlags.IsNullOrEmpty() - # if($value.SharingPermissionFlags.IsNullOrEmpty()) { - # $value.SharingPermissionFlags = $null - # } - # } - # Write-Host "DONE HERE ###################################################################" - - # foreach($value in $ValuesToCheck.UserPermissions) { - # Write-Host $value.SharingPermissionFlags - # Write-Host $value.SharingPermissionFlags.IsNullOrEmpty() - # if($value.SharingPermissionFlags.IsNullOrEmpty()) { - # $value.SharingPermissionFlags = $null - # } - # } - - # foreach($value in $ValuesToCheck.UserPermissions) { - # if ($value.SharingPermissionFlags -ne "None" -and $value.SharingPermissionFlags -ne "Delegate" -and $value.SharingPermissionFlags -ne "CanViewPrivateItems") - # { - # $value.Remove('SharingPermissionFlags') | Out-Null - # } - # } - - for ($i = 0; $i -lt $ValuesToCheck.UserPermissions.Count; $i++) { - # $value = $ValuesToCheck.UserPermissions[$i] - - Write-Host "$i : Target Values: $ValuesToCheck.UserPermissions[$i]" - Write-Host "$i : Target Values: $CurrentValues.UserPermissions[$i]" - # if ($value.SharingPermissionFlags -ne "None" -and $value.SharingPermissionFlags -ne "Delegate" -and $value.SharingPermissionFlags -ne "CanViewPrivateItems") { - # # Update the value in place - # $ValuesToCheck.UserPermissions[$i].Remove('SharingPermissionFlags') | Out-Null - # Write-Verbose $ValuesToCheck.UserPermissions[$i] - # } + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-not $testResult) + { + $testTargetResource = $false + } + else { + $ValuesToCheck.Remove($key) | Out-Null + } + } } Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + $ValuesToCheck.Remove('ObjectId') | Out-Null + $ValuesToCheck.Remove('AppId') | Out-Null + $ValuesToCheck.Remove('Permissions') | Out-Null - $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` - -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` - -ValuesToCheck $ValuesToCheck.Keys + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys ` + -IncludedDrifts $driftedParams + + if(-not $TestResult) + { + $testTargetResource = $false + } - Write-Verbose -Message "Test-TargetResource returned $testResult" + Write-Verbose -Message "Test-TargetResource returned $testTargetResource" - return $testResult + return $testTargetResource } function Export-TargetResource diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 490ba44942..fcb133f534 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -236,8 +236,6 @@ function Convert-M365DscCIMInstanceToString $CIMInstance ) - Write-Host $CIMInstance - Write-Host "entering for loop*******************************************" $str = '{' foreach ($prop in $CIMInstance.CimInstanceProperties) { diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxFolderPermission.Tests.ps1 similarity index 74% rename from Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 rename to Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxFolderPermission.Tests.ps1 index 20857e0393..8b29aab035 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxFolderPermission.Tests.ps1 @@ -35,7 +35,20 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets + Mock -CommandName Get-MailboxFolderPermission -MockWith { + } + + Mock -CommandName Set-MailboxFolderPermission -MockWith { + } + + Mock -CommandName Add-MailboxFolderPermission -MockWith { + } + + Mock -CommandName Remove-MailboxFolderPermission -MockWith { + } + + Mock -CommandName Get-MailboxFolder -MockWith { + } # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { @@ -47,13 +60,20 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters + Identity = 'FakeStringValue1' + UserPermissions = @( + (New-CimInstance -ClassName MSFT_EXOMailboxFolderUserPermission -Property @{ + User = 'User' + AccessRights = @('Editor') + SharingPermissionFlags = 'Delegate' + } -ClientOnly) + ) Ensure = 'Present' Credential = $Credential; } ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MailboxFolderPermission -MockWith { return $null } } @@ -65,24 +85,35 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should create a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one - Should -Invoke -CommandName New-Cmdlet -Exactly 1 + Set-TargetResource @testParams + Should -Invoke -CommandName Add-MailboxFolderPermission -Exactly 1 } } Context -Name "The instance exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters + Identity = 'FakeStringValue1' + UserPermissions = @( + (New-CimInstance -ClassName MSFT_EXOMailboxFolderUserPermission -Property @{ + User = 'User' + AccessRights = @('Editor') + SharingPermissionFlags = 'Delegate' + } -ClientOnly) + ) Ensure = 'Absent' Credential = $Credential; } ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - - } + Mock -CommandName Get-MailboxFolderPermission -MockWith { + return @( + @{ + User = 'User' + AccessRights = @('Editor') + SharingPermissionFlags = 'Delegate' + } + ) } } It 'Should return Values from the Get method' { @@ -93,8 +124,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should remove the instance from the Set method' { - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MailboxFolderPermission -Exactly 1 } } diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index d8d8db6694..6ccc81969b 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -1091,6 +1091,122 @@ function Get-MailboxFolder $Recurse ) } +function Get-MailboxFolderPermission +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Int32] + $SkipCount, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $GroupMailbox, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $UseCustomRouting, + + [Parameter()] + [System.Object] + $User, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $ResultSize + ) +} +function Set-MailboxFolderPermission +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object[]] + $AccessRights, + + [Parameter()] + [System.Object] + $SharingPermissionFlags, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $User, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Boolean] + $SendNotificationToUser + ) +} +function Add-MailboxFolderPermission +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object[]] + $AccessRights, + + [Parameter()] + [System.Object] + $SharingPermissionFlags, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $User, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Boolean] + $SendNotificationToUser + ) +} +function Remove-MailboxFolderPermission +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $User, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ResetDelegateUserCollection, + + [Parameter()] + [System.Boolean] + $SendNotificationToUser, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force + ) +} function Get-MailboxFolderStatistics { [CmdletBinding()] From 2a06cfbab85ff6a0818665f8a423f2d4db15ceaf Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Thu, 26 Sep 2024 15:32:33 +0530 Subject: [PATCH 295/465] Added AADPolicyFeatureRolloutPolicy resource --- .../MSFT_AADPolicyFeatureRolloutPolicy.psm1 | 554 ++++++++++++++++++ ...T_AADPolicyFeatureRolloutPolicy.schema.mof | 19 + .../readme.md | 6 + .../settings.json | 25 + .../1-Create.ps1 | 38 ++ ...SC.AADPolicyFeatureRolloutPolicy.Tests.ps1 | 233 ++++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 311 ++++++++++ 7 files changed, 1186 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/MSFT_AADPolicyFeatureRolloutPolicy.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/MSFT_AADPolicyFeatureRolloutPolicy.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADPolicyFeatureRolloutPolicy/1-Create.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPolicyFeatureRolloutPolicy.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/MSFT_AADPolicyFeatureRolloutPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/MSFT_AADPolicyFeatureRolloutPolicy.psm1 new file mode 100644 index 0000000000..30d7314afc --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/MSFT_AADPolicyFeatureRolloutPolicy.psm1 @@ -0,0 +1,554 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [ValidateSet('passthroughAuthentication','seamlessSso','passwordHashSync','emailAsAlternateId','unknownFutureValue','certificateBasedAuthentication')] + [System.String] + $Feature, + + [Parameter()] + [System.Boolean] + $IsAppliedToOrganization, + + [Parameter()] + [System.Boolean] + $IsEnabled, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + try + { + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -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 + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + $getValue = $null + #region resource generator code + $getValue = Get-MgBetaPolicyFeatureRolloutPolicy -FeatureRolloutPolicyId $Id -ErrorAction SilentlyContinue + + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Azure AD Policy Feature Rollout Policy with Id {$Id}" + + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + $getValue = Get-MgBetaPolicyFeatureRolloutPolicy ` + -Filter "DisplayName eq '$DisplayName'" ` + -ErrorAction SilentlyContinue | Where-Object ` + -FilterScript { + $_.AdditionalProperties.'@odata.type' -eq "#microsoft.graph.FeatureRolloutPolicy" + } + } + } + #endregion + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Azure AD Policy Feature Rollout Policy with DisplayName {$DisplayName}." + return $nullResult + } + $Id = $getValue.Id + Write-Verbose -Message "An Azure AD Policy Feature Rollout Policy with Id {$Id} and DisplayName {$DisplayName} was found" + + #region resource generator code + $enumFeature = $null + if ($null -ne $getValue.Feature) + { + $enumFeature = $getValue.Feature.ToString() + } + #endregion + + $results = @{ + #region resource generator code + Description = $getValue.Description + DisplayName = $getValue.DisplayName + Feature = $enumFeature + IsAppliedToOrganization = $getValue.IsAppliedToOrganization + IsEnabled = $getValue.IsEnabled + Id = $getValue.Id + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + #endregion + } + + 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 + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [ValidateSet('passthroughAuthentication','seamlessSso','passwordHashSync','emailAsAlternateId','unknownFutureValue','certificateBasedAuthentication')] + [System.String] + $Feature, + + [Parameter()] + [System.Boolean] + $IsAppliedToOrganization, + + [Parameter()] + [System.Boolean] + $IsEnabled, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + #endregion + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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') + { + Write-Verbose -Message "Creating an Azure AD Policy Feature Rollout Policy with DisplayName {$DisplayName}" + + $createParameters = ([Hashtable]$BoundParameters).Clone() + $createParameters = Rename-M365DSCCimInstanceParameter -Properties $createParameters + $createParameters.Remove('Id') | Out-Null + + $keys = (([Hashtable]$createParameters).Clone()).Keys + foreach ($key in $keys) + { + if ($null -ne $createParameters.$key -and $createParameters.$key.GetType().Name -like '*CimInstance*') + { + $createParameters.$key = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $createParameters.$key + } + } + #region resource generator code + $policy = New-MgBetaPolicyFeatureRolloutPolicy -BodyParameter $createParameters + #endregion + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating the Azure AD Policy Feature Rollout Policy with Id {$($currentInstance.Id)}" + + $updateParameters = ([Hashtable]$BoundParameters).Clone() + $updateParameters = Rename-M365DSCCimInstanceParameter -Properties $updateParameters + + $updateParameters.Remove('Id') | Out-Null + $updateParameters.Remove('Feature') | Out-Null + + $keys = (([Hashtable]$updateParameters).Clone()).Keys + foreach ($key in $keys) + { + if ($null -ne $pdateParameters.$key -and $updateParameters.$key.GetType().Name -like '*CimInstance*') + { + $updateParameters.$key = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $updateParameters.FeatureRolloutPolicyId + } + } + + #region resource generator code + Update-MgBetaPolicyFeatureRolloutPolicy ` + -FeatureRolloutPolicyId $currentInstance.Id ` + -BodyParameter $UpdateParameters + #endregion + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing the Azure AD Policy Feature Rollout Policy with Id {$($currentInstance.Id)}" + #region resource generator code + Remove-MgBetaPolicyFeatureRolloutPolicy -FeatureRolloutPolicyId $currentInstance.Id + #endregion + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [ValidateSet('passthroughAuthentication','seamlessSso','passwordHashSync','emailAsAlternateId','unknownFutureValue','certificateBasedAuthentication')] + [System.String] + $Feature, + + [Parameter()] + [System.Boolean] + $IsAppliedToOrganization, + + [Parameter()] + [System.Boolean] + $IsEnabled, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 the Azure AD Policy Feature Rollout Policy with Id {$Id} and DisplayName {$DisplayName}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + + if ($CurrentValues.Ensure -ne $Ensure) + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + $testResult = $true + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-not $testResult) + { + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } + + $ValuesToCheck.Remove('Id') | Out-Null + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + if ($testResult) + { + $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.String] + $Filter, + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -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 + { + #region resource generator code + [array]$getValue = Get-MgBetaPolicyFeatureRolloutPolicy ` + -Filter $Filter ` + -All ` + -ErrorAction Stop + #endregion + + $i = 1 + $dscContent = '' + if ($getValue.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $getValue) + { + $displayedKey = $config.Id + if (-not [String]::IsNullOrEmpty($config.displayName)) + { + $displayedKey = $config.displayName + } + elseif (-not [string]::IsNullOrEmpty($config.name)) + { + $displayedKey = $config.name + } + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + DisplayName = $config.DisplayName + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_AADPolicyFeatureRolloutPolicy/MSFT_AADPolicyFeatureRolloutPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/MSFT_AADPolicyFeatureRolloutPolicy.schema.mof new file mode 100644 index 0000000000..43921a4d70 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/MSFT_AADPolicyFeatureRolloutPolicy.schema.mof @@ -0,0 +1,19 @@ + +[ClassVersion("1.0.0.0"), FriendlyName("AADPolicyFeatureRolloutPolicy")] +class MSFT_AADPolicyFeatureRolloutPolicy : OMI_BaseResource +{ + [Write, Description("A description for this feature rollout policy.")] String Description; + [Required, Description("The display name for this feature rollout policy.")] String DisplayName; + [Write, Description("Possible values are: passthroughAuthentication, seamlessSso, passwordHashSync, emailAsAlternateId, unknownFutureValue, certificateBasedAuthentication. You must use the Prefer: include-unknown-enum-members request header to get the following value or values in this evolvable enum: certificateBasedAuthentication. For more information about the prerequisites for the enabled features, see Prerequisites for enabled features."), ValueMap{"passthroughAuthentication","seamlessSso","passwordHashSync","emailAsAlternateId","unknownFutureValue","certificateBasedAuthentication"}, Values{"passthroughAuthentication","seamlessSso","passwordHashSync","emailAsAlternateId","unknownFutureValue","certificateBasedAuthentication"}] String Feature; + [Write, Description("Indicates whether this feature rollout policy should be applied to the entire organization.")] Boolean IsAppliedToOrganization; + [Write, Description("Indicates whether the feature rollout is enabled.")] Boolean IsEnabled; + [Key, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; + [Write, Description("Credentials of the 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("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/readme.md new file mode 100644 index 0000000000..588d84b2fd --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/readme.md @@ -0,0 +1,6 @@ + +# AADPolicyFeatureRolloutPolicy + +## Description + +Azure AD Policy Feature Rollout Policy diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/settings.json new file mode 100644 index 0000000000..8d993eaf72 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/settings.json @@ -0,0 +1,25 @@ +{ + "resourceName": "AADPolicyFeatureRolloutPolicy", + "description": "This resource configures an Azure AD Policy Feature Rollout Policy.", + "permissions": { + "graph": { + "delegated": { + "read": [ + + ], + "update": [ + + ] + }, + "application": { + "read": [ + + ], + "update": [ + + ] + } + } +} + +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADPolicyFeatureRolloutPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADPolicyFeatureRolloutPolicy/1-Create.ps1 new file mode 100644 index 0000000000..a9fa8ac440 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADPolicyFeatureRolloutPolicy/1-Create.ps1 @@ -0,0 +1,38 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADPolicyFeatureRolloutPolicy "AADPolicyFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Description = "CertificateBasedAuthentication rollout policy"; + DisplayName = "CertificateBasedAuthentication rollout policy"; + Ensure = "Present"; + Feature = "certificateBasedAuthentication"; + IsAppliedToOrganization = $False; + IsEnabled = $True; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPolicyFeatureRolloutPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPolicyFeatureRolloutPolicy.Tests.ps1 new file mode 100644 index 0000000000..14ad41891a --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPolicyFeatureRolloutPolicy.Tests.ps1 @@ -0,0 +1,233 @@ +[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 "AADPolicyFeatureRolloutPolicy" -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 Update-MgBetaPolicyFeatureRolloutPolicy -MockWith { + return $null + } + + Mock -CommandName New-MgBetaPolicyFeatureRolloutPolicy -MockWith { + return $null + } + + Mock -CommandName Remove-MgBetaPolicyFeatureRolloutPolicy -MockWith { + return $null + } + + 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 AADPolicyFeatureRolloutPolicy should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Description = "FakeStringValue" + DisplayName = "FakeStringValue" + Feature = "passthroughAuthentication" + Id = "FakeStringValue" + IsAppliedToOrganization = $True + IsEnabled = $True + Ensure = "Present" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaPolicyFeatureRolloutPolicy -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-MgBetaPolicyFeatureRolloutPolicy -Exactly 1 + } + } + + Context -Name "The AADPolicyFeatureRolloutPolicy exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Description = "FakeStringValue" + DisplayName = "FakeStringValue" + Feature = "passthroughAuthentication" + Id = "FakeStringValue" + IsAppliedToOrganization = $True + IsEnabled = $True + Ensure = 'Absent' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaPolicyFeatureRolloutPolicy -MockWith { + return @{ + AdditionalProperties = @{ + '@odata.type' = "#microsoft.graph.FeatureRolloutPolicy" + } + Description = "FakeStringValue" + DisplayName = "FakeStringValue" + Feature = "passthroughAuthentication" + Id = "FakeStringValue" + IsAppliedToOrganization = $True + IsEnabled = $True + + } + } + } + + 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-MgBetaPolicyFeatureRolloutPolicy -Exactly 1 + } + } + Context -Name "The AADPolicyFeatureRolloutPolicy Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Description = "FakeStringValue" + DisplayName = "FakeStringValue" + Feature = "passthroughAuthentication" + Id = "FakeStringValue" + IsAppliedToOrganization = $True + IsEnabled = $True + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaPolicyFeatureRolloutPolicy -MockWith { + return @{ + AdditionalProperties = @{ + '@odata.type' = "#microsoft.graph.FeatureRolloutPolicy" + } + Description = "FakeStringValue" + DisplayName = "FakeStringValue" + Feature = "passthroughAuthentication" + Id = "FakeStringValue" + IsAppliedToOrganization = $True + IsEnabled = $True + + } + } + } + + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The AADPolicyFeatureRolloutPolicy exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Description = "FakeStringValue" + DisplayName = "FakeStringValue" + Feature = "passthroughAuthentication" + Id = "FakeStringValue" + IsAppliedToOrganization = $True + IsEnabled = $True + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaPolicyFeatureRolloutPolicy -MockWith { + return @{ + Description = "FakeStringValue" + DisplayName = "FakeStringValue" + Feature = "passthroughAuthentication" + Id = "FakeStringValue" + } + } + } + + 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 Update-MgBetaPolicyFeatureRolloutPolicy -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-MgBetaPolicyFeatureRolloutPolicy -MockWith { + return @{ + AdditionalProperties = @{ + '@odata.type' = "#microsoft.graph.FeatureRolloutPolicy" + } + Description = "FakeStringValue" + DisplayName = "FakeStringValue" + Feature = "passthroughAuthentication" + Id = "FakeStringValue" + IsAppliedToOrganization = $True + IsEnabled = $True + + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 625bc887df..927d456f93 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -86536,3 +86536,314 @@ function Get-MgBetaDeviceManagementWindowsQualityUpdateProfileAssignment #endregion +#region MgBetaPolicyFeatureRolloutPolicy +function Get-MgBetaPolicyFeatureRolloutPolicy +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $FeatureRolloutPolicyId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $CountVariable + ) +} + +function New-MgBetaPolicyFeatureRolloutPolicy +{ + [CmdletBinding()] + param + ( + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [PSObject[]] + $AppliesTo, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Feature, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsAppliedToOrganization, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsEnabled, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} + +function Remove-MgBetaPolicyFeatureRolloutPolicy +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $FeatureRolloutPolicyId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} + +function Update-MgBetaPolicyFeatureRolloutPolicy +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $FeatureRolloutPolicyId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [PSObject[]] + $AppliesTo, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $Feature, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsAppliedToOrganization, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsEnabled, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} + +#endregion + From 2e38953f67d502bc187a8b2c1f55cdf8dbd18503 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 26 Sep 2024 10:04:02 +0000 Subject: [PATCH 296/465] Updated {Create} AAD Integration Tests --- .../M365DSCIntegration.AAD.Create.Tests.ps1 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 index 961f04f285..8a7e6c19ed 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 @@ -318,6 +318,18 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + AADPolicyFeatureRolloutPolicy 'AADPolicyFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy' + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Description = "CertificateBasedAuthentication rollout policy"; + DisplayName = "CertificateBasedAuthentication rollout policy"; + Ensure = "Present"; + Feature = "certificateBasedAuthentication"; + IsAppliedToOrganization = $False; + IsEnabled = $True; + } AADRoleDefinition 'AADRoleDefinition1' { DisplayName = "DSCRole1" From 96a4cf3e368e53adc2e8a170e33f894b7da9002a Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 26 Sep 2024 10:06:00 +0000 Subject: [PATCH 297/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 7acf32a9b7..072501b4ef 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -3999,6 +3999,81 @@ } ] }, + { + "ClassName": "MSFT_AADPolicyFeatureRolloutPolicy", + "Parameters": [ + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Required" + }, + { + "CIMType": "String", + "Name": "Feature", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsAppliedToOrganization", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Key" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AADRoleDefinition", "Parameters": [ From 3effecba36e5273d214c357ac64d1ce17ed09b0d Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Thu, 26 Sep 2024 16:01:26 +0530 Subject: [PATCH 298/465] Added UTs --- .../Modules/M365DSCStubsUtility.psm1 | 1 + .../Microsoft365DSC.AADApplication.Tests.ps1 | 144 ++++++- Tests/Unit/Stubs/Microsoft365.psm1 | 350 ++++++++++++++++++ 3 files changed, 490 insertions(+), 5 deletions(-) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCStubsUtility.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCStubsUtility.psm1 index b96d480372..8a98b55211 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCStubsUtility.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCStubsUtility.psm1 @@ -52,6 +52,7 @@ function New-M365DSCStubFiles @{Name = 'ExchangeOnline'; ModuleName = 'ExchangeOnlineManagement'; CommandName = 'Get-Mailbox' }, # This is the EXO Proxy @{Name = 'MicrosoftGraph'; ModuleName = 'Microsoft.Graph.Applications'}, @{Name = 'MicrosoftGraph'; ModuleName = 'Microsoft.Graph.Authentication'}, + @{Name = 'MicrosoftGraph'; ModuleName = 'Microsoft.Graph.Beta.Applications'}, @{Name = 'MicrosoftGraph'; ModuleName = 'Microsoft.Graph.Beta.DeviceManagement'}, @{Name = 'MicrosoftGraph'; ModuleName = 'Microsoft.Graph.Beta.Devices.CorporateManagement'}, @{Name = 'MicrosoftGraph'; ModuleName = 'Microsoft.Graph.Beta.DeviceManagement.Administration'}, diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 index c801d194e8..27adaeb989 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 @@ -32,6 +32,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Remove-PSSession -MockWith { } + Mock -CommandName Update-MgBetaApplication -MockWith { + } + Mock -CommandName Update-MgApplication -MockWith { } @@ -144,7 +147,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return values from the get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Present' - Should -Invoke -CommandName 'Get-MgApplication' -Exactly 1 + Should -Invoke -CommandName 'Get-MgApplication' -Exactly 2 } It 'Should return false from the test method' { @@ -156,6 +159,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Should -Invoke -CommandName 'Remove-MgApplication' -Exactly 1 } } + Context -Name 'The app exists and values are already in the desired state' -Fixture { BeforeAll { $testParams = @{ @@ -169,10 +173,56 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { LogoutURL = 'https://app.contoso.com/logout' PublicClient = $false ReplyURLs = 'https://app.contoso.com' + AppRoles = @( + New-CimInstance -ClassName MSFT_MicrosoftGraphappRole -Property @{ + AllowedMemberTypes = @('Application') + Id = 'Task Reader' + IsEnabled = $True + Origin = 'Application' + Description = 'Readers have ability to read task' + Value = 'Task.Read' + DisplayName = 'Readers' + } -ClientOnly + New-CimInstance -ClassName MSFT_MicrosoftGraphappRole @{ + AllowedMemberTypes = @('Application') + Id = 'Task Writer' + IsEnabled = $True + Origin = 'Application' + Description = 'Writers have ability to write task' + Value = 'Task.Write' + DisplayName = 'Writers' + } -ClientOnly + ) + PasswordCredentials = @( + New-CimInstance -ClassName MSFT_MicrosoftGraphpasswordCredential -Property @{ + KeyId = 'keyid' + EndDateTime = '2025-03-15T19:50:29.0310000+00:00' + Hint = 'VsO' + DisplayName = 'Super Secret' + StartDateTime = '2024-09-16T19:50:29.0310000+00:00' + } -ClientOnly + ) + AuthenticationBehaviors = New-CimInstance -ClassName MSFT_MicrosoftGraphAuthenticationBehaviors -Property @{ + blockAzureADGraphAccess = $false + removeUnverifiedEmailClaim = $true + requireClientServicePrincipal = $false + } -ClientOnly Ensure = 'Present' Credential = $Credential } + Mock -CommandName Get-MgBetaApplication -MockWith { + $AADApp = New-Object PSCustomObject + $AADApp | Add-Member -MemberType NoteProperty -Name DisplayName -Value 'App1' + $AADApp | Add-Member -MemberType NoteProperty -Name Id -Value '5dcb2237-c61b-4258-9c85-eae2aaeba9d6' + $AADApp | Add-Member -MemberType NoteProperty -Name AppId -Value '5dcb2237-c61b-4258-9c85-eae2aaeba9d6' + $AADApp | Add-Member -MemberType NoteProperty -Name AuthenticationBehaviors -Value @{ + blockAzureADGraphAccess = $false + removeUnverifiedEmailClaim = $true + requireClientServicePrincipal = $false + } + return $AADApp + } Mock -CommandName Get-MgApplication -MockWith { $AADApp = New-Object PSCustomObject $AADApp | Add-Member -MemberType NoteProperty -Name DisplayName -Value 'App1' @@ -185,10 +235,37 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { LogoutURL = 'https://app.contoso.com/logout' RedirectUris = @('https://app.contoso.com') } - $AADApp | Add-Member -MemberType NoteProperty -Name IdentifierUris -Value 'https://app.contoso.com' + $AADApp | Add-Member -MemberType NoteProperty -Name AppRoles -Value @( + @{ + AllowedMemberTypes = @('Application') + Id = 'Task Reader' + IsEnabled = $True + Origin = 'Application' + Description = 'Readers have ability to read task' + Value = 'Task.Read' + DisplayName = 'Readers' + } + @{ + AllowedMemberTypes = @('Application') + Id = 'Task Writer' + IsEnabled = $True + Origin = 'Application' + Description = 'Writers have ability to write task' + Value = 'Task.Write' + DisplayName = 'Writers' + } + ) + $AADApp | Add-Member -MemberType NoteProperty -Name PasswordCredentials -Value @{ + KeyId = 'keyid' + EndDateTime = '2025-03-15T19:50:29.0310000+00:00' + Hint = 'VsO' + DisplayName = 'Super Secret' + StartDateTime = '2024-09-16T19:50:29.0310000+00:00' + } $AADApp | Add-Member -MemberType NoteProperty -Name API -Value @{ KnownClientApplications = '' } + $AADApp | Add-Member -MemberType NoteProperty -Name IdentifierUris -Value 'https://app.contoso.com' $AADApp | Add-Member -MemberType NoteProperty -Name Oauth2RequirePostResponse -Value $false $AADApp | Add-Member -MemberType NoteProperty -Name PublicClient -Value $false return $AADApp @@ -197,11 +274,11 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return Values from the get method' { Get-TargetResource @testParams - Should -Invoke -CommandName 'Get-MgApplication' -Exactly 1 + Should -Invoke -CommandName 'Get-MgApplication' -Exactly 2 } It 'Should return true from the test method' { - Test-TargetResource @testParams | Should -Be $true + Test-TargetResource @testParams -Verbose | Should -Be $true } } @@ -242,7 +319,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return values from the get method' { Get-TargetResource @testParams - Should -Invoke -CommandName 'Get-MgApplication' -Exactly 1 + Should -Invoke -CommandName 'Get-MgApplication' -Exactly 2 } It 'Should return false from the test method' { @@ -255,6 +332,63 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } + Context -Name 'Assigning Authentication Behaviors to a new Application' -Fixture { + BeforeAll { + $testParams = @{ + DisplayName = 'App1' + AvailableToOtherTenants = $false + Description = 'App description' + GroupMembershipClaims = '0' + IdentifierUris = 'https://app.contoso.com' + KnownClientApplications = '' + LogoutURL = 'https://app.contoso.com/logout' + PublicClient = $false + ReplyURLs = 'https://app.contoso.com' + AuthenticationBehaviors = New-CimInstance -ClassName MSFT_MicrosoftGraphAuthenticationBehaviors -Property @{ + blockAzureADGraphAccess = $false + removeUnverifiedEmailClaim = $true + requireClientServicePrincipal = $false + } -ClientOnly + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName Get-MgApplication -MockWith { + return $null + } + + Mock -CommandName Get-MgBetaApplication -MockWith { + return @{ + id = '12345-12345-12345-12345-12345' + appId = '12345-12345-12345-12345-12345' + DisplayName = 'App1' + AuthenticationBehaviours = @{ + blockAzureADGraphAccess = $false + removeUnverifiedEmailClaim = $true + requireClientServicePrincipal = $false + } + + } + } + } + + It 'Should return values from the get method' { + Get-TargetResource @testParams + Should -Invoke -CommandName 'Get-MgApplication' -Exactly 1 + } + + It 'Should return false from the test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the new method' { + Set-TargetResource @testParams + Should -Invoke -CommandName 'New-MgApplication' -Exactly 1 + Should -Invoke -CommandName 'Update-MgBetaApplication' -Exactly 1 + } + + } + Context -Name 'Assigning Permissions to a new Application' -Fixture { BeforeAll { $testParams = @{ diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 1cbd830f9e..e0644108dc 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -1,3 +1,353 @@ + +#region Microsoft.Graph.Beta.Applications +function Get-MgBetaApplication +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.String] + $ConsistencyLevel, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Update-MgBetaApplication +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [PSObject] + $HomeRealmDiscoveryPolicies, + + [Parameter()] + [PSObject] + $Spa, + + [Parameter()] + [PSObject] + $Synchronization, + + [Parameter()] + [System.String] + $DefaultRedirectUri, + + [Parameter()] + [System.DateTime] + $CreatedDateTime, + + [Parameter()] + [System.String] + $SignInAudience, + + [Parameter()] + [PSObject] + $VerifiedPublisher, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $OptionalClaims, + + [Parameter()] + [System.String[]] + $IdentifierUris, + + [Parameter()] + [PSObject] + $AuthenticationBehaviors, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsDeviceOnlyAuthSupported, + + [Parameter()] + [System.String] + $TokenEncryptionKeyId, + + [Parameter()] + [System.String] + $UniqueName, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [PSObject] + $TokenIssuancePolicies, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $Api, + + [Parameter()] + [System.String] + $PublisherDomain, + + [Parameter()] + [System.String] + $GroupMembershipClaims, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String[]] + $Tags, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [PSObject] + $Owners, + + [Parameter()] + [PSObject] + $FederatedIdentityCredentials, + + [Parameter()] + [PSObject] + $TokenLifetimePolicies, + + [Parameter()] + [PSObject] + $AppManagementPolicies, + + [Parameter()] + [System.String] + $DisabledByMicrosoftStatus, + + [Parameter()] + [PSObject] + $PasswordCredentials, + + [Parameter()] + [PSObject] + $PublicClient, + + [Parameter()] + [System.String] + $Notes, + + [Parameter()] + [PSObject] + $RequiredResourceAccess, + + [Parameter()] + [PSObject] + $ParentalControlSettings, + + [Parameter()] + [PSObject] + $Web, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsFallbackPublicClient, + + [Parameter()] + [System.String] + $NativeAuthenticationApisEnabled, + + [Parameter()] + [System.DateTime] + $DeletedDateTime, + + [Parameter()] + [PSObject] + $RequestSignatureVerification, + + [Parameter()] + [System.String] + $LogoInputFile, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [PSObject] + $AppRoles, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $ExtensionProperties, + + [Parameter()] + [PSObject] + $Windows, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [PSObject] + $CreatedOnBehalfOf, + + [Parameter()] + [PSObject] + $ConnectorGroup, + + [Parameter()] + [PSObject] + $ServicePrincipalLockConfiguration, + + [Parameter()] + [System.String] + $ServiceManagementReference, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [PSObject] + $KeyCredentials, + + [Parameter()] + [PSObject] + $Certification, + + [Parameter()] + [PSObject] + $OnPremisesPublishing, + + [Parameter()] + [System.String] + $SamlMetadataUrl, + + [Parameter()] + [PSObject] + $Info, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $AppId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +#endregion + #region Azure function Get-AzSentinelSetting { From 821f7ef4b1f23bb09adb75360cad01ac03460016 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 26 Sep 2024 06:37:22 -0400 Subject: [PATCH 299/465] AADEntitlementManagementSettings - Initial Release --- CHANGELOG.md | 5 +- ...MSFT_AADEntitlementManagementSettings.psm1 | 322 ++++++++++++++++++ ...ADEntitlementManagementSettings.schema.mof | 14 + .../readme.md | 6 + .../settings.json | 32 ++ .../2-Update.ps1 | 34 ++ ...AADEntitlementManagementSettings.Tests.ps1 | 108 ++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 107 ++++++ 8 files changed, 626 insertions(+), 2 deletions(-) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/MSFT_AADEntitlementManagementSettings.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/MSFT_AADEntitlementManagementSettings.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADEntitlementManagementSettings/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADEntitlementManagementSettings.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c6727ac84..2b98dbd87c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,9 @@ # Change log for Microsoft365DSC # UNRELEASED -* MdcSubscriptionDefenderPlan - * Initial release + +* AADEntitlementManagementSettings + * Initial release. * AADPasswordRuleSettings * Initial release * ADOOrganizationOwner diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/MSFT_AADEntitlementManagementSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/MSFT_AADEntitlementManagementSettings.psm1 new file mode 100644 index 0000000000..f145e6744d --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/MSFT_AADEntitlementManagementSettings.psm1 @@ -0,0 +1,322 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $IsSingleInstance = 'Yes', + + [Parameter()] + [System.UInt32] + $DaysUntilExternalUserDeletedAfterBlocked, + + [Parameter()] + [System.String] + $ExternalUserLifecycleAction, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -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 + try + { + $instance = Get-MgBetaEntitlementManagementSetting + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + IsSingleInstance = 'Yes' + DaysUntilExternalUserDeletedAfterBlocked = $instance.DaysUntilExternalUserDeletedAfterBlocked + ExternalUserLifecycleAction = $instance.ExternalUserLifecycleAction + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $IsSingleInstance = 'Yes', + + [Parameter()] + [System.UInt32] + $DaysUntilExternalUserDeletedAfterBlocked, + + [Parameter()] + [System.String] + $ExternalUserLifecycleAction, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $setParameters.Remove('IsSingleInstance') | Out-Null + Write-Verbose -Message "Updating Entitlement Management settings" + Update-MgBetaEntitlementManagementSetting @setParameters | Out-Null +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $IsSingleInstance = 'Yes', + + [Parameter()] + [System.UInt32] + $DaysUntilExternalUserDeletedAfterBlocked, + + [Parameter()] + [System.String] + $ExternalUserLifecycleAction, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -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 + { + $Script:ExportMode = $true + + $params = @{ + IsSIngleInstance = 'Yes' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + $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_AADEntitlementManagementSettings/MSFT_AADEntitlementManagementSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/MSFT_AADEntitlementManagementSettings.schema.mof new file mode 100644 index 0000000000..7ed1c6993a --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/MSFT_AADEntitlementManagementSettings.schema.mof @@ -0,0 +1,14 @@ +[ClassVersion("1.0.0.0"), FriendlyName("AADEntitlementManagementSettings")] +class MSFT_AADEntitlementManagementSettings : OMI_BaseResource +{ + [Key, Description("Only accepted value is 'Yes'."), ValueMap{"Yes"}, Values{"Yes"}] String IsSingleInstance; + [Write, Description("If externalUserLifecycleAction is blockSignInAndDelete, the duration, typically many days, after an external user is blocked from sign in before their account is deleted.")] UInt32 DaysUntilExternalUserDeletedAfterBlocked; + [Write, Description("Automatic action that the service should take when an external user's last access package assignment is removed. The possible values are: none, blockSignIn, blockSignInAndDelete, unknownFutureValue.")] String ExternalUserLifecycleAction; + + [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/readme.md new file mode 100644 index 0000000000..32e0e7fb27 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/readme.md @@ -0,0 +1,6 @@ + +# ResourceName + +## Description + +##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/settings.json new file mode 100644 index 0000000000..edf14b05e4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "ResourceName", + "description": "Description of what the resource is about.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADEntitlementManagementSettings/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADEntitlementManagementSettings/2-Update.ps1 new file mode 100644 index 0000000000..00107cb07d --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADEntitlementManagementSettings/2-Update.ps1 @@ -0,0 +1,34 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADEntitlementManagementSettings "AADEntitlementManagementSettings" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + DaysUntilExternalUserDeletedAfterBlocked = 30; + ExternalUserLifecycleAction = "blockSignInAndDelete"; + IsSingleInstance = "Yes"; + TenantId = $TenantId; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADEntitlementManagementSettings.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADEntitlementManagementSettings.Tests.ps1 new file mode 100644 index 0000000000..1ffd4c4aab --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADEntitlementManagementSettings.Tests.ps1 @@ -0,0 +1,108 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Update-MgBetaEntitlementManagementSetting { + } + + Mock -CommandName Get-MgBetaEntitlementManagementSetting { + return @{ + Id = 'singleton' + DaysUntilExternalUserDeletedAfterBlocked = 30 + ExternalUserLifecycleAction = 'BlockSignInAndDelete' + } + } + + # 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 instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + IsSingleInstance = 'Yes' + DaysUntilExternalUserDeletedAfterBlocked = 30 + ExternalUserLifecycleAction = 'BlockSignInAndDelete' + Credential = $Credential; + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + IsSingleInstance = 'Yes' + DaysUntilExternalUserDeletedAfterBlocked = 29 #drift + ExternalUserLifecycleAction = 'BlockSignInAndDelete' + Credential = $Credential; + } + } + + 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 Update-MgBetaEntitlementManagementSetting -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 7d67c66895..37993f422c 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -2668,6 +2668,113 @@ function Get-MgBetaRoleManagementEntitlementManagementRoleAssignment $All ) } +function Update-MgBetaEntitlementManagementSetting +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Int32] + $DaysUntilExternalUserDeletedAfterBlocked, + + [Parameter()] + [System.String] + $ExternalUserLifecycleAction + ) +} + +function Get-MgBetaEntitlementManagementSetting +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} function Get-MgBetaRoleManagementEntitlementManagementRoleDefinition { From 0aff9ce6aad5117c7176cd1a45faf70da221544c Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Thu, 26 Sep 2024 16:15:00 +0530 Subject: [PATCH 300/465] Fixed UTs --- .../Microsoft365DSC.AADApplication.Tests.ps1 | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 index 27adaeb989..f55ba61877 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 @@ -207,6 +207,15 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { removeUnverifiedEmailClaim = $true requireClientServicePrincipal = $false } -ClientOnly + Api = New-CimInstance -ClassName MSFT_MicrosoftGraphapiApplication -Property @{ + PreAuthorizedApplications = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_MicrosoftGraphPreAuthorizedApplication -Property @{ + AppId = '12345-12345-12345-12345-12345' + PermissionIds = @('12345-12345-12345-12345-12345') + } -ClientOnly + ) + + } -ClientOnly Ensure = 'Present' Credential = $Credential } @@ -264,6 +273,12 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } $AADApp | Add-Member -MemberType NoteProperty -Name API -Value @{ KnownClientApplications = '' + PreAuthorizedApplications = @( + @{ + AppId = '12345-12345-12345-12345-12345' + PermissionIds = @('12345-12345-12345-12345-12345') + } + ) } $AADApp | Add-Member -MemberType NoteProperty -Name IdentifierUris -Value 'https://app.contoso.com' $AADApp | Add-Member -MemberType NoteProperty -Name Oauth2RequirePostResponse -Value $false @@ -278,7 +293,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should return true from the test method' { - Test-TargetResource @testParams -Verbose | Should -Be $true + Test-TargetResource @testParams | Should -Be $true } } From e44156414ab6d80d1bdc1b7dfd166ec7cfc58ad6 Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Thu, 26 Sep 2024 16:18:50 +0530 Subject: [PATCH 301/465] Renamed resource --- .../MSFT_AADFeatureRolloutPolicy.psm1} | 0 .../MSFT_AADFeatureRolloutPolicy.schema.mof} | 4 ++-- .../readme.md | 2 +- .../settings.json | 0 .../1-Create.ps1 | 2 +- ResourceGenerator/M365DSCResourceGenerator.psm1 | 4 +--- ....ps1 => Microsoft365DSC.AADFeatureRolloutPolicy.Tests.ps1} | 0 7 files changed, 5 insertions(+), 7 deletions(-) rename Modules/Microsoft365DSC/DSCResources/{MSFT_AADPolicyFeatureRolloutPolicy/MSFT_AADPolicyFeatureRolloutPolicy.psm1 => MSFT_AADFeatureRolloutPolicy/MSFT_AADFeatureRolloutPolicy.psm1} (100%) rename Modules/Microsoft365DSC/DSCResources/{MSFT_AADPolicyFeatureRolloutPolicy/MSFT_AADPolicyFeatureRolloutPolicy.schema.mof => MSFT_AADFeatureRolloutPolicy/MSFT_AADFeatureRolloutPolicy.schema.mof} (94%) rename Modules/Microsoft365DSC/DSCResources/{MSFT_AADPolicyFeatureRolloutPolicy => MSFT_AADFeatureRolloutPolicy}/readme.md (64%) rename Modules/Microsoft365DSC/DSCResources/{MSFT_AADPolicyFeatureRolloutPolicy => MSFT_AADFeatureRolloutPolicy}/settings.json (100%) rename Modules/Microsoft365DSC/Examples/Resources/{AADPolicyFeatureRolloutPolicy => AADFeatureRolloutPolicy}/1-Create.ps1 (90%) rename Tests/Unit/Microsoft365DSC/{Microsoft365DSC.AADPolicyFeatureRolloutPolicy.Tests.ps1 => Microsoft365DSC.AADFeatureRolloutPolicy.Tests.ps1} (100%) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/MSFT_AADPolicyFeatureRolloutPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/MSFT_AADFeatureRolloutPolicy.psm1 similarity index 100% rename from Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/MSFT_AADPolicyFeatureRolloutPolicy.psm1 rename to Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/MSFT_AADFeatureRolloutPolicy.psm1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/MSFT_AADPolicyFeatureRolloutPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/MSFT_AADFeatureRolloutPolicy.schema.mof similarity index 94% rename from Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/MSFT_AADPolicyFeatureRolloutPolicy.schema.mof rename to Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/MSFT_AADFeatureRolloutPolicy.schema.mof index 43921a4d70..2f3aec73da 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/MSFT_AADPolicyFeatureRolloutPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/MSFT_AADFeatureRolloutPolicy.schema.mof @@ -1,6 +1,6 @@ -[ClassVersion("1.0.0.0"), FriendlyName("AADPolicyFeatureRolloutPolicy")] -class MSFT_AADPolicyFeatureRolloutPolicy : OMI_BaseResource +[ClassVersion("1.0.0.0"), FriendlyName("AADFeatureRolloutPolicy")] +class MSFT_AADFeatureRolloutPolicy : OMI_BaseResource { [Write, Description("A description for this feature rollout policy.")] String Description; [Required, Description("The display name for this feature rollout policy.")] String DisplayName; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/readme.md similarity index 64% rename from Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/readme.md rename to Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/readme.md index 588d84b2fd..b1e4f319bc 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/readme.md @@ -1,5 +1,5 @@ -# AADPolicyFeatureRolloutPolicy +# AADFeatureRolloutPolicy ## Description diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/settings.json similarity index 100% rename from Modules/Microsoft365DSC/DSCResources/MSFT_AADPolicyFeatureRolloutPolicy/settings.json rename to Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/settings.json diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADPolicyFeatureRolloutPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/1-Create.ps1 similarity index 90% rename from Modules/Microsoft365DSC/Examples/Resources/AADPolicyFeatureRolloutPolicy/1-Create.ps1 rename to Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/1-Create.ps1 index a9fa8ac440..7d729800c4 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADPolicyFeatureRolloutPolicy/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/1-Create.ps1 @@ -22,7 +22,7 @@ Configuration Example node localhost { - AADPolicyFeatureRolloutPolicy "AADPolicyFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy" + AADFeatureRolloutPolicy "AADFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy" { ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/ResourceGenerator/M365DSCResourceGenerator.psm1 b/ResourceGenerator/M365DSCResourceGenerator.psm1 index 803062322d..bbaade9b4e 100644 --- a/ResourceGenerator/M365DSCResourceGenerator.psm1 +++ b/ResourceGenerator/M365DSCResourceGenerator.psm1 @@ -902,7 +902,6 @@ class MSFT_DeviceManagementConfigurationPolicyAssignments #region Examples if ($null -ne $Credential) { - Import-Module Microsoft365DSC -Force New-M365DSCExampleFile -ResourceName $ResourceName ` -Path $ExampleFilePath ` -Credential $Credential @@ -1635,8 +1634,7 @@ function Get-Microsoft365DSCModuleCimClass $ResourceName ) - Import-Module -Name Microsoft365DSC -Force - $modulePath = Split-Path -Path (Get-Module -Name Microsoft365DSC).Path + $modulePath = "C:\Program Files\WindowsPowerShell\Modules\Microsoft365DSC\Modules\Microsoft365DSC" $resourcesPath = "$modulePath\DSCResources\*\*.mof" $resources = (Get-ChildItem $resourcesPath).FullName $resources = $resources | Where-Object -FilterScript {$_ -notlike "*MSFT_$ResourceName.schema.mof"} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPolicyFeatureRolloutPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADFeatureRolloutPolicy.Tests.ps1 similarity index 100% rename from Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADPolicyFeatureRolloutPolicy.Tests.ps1 rename to Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADFeatureRolloutPolicy.Tests.ps1 From f0d323d952f1aa607da4a72a3f0781f33af9b90c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 26 Sep 2024 10:50:31 +0000 Subject: [PATCH 302/465] Updated {Create} AAD Integration Tests --- .../M365DSCIntegration.AAD.Create.Tests.ps1 | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 index 8a7e6c19ed..acc46c6e4b 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 @@ -290,6 +290,18 @@ Principal = "AdeleV@$TenantId"; RoleDefinition = "Catalog creator"; } + AADFeatureRolloutPolicy 'AADFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy' + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Description = "CertificateBasedAuthentication rollout policy"; + DisplayName = "CertificateBasedAuthentication rollout policy"; + Ensure = "Present"; + Feature = "certificateBasedAuthentication"; + IsAppliedToOrganization = $False; + IsEnabled = $True; + } AADGroup 'MyGroups' { DisplayName = "DSCGroup" @@ -318,18 +330,6 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } - AADPolicyFeatureRolloutPolicy 'AADPolicyFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy' - { - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - Description = "CertificateBasedAuthentication rollout policy"; - DisplayName = "CertificateBasedAuthentication rollout policy"; - Ensure = "Present"; - Feature = "certificateBasedAuthentication"; - IsAppliedToOrganization = $False; - IsEnabled = $True; - } AADRoleDefinition 'AADRoleDefinition1' { DisplayName = "DSCRole1" From 469986baa7bf41de60e43d9cc3b4374e819f3437 Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Thu, 26 Sep 2024 16:21:28 +0530 Subject: [PATCH 303/465] More renames --- Modules/Microsoft365DSC/SchemaDefinition.json | 2 +- .../M365DSCIntegration.AAD.Create.Tests.ps1 | 2 +- .../Microsoft365DSC.AADFeatureRolloutPolicy.Tests.ps1 | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 072501b4ef..4f4803666e 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -4000,7 +4000,7 @@ ] }, { - "ClassName": "MSFT_AADPolicyFeatureRolloutPolicy", + "ClassName": "MSFT_AADFeatureRolloutPolicy", "Parameters": [ { "CIMType": "String", diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 index 8a7e6c19ed..66214537b9 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 @@ -318,7 +318,7 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } - AADPolicyFeatureRolloutPolicy 'AADPolicyFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy' + AADFeatureRolloutPolicy 'AADFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy' { ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADFeatureRolloutPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADFeatureRolloutPolicy.Tests.ps1 index 14ad41891a..6a27a6c4e6 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADFeatureRolloutPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADFeatureRolloutPolicy.Tests.ps1 @@ -15,7 +15,7 @@ Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` -Resolve) $Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` - -DscResource "AADPolicyFeatureRolloutPolicy" -GenericStubModule $GenericStubPath + -DscResource "AADFeatureRolloutPolicy" -GenericStubModule $GenericStubPath Describe -Name $Global:DscHelper.DescribeHeader -Fixture { InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope @@ -56,7 +56,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $Script:ExportMode = $false } # Test contexts - Context -Name "The AADPolicyFeatureRolloutPolicy should exist but it DOES NOT" -Fixture { + Context -Name "The AADFeatureRolloutPolicy should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ Description = "FakeStringValue" @@ -85,7 +85,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } - Context -Name "The AADPolicyFeatureRolloutPolicy exists but it SHOULD NOT" -Fixture { + Context -Name "The AADFeatureRolloutPolicy exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ Description = "FakeStringValue" @@ -127,7 +127,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Should -Invoke -CommandName Remove-MgBetaPolicyFeatureRolloutPolicy -Exactly 1 } } - Context -Name "The AADPolicyFeatureRolloutPolicy Exists and Values are already in the desired state" -Fixture { + Context -Name "The AADFeatureRolloutPolicy Exists and Values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ Description = "FakeStringValue" @@ -162,7 +162,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } - Context -Name "The AADPolicyFeatureRolloutPolicy exists and values are NOT in the desired state" -Fixture { + Context -Name "The AADFeatureRolloutPolicy exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ Description = "FakeStringValue" From 4e1ca7e51b42ad7d8c6b9f8f227749d64b6896b3 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 26 Sep 2024 10:52:19 +0000 Subject: [PATCH 304/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 150 +++++++++--------- 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 072501b4ef..1fe3a4e303 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -3469,6 +3469,81 @@ } ] }, + { + "ClassName": "MSFT_AADFeatureRolloutPolicy", + "Parameters": [ + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Required" + }, + { + "CIMType": "String", + "Name": "Feature", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsAppliedToOrganization", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Key" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AADGroupLicense", "Parameters": [ @@ -3999,81 +4074,6 @@ } ] }, - { - "ClassName": "MSFT_AADPolicyFeatureRolloutPolicy", - "Parameters": [ - { - "CIMType": "String", - "Name": "Description", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "DisplayName", - "Option": "Required" - }, - { - "CIMType": "String", - "Name": "Feature", - "Option": "Write" - }, - { - "CIMType": "Boolean", - "Name": "IsAppliedToOrganization", - "Option": "Write" - }, - { - "CIMType": "Boolean", - "Name": "IsEnabled", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "Id", - "Option": "Key" - }, - { - "CIMType": "string", - "Name": "Ensure", - "Option": "Write" - }, - { - "CIMType": "MSFT_Credential", - "Name": "Credential", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "ApplicationId", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "TenantId", - "Option": "Write" - }, - { - "CIMType": "MSFT_Credential", - "Name": "ApplicationSecret", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "CertificateThumbprint", - "Option": "Write" - }, - { - "CIMType": "Boolean", - "Name": "ManagedIdentity", - "Option": "Write" - }, - { - "CIMType": "String[]", - "Name": "AccessTokens", - "Option": "Write" - } - ] - }, { "ClassName": "MSFT_AADRoleDefinition", "Parameters": [ From 2832679021de85b3f0c9e99cbd9afe53e6461379 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 26 Sep 2024 06:53:18 -0400 Subject: [PATCH 305/465] Fixes settings.json --- .../readme.md | 4 +-- .../settings.json | 33 ++++++++++++++----- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/readme.md index 32e0e7fb27..856052c457 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/readme.md @@ -1,6 +1,6 @@ -# ResourceName +# AADEntitlementManagementSettings ## Description -##TODO - Provide a short description of what the resource is set to configure. +Manages Entra Id Entitlement Management settings. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/settings.json index edf14b05e4..3005622fd8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementSettings/settings.json @@ -1,29 +1,46 @@ { - "resourceName": "ResourceName", - "description": "Description of what the resource is about.", + "resourceName": "AADEntitlementManagementSettings", + "description": "Manages Entra Id Entitlement Management settings.", "roles": { "read": [ - "Role" + "Security Reader" ], "update": [ - "Role" + "Identity Governance Administrator" ] }, "permissions": { "graph": { "delegated": { - "read": [], - "update": [] + "read": [ + { + "name": "EntitlementManagement.Read.All" + } + ], + "update": [ + { + "name": "EntitlementManagement.Read.All" + }, + { + "name": "EntitlementManagement.ReadWrite.All" + } + ] }, "application": { "read": [ { - "name": "Permission for Monitoring and Export" + "name": "EntitlementManagement.Read.All" } ], "update": [ { - "name": "Permission for deploying" + "name": "EntitlementManagement.Read.All" + }, + { + "name": "EntitlementManagement.ReadWrite.All" + }, + { + "name" : "RoleManagement.ReadWrite.Directory" } ] } From 4082e059ddef10218de766702b52cad4fb57535a Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 26 Sep 2024 10:54:53 +0000 Subject: [PATCH 306/465] Updated {Create} AAD Integration Tests --- .../M365DSCIntegration.AAD.Create.Tests.ps1 | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 index 8ac23a0c7f..acc46c6e4b 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 @@ -330,21 +330,6 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } -<<<<<<< HEAD - AADFeatureRolloutPolicy 'AADFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy' - { - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - Description = "CertificateBasedAuthentication rollout policy"; - DisplayName = "CertificateBasedAuthentication rollout policy"; - Ensure = "Present"; - Feature = "certificateBasedAuthentication"; - IsAppliedToOrganization = $False; - IsEnabled = $True; - } -======= ->>>>>>> f0d323d952f1aa607da4a72a3f0781f33af9b90c AADRoleDefinition 'AADRoleDefinition1' { DisplayName = "DSCRole1" From f11b86f1fca5514c24c6eb61a44b46227798b365 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 26 Sep 2024 10:56:25 +0000 Subject: [PATCH 307/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 75 ------------------- 1 file changed, 75 deletions(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 8290733ffa..1fe3a4e303 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -4074,81 +4074,6 @@ } ] }, - { - "ClassName": "MSFT_AADFeatureRolloutPolicy", - "Parameters": [ - { - "CIMType": "String", - "Name": "Description", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "DisplayName", - "Option": "Required" - }, - { - "CIMType": "String", - "Name": "Feature", - "Option": "Write" - }, - { - "CIMType": "Boolean", - "Name": "IsAppliedToOrganization", - "Option": "Write" - }, - { - "CIMType": "Boolean", - "Name": "IsEnabled", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "Id", - "Option": "Key" - }, - { - "CIMType": "string", - "Name": "Ensure", - "Option": "Write" - }, - { - "CIMType": "MSFT_Credential", - "Name": "Credential", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "ApplicationId", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "TenantId", - "Option": "Write" - }, - { - "CIMType": "MSFT_Credential", - "Name": "ApplicationSecret", - "Option": "Write" - }, - { - "CIMType": "String", - "Name": "CertificateThumbprint", - "Option": "Write" - }, - { - "CIMType": "Boolean", - "Name": "ManagedIdentity", - "Option": "Write" - }, - { - "CIMType": "String[]", - "Name": "AccessTokens", - "Option": "Write" - } - ] - }, { "ClassName": "MSFT_AADRoleDefinition", "Parameters": [ From 39922148a0f0de18aea7a76e73ab7ac3de037c5e Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Thu, 26 Sep 2024 16:31:34 +0530 Subject: [PATCH 308/465] Added changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bf8282a0c..26326b485e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* AADFeatureRolloutPolicy + * Initial release * AADPasswordRuleSettings * Initial release * ADOOrganizationOwner From 8cf25113257ad09bfa796f75439cf73ad058abf0 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 26 Sep 2024 11:10:52 +0000 Subject: [PATCH 309/465] Updated Resources and Cmdlet documentation pages --- .../AADEntitlementManagementSettings.md | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 docs/docs/resources/azure-ad/AADEntitlementManagementSettings.md diff --git a/docs/docs/resources/azure-ad/AADEntitlementManagementSettings.md b/docs/docs/resources/azure-ad/AADEntitlementManagementSettings.md new file mode 100644 index 0000000000..059fa3d81c --- /dev/null +++ b/docs/docs/resources/azure-ad/AADEntitlementManagementSettings.md @@ -0,0 +1,86 @@ +# AADEntitlementManagementSettings + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **IsSingleInstance** | Key | String | Only accepted value is 'Yes'. | `Yes` | +| **DaysUntilExternalUserDeletedAfterBlocked** | Write | UInt32 | If externalUserLifecycleAction is blockSignInAndDelete, the duration, typically many days, after an external user is blocked from sign in before their account is deleted. | | +| **ExternalUserLifecycleAction** | Write | String | Automatic action that the service should take when an external user's last access package assignment is removed. The possible values are: none, blockSignIn, blockSignInAndDelete, unknownFutureValue. | | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Manages Entra Id Entitlement Management settings. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - EntitlementManagement.Read.All + +- **Update** + + - EntitlementManagement.Read.All, EntitlementManagement.ReadWrite.All + +#### Application permissions + +- **Read** + + - EntitlementManagement.Read.All + +- **Update** + + - EntitlementManagement.Read.All, EntitlementManagement.ReadWrite.All, RoleManagement.ReadWrite.Directory + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADEntitlementManagementSettings "AADEntitlementManagementSettings" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + DaysUntilExternalUserDeletedAfterBlocked = 30; + ExternalUserLifecycleAction = "blockSignInAndDelete"; + IsSingleInstance = "Yes"; + TenantId = $TenantId; + } + } +} +``` + From 9e5c36d12f0c05c7b21dc8dc4680b24ad916cea2 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 26 Sep 2024 11:11:08 +0000 Subject: [PATCH 310/465] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Update.Tests.ps1 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index 2567b8af3a..f7b70c49f1 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -646,6 +646,15 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + AADEntitlementManagementSettings 'AADEntitlementManagementSettings' + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + DaysUntilExternalUserDeletedAfterBlocked = 30; + ExternalUserLifecycleAction = "blockSignInAndDelete"; + IsSingleInstance = "Yes"; + TenantId = $TenantId; + } AADExternalIdentityPolicy 'AADExternalIdentityPolicy' { AllowDeletedIdentitiesDataRemoval = $False; From 697432c245deaad07a156b50ada5b635ec6aae42 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 26 Sep 2024 11:12:23 +0000 Subject: [PATCH 311/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index cafe85b791..3d43328188 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -3414,6 +3414,56 @@ } ] }, + { + "ClassName": "MSFT_AADEntitlementManagementSettings", + "Parameters": [ + { + "CIMType": "String", + "Name": "IsSingleInstance", + "Option": "Key" + }, + { + "CIMType": "UInt32", + "Name": "DaysUntilExternalUserDeletedAfterBlocked", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ExternalUserLifecycleAction", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AADExternalIdentityPolicy", "Parameters": [ From a4187962e2f0605b9f30e5820561b0d7c4e7e6a9 Mon Sep 17 00:00:00 2001 From: ritikmit <88980817+ritikmit@users.noreply.github.com> Date: Thu, 26 Sep 2024 16:46:14 +0530 Subject: [PATCH 312/465] Update CHANGELOG.md --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ab7618eb4..a172f991d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,6 @@ # UNRELEASED * AADFeatureRolloutPolicy * Initial release -* MdcSubscriptionDefenderPlan - * Initial release * AADEntitlementManagementSettings * Initial release. * AADPasswordRuleSettings From 9c5ab76c12b24481120ad13730ac68aaca41ad63 Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Thu, 26 Sep 2024 16:51:02 +0530 Subject: [PATCH 313/465] Fixed example --- .../Examples/Resources/AADFeatureRolloutPolicy/1-Create.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/1-Create.ps1 index 7d729800c4..eeeb5dd866 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/1-Create.ps1 @@ -33,6 +33,7 @@ Configuration Example Feature = "certificateBasedAuthentication"; IsAppliedToOrganization = $False; IsEnabled = $True; + Id = "e6f15f6f-1ebe-4007-aa6c-0590844080d2"; } } } From 7461bbeaa631b1358b0b7035f12774c995014a3b Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 26 Sep 2024 11:22:16 +0000 Subject: [PATCH 314/465] Updated {Create} AAD Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 index acc46c6e4b..7919be2555 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 @@ -301,6 +301,7 @@ Feature = "certificateBasedAuthentication"; IsAppliedToOrganization = $False; IsEnabled = $True; + Id = "e6f15f6f-1ebe-4007-aa6c-0590844080d2"; } AADGroup 'MyGroups' { From 292146d0cec4410d743b25b459b3784a543de23b Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Thu, 26 Sep 2024 17:08:38 +0530 Subject: [PATCH 315/465] Added Change Logs --- CHANGELOG.md | 6 +++ .../MSFT_AADApplication.psm1 | 45 +------------------ 2 files changed, 7 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1f55085e4..8987633b1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Change log for Microsoft365DSC # UNRELEASED +* AADApplication + * Added AppRoles + * Added AuthenticationBehavior + * Added KeyCredentials + * Added PaswordCredentials + * Added PreAuthorizationApplications * MdcSubscriptionDefenderPlan * Initial release * AADPasswordRuleSettings diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 3dfbe3f422..ebe3fff97c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -869,50 +869,7 @@ function Set-TargetResource if($needToUpdateKeyCredentials -and $KeyCredentials) { - Write-Verbose -Message "Updating for Azure AD Application {$($currentAADApp.DisplayName)} with KeyCredentials:`r`n$($KeyCredentials| Out-String)" - Write-Verbose -Message "Current App Id: $($currentAADApp.AppId)" - - $CurrentKeyCredentials = (Get-MgApplication -Property "keyCredentials" -ApplicationId $ObjectID -ErrorAction SilentlyContinue).KeyCredentials - - $CurrentKeyCredentialsKeyIds = $CurrentKeyCredentials | ForEach-Object { $_.KeyId } - $DesiredKeyCredentialsKeyIds = $KeyCredentials | ForEach-Object { $_.KeyId } - - $AddKeyCredentials = $KeyCredentials | Where-Object {$_.KeyId -notin $CurrentKeyCredentialsKeyIds}; - $RemoveKeyCredentials = $CurrentKeyCredentials | Where-Object {$_.KeyId -notin $DesiredKeyCredentialsKeyIds}; - - Write-Verbose -Message "Key Credentials to be added:`r`n$($AddKeyCredentials| Out-String)" - Write-Verbose -Message "Key Credentials to be removed:`r`n$($RemoveKeyCredentials| Out-String)" - - foreach ($KeyCredential in $AddKeyCredentials) - { - $IKeyCredential = @{ - DisplayName = $KeyCredential.displayName - EndDateTime = $KeyCredential.endDateTime - KeyId = $KeyCredential.keyId - Key = [System.Text.Encoding]::UTF8.GetBytes($KeyCredential.key) - StartDateTime = $KeyCredential.startDateTime - Type = $KeyCredential.type - Usage = $KeyCredential.usage - } - - $CustomKeyIdentifier = $null - if($KeyCredential.CustomKeyIdentifier -ne $null) - { - $CustomKeyIdentifier = [System.Text.Encoding]::UTF8.GetBytes($KeyCredential.customKeyIdentifier) - $IKeyCredential.Add('CustomKeyIdentifier', $CustomKeyIdentifier) - } - - Write-Verbose -Message "Adding KeyCredentials:`r`n$($KeyCredential| Out-String) to Azure AD Application {$($currentAADApp.DisplayName)} " - Add-MgApplicationKey -ApplicationId $currentAADApp.Id -KeyCredential $IKeyCredentials - } - - - foreach ($KeyCredential in $RemoveKeyCredentials) - { - Write-Verbose -Message "Removing KeyCredentials:`r`n$($KeyCredential| Out-String) to Azure AD Application {$($currentAADApp.DisplayName)} " - Remove-MgApplicationKey -ApplicationId $currentAADApp.Id -KeyId $KeyCredentials.KeyId - } - + Write-Warning -Message "KeyCredentials is a readonly property and cannot be configured." } } From 63c97148a192ab3aff0c118d77e8f5f59fe7134e Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Thu, 26 Sep 2024 17:48:44 +0530 Subject: [PATCH 316/465] Fixed UTs --- .../MSFT_AADApplication.psm1 | 13 +++++++++++-- .../Microsoft365DSC.AADApplication.Tests.ps1 | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index ebe3fff97c..7f98342cac 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -229,14 +229,23 @@ function Get-TargetResource foreach ($currentkeyCredentials in $AADAppKeyCredentials.keyCredentials) { $mykeyCredentials = @{} - $mykeyCredentials.Add('CustomKeyIdentifier', [convert]::ToBase64String($currentkeyCredentials.customKeyIdentifier)) + if($null -ne $currentkeyCredentials.customKeyIdentifier) + { + $mykeyCredentials.Add('CustomKeyIdentifier', [convert]::ToBase64String($currentkeyCredentials.customKeyIdentifier)) + } $mykeyCredentials.Add('DisplayName', $currentkeyCredentials.displayName) if ($null -ne $currentkeyCredentials.endDateTime) { $mykeyCredentials.Add('EndDateTime', ([DateTimeOffset]$currentkeyCredentials.endDateTime).ToString('o')) } $mykeyCredentials.Add('KeyId', $currentkeyCredentials.keyId) - $mykeyCredentials.Add('Key', [convert]::ToBase64String($currentkeyCredentials.key)) + + + if($null -ne $currentkeyCredentials.Key) + { + $mykeyCredentials.Add('Key', [convert]::ToBase64String($currentkeyCredentials.key)) + } + if ($null -ne $currentkeyCredentials.startDateTime) { $mykeyCredentials.Add('StartDateTime', ([DateTimeOffset]$currentkeyCredentials.startDateTime).ToString('o')) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 index f55ba61877..eafea2820d 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 @@ -202,6 +202,16 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { StartDateTime = '2024-09-16T19:50:29.0310000+00:00' } -ClientOnly ) + KeyCredentials = @( + New-CimInstance -ClassName MSFT_MicrosoftGraphkeyCredential -Property @{ + Usage = 'Verify' + StartDateTime = '2024-09-25T09:13:11.0000000+00:00' + Type = 'AsymmetricX509Cert' + KeyId = 'Key ID' + EndDateTime = '2025-09-25T09:33:11.0000000+00:00' + DisplayName = 'anexas_test_2' + } -ClientOnly + ) AuthenticationBehaviors = New-CimInstance -ClassName MSFT_MicrosoftGraphAuthenticationBehaviors -Property @{ blockAzureADGraphAccess = $false removeUnverifiedEmailClaim = $true @@ -264,6 +274,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { DisplayName = 'Writers' } ) + $AADApp | Add-Member -MemberType NoteProperty -Name KeyCredentials -Value @{ + Usage = 'Verify' + StartDateTime = '2024-09-25T09:13:11.0000000+00:00' + Type = 'AsymmetricX509Cert' + KeyId = 'Key ID' + EndDateTime = '2025-09-25T09:33:11.0000000+00:00' + DisplayName = 'anexas_test_2' + } $AADApp | Add-Member -MemberType NoteProperty -Name PasswordCredentials -Value @{ KeyId = 'keyid' EndDateTime = '2025-03-15T19:50:29.0310000+00:00' From ff162dc03cf8c52bfa2ea913b65270dfb9b103ae Mon Sep 17 00:00:00 2001 From: Dan Lag Date: Thu, 26 Sep 2024 08:51:02 -0400 Subject: [PATCH 317/465] Add support for IsMemberManagementRestricted parameter --- CHANGELOG.md | 2 + .../MSFT_AADAdministrativeUnit.psm1 | 58 ++++++++++++------- .../MSFT_AADAdministrativeUnit.schema.mof | 1 + .../AADAdministrativeUnit/1-Create.ps1 | 1 + .../AADAdministrativeUnit/2-Update.ps1 | 1 + 5 files changed, 41 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bf8282a0c..61fbbe867f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* AADAdministrativeUnit + * Added support for property IsMemberManagementRestricted. * AADPasswordRuleSettings * Initial release * ADOOrganizationOwner diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdministrativeUnit/MSFT_AADAdministrativeUnit.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdministrativeUnit/MSFT_AADAdministrativeUnit.psm1 index 3440d0cdc3..79a22b7d46 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdministrativeUnit/MSFT_AADAdministrativeUnit.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdministrativeUnit/MSFT_AADAdministrativeUnit.psm1 @@ -22,6 +22,10 @@ function Get-TargetResource [System.String] $Visibility, + [Parameter()] + [System.Boolean] + $IsMemberManagementRestricted, + [Parameter()] [validateset('Assigned', 'Dynamic')] [System.String] @@ -143,18 +147,19 @@ function Get-TargetResource Write-Verbose -Message "An Azure AD Administrative Unit with Id {$Id} and DisplayName {$DisplayName} was found." $results = @{ #region resource generator code - Description = $getValue.Description - DisplayName = $getValue.DisplayName - Visibility = $getValue.Visibility - Id = $getValue.Id - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - ApplicationSecret = $ApplicationSecret - CertificateThumbprint = $CertificateThumbprint - Managedidentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens + Description = $getValue.Description + DisplayName = $getValue.DisplayName + Visibility = $getValue.Visibility + IsMemberManagementRestricted = $getValue.IsMemberManagementRestricted + Id = $getValue.Id + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + Managedidentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens #endregion } @@ -293,6 +298,10 @@ function Set-TargetResource [System.String] $Visibility, + [Parameter()] + [System.Boolean] + $IsMemberManagementRestricted, + [Parameter()] [validateset('Assigned', 'Dynamic')] [System.String] @@ -352,7 +361,7 @@ function Set-TargetResource try { $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` - -InboundParameters $PSBoundParameters ` + -InboundParameters $PSBoundParameters } catch { @@ -547,11 +556,13 @@ function Set-TargetResource #region resource generator code Write-Verbose -Message "Creating new Administrative Unit with: $(Convert-M365DscHashtableToString -Hashtable $CreateParameters)" - $jsonParams = ConvertTo-Json $CreateParameters + #$jsonParams = ConvertTo-Json $CreateParameters # TODO - Replace by cmdlet call which has an issue in 2.11.1 - $url = $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.ResourceUrl + 'beta/administrativeUnits' - $policy = Invoke-MgGraphRequest -Method POST -Uri $url -Body $jsonParams + #$url = $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.ResourceUrl + 'beta/administrativeUnits' + #$policy = Invoke-MgGraphRequest -Method POST -Uri $url -Body $jsonParams + Write-Verbose "$memberSpecification" + $policy = New-MgBetaDirectoryAdministrativeUnit @CreateParameters if ($MembershipType -ne 'Dynamic') { @@ -599,12 +610,11 @@ function Set-TargetResource $UpdateParameters.Remove('ScopedRoleMembers') | Out-Null #region resource generator code - $jsonParams = ConvertTo-Json $UpdateParameters - $url = $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.ResourceUrl + "beta/administrativeUnits/$($currentInstance.Id)" - Invoke-MgGraphRequest -Method PATCH -Uri $url -Body $jsonParams - <#Update-MgBetaDirectoryAdministrativeUnit @UpdateParameters ` - -AdministrativeUnitId $currentInstance.Id #> - + #$jsonParams = ConvertTo-Json $UpdateParameters + #$url = $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.ResourceUrl + "beta/administrativeUnits/$($currentInstance.Id)" + #Invoke-MgGraphRequest -Method PATCH -Uri $url -Body $jsonParams + Update-MgBetaDirectoryAdministrativeUnit @UpdateParameters ` + -AdministrativeUnitId $currentInstance.Id #endregion if ($MembershipType -ne 'Dynamic') @@ -818,6 +828,10 @@ function Test-TargetResource [System.String] $Visibility, + [Parameter()] + [System.Boolean] + $IsMemberManagementRestricted, + [Parameter()] [validateset('Assigned', 'Dynamic')] [System.String] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdministrativeUnit/MSFT_AADAdministrativeUnit.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdministrativeUnit/MSFT_AADAdministrativeUnit.schema.mof index 53939212e8..3b580b2a20 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdministrativeUnit/MSFT_AADAdministrativeUnit.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdministrativeUnit/MSFT_AADAdministrativeUnit.schema.mof @@ -18,6 +18,7 @@ class MSFT_AADAdministrativeUnit : OMI_BaseResource [Write, Description("Object-Id of the Administrative Unit")] String Id; [Write, Description("Description of the Administrative Unit")] String Description; [Write, Description("Visibility of the Administrative Unit. Specify HiddenMembership if members of the AU are hidden")] String Visibility; + [Write, Description("Indicates whether the management rights on resources in the administrative units should be restricted to ONLY the administrators scoped on the administrative unit object.")] Boolean IsMemberManagementRestricted; [Write, Description("Specify membership type. Possible values are Assigned and Dynamic. Note that the functionality is currently in preview.")] String MembershipType; [Write, Description("Specify membership rule. Requires that MembershipType is set to Dynamic. Note that the functionality is currently in preview.")] String MembershipRule; [Write, Description("Specify dynamic membership-rule processing-state. Valid values are 'On' and 'Paused'. Requires that MembershipType is set to Dynamic. Note that the functionality is currently in preview.")] String MembershipRuleProcessingState; diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADAdministrativeUnit/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADAdministrativeUnit/1-Create.ps1 index a9e23649f8..f44ba9bed4 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADAdministrativeUnit/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADAdministrativeUnit/1-Create.ps1 @@ -29,6 +29,7 @@ Configuration Example MembershipRule = "(user.country -eq `"Canada`")" MembershipRuleProcessingState = 'On' MembershipType = 'Dynamic' + IsMemberManagementRestricted = $False; ScopedRoleMembers = @( MSFT_MicrosoftGraphScopedRoleMembership { diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADAdministrativeUnit/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADAdministrativeUnit/2-Update.ps1 index f6e5d23508..6d08a2ef5c 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADAdministrativeUnit/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADAdministrativeUnit/2-Update.ps1 @@ -30,6 +30,7 @@ Configuration Example MembershipRule = "(user.country -eq `"US`")" # Updated Property MembershipRuleProcessingState = 'On' MembershipType = 'Dynamic' + IsMemberManagementRestricted = $False ScopedRoleMembers = @( MSFT_MicrosoftGraphScopedRoleMembership { From eda8616c9ae553f8754e342572c4235c7ffc5fae Mon Sep 17 00:00:00 2001 From: Dan Lag Date: Thu, 26 Sep 2024 08:53:35 -0400 Subject: [PATCH 318/465] Add support for IsMemberManagementRestricted parameter --- .../MSFT_AADAdministrativeUnit.psm1 | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdministrativeUnit/MSFT_AADAdministrativeUnit.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdministrativeUnit/MSFT_AADAdministrativeUnit.psm1 index 79a22b7d46..0685ca72c5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdministrativeUnit/MSFT_AADAdministrativeUnit.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAdministrativeUnit/MSFT_AADAdministrativeUnit.psm1 @@ -556,12 +556,6 @@ function Set-TargetResource #region resource generator code Write-Verbose -Message "Creating new Administrative Unit with: $(Convert-M365DscHashtableToString -Hashtable $CreateParameters)" - #$jsonParams = ConvertTo-Json $CreateParameters - - # TODO - Replace by cmdlet call which has an issue in 2.11.1 - #$url = $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.ResourceUrl + 'beta/administrativeUnits' - #$policy = Invoke-MgGraphRequest -Method POST -Uri $url -Body $jsonParams - Write-Verbose "$memberSpecification" $policy = New-MgBetaDirectoryAdministrativeUnit @CreateParameters if ($MembershipType -ne 'Dynamic') @@ -610,9 +604,6 @@ function Set-TargetResource $UpdateParameters.Remove('ScopedRoleMembers') | Out-Null #region resource generator code - #$jsonParams = ConvertTo-Json $UpdateParameters - #$url = $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.ResourceUrl + "beta/administrativeUnits/$($currentInstance.Id)" - #Invoke-MgGraphRequest -Method PATCH -Uri $url -Body $jsonParams Update-MgBetaDirectoryAdministrativeUnit @UpdateParameters ` -AdministrativeUnitId $currentInstance.Id #endregion From 526e1c492e3d6a2ede0d67a8a96a2fc529be32e8 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Thu, 26 Sep 2024 18:58:23 +0530 Subject: [PATCH 319/465] minor --- .../MSFT_EXOMailboxFolderPermission.psm1 | 17 +++-- .../settings.json | 14 +++- .../EXOMailboxFolderPermission/1-Create.ps1 | 47 ++++++++++++ .../EXOMailboxFolderPermission/2-Update.ps1 | 45 ++++++++++++ .../Resources/ResourceName/1-Create.ps1 | 26 ------- .../Resources/ResourceName/2-Update.ps1 | 26 ------- .../Resources/ResourceName/3-Remove.ps1 | 26 ------- ...65DSC.EXOMailboxFolderPermission.Tests.ps1 | 71 ++++++++++++++----- 8 files changed, 169 insertions(+), 103 deletions(-) create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/2-Update.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 index 6e81cac535..419d5aea79 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 @@ -185,6 +185,17 @@ function Set-TargetResource $currentInstance = Get-TargetResource @PSBoundParameters $currentMailboxFolderPermissions = $currentInstance.UserPermissions + if ($Ensure -eq 'Present' -and $currentValues.Ensure -eq 'Absent') + { + Write-Verbose -Message "There was some error in fetching the mailbox folder permissions for the folder {$Identity}." + return + } + elseif ($Ensure -eq 'Absent') + { + Write-Verbose -Message "Supplying Ensure = 'Absent' doesn't remove the permissions for the current mailbox folder. Send an array of required permissions instead." + return + } + # Remove all the current existing pemrissions on this folder. # Skip removing the default and anonymous permissions, as can't be removed, and should just be directly updated. foreach($currentUserPermission in $currentMailboxFolderPermissions) { @@ -193,6 +204,8 @@ function Set-TargetResource } } + # Add the desired state permissions on the mailbox folder + # For Default and anonymous users, as the permissions were not removed, we just need to call set. foreach($userPermission in $UserPermissions) { if($userPermission.User.ToString().ToLower() -eq "default" -or $userPermission.User.ToString().ToLower() -eq "anonymous"){ if ($userPermission.SharingPermissionFlags -eq ""){ @@ -305,10 +318,6 @@ function Test-TargetResource Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" - $ValuesToCheck.Remove('ObjectId') | Out-Null - $ValuesToCheck.Remove('AppId') | Out-Null - $ValuesToCheck.Remove('Permissions') | Out-Null - $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` -DesiredValues $PSBoundParameters ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/settings.json index 585ca11f72..874090d3bc 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/settings.json @@ -3,10 +3,10 @@ "description": "Use this resource to add/set/remove mailbox folder permissions for users in your tenant.", "roles": { "read": [ - "Role" + "Global Reader" ], "update": [ - "Role" + "Exchange Administrator" ] }, "permissions": { @@ -19,6 +19,16 @@ "read": [], "update": [] } + }, + "exchange": { + "requiredroles": [ + "Organization Management", + "Recipient Management" + ], + "requiredrolegroups": [ + "Organization Management", + "Help Desk" + ] } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/1-Create.ps1 new file mode 100644 index 0000000000..a2ae2e2fdc --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/1-Create.ps1 @@ -0,0 +1,47 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + EXOMailboxFolderPermission "EXOMailboxFolderPermission-admin:\Calendar" + { + Credential = $Credscredential; + Ensure = "Present"; + Identity = "amdin:\Calendar"; + UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { + User = 'Default' + AccessRights = 'AvailabilityOnly' + } + MSFT_EXOMailboxFolderUserPermission { + User = 'Anonymous' + AccessRights = 'AvailabilityOnly' + } + MSFT_EXOMailboxFolderUserPermission { + User = 'AlexW' + AccessRights = 'Owner' + SharingSharingPermissionFlags = 'Delegate' + } + ); + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/2-Update.ps1 new file mode 100644 index 0000000000..fc78d04bd0 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/2-Update.ps1 @@ -0,0 +1,45 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOMailboxFolderPermission "EXOMailboxFolderPermission-admin:\Calendar" + { + Credential = $Credscredential; + Ensure = "Present"; + Identity = "admin:\Calendar"; + UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { + User = 'Default' + AccessRights = 'AvailabilityOnly' + } +MSFT_EXOMailboxFolderUserPermission { + User = 'Anonymous' + AccessRights = 'AvailabilityOnly' + } +MSFT_EXOMailboxFolderUserPermission { + User = 'AlexW' + AccessRights = 'Editor' + SharingPermissionFlags = 'Delegate' + } + ); + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 deleted file mode 100644 index b516274848..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/1-Create.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -<# -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()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 deleted file mode 100644 index b516274848..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/2-Update.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -<# -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()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 deleted file mode 100644 index b516274848..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/ResourceName/3-Remove.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -<# -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()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - - } -} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxFolderPermission.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxFolderPermission.Tests.ps1 index 8b29aab035..46efb1d157 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxFolderPermission.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxFolderPermission.Tests.ps1 @@ -72,7 +72,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return $null + ##TODO - Mock the Get-MailboxFolderPermission to return $null Mock -CommandName Get-MailboxFolderPermission -MockWith { return $null } @@ -105,7 +105,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance + ##TODO - Mock the Get-MailboxFolderPermission to return an instance Mock -CommandName Get-MailboxFolderPermission -MockWith { return @( @{ @@ -132,16 +132,27 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters + Identity = 'FakeStringValue1' + UserPermissions = @( + (New-CimInstance -ClassName MSFT_EXOMailboxFolderUserPermission -Property @{ + User = 'User' + AccessRights = @('Editor') + SharingPermissionFlags = 'Delegate' + } -ClientOnly) + ) Ensure = 'Present' Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - - } + ##TODO - Mock the Get-MailboxFolderPermission to return the desired values + Mock -CommandName Get-MailboxFolderPermission -MockWith { + return @( + @{ + User = 'User' + AccessRights = @('Editor') + SharingPermissionFlags = 'Delegate' + } + ) } } @@ -153,16 +164,27 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters + Identity = 'FakeStringValue1' + UserPermissions = @( + (New-CimInstance -ClassName MSFT_EXOMailboxFolderUserPermission -Property @{ + User = 'User' + AccessRights = @('Editor') + SharingPermissionFlags = 'Delegate' + } -ClientOnly) + ) Ensure = 'Present' Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - - } + ##TODO - Mock the Get-MailboxFolderPermission to return a drift + Mock -CommandName Get-MailboxFolderPermission -MockWith { + return @( + @{ + User = 'User' + AccessRights = @('Owner') + SharingPermissionFlags = 'Delegate' + } + ) } } @@ -176,8 +198,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the Set method' { Set-TargetResource @testParams - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + Should -Invoke -CommandName Remove-MailboxFolderPermission -Exactly 1 + Should -Invoke -CommandName Add-MailboxFolderPermission -Exactly 1 } } @@ -189,11 +211,22 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { - return @{ + ##TODO - Mock the Get-MailboxFolderPermission to return an instance + Mock -CommandName Get-MailboxFolderPermission -MockWith { + return @( + @{ + User = 'User' + AccessRights = @('Editor') + SharingPermissionFlags = 'Delegate' + } + ) + } + Mock -CommandName Get-MailboxFolder -MockWith { + return @{ + Identity = "admin:/Calendar" } + } } It 'Should Reverse Engineer resource from the Export method' { From ec1e651e972ba2b844947bcdeae212dae36a8863 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Thu, 26 Sep 2024 19:01:23 +0530 Subject: [PATCH 320/465] minor --- CHANGELOG.md | 2 ++ .../Microsoft365DSC.EXOMailboxFolderPermission.Tests.ps1 | 7 +------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5edfcd2dd..f4351d8fde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ * Initial Release. * EXOMailboxCalendarConfiguration * Initial Release. +* EXOMailboxFolderPermission + * Initial Release. * EXOMailboxIRMAccess * Initial Release. * EXOManagementScope diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxFolderPermission.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxFolderPermission.Tests.ps1 index 46efb1d157..dfced05ad1 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxFolderPermission.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMailboxFolderPermission.Tests.ps1 @@ -72,7 +72,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-MailboxFolderPermission to return $null Mock -CommandName Get-MailboxFolderPermission -MockWith { return $null } @@ -105,7 +104,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-MailboxFolderPermission to return an instance Mock -CommandName Get-MailboxFolderPermission -MockWith { return @( @{ @@ -125,7 +123,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should remove the instance from the Set method' { Set-TargetResource @testParams - Should -Invoke -CommandName Remove-MailboxFolderPermission -Exactly 1 + Should -Invoke -CommandName Remove-MailboxFolderPermission -Exactly 0 } } @@ -144,7 +142,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-MailboxFolderPermission to return the desired values Mock -CommandName Get-MailboxFolderPermission -MockWith { return @( @{ @@ -176,7 +173,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-MailboxFolderPermission to return a drift Mock -CommandName Get-MailboxFolderPermission -MockWith { return @( @{ @@ -211,7 +207,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-MailboxFolderPermission to return an instance Mock -CommandName Get-MailboxFolderPermission -MockWith { return @( @{ From c5ed91d687168b9e89b1ae997fe78bca74c76d4b Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Thu, 26 Sep 2024 19:04:23 +0530 Subject: [PATCH 321/465] minor --- Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 7095113564..3882742237 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -240,7 +240,6 @@ function Convert-M365DscCIMInstanceToString $str = '{' foreach ($prop in $CIMInstance.CimInstanceProperties) { - Write-Host $prop.Name if ($str -notmatch '{$') { $str += '; ' From 1598e0486f0c572584d5e6098e3a7d0931dda1d9 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Thu, 26 Sep 2024 12:44:33 -0700 Subject: [PATCH 322/465] Microsoft365 DSC for Intune App categories. - Added the skeleton files. --- .../MSFT_IntuneAppCategories.psm1 | 366 ++++++++++++++++++ .../MSFT_IntuneAppCategories.schema.mof | 14 + .../MSFT_IntuneAppCategories/readme.md | 6 + .../MSFT_IntuneAppCategories/settings.json | 32 ++ .../Resources/IntuneAppCategory/1-Create.ps1 | 26 ++ .../Resources/IntuneAppCategory/2-Update.ps1 | 26 ++ .../Resources/IntuneAppCategory/3-Remove.ps1 | 26 ++ ...icrosoft365DSC.IntuneAppCategory.Tests.ps1 | 177 +++++++++ 8 files changed, 673 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 new file mode 100644 index 0000000000..0990631700 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 @@ -0,0 +1,366 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace the workload by the one associated to your resource + New-M365DSCConnection -Workload 'Workload' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + ##TODO - Replace the PrimaryKey in the Filter by the one for the resource + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.PrimaryKey -eq $PrimaryKey} + } + else + { + ##TODO - Replace the cmdlet by the one to retrieve a specific instance. + $instance = Get-cmdlet -PrimaryKey $PrimaryKey -ErrorAction Stop + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + ##TODO - Add the list of parameters to be returned + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + ##TODO - Replace by the New cmdlet for the resource + New-Cmdlet @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Update/Set cmdlet for the resource + Set-cmdlet @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Remove cmdlet for the resource + Remove-cmdlet @SetParameters + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + ##TODO - Replace the PrimaryKey + [Parameter(Mandatory = $true)] + [System.String] + $PrimaryKey, + + ##TODO - Add the list of Parameters + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + ##TODO - Replace workload + $ConnectionMode = New-M365DSCConnection -Workload 'Workload' ` + -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 + { + $Script:ExportMode = $true + ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances + [array] $Script:exportedInstances = Get-Cmdlet -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + ##TODO - Specify the Primary Key + #PrimaryKey = $config.PrimaryKey + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof new file mode 100644 index 0000000000..be6b06c877 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof @@ -0,0 +1,14 @@ +[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] +class MSFT_ResourceName : OMI_BaseResource +{ + [Key, Description("")] String PrimaryKey; + [Write, Description("")] String OtherProperties; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] 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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/readme.md new file mode 100644 index 0000000000..32e0e7fb27 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/readme.md @@ -0,0 +1,6 @@ + +# ResourceName + +## Description + +##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/settings.json new file mode 100644 index 0000000000..edf14b05e4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "ResourceName", + "description": "Description of what the resource is about.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 new file mode 100644 index 0000000000..f3ddc7d594 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 @@ -0,0 +1,177 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -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 a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Set-TargetResource @testParams + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 remove the instance from the Set method' { + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + 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 + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 7657dc4b4ac0355016d32e49104244e66f276b55 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 26 Sep 2024 16:00:46 -0400 Subject: [PATCH 323/465] AADGroup - Various Fixes --- CHANGELOG.md | 5 + .../MSFT_AADGroup/MSFT_AADGroup.psm1 | 133 +++++++++++++----- .../Dependencies/Manifest.psd1 | 4 + 3 files changed, 103 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5edfcd2dd..19384eeb54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ * AADEntitlementManagementSettings * Initial release. +* AADGroup + * Fixes logic to evaluate license assignments and disabled plans. + FIXES [#5101](https://github.com/microsoft/Microsoft365DSC/issues/5101) + * Adds support to assign Service Principal as members or owners. + FIXES [#4972](https://github.com/microsoft/Microsoft365DSC/issues/4972) * AADPasswordRuleSettings * Initial release * ADOOrganizationOwner diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 index 0a74f43a58..b5540084ee 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 @@ -201,7 +201,7 @@ function Get-TargetResource Write-Verbose -Message 'Found existing AzureAD Group' # Owners - [Array]$owners = Get-MgGroupOwner -GroupId $Group.Id -All:$true + [Array]$owners = Get-MgBetaGroupOwner -GroupId $Group.Id -All:$true $OwnersValues = @() foreach ($owner in $owners) { @@ -209,13 +209,17 @@ function Get-TargetResource { $OwnersValues += $owner.AdditionalProperties.userPrincipalName } + elseif($owner.AdditionalProperties.'@odata.type' -eq "#microsoft.graph.servicePrincipal") + { + $OwnersValues += $owner.AdditionalProperties.displayName + } } $MembersValues = $null if ($Group.MembershipRuleProcessingState -ne 'On') { # Members - [Array]$members = Get-MgGroupMember -GroupId $Group.Id -All:$true + [Array]$members = Get-MgBetaGroupMember -GroupId $Group.Id -All:$true $MembersValues = @() $GroupAsMembersValues = @() foreach ($member in $members) @@ -224,6 +228,10 @@ function Get-TargetResource { $MembersValues += $member.AdditionalProperties.userPrincipalName } + elseif ($member.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.servicePrincipal') + { + $MembersValues += $member.AdditionalProperties.displayName + } elseif($member.AdditionalProperties.'@odata.type' -eq "#microsoft.graph.group") { $GroupAsMembersValues += $member.AdditionalProperties.displayName @@ -232,7 +240,7 @@ function Get-TargetResource } # MemberOf - [Array]$memberOf = Get-MgGroupMemberOf -GroupId $Group.Id -All # result also used for/by AssignedToRole + [Array]$memberOf = Get-MgBetaGroupMemberOf -GroupId $Group.Id -All # result also used for/by AssignedToRole $MemberOfValues = @() # Note: only process security-groups that this group is a member of and not directory roles (if any) foreach ($member in ($memberOf | Where-Object -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.group' })) @@ -616,6 +624,7 @@ function Set-TargetResource { try { + Write-Verbose -Message "Setting Group Licenses" Set-MgGroupLicense -GroupId $currentGroup.Id ` -AddLicenses $licensesToAdd ` -RemoveLicenses $licensesToRemove ` @@ -651,6 +660,7 @@ function Set-TargetResource if ($Ensure -ne 'Absent') { #Owners + Write-Verbose -Message "Updating Owners" if ($PSBoundParameters.ContainsKey('Owners')) { $currentOwnersValue = @() @@ -670,13 +680,21 @@ function Set-TargetResource $ownersDiff = Compare-Object -ReferenceObject $backCurrentOwners -DifferenceObject $desiredOwnersValue foreach ($diff in $ownersDiff) { - $user = Get-MgUser -UserId $diff.InputObject - + $directoryObject = Get-MgUser -UserId $diff.InputObject -ErrorAction SilentlyContinue + if ($null -eq $directoryObject) + { + Write-Verbose -Message "Trying to retrieve Service Principal {$($diff.InputObject)}" + $app = Get-MgApplication -Filter "DisplayName eq '$($diff.InputObject)'" + if ($null -ne $app) + { + $directoryObject = Get-MgServicePrincipal -Filter "AppId eq '$($app.AppId)'" + } + } if ($diff.SideIndicator -eq '=>') { Write-Verbose -Message "Adding new owner {$($diff.InputObject)} to AAD Group {$($currentGroup.DisplayName)}" $ownerObject = @{ - '@odata.id' = "https://graph.microsoft.com/v1.0/users/{$($user.Id)}" + '@odata.id' = "https://graph.microsoft.com/v1.0/directoryObjects/{$($directoryObject.Id)}" } try { @@ -700,6 +718,7 @@ function Set-TargetResource } #Members + Write-Verbose -Message "Updating Members" if ($MembershipRuleProcessingState -ne 'On' -and $PSBoundParameters.ContainsKey('Members')) { $currentMembersValue = @() @@ -716,16 +735,28 @@ function Set-TargetResource { $backCurrentMembers = @() } + Write-Verbose -Message "Comparing current members and desired list" $membersDiff = Compare-Object -ReferenceObject $backCurrentMembers -DifferenceObject $desiredMembersValue foreach ($diff in $membersDiff) { - $user = Get-MgUser -UserId $diff.InputObject + Write-Verbose -Message "Found difference for member {$($diff.InputObject)}" + $directoryObject = Get-MgUser -UserId $diff.InputObject -ErrorAction SilentlyContinue + + if ($null -eq $directoryObject) + { + Write-Verbose -Message "Trying to retrieve Service Principal {$($diff.InputObject)}" + $app = Get-MgApplication -Filter "DisplayName eq '$($diff.InputObject)'" + if ($null -ne $app) + { + $directoryObject = Get-MgServicePrincipal -Filter "AppId eq '$($app.AppId)'" + } + } if ($diff.SideIndicator -eq '=>') { Write-Verbose -Message "Adding new member {$($diff.InputObject)} to AAD Group {$($currentGroup.DisplayName)}" $memberObject = @{ - '@odata.id' = "https://graph.microsoft.com/v1.0/users/{$($user.Id)}" + '@odata.id' = "https://graph.microsoft.com/v1.0/directoryObjects/{$($directoryObject.Id)}" } New-MgGroupMemberByRef -GroupId ($currentGroup.Id) -BodyParameter $memberObject | Out-Null } @@ -733,9 +764,9 @@ function Set-TargetResource { Write-Verbose -Message "Removing new member {$($diff.InputObject)} to AAD Group {$($currentGroup.DisplayName)}" $memberObject = @{ - '@odata.id' = "https://graph.microsoft.com/v1.0/users/{$($user.Id)}" + '@odata.id' = "https://graph.microsoft.com/v1.0/directoryObjects/{$($directoryObject.Id)}" } - Remove-MgGroupMemberDirectoryObjectByRef -GroupId ($currentGroup.Id) -DirectoryObjectId ($user.Id) | Out-Null + Remove-MgGroupMemberDirectoryObjectByRef -GroupId ($currentGroup.Id) -DirectoryObjectId ($directoryObject.Id) | Out-Null } } } @@ -745,6 +776,7 @@ function Set-TargetResource } #GroupAsMembers + Write-Verbose -Message "Updating GroupAsMembers" if ($MembershipRuleProcessingState -ne 'On' -and $PSBoundParameters.ContainsKey('GroupAsMembers')) { $currentGroupAsMembersValue = @() @@ -766,7 +798,7 @@ function Set-TargetResource { try { - $groupAsMember = Get-MgGroup -Filter "DisplayName eq '$($diff.InputObject)'" -ErrorAction Stop + $groupAsMember = Get-MgGroup -Filter "DisplayName eq '$($diff.InputObject)'" -ErrorAction SilentlyContinue } catch { @@ -784,18 +816,19 @@ function Set-TargetResource $groupAsMemberObject = @{ "@odata.id"= "https://graph.microsoft.com/v1.0/directoryObjects/$($groupAsMember.Id)" } - New-MgGroupMemberByRef -GroupId ($currentGroup.Id) -Body $groupAsMemberObject | Out-Null + New-MgBetaGroupMemberByRef -GroupId ($currentGroup.Id) -Body $groupAsMemberObject | Out-Null } if ($diff.SideIndicator -eq '<=') { Write-Verbose -Message "Removing AAD Group {$($groupAsMember.DisplayName)} from AAD group {$($currentGroup.DisplayName)}" - Remove-MgGroupMemberDirectoryObjectByRef -GroupId ($currentGroup.Id) -DirectoryObjectId ($groupAsMember.Id) | Out-Null + Remove-MgBetaGroupMemberDirectoryObjectByRef -GroupId ($currentGroup.Id) -DirectoryObjectId ($groupAsMember.Id) | Out-Null } } } } #MemberOf + Write-Verbose -Message "Updating MemberOf" if ($PSBoundParameters.ContainsKey('MemberOf')) { $currentMemberOfValue = @() @@ -1050,55 +1083,77 @@ function Test-TargetResource Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" # Check Licenses - if (-not ($AssignedLicenses -eq $null -and $CurrentValues.AssignedLicenses -eq $null)) + if (-not ($null -eq $AssignedLicenses -and $null -eq $CurrentValues.AssignedLicenses)) { try { - $licensesDiff = Compare-Object -ReferenceObject ($CurrentValues.AssignedLicenses.SkuId) -DifferenceObject ($AssignedLicenses.SkuId) - if ($null -ne $licensesDiff) + if ($null -ne $CurrentValues.AssignedLicenses -and $CurrentValues.AssignedLicenses.Length -gt 0 -and ` + $null -eq $AssignedLicenses) { - Write-Verbose -Message "AssignedLicenses differ: $($licensesDiff | Out-String)" + Write-Verbose -Message "The group currently has licenses assigned but it shouldn't" Write-Verbose -Message "Test-TargetResource returned $false" - $EventMessage = "Assigned Licenses for Azure AD Group {$DisplayName} were not in the desired state.`r`n" + ` - "They should contain {$($AssignedLicenses.SkuId)} but instead contained {$($CurrentValues.AssignedLicenses.SkuId)}" + $EventMessage = "Assigned Licenses for Azure AD Group {$DisplayName} were not in the desired state.`r`nThe group should not have any licenses assigned but instead contained {$($CurrentValues.AssignedLicenses.SkuId)}" Add-M365DSCEvent -Message $EventMessage -EntryType 'Warning' ` -EventID 1 -Source $($MyInvocation.MyCommand.Source) return $false } - else - { - Write-Verbose -Message 'AssignedLicenses for Azure AD Group are the same' - } - } - catch - { - Write-Verbose -Message "Test-TargetResource returned $false" - return $false - } - - #Check DisabledPlans - try - { - $licensesDiff = Compare-Object -ReferenceObject ($CurrentValues.AssignedLicenses.DisabledPlans) -DifferenceObject ($AssignedLicenses.DisabledPlans) - if ($null -ne $licensesDiff) + elseif ($null -eq $CurrentValues.AssignedLicenses -and $null -ne $AssignedLicenses -and ` + $AssignedLicenses.Length -gt 0) { - Write-Verbose -Message "DisabledPlans differ: $($licensesDiff | Out-String)" + Write-Verbose -Message "The group currently doesn't have licenses assigned but it should" Write-Verbose -Message "Test-TargetResource returned $false" - $EventMessage = "Disabled Plans for Azure AD Group Licenses {$DisplayName} were not in the desired state.`r`n" + ` - "They should contain {$($AssignedLicenses.DisabledPlans)} but instead contained {$($CurrentValues.AssignedLicenses.DisabledPlans)}" + $EventMessage = "Assigned Licenses for Azure AD Group {$DisplayName} were not in the desired state.`r`nThe group doesn't not have any licenses assigned but should have {$($CurrentValues.AssignedLicenses.SkuId)}" Add-M365DSCEvent -Message $EventMessage -EntryType 'Warning' ` -EventID 1 -Source $($MyInvocation.MyCommand.Source) return $false } + elseif ($CurrentValues.AssignedLicenses.Length -gt 0 -and $AssignedLicenses.Length -gt 0) + { + Write-Verbose -Message "Current assigned licenses and desired assigned licenses are not null" + $licensesDiff = Compare-Object -ReferenceObject ($CurrentValues.AssignedLicenses.SkuId) -DifferenceObject ($AssignedLicenses.SkuId) + if ($null -ne $licensesDiff) + { + Write-Verbose -Message "AssignedLicenses differ: $($licensesDiff | Out-String)" + Write-Verbose -Message "Test-TargetResource returned $false" + $EventMessage = "Assigned Licenses for Azure AD Group {$DisplayName} were not in the desired state.`r`nThey should contain {$($AssignedLicenses.SkuId)} but instead contained {$($CurrentValues.AssignedLicenses.SkuId)}" + Add-M365DSCEvent -Message $EventMessage -EntryType 'Warning' ` + -EventID 1 -Source $($MyInvocation.MyCommand.Source) + + return $false + } + else + { + Write-Verbose -Message 'AssignedLicenses for Azure AD Group are the same' + } + + # Disabled Plans + $licensesDiff = Compare-Object -ReferenceObject ($CurrentValues.AssignedLicenses.DisabledPlans) -DifferenceObject ($AssignedLicenses.DisabledPlans) + if ($null -ne $licensesDiff) + { + Write-Verbose -Message "DisabledPlans differ: $($licensesDiff | Out-String)" + Write-Verbose -Message "Test-TargetResource returned $false" + $EventMessage = "Disabled Plans for Azure AD Group Licenses {$DisplayName} were not in the desired state.`r`n" + ` + "They should contain {$($AssignedLicenses.DisabledPlans)} but instead contained {$($CurrentValues.AssignedLicenses.DisabledPlans)}" + Add-M365DSCEvent -Message $EventMessage -EntryType 'Warning' ` + -EventID 1 -Source $($MyInvocation.MyCommand.Source) + + return $false + } + else + { + Write-Verbose -Message 'DisabledPlans for Azure AD Group Licensing are the same' + } + } else { - Write-Verbose -Message 'DisabledPlans for Azure AD Group Licensing are the same' + Write-Verbose -Message "Both the current and desired assigned licenses lists are empty." } } catch { + Write-Verbose -Message "Error evaluating the AssignedLicenses: $_" Write-Verbose -Message "Test-TargetResource returned $false" return $false } diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 85952adab5..4e685deb6e 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -76,6 +76,10 @@ ModuleName = 'Microsoft.Graph.Groups' RequiredVersion = '2.23.0' }, + @{ + ModuleName = 'Microsoft.Graph.Beta.Groups' + RequiredVersion = '2.23.0' + }, @{ ModuleName = 'Microsoft.Graph.Planner' RequiredVersion = '2.23.0' From a74019f8a89b4cb190b12c195366e5b555ce11d9 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 26 Sep 2024 16:36:47 -0400 Subject: [PATCH 324/465] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 4891 ++++++++++++++++++++++++++++ 1 file changed, 4891 insertions(+) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 37993f422c..58cacebfea 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -38327,6 +38327,4897 @@ function Get-MgDirectoryObject ) } #endregion +#region Microsoft.Graph.Beta.Identity.Governance +function Get-MgBetaAgreement +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.String] + $AgreementId, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaEntitlementManagementAccessPackage +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.String] + $CatalogId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.String] + $DisplayNameContains, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.String] + $DisplayNameEq, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaEntitlementManagementAccessPackageAssignment +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.String] + $AccessPackageAssignmentId, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaEntitlementManagementAccessPackageAssignmentPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.String] + $AccessPackageAssignmentPolicyId, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.String] + $DisplayNameContains, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.String] + $DisplayNameEq, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaEntitlementManagementAccessPackageCatalog +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.String] + $DisplayNameContains, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String] + $AccessPackageCatalogId, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.String] + $DisplayNameEq, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaEntitlementManagementAccessPackageCatalogAccessPackageResource +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String] + $AccessPackageCatalogId, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaEntitlementManagementAccessPackageCatalogAccessPackageResourceRole +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String] + $AccessPackageCatalogId, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaEntitlementManagementAccessPackageIncompatibleAccessPackage +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaEntitlementManagementAccessPackageIncompatibleGroup +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaEntitlementManagementAccessPackageIncompatibleWith +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $AccessPackageId1, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaEntitlementManagementConnectedOrganization +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.String] + $DisplayNameContains, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.String] + $ConnectedOrganizationId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.String] + $DisplayNameEq, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaEntitlementManagementConnectedOrganizationExternalSponsor +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.String] + $ConnectedOrganizationId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaEntitlementManagementConnectedOrganizationInternalSponsor +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.String] + $ConnectedOrganizationId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaEntitlementManagementSetting +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Get-MgBetaRoleManagementDirectory +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Get-MgBetaRoleManagementDirectoryRoleAssignment +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $UnifiedRoleAssignmentId, + + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaRoleManagementDirectoryRoleDefinition +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [System.String] + $UnifiedRoleDefinitionId, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaRoleManagementDirectoryRoleEligibilitySchedule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String] + $UnifiedRoleEligibilityScheduleId, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaRoleManagementDirectoryRoleEligibilityScheduleRequest +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.String] + $UnifiedRoleEligibilityScheduleRequestId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaRoleManagementEntitlementManagement +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Get-MgBetaRoleManagementEntitlementManagementRoleAssignment +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $UnifiedRoleAssignmentId, + + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Get-MgBetaRoleManagementEntitlementManagementRoleDefinition +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [System.String] + $UnifiedRoleDefinitionId, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaEntitlementManagementAccessPackage +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $UniqueName, + + [Parameter()] + [PSObject] + $AccessPackagesIncompatibleWith, + + [Parameter()] + [System.DateTime] + $CreatedDateTime, + + [Parameter()] + [PSObject] + $IncompatibleGroups, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $AccessPackageCatalog, + + [Parameter()] + [System.String] + $CatalogId, + + [Parameter()] + [System.DateTime] + $ModifiedDateTime, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $AccessPackageAssignmentPolicies, + + [Parameter()] + [System.String] + $CreatedBy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsRoleScopesVisible, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [PSObject] + $IncompatibleAccessPackages, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $AccessPackageResourceRoleScopes, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.String] + $ModifiedBy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsHidden + ) +} +function New-MgBetaEntitlementManagementAccessPackageAssignment +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Justification, + + [Parameter()] + [System.String[]] + $RequiredUserId, + + [Parameter()] + [PSObject] + $Answers, + + [Parameter()] + [PSObject] + $ExistingAssignment, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.PSObject[]] + $RequiredGroupMember, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $StartDate, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String] + $AssignmentPolicyId, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaEntitlementManagementAccessPackageAssignmentPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.DateTime] + $CreatedDateTime, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [PSObject] + $CustomExtensionStageSettings, + + [Parameter()] + [PSObject] + $AccessPackageCatalog, + + [Parameter()] + [PSObject] + $Questions, + + [Parameter()] + [System.DateTime] + $ModifiedDateTime, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [PSObject] + $VerifiableCredentialSettings, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $AccessReviewSettings, + + [Parameter()] + [System.String] + $CreatedBy, + + [Parameter()] + [PSObject] + $RequestorSettings, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $CanExtend, + + [Parameter()] + [PSObject] + $CustomExtensionHandlers, + + [Parameter()] + [System.Int32] + $DurationInDays, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.DateTime] + $ExpirationDateTime, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $RequestApprovalSettings, + + [Parameter()] + [PSObject] + $AccessPackage, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ModifiedBy, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [PSObject] + $AccessPackageNotificationSettings, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaEntitlementManagementAccessPackageCatalog +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsExternallyVisible, + + [Parameter()] + [System.String] + $UniqueName, + + [Parameter()] + [PSObject] + $AccessPackageCustomWorkflowExtensions, + + [Parameter()] + [System.DateTime] + $CreatedDateTime, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.DateTime] + $ModifiedDateTime, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [PSObject] + $AccessPackages, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.String] + $CreatedBy, + + [Parameter()] + [PSObject] + $AccessPackageResourceScopes, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [PSObject] + $AccessPackageResources, + + [Parameter()] + [System.String] + $ModifiedBy, + + [Parameter()] + [PSObject] + $CustomAccessPackageWorkflowExtensions, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.String] + $CatalogStatus, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [PSObject] + $AccessPackageResourceRoles, + + [Parameter()] + [System.String] + $CatalogType, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaEntitlementManagementAccessPackageIncompatibleAccessPackageByRef +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String] + $OdataId, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaEntitlementManagementAccessPackageIncompatibleGroupByRef +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String] + $OdataId, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaEntitlementManagementAccessPackageResourceRequest +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Justification, + + [Parameter()] + [PSObject] + $AccessPackageResource, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ExecuteImmediately, + + [Parameter()] + [System.String] + $CatalogId, + + [Parameter()] + [System.String] + $RequestType, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $Requestor, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsValidationOnly, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.DateTime] + $ExpirationDateTime, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $RequestState, + + [Parameter()] + [System.String] + $RequestStatus, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaEntitlementManagementAccessPackageResourceRoleScope +{ + [CmdletBinding()] + param( + [Parameter()] + [System.DateTime] + $CreatedDateTime, + + [Parameter()] + [System.DateTime] + $ModifiedDateTime, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.String] + $CreatedBy, + + [Parameter()] + [PSObject] + $AccessPackageResourceScope, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $AccessPackageResourceRole, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ModifiedBy, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaEntitlementManagementConnectedOrganization +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $ExternalSponsors, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.DateTime] + $CreatedDateTime, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.DateTime] + $ModifiedDateTime, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $IdentitySources, + + [Parameter()] + [System.String] + $State, + + [Parameter()] + [System.String] + $CreatedBy, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $InternalSponsors, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ModifiedBy, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.String] + $DomainName, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaEntitlementManagementConnectedOrganizationExternalSponsorByRef +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String] + $ConnectedOrganizationId, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String] + $OdataId, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaEntitlementManagementConnectedOrganizationInternalSponsorByRef +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String] + $ConnectedOrganizationId, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String] + $OdataId, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaRoleManagementDirectoryRoleAssignment +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $Principal, + + [Parameter()] + [System.String] + $ResourceScope, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $DirectoryScope, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.String] + $PrincipalId, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $Condition, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $RoleDefinitionId, + + [Parameter()] + [PSObject] + $RoleDefinition, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [PSObject] + $AppScope, + + [Parameter()] + [System.String] + $DirectoryScopeId, + + [Parameter()] + [System.String] + $PrincipalOrganizationId, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.String] + $AppScopeId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaRoleManagementDirectoryRoleDefinition +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $ResourceScopes, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsPrivileged, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.String] + $Version, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsBuiltIn, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [PSObject] + $InheritsPermissionsFrom, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $AllowedPrincipalTypes, + + [Parameter()] + [PSObject] + $RolePermissions, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.String] + $TemplateId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsEnabled, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaRoleManagementDirectoryRoleEligibilitySchedule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $MemberType, + + [Parameter()] + [PSObject] + $Principal, + + [Parameter()] + [System.DateTime] + $CreatedDateTime, + + [Parameter()] + [System.String] + $CreatedUsing, + + [Parameter()] + [System.DateTime] + $ModifiedDateTime, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $ScheduleInfo, + + [Parameter()] + [PSObject] + $DirectoryScope, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.String] + $PrincipalId, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Status, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $RoleDefinitionId, + + [Parameter()] + [PSObject] + $RoleDefinition, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [PSObject] + $AppScope, + + [Parameter()] + [System.String] + $DirectoryScopeId, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.String] + $AppScopeId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaRoleManagementDirectoryRoleEligibilityScheduleRequest +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Justification, + + [Parameter()] + [PSObject] + $Principal, + + [Parameter()] + [System.DateTime] + $CreatedDateTime, + + [Parameter()] + [System.String] + $Action, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $ScheduleInfo, + + [Parameter()] + [PSObject] + $DirectoryScope, + + [Parameter()] + [PSObject] + $TargetSchedule, + + [Parameter()] + [System.String] + $ApprovalId, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.String] + $CustomData, + + [Parameter()] + [PSObject] + $CreatedBy, + + [Parameter()] + [System.String] + $PrincipalId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsValidationOnly, + + [Parameter()] + [System.DateTime] + $CompletedDateTime, + + [Parameter()] + [PSObject] + $TicketInfo, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Status, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $TargetScheduleId, + + [Parameter()] + [System.String] + $RoleDefinitionId, + + [Parameter()] + [PSObject] + $RoleDefinition, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [PSObject] + $AppScope, + + [Parameter()] + [System.String] + $DirectoryScopeId, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.String] + $AppScopeId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaRoleManagementEntitlementManagementRoleAssignment +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $Principal, + + [Parameter()] + [System.String] + $ResourceScope, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $DirectoryScope, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.String] + $PrincipalId, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $Condition, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $RoleDefinitionId, + + [Parameter()] + [PSObject] + $RoleDefinition, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [PSObject] + $AppScope, + + [Parameter()] + [System.String] + $DirectoryScopeId, + + [Parameter()] + [System.String] + $PrincipalOrganizationId, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.String] + $AppScopeId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Remove-MgBetaEntitlementManagementAccessPackage +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Remove-MgBetaEntitlementManagementAccessPackageAssignment +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.String] + $AccessPackageAssignmentId, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Remove-MgBetaEntitlementManagementAccessPackageAssignmentPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.String] + $AccessPackageAssignmentPolicyId, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Remove-MgBetaEntitlementManagementAccessPackageCatalog +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $AccessPackageCatalogId, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Remove-MgBetaEntitlementManagementAccessPackageIncompatibleAccessPackageByRef +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Remove-MgBetaEntitlementManagementAccessPackageIncompatibleGroupByRef +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Remove-MgBetaEntitlementManagementAccessPackageResourceRoleScope +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.String] + $AccessPackageResourceRoleScopeId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Remove-MgBetaEntitlementManagementConnectedOrganization +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.String] + $ConnectedOrganizationId, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Remove-MgBetaEntitlementManagementConnectedOrganizationExternalSponsorDirectoryObjectByRef +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.String] + $DirectoryObjectId, + + [Parameter()] + [System.String] + $ConnectedOrganizationId, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Remove-MgBetaEntitlementManagementConnectedOrganizationInternalSponsorDirectoryObjectByRef +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.String] + $DirectoryObjectId, + + [Parameter()] + [System.String] + $ConnectedOrganizationId, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Remove-MgBetaRoleManagementDirectory +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Remove-MgBetaRoleManagementDirectoryRoleAssignment +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $UnifiedRoleAssignmentId, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Remove-MgBetaRoleManagementDirectoryRoleDefinition +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $UnifiedRoleDefinitionId, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Remove-MgBetaRoleManagementEntitlementManagement +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Remove-MgBetaRoleManagementEntitlementManagementRoleAssignment +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $UnifiedRoleAssignmentId, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Set-MgBetaEntitlementManagementAccessPackageAssignmentPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.DateTime] + $CreatedDateTime, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [PSObject] + $CustomExtensionStageSettings, + + [Parameter()] + [PSObject] + $AccessPackageCatalog, + + [Parameter()] + [PSObject] + $Questions, + + [Parameter()] + [System.DateTime] + $ModifiedDateTime, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $AccessReviewSettings, + + [Parameter()] + [System.String] + $CreatedBy, + + [Parameter()] + [System.String] + $AccessPackageAssignmentPolicyId, + + [Parameter()] + [PSObject] + $RequestorSettings, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $CanExtend, + + [Parameter()] + [PSObject] + $VerifiableCredentialSettings, + + [Parameter()] + [PSObject] + $CustomExtensionHandlers, + + [Parameter()] + [System.Int32] + $DurationInDays, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.DateTime] + $ExpirationDateTime, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $RequestApprovalSettings, + + [Parameter()] + [PSObject] + $AccessPackage, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ModifiedBy, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [PSObject] + $AccessPackageNotificationSettings, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Update-MgBetaEntitlementManagementAccessPackage +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [PSObject] + $AccessPackagesIncompatibleWith, + + [Parameter()] + [System.DateTime] + $CreatedDateTime, + + [Parameter()] + [PSObject] + $IncompatibleGroups, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [PSObject] + $AccessPackageCatalog, + + [Parameter()] + [System.String] + $CatalogId, + + [Parameter()] + [System.DateTime] + $ModifiedDateTime, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $AccessPackageAssignmentPolicies, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.String] + $CreatedBy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsRoleScopesVisible, + + [Parameter()] + [System.String] + $AccessPackageId, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $IncompatibleAccessPackages, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $AccessPackageResourceRoleScopes, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ModifiedBy, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String] + $UniqueName, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsHidden + ) +} +function Update-MgBetaEntitlementManagementAccessPackageCatalog +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsExternallyVisible, + + [Parameter()] + [System.String] + $UniqueName, + + [Parameter()] + [PSObject] + $AccessPackageCustomWorkflowExtensions, + + [Parameter()] + [System.DateTime] + $CreatedDateTime, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.DateTime] + $ModifiedDateTime, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [PSObject] + $AccessPackages, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.String] + $CreatedBy, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String] + $AccessPackageCatalogId, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [PSObject] + $AccessPackageResources, + + [Parameter()] + [System.String] + $ModifiedBy, + + [Parameter()] + [PSObject] + $CustomAccessPackageWorkflowExtensions, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.String] + $CatalogStatus, + + [Parameter()] + [PSObject] + $AccessPackageResourceScopes, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [PSObject] + $AccessPackageResourceRoles, + + [Parameter()] + [System.String] + $CatalogType, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Update-MgBetaEntitlementManagementConnectedOrganization +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $ExternalSponsors, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.DateTime] + $CreatedDateTime, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.DateTime] + $ModifiedDateTime, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $IdentitySources, + + [Parameter()] + [System.String] + $State, + + [Parameter()] + [System.String] + $CreatedBy, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $ConnectedOrganizationId, + + [Parameter()] + [PSObject] + $InternalSponsors, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ModifiedBy, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Update-MgBetaEntitlementManagementSetting +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Int32] + $DaysUntilExternalUserDeletedAfterBlocked, + + [Parameter()] + [System.String] + $ExternalUserLifecycleAction + ) +} +function Update-MgBetaRoleManagementDirectory +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $RoleAssignmentScheduleRequests, + + [Parameter()] + [PSObject] + $TransitiveRoleAssignments, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $RoleEligibilitySchedules, + + [Parameter()] + [PSObject] + $ResourceNamespaces, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $RoleDefinitions, + + [Parameter()] + [PSObject] + $RoleEligibilityScheduleRequests, + + [Parameter()] + [PSObject] + $RoleAssignmentSchedules, + + [Parameter()] + [PSObject] + $RoleAssignments, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [PSObject] + $RoleEligibilityScheduleInstances, + + [Parameter()] + [PSObject] + $RoleAssignmentScheduleInstances, + + [Parameter()] + [PSObject] + $RoleAssignmentApprovals, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Update-MgBetaRoleManagementDirectoryRoleDefinition +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $ResourceScopes, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsPrivileged, + + [Parameter()] + [System.String] + $UnifiedRoleDefinitionId, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.String] + $Version, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsBuiltIn, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [PSObject] + $InheritsPermissionsFrom, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String] + $AllowedPrincipalTypes, + + [Parameter()] + [PSObject] + $RolePermissions, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.String] + $TemplateId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsEnabled, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +#endregion + #region Microsoft.Graph.Groups function Get-MgGroup { From 968677833f4785f3c760c1af422bb90503d42e95 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 26 Sep 2024 16:41:09 -0400 Subject: [PATCH 325/465] Update Microsoft365DSC.AADGroup.Tests.ps1 --- .../Microsoft365DSC.AADGroup.Tests.ps1 | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADGroup.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADGroup.Tests.ps1 index 0215457741..87431e0b50 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADGroup.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADGroup.Tests.ps1 @@ -36,6 +36,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgGroupMember -MockWith { } + Mock -CommandName Get-MgBetaGroupMember -MockWith { + } Mock -CommandName Get-MgGroup -MockWith { } @@ -51,6 +53,12 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgGroupOwner -MockWith { } + Mock -CommandName Get-MgBetaGroupMemberOf -MockWith { + } + + Mock -CommandName Get-MgBetaGroupOwner -MockWith { + } + Mock -CommandName Invoke-MgGraphRequest -MockWith { } @@ -66,8 +74,15 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName New-MgGroupOwnerByRef -MockWith { } - Mock -CommandName New-MgGroupMember -MockWith { + Mock -CommandName New-MgGroupMember -MockWith { } + + Mock -CommandName New-MgBetaGroupOwnerByRef -MockWith { } + + Mock -CommandName New-MgBetaGroupMemberByRef -MockWith { + } + + Mock -CommandName New-MgBetaGroupMember -MockWith {} Mock -CommandName New-MgBetaDirectoryRoleMemberByRef -MockWith { } @@ -240,7 +255,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { GroupTypes = @() } } - Mock -CommandName Get-MgGroupMemberOf -MockWith { + Mock -CommandName Get-MgBetaGroupMemberOf -MockWith { return @{ AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.group' @@ -267,7 +282,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return Values from the Get method' { Get-TargetResource @testParams Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 - Should -Invoke -CommandName 'Get-MgGroupMemberOf' -Exactly 1 + Should -Invoke -CommandName 'Get-MgBetaGroupMemberOf' -Exactly 1 } It 'Should return true from the Test method' { @@ -308,7 +323,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { IsAssignableToRole = $true } } - Mock -CommandName Get-MgGroupMemberOf -MockWith { + Mock -CommandName Get-MgBetaGroupMemberOf -MockWith { return @{ AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.directoryRole' @@ -321,7 +336,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return Values from the Get method' { Get-TargetResource @testParams Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 - Should -Invoke -CommandName 'Get-MgGroupMemberOf' -Exactly 1 + Should -Invoke -CommandName 'Get-MgBEtaGroupMemberOf' -Exactly 1 } It 'Should return true from the Test method' { @@ -429,7 +444,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return Values from the Get method' { Get-TargetResource @testParams Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 - Should -Invoke -CommandName 'Get-MgGroupMemberOf' -Exactly 1 + Should -Invoke -CommandName 'Get-MgBetaGroupMemberOf' -Exactly 1 } It 'Should return false from the Test method' { @@ -539,7 +554,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } - Mock -CommandName New-MgGroupMemberByRef -MockWith { + Mock -CommandName New-MgBetaGroupMemberByRef -MockWith { } } @@ -555,7 +570,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the Set method' { Set-TargetResource @testParams Should -Invoke -CommandName 'Get-MgGroup' -Exactly 2 - Should -Invoke -CommandName 'New-MgGroupMemberByRef' -Exactly 1 + Should -Invoke -CommandName 'New-MgBetaGroupMemberByRef' -Exactly 1 #Should -Invoke -CommandName 'Remove-MgGroupMemberDirectoryObjectByRef' -Exactly 1 } } @@ -593,7 +608,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { IsAssignableToRole = $true } } - Mock -CommandName Get-MgGroupMemberOf -MockWith { + Mock -CommandName Get-MgBEtaGroupMemberOf -MockWith { return @{ AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.directoryRole' @@ -612,7 +627,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return Values from the Get method' { Get-TargetResource @testParams Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 - Should -Invoke -CommandName 'Get-MgGroupMemberOf' -Exactly 1 + Should -Invoke -CommandName 'Get-MgBetaGroupMemberOf' -Exactly 1 } It 'Should return false from the Test method' { From 08593328f9a7b98db4c2bf51110510ae1d37fd5a Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 26 Sep 2024 16:57:35 -0400 Subject: [PATCH 326/465] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 77 ++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 58cacebfea..9620ec2b56 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -43381,6 +43381,83 @@ function Get-MgGroupLifecyclePolicy $HttpPipelineAppend ) } +function Get-MgBetaGroupMember +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.String] + $GroupId, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.String] + $ConsistencyLevel, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} function Get-MgGroupMember { [CmdletBinding()] From 2d00ca169bcdf9b5ea3cff50769754790435591f Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 26 Sep 2024 17:12:06 -0400 Subject: [PATCH 327/465] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 85 ++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 9620ec2b56..ea7ef36f92 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -43620,6 +43620,91 @@ function Get-MgGroupMemberOf $HttpPipelineAppend ) } +function Get-MgBetaGroupMemberOf +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.String] + $GroupId, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.String] + $ConsistencyLevel, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $DirectoryObjectId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} function Get-MgGroupOwner { [CmdletBinding()] From 4b85f0de1600216e36ef6b5e78804071a9714af1 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 26 Sep 2024 17:26:14 -0400 Subject: [PATCH 328/465] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 77 ++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index ea7ef36f92..ba3a19e36d 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -43782,6 +43782,83 @@ function Get-MgGroupOwner $HttpPipelineAppend ) } +function Get-MgBetaGroupOwner +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.String] + $GroupId, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.String] + $ConsistencyLevel, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} function New-MgGroup { [CmdletBinding()] From 88f70fbbbfa5326aea1afa795e26c597a258d1c7 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 26 Sep 2024 17:39:16 -0400 Subject: [PATCH 329/465] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 57 ++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index ba3a19e36d..b790ae7bfc 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -44388,6 +44388,63 @@ function New-MgGroupOwner $Break ) } +function New-MgBetaGroupOwnerByRef +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String] + $OdataId, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.String] + $GroupId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} function New-MgGroupOwnerByRef { [CmdletBinding()] From 9ffdd43721510ed333cb23ffa2476af0f6ce8994 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Thu, 26 Sep 2024 16:22:38 -0700 Subject: [PATCH 330/465] Added DisplayName has mandatory. --- .../MSFT_IntuneAppCategories.psm1 | 89 ++++++++++++------- .../MSFT_IntuneAppCategories.schema.mof | 8 +- .../MSFT_IntuneAppCategories/readme.md | 4 +- .../MSFT_IntuneAppCategories/settings.json | 28 +++--- 4 files changed, 75 insertions(+), 54 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 index 0990631700..9b990183a7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 @@ -4,12 +4,17 @@ function Get-TargetResource [OutputType([System.Collections.Hashtable])] param ( - ##TODO - Replace the PrimaryKey + #region Intune params + [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $Id, - ##TODO - Add the list of Parameters + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + #endregion Intune params [Parameter()] [ValidateSet('Present', 'Absent')] @@ -41,8 +46,7 @@ function Get-TargetResource $AccessTokens ) - ##TODO - Replace the workload by the one associated to your resource - New-M365DSCConnection -Workload 'Workload' ` + New-M365DSCConnection -Workload 'MicrosoftGraph' ` -InboundParameters $PSBoundParameters | Out-Null #Ensure the proper dependencies are installed in the current environment. @@ -59,25 +63,38 @@ function Get-TargetResource $nullResult = $PSBoundParameters $nullResult.Ensure = 'Absent' + try { if ($null -ne $Script:exportedInstances -and $Script:ExportMode) { - ##TODO - Replace the PrimaryKey in the Filter by the one for the resource - $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.PrimaryKey -eq $PrimaryKey} + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} } - else - { - ##TODO - Replace the cmdlet by the one to retrieve a specific instance. - $instance = Get-cmdlet -PrimaryKey $PrimaryKey -ErrorAction Stop - } - if ($null -eq $instance) - { - return $nullResult + else { + $instance = Get-MgBetaDeviceAppManagementMobileAppCategory -MobileAppCategoryId $Id -ErrorAction Stop + + if ($null -eq $instance) + { + Write-Verbose -Message "Could not find by Id {$Id}." + + if (-Not [string]::IsNullOrEmpty($DisplayName)) + { + $instance = Get-MgBetaDeviceAppManagementMobileAppConfiguration ` + -Filter "DisplayName eq '$DisplayName'" ` + -ErrorAction SilentlyContinue + } + } + + if ($null -eq $instance) + { + Write-Verbose -Message "Could not find by DisplayName {$DisplayName}." + return $nullResult + } } $results = @{ - ##TODO - Add the list of parameters to be returned + Id = $instance.Id + DisplayName = $instance.DisplayName Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -106,12 +123,17 @@ function Set-TargetResource [CmdletBinding()] param ( - ##TODO - Replace the PrimaryKey + #region Intune params + [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $Id, + + [Parameter()] + [Parameter(Mandatory = $true)] + $DisplayName, - ##TODO - Add the list of Parameters + #endregion Intune params [Parameter()] [ValidateSet('Present', 'Absent')] @@ -162,20 +184,17 @@ function Set-TargetResource # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - ##TODO - Replace by the New cmdlet for the resource - New-Cmdlet @SetParameters + New-MgBetaDeviceAppManagementMobileAppCategory @SetParameters } # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - ##TODO - Replace by the Update/Set cmdlet for the resource - Set-cmdlet @SetParameters + Set-MgBetaDeviceAppManagementMobileAppCategory @SetParameters } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - ##TODO - Replace by the Remove cmdlet for the resource - Remove-cmdlet @SetParameters + Remove-MgBetaDeviceAppManagementMobileAppCategory @SetParameters } } @@ -185,12 +204,17 @@ function Test-TargetResource [OutputType([System.Boolean])] param ( - ##TODO - Replace the PrimaryKey + #region Intune params + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + [Parameter(Mandatory = $true)] [System.String] - $PrimaryKey, + $DisplayName, - ##TODO - Add the list of Parameters + #endregion Intune params [Parameter()] [ValidateSet('Present', 'Absent')] @@ -285,8 +309,7 @@ function Export-TargetResource $AccessTokens ) - ##TODO - Replace workload - $ConnectionMode = New-M365DSCConnection -Workload 'Workload' ` + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` -InboundParameters $PSBoundParameters #Ensure the proper dependencies are installed in the current environment. @@ -304,8 +327,7 @@ function Export-TargetResource try { $Script:ExportMode = $true - ##TODO - Replace Get-Cmdlet by the cmdlet to retrieve all instances - [array] $Script:exportedInstances = Get-Cmdlet -ErrorAction Stop + [array] $Script:exportedInstances = Get-MgBetaDeviceAppManagementMobileAppCategory -ErrorAction Stop $i = 1 $dscContent = '' @@ -322,8 +344,7 @@ function Export-TargetResource $displayedKey = $config.Id Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline $params = @{ - ##TODO - Specify the Primary Key - #PrimaryKey = $config.PrimaryKey + Id = $config.Id Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof index be6b06c877..b4e30581a5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof @@ -1,8 +1,8 @@ -[ClassVersion("1.0.0.0"), FriendlyName("ResourceName")] -class MSFT_ResourceName : OMI_BaseResource +[ClassVersion("1.0.0.0"), FriendlyName("IntuneAppCategories")] +class MSFT_IntuneAppCategories : OMI_BaseResource { - [Key, Description("")] String PrimaryKey; - [Write, Description("")] String OtherProperties; + [Key, Description("The unique identifier for an entity. Read-only.")] String Id; + [Required, Description("The name of the app category.")] String DisplayName; [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/readme.md index 32e0e7fb27..cef6d76862 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/readme.md @@ -1,6 +1,6 @@ -# ResourceName +# IntuneAppCategories ## Description -##TODO - Provide a short description of what the resource is set to configure. +Configures a resource for navigation property for Intune mobile app categories. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/settings.json index edf14b05e4..9fff933f93 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/settings.json @@ -1,29 +1,29 @@ { - "resourceName": "ResourceName", - "description": "Description of what the resource is about.", - "roles": { - "read": [ - "Role" - ], - "update": [ - "Role" - ] - }, + "resourceName": "IntuneAppCategories", + "description": "Configures a resource for navigation property for Intune mobile app categories.", "permissions": { "graph": { "delegated": { - "read": [], - "update": [] + "read": [ + { + "name": "DeviceManagementApps.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementApps.ReadWrite.All" + } + ] }, "application": { "read": [ { - "name": "Permission for Monitoring and Export" + "name": "DeviceManagementApps.Read.All" } ], "update": [ { - "name": "Permission for deploying" + "name": "DeviceManagementApps.ReadWrite.All" } ] } From 9b11ec4eae7acb38a7d31e56af23723cf41000eb Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Thu, 26 Sep 2024 22:49:28 -0700 Subject: [PATCH 331/465] Added examples and tests. --- .../MSFT_IntuneAppCategories.psm1 | 5 +- .../Resources/IntuneAppCategory/1-Create.ps1 | 4 +- .../Resources/IntuneAppCategory/3-Remove.ps1 | 3 +- ...icrosoft365DSC.IntuneAppCategory.Tests.ps1 | 69 +++++++++++-------- Tests/Unit/Stubs/Microsoft365.psm1 | 48 +++++++++++++ 5 files changed, 95 insertions(+), 34 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 index 9b990183a7..ae3403f681 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 @@ -129,8 +129,8 @@ function Set-TargetResource [System.String] $Id, - [Parameter()] [Parameter(Mandatory = $true)] + [System.String] $DisplayName, #endregion Intune params @@ -189,7 +189,7 @@ function Set-TargetResource # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - Set-MgBetaDeviceAppManagementMobileAppCategory @SetParameters + Update-MgBetaDeviceAppManagementMobileAppCategory @SetParameters } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') @@ -197,7 +197,6 @@ function Set-TargetResource Remove-MgBetaDeviceAppManagementMobileAppCategory @SetParameters } } - function Test-TargetResource { [CmdletBinding()] diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 index b516274848..f692f74739 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 @@ -18,9 +18,11 @@ Configuration Example [System.String] $CertificateThumbprint ) + Import-DscResource -ModuleName Microsoft365DSC node localhost { - + Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Books & Reference"; } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 index b516274848..1357c5eb7a 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 @@ -21,6 +21,7 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Books & Reference"; } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 index f3ddc7d594..4097fc5c5d 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 @@ -35,82 +35,92 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets - - # Mock Write-Host to hide output during the tests + # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { } + + Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { + } + Mock -CommandName New-MgBetaDeviceAppManagementMobileAppCategory -MockWith { + } + Mock -CommandName Update-MgBetaDeviceAppManagementMobileAppCategory -MockWith { + } + Mock -CommandName Remove-MgBetaDeviceAppManagementMobileAppCategory -MockWith { + } + $Script:exportedInstances =$null $Script:ExportMode = $false } + # Test contexts Context -Name "The instance should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters + Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Books & Reference"; Ensure = 'Present' Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -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 a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one Set-TargetResource @testParams - Should -Invoke -CommandName New-Cmdlet -Exactly 1 + Should -Invoke -CommandName New-MgBetaDeviceAppManagementMobileAppCategory -Exactly 1 } } Context -Name "The instance exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters + Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Books & Reference"; Ensure = 'Absent' Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { return @{ - + Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Books & Reference"; } } } + 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 remove the instance from the Set method' { - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaDeviceAppManagementMobileAppCategory -Exactly 1 } } Context -Name "The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters + Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Books & Reference"; Ensure = 'Present' Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { return @{ - + Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Books & Reference"; } } } @@ -123,15 +133,16 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters + Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Books & Reference"; Ensure = 'Present' Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { return @{ - + Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Books & Reference"; } } } @@ -146,8 +157,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the Set method' { Set-TargetResource @testParams - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + Should -Invoke -CommandName Update-MgBetaDeviceAppManagementMobileAppCategory -Exactly 1 } } @@ -159,13 +169,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { return @{ - + Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Books & Reference"; } } } + It 'Should Reverse Engineer resource from the Export method' { $result = Export-TargetResource @testParams $result | Should -Not -BeNullOrEmpty diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 37993f422c..11385cd7cb 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -37633,6 +37633,51 @@ function Update-MgBetaTeamChannelTab ) } #endregion + +#region Microsoft.Graph.deviceManagement + +function Get-MgBetaDeviceAppManagementMobileAppCategory +{ + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName + ) +} + +function Update-MgBetaDeviceAppManagementMobileAppCategory +{ + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName + ) +} + +function Remove-MgBetaDeviceAppManagementMobileAppCategory +{ + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName + ) +} + #region Microsoft.Graph.DeviceManagement.Administration function Get-MgDeviceManagementRoleAssignment { @@ -38244,6 +38289,9 @@ function Update-MgDeviceManagementRoleDefinition ) } #endregion + +#endregion Microsoft.Graph.DeviceManagement + #region Microsoft.Graph.DirectoryObjects function Get-MgDirectoryObject { From f7552a420db952d9596dc85809b405aa4e8bd941 Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Fri, 27 Sep 2024 12:05:23 +0530 Subject: [PATCH 332/465] PR comments --- .../MSFT_AADFeatureRolloutPolicy.psm1 | 50 ++----------------- .../MSFT_AADFeatureRolloutPolicy.schema.mof | 4 +- .../settings.json | 49 ++++++++++-------- .../AADFeatureRolloutPolicy/1-Create.ps1 | 1 - .../AADFeatureRolloutPolicy/2-Update.ps1 | 36 +++++++++++++ .../AADFeatureRolloutPolicy/3-Remove.ps1 | 34 +++++++++++++ .../M365DSCResourceGenerator.psm1 | 4 +- .../M365DSCIntegration.AAD.Create.Tests.ps1 | 12 ----- 8 files changed, 107 insertions(+), 83 deletions(-) create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/3-Remove.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/MSFT_AADFeatureRolloutPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/MSFT_AADFeatureRolloutPolicy.psm1 index 30d7314afc..97857762ed 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/MSFT_AADFeatureRolloutPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/MSFT_AADFeatureRolloutPolicy.psm1 @@ -26,7 +26,7 @@ function Get-TargetResource [System.Boolean] $IsEnabled, - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Id, @@ -180,7 +180,7 @@ function Set-TargetResource [System.Boolean] $IsEnabled, - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Id, @@ -241,17 +241,8 @@ function Set-TargetResource Write-Verbose -Message "Creating an Azure AD Policy Feature Rollout Policy with DisplayName {$DisplayName}" $createParameters = ([Hashtable]$BoundParameters).Clone() - $createParameters = Rename-M365DSCCimInstanceParameter -Properties $createParameters $createParameters.Remove('Id') | Out-Null - $keys = (([Hashtable]$createParameters).Clone()).Keys - foreach ($key in $keys) - { - if ($null -ne $createParameters.$key -and $createParameters.$key.GetType().Name -like '*CimInstance*') - { - $createParameters.$key = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $createParameters.$key - } - } #region resource generator code $policy = New-MgBetaPolicyFeatureRolloutPolicy -BodyParameter $createParameters #endregion @@ -261,20 +252,10 @@ function Set-TargetResource Write-Verbose -Message "Updating the Azure AD Policy Feature Rollout Policy with Id {$($currentInstance.Id)}" $updateParameters = ([Hashtable]$BoundParameters).Clone() - $updateParameters = Rename-M365DSCCimInstanceParameter -Properties $updateParameters $updateParameters.Remove('Id') | Out-Null $updateParameters.Remove('Feature') | Out-Null - $keys = (([Hashtable]$updateParameters).Clone()).Keys - foreach ($key in $keys) - { - if ($null -ne $pdateParameters.$key -and $updateParameters.$key.GetType().Name -like '*CimInstance*') - { - $updateParameters.$key = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $updateParameters.FeatureRolloutPolicyId - } - } - #region resource generator code Update-MgBetaPolicyFeatureRolloutPolicy ` -FeatureRolloutPolicyId $currentInstance.Id ` @@ -318,7 +299,7 @@ function Test-TargetResource [System.Boolean] $IsEnabled, - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Id, @@ -382,26 +363,6 @@ function Test-TargetResource } $testResult = $true - #Compare Cim instances - foreach ($key in $PSBoundParameters.Keys) - { - $source = $PSBoundParameters.$key - $target = $CurrentValues.$key - if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') - { - $testResult = Compare-M365DSCComplexObject ` - -Source ($source) ` - -Target ($target) - - if (-not $testResult) - { - break - } - - $ValuesToCheck.Remove($key) | Out-Null - } - } - $ValuesToCheck.Remove('Id') | Out-Null $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck @@ -501,10 +462,7 @@ function Export-TargetResource { $displayedKey = $config.displayName } - elseif (-not [string]::IsNullOrEmpty($config.name)) - { - $displayedKey = $config.name - } + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline $params = @{ Id = $config.Id diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/MSFT_AADFeatureRolloutPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/MSFT_AADFeatureRolloutPolicy.schema.mof index 2f3aec73da..eab252ba3b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/MSFT_AADFeatureRolloutPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/MSFT_AADFeatureRolloutPolicy.schema.mof @@ -3,11 +3,11 @@ class MSFT_AADFeatureRolloutPolicy : OMI_BaseResource { [Write, Description("A description for this feature rollout policy.")] String Description; - [Required, Description("The display name for this feature rollout policy.")] String DisplayName; + [Key, Description("The display name for this feature rollout policy.")] String DisplayName; [Write, Description("Possible values are: passthroughAuthentication, seamlessSso, passwordHashSync, emailAsAlternateId, unknownFutureValue, certificateBasedAuthentication. You must use the Prefer: include-unknown-enum-members request header to get the following value or values in this evolvable enum: certificateBasedAuthentication. For more information about the prerequisites for the enabled features, see Prerequisites for enabled features."), ValueMap{"passthroughAuthentication","seamlessSso","passwordHashSync","emailAsAlternateId","unknownFutureValue","certificateBasedAuthentication"}, Values{"passthroughAuthentication","seamlessSso","passwordHashSync","emailAsAlternateId","unknownFutureValue","certificateBasedAuthentication"}] String Feature; [Write, Description("Indicates whether this feature rollout policy should be applied to the entire organization.")] Boolean IsAppliedToOrganization; [Write, Description("Indicates whether the feature rollout is enabled.")] Boolean IsEnabled; - [Key, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/settings.json index 8d993eaf72..2a2839156c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADFeatureRolloutPolicy/settings.json @@ -1,25 +1,32 @@ { "resourceName": "AADPolicyFeatureRolloutPolicy", "description": "This resource configures an Azure AD Policy Feature Rollout Policy.", - "permissions": { - "graph": { - "delegated": { - "read": [ - - ], - "update": [ - - ] - }, - "application": { - "read": [ - - ], - "update": [ - - ] - } - } -} - + "permissions": { + "graph": { + "delegated": { + "read": [ + { + "name": "Directory.Read.All" + } + ], + "update": [ + { + "name": "Directory.ReadWrite.All" + } + ] + }, + "application": { + "read": [ + { + "name": "Directory.Read.All" + } + ], + "update": [ + { + "name": "Directory.ReadWrite.All" + } + ] + } + } + } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/1-Create.ps1 index eeeb5dd866..7d729800c4 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/1-Create.ps1 @@ -33,7 +33,6 @@ Configuration Example Feature = "certificateBasedAuthentication"; IsAppliedToOrganization = $False; IsEnabled = $True; - Id = "e6f15f6f-1ebe-4007-aa6c-0590844080d2"; } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/2-Update.ps1 new file mode 100644 index 0000000000..1773c749d5 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/2-Update.ps1 @@ -0,0 +1,36 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADFeatureRolloutPolicy "AADFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Description = "CertificateBasedAuthentication rollout policy"; + DisplayName = "CertificateBasedAuthentication rollout policy"; + Ensure = "Present"; + IsAppliedToOrganization = $False; + IsEnabled = $False; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/3-Remove.ps1 new file mode 100644 index 0000000000..4f6fa5b3f4 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADFeatureRolloutPolicy/3-Remove.ps1 @@ -0,0 +1,34 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADFeatureRolloutPolicy "AADFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + DisplayName = "CertificateBasedAuthentication rollout policy"; + Ensure = "Absent"; + } + } +} diff --git a/ResourceGenerator/M365DSCResourceGenerator.psm1 b/ResourceGenerator/M365DSCResourceGenerator.psm1 index bbaade9b4e..803062322d 100644 --- a/ResourceGenerator/M365DSCResourceGenerator.psm1 +++ b/ResourceGenerator/M365DSCResourceGenerator.psm1 @@ -902,6 +902,7 @@ class MSFT_DeviceManagementConfigurationPolicyAssignments #region Examples if ($null -ne $Credential) { + Import-Module Microsoft365DSC -Force New-M365DSCExampleFile -ResourceName $ResourceName ` -Path $ExampleFilePath ` -Credential $Credential @@ -1634,7 +1635,8 @@ function Get-Microsoft365DSCModuleCimClass $ResourceName ) - $modulePath = "C:\Program Files\WindowsPowerShell\Modules\Microsoft365DSC\Modules\Microsoft365DSC" + Import-Module -Name Microsoft365DSC -Force + $modulePath = Split-Path -Path (Get-Module -Name Microsoft365DSC).Path $resourcesPath = "$modulePath\DSCResources\*\*.mof" $resources = (Get-ChildItem $resourcesPath).FullName $resources = $resources | Where-Object -FilterScript {$_ -notlike "*MSFT_$ResourceName.schema.mof"} diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 index acc46c6e4b..961f04f285 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 @@ -290,18 +290,6 @@ Principal = "AdeleV@$TenantId"; RoleDefinition = "Catalog creator"; } - AADFeatureRolloutPolicy 'AADFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy' - { - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - Description = "CertificateBasedAuthentication rollout policy"; - DisplayName = "CertificateBasedAuthentication rollout policy"; - Ensure = "Present"; - Feature = "certificateBasedAuthentication"; - IsAppliedToOrganization = $False; - IsEnabled = $True; - } AADGroup 'MyGroups' { DisplayName = "DSCGroup" From c9423265ae990344ebb70ee1de87c5aec249f782 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 06:38:11 +0000 Subject: [PATCH 333/465] Updated {Create} AAD Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 index 7919be2555..acc46c6e4b 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 @@ -301,7 +301,6 @@ Feature = "certificateBasedAuthentication"; IsAppliedToOrganization = $False; IsEnabled = $True; - Id = "e6f15f6f-1ebe-4007-aa6c-0590844080d2"; } AADGroup 'MyGroups' { From 8231397cddc2f26d01b110a58734a7518836f8ce Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 06:38:27 +0000 Subject: [PATCH 334/465] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Update.Tests.ps1 | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index f7b70c49f1..a16837b9e2 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -664,6 +664,17 @@ CertificateThumbprint = $CertificateThumbprint IsSingleInstance = "Yes"; } + AADFeatureRolloutPolicy 'AADFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy' + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Description = "CertificateBasedAuthentication rollout policy"; + DisplayName = "CertificateBasedAuthentication rollout policy"; + Ensure = "Present"; + IsAppliedToOrganization = $False; + IsEnabled = $False; + } AADGroup 'MyGroups' { DisplayName = "DSCGroup" From 60aed9d47a8bc99a53e52c318cfbef54a047c070 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 06:38:39 +0000 Subject: [PATCH 335/465] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Remove.Tests.ps1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 index 656177cd9a..459d95f51e 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 @@ -199,6 +199,14 @@ Principal = "AdeleV@$TenantId"; RoleDefinition = "Catalog creator"; } + AADFeatureRolloutPolicy 'AADFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy' + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + DisplayName = "CertificateBasedAuthentication rollout policy"; + Ensure = "Absent"; + } AADGroup 'MyGroups' { MailNickname = "M365DSC" From 64a0a41f72f4c25c19fe9c4aa8550d7a30c883ef Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 06:40:07 +0000 Subject: [PATCH 336/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index f25f807e95..09fbd1bc0a 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -3530,7 +3530,7 @@ { "CIMType": "String", "Name": "DisplayName", - "Option": "Required" + "Option": "Key" }, { "CIMType": "String", @@ -3550,7 +3550,7 @@ { "CIMType": "String", "Name": "Id", - "Option": "Key" + "Option": "Write" }, { "CIMType": "string", From 7732e6e5f57df319512aa3fdc8e8501e87c30056 Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Fri, 27 Sep 2024 14:52:04 +0530 Subject: [PATCH 337/465] Added AADAuthenticationMethodPolicyHardware resource --- ...AADAuthenticationMethodPolicyHardware.psm1 | 589 ++++++++++++++++++ ...henticationMethodPolicyHardware.schema.mof | 29 + .../readme.md | 6 + .../settings.json | 52 ++ .../2-Update.ps1 | 51 ++ .../3-Remove.ps1 | 34 + ...thenticationMethodPolicyHardware.Tests.ps1 | 311 +++++++++ 7 files changed, 1072 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/MSFT_AADAuthenticationMethodPolicyHardware.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/MSFT_AADAuthenticationMethodPolicyHardware.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationMethodPolicyHardware/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationMethodPolicyHardware/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationMethodPolicyHardware.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/MSFT_AADAuthenticationMethodPolicyHardware.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/MSFT_AADAuthenticationMethodPolicyHardware.psm1 new file mode 100644 index 0000000000..30be7f9089 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/MSFT_AADAuthenticationMethodPolicyHardware.psm1 @@ -0,0 +1,589 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region resource generator code + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $ExcludeTargets, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $IncludeTargets, + + [Parameter()] + [ValidateSet('enabled', 'disabled')] + [System.String] + $State, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + try + { + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -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 + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + $getValue = $null + #region resource generator code + $getValue = Get-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration -AuthenticationMethodConfigurationId $Id -ErrorAction SilentlyContinue + + #endregion + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Azure AD Authentication Method Policy Hardware with id {$id}" + return $nullResult + } + $Id = $getValue.Id + Write-Verbose -Message "An Azure AD Authentication Method Policy Hardware with Id {$Id} was found." + + #region resource generator code + $complexExcludeTargets = @() + foreach ($currentExcludeTargets in $getValue.excludeTargets) + { + $myExcludeTargets = @{} + if ($currentExcludeTargets.id -ne 'all_users'){ + $myExcludeTargetsDisplayName = get-MgGroup -GroupId $currentExcludeTargets.id + $myExcludeTargets.Add('Id', $myExcludeTargetsDisplayName.DisplayName) + } + else{ + $myExcludeTargets.Add('Id', $currentExcludeTargets.id) + } + if ($null -ne $currentExcludeTargets.targetType) + { + $myExcludeTargets.Add('TargetType', $currentExcludeTargets.targetType.toString()) + } + if ($myExcludeTargets.values.Where({ $null -ne $_ }).count -gt 0) + { + $complexExcludeTargets += $myExcludeTargets + } + } + #endregion + + $complexincludeTargets = @() + foreach ($currentincludeTargets in $getValue.AdditionalProperties.includeTargets) + { + $myincludeTargets = @{} + if ($currentIncludeTargets.id -ne 'all_users'){ + $myIncludeTargetsDisplayName = get-MgGroup -GroupId $currentIncludeTargets.id + $myIncludeTargets.Add('Id', $myIncludeTargetsDisplayName.DisplayName) + } + else{ + $myIncludeTargets.Add('Id', $currentIncludeTargets.id) + } + if ($null -ne $currentincludeTargets.targetType) + { + $myincludeTargets.Add('TargetType', $currentincludeTargets.targetType.toString()) + } + if ($myincludeTargets.values.Where({ $null -ne $_ }).count -gt 0) + { + $complexincludeTargets += $myincludeTargets + } + } + #region resource generator code + $enumState = $null + if ($null -ne $getValue.State) + { + $enumState = $getValue.State.ToString() + } + #endregion + + $results = @{ + #region resource generator code + ExcludeTargets = $complexExcludeTargets + IncludeTargets = $complexincludeTargets + State = $enumState + Id = $getValue.Id + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + Managedidentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + #endregion + } + + 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 + ( + #region resource generator code + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $ExcludeTargets, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $IncludeTargets, + + [Parameter()] + [ValidateSet('enabled', 'disabled')] + [System.String] + $State, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + #endregion + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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') + { + Write-Verbose -Message "Updating the Azure AD Authentication Method Policy Hardware with Id {$($currentInstance.Id)}" + + $UpdateParameters = ([Hashtable]$BoundParameters).clone() + $UpdateParameters = Rename-M365DSCCimInstanceParameter -Properties $UpdateParameters + + $UpdateParameters.Remove('Id') | Out-Null + + $keys = (([Hashtable]$UpdateParameters).clone()).Keys + foreach ($key in $keys) + { + if ($null -ne $UpdateParameters.$key -and $UpdateParameters.$key.getType().Name -like '*cimInstance*') + { + $UpdateParameters.$key = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $UpdateParameters.$key + } + if ($key -eq 'IncludeTargets') + { + $i = 0 + foreach ($entry in $UpdateParameters.$key){ + if ($entry.id -notmatch '^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$|all_users') + { + $Filter = "Displayname eq '$($entry.id)'" | Out-String + $UpdateParameters.$key[$i].foreach('id',(Get-MgGroup -Filter $Filter).id.ToString()) + } + $i++ + } + } + if ($key -eq 'ExcludeTargets') + { + $i = 0 + foreach ($entry in $UpdateParameters.$key){ + if ($entry.id -notmatch '^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$|all_users') + { + $Filter = "Displayname eq '$($entry.id)'" | Out-String + $UpdateParameters.$key[$i].foreach('id',(Get-MgGroup -Filter $Filter).id.ToString()) + } + $i++ + } + } + } + #region resource generator code + $UpdateParameters.Add('@odata.type', '#microsoft.graph.hardwareOathAuthenticationMethodConfiguration') + Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration ` + -AuthenticationMethodConfigurationId $currentInstance.Id ` + -BodyParameter $UpdateParameters + #endregion + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing the Azure AD Authentication Method Policy Hardware with Id {$($currentInstance.Id)}" + #region resource generator code + Remove-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration -AuthenticationMethodConfigurationId $currentInstance.Id + #endregion + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region resource generator code + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $ExcludeTargets, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $IncludeTargets, + + [Parameter()] + [ValidateSet('enabled', 'disabled')] + [System.String] + $State, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 the Azure AD Authentication Method Policy Hardware with Id {$Id}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + + if ($CurrentValues.Ensure -ne $Ensure) + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + $testResult = $true + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($source.getType().Name -like '*CimInstance*') + { + $source = Get-M365DSCDRGComplexTypeToHashtable -ComplexObject $source + + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-Not $testResult) + { + $testResult = $false + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } + + $ValuesToCheck.remove('Id') | Out-Null + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + if ($testResult) + { + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -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 + { + #region resource generator code + [array]$getValue = Get-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration ` + -AuthenticationMethodConfigurationId HardwareOath ` + -ErrorAction Stop | Where-Object -FilterScript {$null -ne $_.Id} + #endregion + + $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.Id + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + Managedidentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + if ($null -ne $Results.ExcludeTargets) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.ExcludeTargets ` + -CIMInstanceName 'AADAuthenticationMethodPolicyHardwareExcludeTarget' + if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.ExcludeTargets = $complexTypeStringResult + } + else + { + $Results.Remove('ExcludeTargets') | Out-Null + } + } + + if ($null -ne $Results.IncludeTargets) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.IncludeTargets ` + -CIMInstanceName 'AADAuthenticationMethodPolicyHardwareIncludeTarget' + if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.IncludeTargets = $complexTypeStringResult + } + else + { + $Results.Remove('IncludeTargets') | Out-Null + } + } + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + if ($Results.ExcludeTargets) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ExcludeTargets' -IsCIMArray:$True + } + if ($Results.IncludeTargets) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'IncludeTargets' -IsCIMArray:$True + } + $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_AADAuthenticationMethodPolicyHardware/MSFT_AADAuthenticationMethodPolicyHardware.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/MSFT_AADAuthenticationMethodPolicyHardware.schema.mof new file mode 100644 index 0000000000..e82fa5d554 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/MSFT_AADAuthenticationMethodPolicyHardware.schema.mof @@ -0,0 +1,29 @@ +[ClassVersion("1.0.0")] +class MSFT_AADAuthenticationMethodPolicyHardwareExcludeTarget +{ + [Write, Description("The object identifier of an Azure AD group.")] String Id; + [Write, Description("The type of the authentication method target. Possible values are: group and unknownFutureValue."), ValueMap{"user","group","unknownFutureValue"}, Values{"user","group","unknownFutureValue"}] String TargetType; +}; +[ClassVersion("1.0.0")] +class MSFT_AADAuthenticationMethodPolicyHardwareIncludeTarget +{ + [Write, Description("The object identifier of an Azure AD group.")] String Id; + [Write, Description("The type of the authentication method target. Possible values are: group and unknownFutureValue."), ValueMap{"user","group","unknownFutureValue"}, Values{"user","group","unknownFutureValue"}] String TargetType; +}; + +[ClassVersion("1.0.0.0"), FriendlyName("AADAuthenticationMethodPolicyHardware")] +class MSFT_AADAuthenticationMethodPolicyHardware : OMI_BaseResource +{ + [Write, Description("Displayname of the groups of users that are excluded from a policy."), EmbeddedInstance("MSFT_AADAuthenticationMethodPolicyHardwareExcludeTarget")] String ExcludeTargets[]; + [Write, Description("Displayname of the groups of users that are included from a policy."), EmbeddedInstance("MSFT_AADAuthenticationMethodPolicyHardwareIncludeTarget")] String IncludeTargets[]; + [Write, Description("The state of the policy. Possible values are: enabled, disabled."), ValueMap{"enabled","disabled"}, Values{"enabled","disabled"}] String State; + [Key, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; + [Write, Description("Credentials of the 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("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/readme.md new file mode 100644 index 0000000000..9cd813b949 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/readme.md @@ -0,0 +1,6 @@ + +# AADAuthenticationMethodPolicySoftware + +## Description + +Azure AD Authentication Method Policy Hardware diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/settings.json new file mode 100644 index 0000000000..b3604ceaec --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/settings.json @@ -0,0 +1,52 @@ +{ + "resourceName": "AADAuthenticationMethodPolicySoftware", + "description": "This resource configures an Azure AD Authentication Method Policy Software.", + "roles": { + "read": [ + "Security Reader" + ], + "update": [ + "Authentication Policy Administrator" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [ + { + "name": "Policy.ReadWrite.AuthenticationMethod" + }, + { + "name": "Policy.Read.All" + } + ], + "update": [ + { + "name": "Policy.ReadWrite.AuthenticationMethod" + }, + { + "name": "Policy.Read.All" + } + ] + }, + "application": { + "read": [ + { + "name": "Policy.ReadWrite.AuthenticationMethod" + }, + { + "name": "Policy.Read.All" + } + ], + "update": [ + { + "name": "Policy.ReadWrite.AuthenticationMethod" + }, + { + "name": "Policy.Read.All" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationMethodPolicyHardware/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationMethodPolicyHardware/2-Update.ps1 new file mode 100644 index 0000000000..e2dad301f1 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationMethodPolicyHardware/2-Update.ps1 @@ -0,0 +1,51 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + Node localhost + { + AADAuthenticationMethodPolicyHardware "AADAuthenticationMethodPolicyHardware-HardwareOath" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + ExcludeTargets = @( + MSFT_AADAuthenticationMethodPolicyHardwareExcludeTarget{ + Id = 'Executives' + TargetType = 'group' + } + MSFT_AADAuthenticationMethodPolicyHardwareExcludeTarget{ + Id = 'Paralegals' + TargetType = 'group' + } + ); + Id = "HardwareOath"; + IncludeTargets = @( + MSFT_AADAuthenticationMethodPolicyHardwareIncludeTarget{ + Id = 'Legal Team' + TargetType = 'group' + } + ); + State = "enabled"; # Updated Property + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationMethodPolicyHardware/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationMethodPolicyHardware/3-Remove.ps1 new file mode 100644 index 0000000000..04fa363b5d --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADAuthenticationMethodPolicyHardware/3-Remove.ps1 @@ -0,0 +1,34 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + Node localhost + { + AADAuthenticationMethodPolicyHardware "AADAuthenticationMethodPolicyHardware-HardwareOath" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Absent"; + Id = "HardwareOath"; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationMethodPolicyHardware.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationMethodPolicyHardware.Tests.ps1 new file mode 100644 index 0000000000..0e851d7849 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAuthenticationMethodPolicyHardware.Tests.ps1 @@ -0,0 +1,311 @@ +[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 "AADAuthenticationMethodPolicyHardware" -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 Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration -MockWith { + } + + Mock -CommandName Remove-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration -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 AADAuthenticationMethodPolicyHardware should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ExcludeTargets = [CimInstance[]]@( + (New-CimInstance -ClassName MSFTAADAuthenticationMethodPolicyHardwareExcludeTarget -Property @{ + TargetType = "group" + Id = "Fakegroup" + } -ClientOnly) + ) + IncludeTargets = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_AADAuthenticationMethodPolicyHardwareIncludeTarget -Property @{ + TargetType = 'group' + Id = 'Fakegroup' + } -ClientOnly) + ) + Id = "HardwareOath" + State = "enabled" + Ensure = "Present" + Credential = $Credential; + } + + Mock -CommandName Get-MgGroup -MockWith { + return @{ + Id = "00000000-0000-0000-0000-000000000000" + DisplayName = "Fakegroup" + } + } + + Mock -CommandName Get-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration -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 Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration -Exactly 1 + } + } + + Context -Name "The AADAuthenticationMethodPolicyHardware exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ExcludeTargets = [CimInstance[]]@( + (New-CimInstance -ClassName MSFTAADAuthenticationMethodPolicyHardwareExcludeTarget -Property @{ + TargetType = "group" + Id = "Fakegroup" + } -ClientOnly) + ) + IncludeTargets = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_AADAuthenticationMethodPolicyHardwareIncludeTarget -Property @{ + TargetType = 'group' + Id = 'Fakegroup' + } -ClientOnly) + ) + Id = "HardwareOath" + State = "enabled" + Ensure = 'Absent' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration -MockWith { + return @{ + AdditionalProperties = @{ + IncludeTargets = @( + @{ + TargetType = 'group' + Id = 'Fakegroup' + } + ) + '@odata.type' = "#microsoft.graph.hardwareOathAuthenticationMethodConfiguration" + } + ExcludeTargets = @( + @{ + TargetType = "group" + Id = "00000000-0000-0000-0000-000000000000" + } + ) + Id = "HardwareOath" + State = "enabled" + + } + } + } + + 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-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration -Exactly 1 + } + } + Context -Name "The AADAuthenticationMethodPolicyHardware Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ExcludeTargets = [CimInstance[]]@( + (New-CimInstance -ClassName MSFTAADAuthenticationMethodPolicyHardwareExcludeTarget -Property @{ + TargetType = "group" + Id = "Fakegroup" + } -ClientOnly) + ) + IncludeTargets = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_AADAuthenticationMethodPolicyHardwareIncludeTarget -Property @{ + TargetType = 'group' + Id = 'Fakegroup' + } -ClientOnly) + ) + Id = "HardwareOath" + State = "enabled" + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MgGroup -MockWith { + return @{ + Id = "00000000-0000-0000-0000-000000000000" + DisplayName = "Fakegroup" + } + } + + Mock -CommandName Get-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration -MockWith { + return @{ + AdditionalProperties = @{ + IncludeTargets = @( + @{ + TargetType = 'group' + Id = 'Fakegroup' + } + ) + '@odata.type' = "#microsoft.graph.hardwareOathAuthenticationMethodConfiguration" + } + ExcludeTargets = @( + @{ + TargetType = "group" + Id = "00000000-0000-0000-0000-000000000000" + } + ) + Id = "HardwareOath" + State = "enabled" + + } + } + } + + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The AADAuthenticationMethodPolicyHardware exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ExcludeTargets = [CimInstance[]]@( + (New-CimInstance -ClassName MSFTAADAuthenticationMethodPolicyHardwareExcludeTarget -Property @{ + TargetType = "group" + Id = "Fakegroup" + } -ClientOnly) + ) + IncludeTargets = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_AADAuthenticationMethodPolicyHardwareIncludeTarget -Property @{ + TargetType = 'group' + Id = 'Fakegroup' + } -ClientOnly) + ) + Id = "HardwareOath" + State = "enabled" + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MgGroup -MockWith { + return @{ + Id = "00000000-0000-0000-0000-000000000000" + DisplayName = "Fakegroup2" + } + } + + Mock -CommandName Get-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration -MockWith { + return @{ + AdditionalProperties = @{ + IncludeTargets = @( + @{ + TargetType = 'group' + Id = 'Fakegroup' + } + ) + '@odata.type' = "#microsoft.graph.hardwareOathAuthenticationMethodConfiguration" + } + ExcludeTargets = @( + @{ + TargetType = "group" + Id = "00000000-0000-0000-0000-000000000000" + } + ) + Id = "HardwareOath" + State = "enabled" + } + } + } + + 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 Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration -MockWith { + return @{ + AdditionalProperties = @{ + IncludeTargets = @( + @{ + TargetType = 'group' + Id = 'Fakegroup' + } + ) + '@odata.type' = "#microsoft.graph.hardwareOathAuthenticationMethodConfiguration" + } + ExcludeTargets = @( + @{ + TargetType = "group" + Id = "Fakegroup" + } + ) + Id = "HardwareOath" + State = "enabled" + + } + } + } + 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 f73db7465e6535e19a359133dcc9e5b0203ed6a7 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 09:26:18 +0000 Subject: [PATCH 338/465] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Update.Tests.ps1 | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index f7b70c49f1..b2c1704766 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -260,6 +260,31 @@ }; State = "enabled"; # Updated Property } + AADAuthenticationMethodPolicyHardware 'AADAuthenticationMethodPolicyHardware-HardwareOath' + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + ExcludeTargets = @( + MSFT_AADAuthenticationMethodPolicyHardwareExcludeTarget{ + Id = 'Executives' + TargetType = 'group' + } + MSFT_AADAuthenticationMethodPolicyHardwareExcludeTarget{ + Id = 'Paralegals' + TargetType = 'group' + } + ); + Id = "HardwareOath"; + IncludeTargets = @( + MSFT_AADAuthenticationMethodPolicyHardwareIncludeTarget{ + Id = 'Legal Team' + TargetType = 'group' + } + ); + State = "enabled"; # Updated Property + } AADAuthenticationMethodPolicySms 'AADAuthenticationMethodPolicySms-Sms' { ApplicationId = $ApplicationId From 80b88f02f14be7d66e93035254746340f9f32a78 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 09:26:31 +0000 Subject: [PATCH 339/465] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Remove.Tests.ps1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 index 656177cd9a..ce1155b172 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 @@ -85,6 +85,14 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + AADAuthenticationMethodPolicyHardware 'AADAuthenticationMethodPolicyHardware-HardwareOath' + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Absent"; + Id = "HardwareOath"; + } AADAuthenticationMethodPolicySms 'AADAuthenticationMethodPolicySms-Sms' { ApplicationId = $ApplicationId From b905d4294b9379f8e74d9930c5ffc3a299f375b9 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 09:28:21 +0000 Subject: [PATCH 340/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 3d43328188..409c0bfa8e 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -1114,6 +1114,101 @@ } ] }, + { + "ClassName": "MSFT_AADAuthenticationMethodPolicyHardwareExcludeTarget", + "Parameters": [ + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TargetType", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_AADAuthenticationMethodPolicyHardwareIncludeTarget", + "Parameters": [ + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TargetType", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_AADAuthenticationMethodPolicyHardware", + "Parameters": [ + { + "CIMType": "MSFT_AADAuthenticationMethodPolicyHardwareExcludeTarget[]", + "Name": "ExcludeTargets", + "Option": "Write" + }, + { + "CIMType": "MSFT_AADAuthenticationMethodPolicyHardwareIncludeTarget[]", + "Name": "IncludeTargets", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "State", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Key" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AADAuthenticationMethodPolicySmsExcludeTarget", "Parameters": [ From cefb00e409817b5c6c84948fbd670b63213f9ffe Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Fri, 27 Sep 2024 15:37:59 +0530 Subject: [PATCH 341/465] minor --- .../Examples/Resources/EXOMailboxFolderPermission/2-Update.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/2-Update.ps1 index fc78d04bd0..22c39789c9 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/2-Update.ps1 @@ -40,6 +40,6 @@ MSFT_EXOMailboxFolderUserPermission { SharingPermissionFlags = 'Delegate' } ); - + } } } From 13d0d24a46d3d7526b65f5a4e13aa9327ff22121 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 27 Sep 2024 06:36:15 -0400 Subject: [PATCH 342/465] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 58 ++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index b790ae7bfc..96a7c97c03 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -44339,6 +44339,64 @@ function New-MgGroupMemberByRef $Break ) } + +function New-MgBetaGroupMemberByRef +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String] + $OdataId, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.String] + $GroupId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} function New-MgGroupOwner { [CmdletBinding()] From 61f01d7f2c40d6256c53fb5582c6ebf32dfa29eb Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 27 Sep 2024 06:59:01 -0400 Subject: [PATCH 343/465] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 49 ++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 96a7c97c03..a8a823c655 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -44282,6 +44282,55 @@ function New-MgGroupMember $Break ) } +function New-MgBetaGroupMember +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Collections.Hashtable] + $BodyParameter, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $GroupId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.String] + $DirectoryObjectId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} function New-MgGroupMemberByRef { [CmdletBinding()] From 4b122bd38f3405d4d11a1a2b6246ced32b146cb5 Mon Sep 17 00:00:00 2001 From: Piyush Dubey Date: Fri, 27 Sep 2024 16:40:50 +0530 Subject: [PATCH 344/465] minor --- .../Examples/Resources/EXOMailboxFolderPermission/1-Create.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/1-Create.ps1 index a2ae2e2fdc..512a22ca2a 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxFolderPermission/1-Create.ps1 @@ -39,7 +39,7 @@ Configuration Example MSFT_EXOMailboxFolderUserPermission { User = 'AlexW' AccessRights = 'Owner' - SharingSharingPermissionFlags = 'Delegate' + SharingPermissionFlags = 'Delegate' } ); } From 1aa7b996bc042fb9f655e665fd752be5ebb52c84 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 11:50:50 +0000 Subject: [PATCH 345/465] Updated Graph Permissions List --- Tests/QA/Graph.PermissionList.txt | Bin 6482 -> 5992 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index c93a18fc2437da9a126bdba3ce5f5eed8484dce2..ab0533d4a562a696ceb8dde1d556c0239f1be4cc 100644 GIT binary patch delta 266 zcmca)^g?gLF6Pigh8%`ehCGH8hD3%UhGGUih9Dq65y;nJa0b%2WSxL=#SEDY$=K9Q z{>Ui0c^k7F<7PWn9gfLdyj=XcK-2Pp_LKol2ih}vA)`DFanZ>IY$6~zc3+^{T!y5{ zf|8OT{^U2zT9dPQize^jlh~ZcSHrwnO^Ah2IG-U6=njxO0~j)Zc9byWPrfK3Er=ny anNc*EY4R`e2dp5cXHPa{5ubcRq6z@OP(Q)| delta 529 zcmaE%cgbkOF6PO8EIgY{Soj#l^BM9OiWyRYWC=qMkS=5>1(L;+4H?BHof&Y+GBPS| zc3{=xm|VrDHMxM#L(zvJlOYYLF`1zfh;x9faG>TQhHRi{4v}9$l$`@4rJv6`2`F*3;{qkai&O5{=>+pO@cX-p9&l6l4LVbhat!oV|=#c z1ASM-kO=f2BqmD0zR8)qkVRA)7*Vs``wSkdIQBKB}LBctTxI#Gkk MpF|%_{vcKX0Ay8s`Tzg` From 22daa9b287fa1345df7c2a62af407e404b8839d6 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 12:10:07 +0000 Subject: [PATCH 346/465] Updated Resources and Cmdlet documentation pages --- .../exchange/EXOMailboxFolderPermission.md | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 docs/docs/resources/exchange/EXOMailboxFolderPermission.md diff --git a/docs/docs/resources/exchange/EXOMailboxFolderPermission.md b/docs/docs/resources/exchange/EXOMailboxFolderPermission.md new file mode 100644 index 0000000000..e73479bb40 --- /dev/null +++ b/docs/docs/resources/exchange/EXOMailboxFolderPermission.md @@ -0,0 +1,147 @@ +# EXOMailboxFolderPermission + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Identity** | Key | String | The Identity parameter specifies the target mailbox and folder. The syntax is MailboxID:\ParentFolder[\SubFolder]. For the MailboxID you can use any value that uniquely identifies the mailbox. | | +| **UserPermissions** | Write | MSFT_EXOMailboxFolderUserPermission[] | Mailbox Folder Permissions for the current user. | | +| **Ensure** | Write | String | Determines wheter or not the permission should exist on the mailbox. | `Present` | +| **Credential** | Write | PSCredential | Credentials of the Exchange Global Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **CertificatePassword** | Write | PSCredential | Username can be made up to anything but password will be used for CertificatePassword | | +| **CertificatePath** | Write | String | Path to certificate used in service principal usually a PFX file. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_EXOMailboxFolderUserPermission + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **AccessRights** | Write | StringArray[] | The AccessRights parameter specifies the permissions that you want to add for the user on the mailbox folder. | | +| **User** | Write | String | The User parameter specifies who gets the permissions on the mailbox folder. | | +| **SharingPermissionFlags** | Write | String | The SharingPermissionFlags parameter assigns calendar delegate permissions. This parameter only applies to calendar folders and can only be used when the AccessRights parameter value is Editor. Valid values are: None, Delegate, CanViewPrivateItems | | + + +## Description + +Use this resource to add/set/remove mailbox folder permissions for users in your tenant. + +## Permissions + +### Exchange + +To authenticate with Microsoft Exchange, this resource required the following permissions: + +#### Roles + +- Organization Management, Recipient Management + +#### Role Groups + +- Organization Management, Help Desk + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + EXOMailboxFolderPermission "EXOMailboxFolderPermission-admin:\Calendar" + { + Credential = $Credscredential; + Ensure = "Present"; + Identity = "amdin:\Calendar"; + UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { + User = 'Default' + AccessRights = 'AvailabilityOnly' + } + MSFT_EXOMailboxFolderUserPermission { + User = 'Anonymous' + AccessRights = 'AvailabilityOnly' + } + MSFT_EXOMailboxFolderUserPermission { + User = 'AlexW' + AccessRights = 'Owner' + SharingPermissionFlags = 'Delegate' + } + ); + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXOMailboxFolderPermission "EXOMailboxFolderPermission-admin:\Calendar" + { + Credential = $Credscredential; + Ensure = "Present"; + Identity = "admin:\Calendar"; + UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { + User = 'Default' + AccessRights = 'AvailabilityOnly' + } +MSFT_EXOMailboxFolderUserPermission { + User = 'Anonymous' + AccessRights = 'AvailabilityOnly' + } +MSFT_EXOMailboxFolderUserPermission { + User = 'AlexW' + AccessRights = 'Editor' + SharingPermissionFlags = 'Delegate' + } + ); + } + } +} +``` + From d2370135a456965ce514343ddc3ce6039c50f410 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 12:12:17 +0000 Subject: [PATCH 347/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 3d43328188..15961af754 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -10449,6 +10449,86 @@ } ] }, + { + "ClassName": "MSFT_EXOMailboxFolderUserPermission", + "Parameters": [ + { + "CIMType": "String[]", + "Name": "AccessRights", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "User", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SharingPermissionFlags", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_EXOMailboxFolderPermission", + "Parameters": [ + { + "CIMType": "String", + "Name": "Identity", + "Option": "Key" + }, + { + "CIMType": "MSFT_EXOMailboxFolderUserPermission[]", + "Name": "UserPermissions", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "CertificatePassword", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificatePath", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOMailboxIRMAccess", "Parameters": [ From 34518433a55823989439ed24957f38fb2f7333f2 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 12:12:26 +0000 Subject: [PATCH 348/465] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index e6ed079a01..a73d8c8c5e 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -401,6 +401,26 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOMailboxFolderPermission 'EXOMailboxFolderPermission-admin:\Calendar' + { + Credential = $Credscredential; + Ensure = "Present"; + Identity = "amdin:\Calendar"; + UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { + User = 'Default' + AccessRights = 'AvailabilityOnly' + } + MSFT_EXOMailboxFolderUserPermission { + User = 'Anonymous' + AccessRights = 'AvailabilityOnly' + } + MSFT_EXOMailboxFolderUserPermission { + User = 'AlexW' + AccessRights = 'Owner' + SharingPermissionFlags = 'Delegate' + } + ); + } EXOMailboxIRMAccess 'EXOMailboxIRMAccess-qwe@testorg.onmicrosoft.com' { AccessLevel = "Block"; From 721f59d6b080bbbef292ca38dac0111b67afe91a Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 12:12:55 +0000 Subject: [PATCH 349/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index 4b112d0d83..1ad7ba24e4 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -669,6 +669,26 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXOMailboxFolderPermission 'EXOMailboxFolderPermission-admin:\Calendar' + { + Credential = $Credscredential; + Ensure = "Present"; + Identity = "admin:\Calendar"; + UserPermissions = @(MSFT_EXOMailboxFolderUserPermission { + User = 'Default' + AccessRights = 'AvailabilityOnly' + } + MSFT_EXOMailboxFolderUserPermission { + User = 'Anonymous' + AccessRights = 'AvailabilityOnly' + } + MSFT_EXOMailboxFolderUserPermission { + User = 'AlexW' + AccessRights = 'Editor' + SharingPermissionFlags = 'Delegate' + } + ); + } EXOMailboxPermission 'TestPermission' { AccessRights = @("FullAccess","ReadPermission"); From 373b5da22d54834a7c07bfbea11c9a1f2f401c66 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 12:15:49 +0000 Subject: [PATCH 350/465] Updated Resources and Cmdlet documentation pages --- .../azure-ad/AADFeatureRolloutPolicy.md | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 docs/docs/resources/azure-ad/AADFeatureRolloutPolicy.md diff --git a/docs/docs/resources/azure-ad/AADFeatureRolloutPolicy.md b/docs/docs/resources/azure-ad/AADFeatureRolloutPolicy.md new file mode 100644 index 0000000000..af846e1668 --- /dev/null +++ b/docs/docs/resources/azure-ad/AADFeatureRolloutPolicy.md @@ -0,0 +1,171 @@ +# AADFeatureRolloutPolicy + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Description** | Write | String | A description for this feature rollout policy. | | +| **DisplayName** | Key | String | The display name for this feature rollout policy. | | +| **Feature** | Write | String | Possible values are: passthroughAuthentication, seamlessSso, passwordHashSync, emailAsAlternateId, unknownFutureValue, certificateBasedAuthentication. You must use the Prefer: include-unknown-enum-members request header to get the following value or values in this evolvable enum: certificateBasedAuthentication. For more information about the prerequisites for the enabled features, see Prerequisites for enabled features. | `passthroughAuthentication`, `seamlessSso`, `passwordHashSync`, `emailAsAlternateId`, `unknownFutureValue`, `certificateBasedAuthentication` | +| **IsAppliedToOrganization** | Write | Boolean | Indicates whether this feature rollout policy should be applied to the entire organization. | | +| **IsEnabled** | Write | Boolean | Indicates whether the feature rollout is enabled. | | +| **Id** | Write | String | The unique identifier for an entity. Read-only. | | +| **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Azure AD Policy Feature Rollout Policy + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - Directory.Read.All + +- **Update** + + - Directory.ReadWrite.All + +#### Application permissions + +- **Read** + + - Directory.Read.All + +- **Update** + + - Directory.ReadWrite.All + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADFeatureRolloutPolicy "AADFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Description = "CertificateBasedAuthentication rollout policy"; + DisplayName = "CertificateBasedAuthentication rollout policy"; + Ensure = "Present"; + Feature = "certificateBasedAuthentication"; + IsAppliedToOrganization = $False; + IsEnabled = $True; + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADFeatureRolloutPolicy "AADFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Description = "CertificateBasedAuthentication rollout policy"; + DisplayName = "CertificateBasedAuthentication rollout policy"; + Ensure = "Present"; + IsAppliedToOrganization = $False; + IsEnabled = $False; + } + } +} +``` + +### Example 3 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + AADFeatureRolloutPolicy "AADFeatureRolloutPolicy-CertificateBasedAuthentication rollout policy" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + DisplayName = "CertificateBasedAuthentication rollout policy"; + Ensure = "Absent"; + } + } +} +``` + From 1cf4cc00057bec1d8fdd0f73f91a8a477c7b130c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 13:11:16 +0000 Subject: [PATCH 351/465] Updated Resources and Cmdlet documentation pages --- .../docs/resources/azure-ad/AADApplication.md | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/docs/docs/resources/azure-ad/AADApplication.md b/docs/docs/resources/azure-ad/AADApplication.md index 00a9a29f14..857f6513b8 100644 --- a/docs/docs/resources/azure-ad/AADApplication.md +++ b/docs/docs/resources/azure-ad/AADApplication.md @@ -14,6 +14,11 @@ | **IdentifierUris** | Write | StringArray[] | User-defined URI(s) that uniquely identify a Web application within its Azure AD tenant, or within a verified custom domain. | | | **IsFallbackPublicClient** | Write | Boolean | Specifies the fallback application type as public client, such as an installed application running on a mobile device. The default value is false, which means the fallback application type is confidential client such as web app. There are certain scenarios where Microsoft Entra ID cannot determine the client application type (for example, ROPC flow where it is configured without specifying a redirect URI). In those cases, Microsoft Entra ID will interpret the application type based on the value of this property. | | | **KnownClientApplications** | Write | StringArray[] | Client applications that are tied to this resource application. | | +| **Api** | Write | MSFT_MicrosoftGraphapiApplication | Specifies settings for an application that implements a web API. | | +| **AuthenticationBehaviors** | Write | MSFT_MicrosoftGraphauthenticationBehaviors | The collection of breaking change behaviors related to token issuance that are configured for the application. Authentication behaviors are unset by default (null) and must be explicitly enabled or disabled. Nullable. Returned only on $select. For more information about authentication behaviors, see Manage application authenticationBehaviors to avoid unverified use of email claims for user identification or authorization. | | +| **PasswordCredentials** | Write | MSFT_MicrosoftGraphpasswordCredential[] | The collection of password credentials associated with the application. Not nullable. | | +| **KeyCredentials** | Write | MSFT_MicrosoftGraphkeyCredential[] | The collection of key credentials associated with the application. Not nullable. Supports $filter (eq, not, ge, le). | | +| **AppRoles** | Write | MSFT_MicrosoftGraphappRole[] | The collection of roles defined for the application. With app role assignments, these roles can be assigned to users, groups, or service principals associated with other applications. Not nullable. | | | **LogoutURL** | Write | String | The logout url for this application. | | | **PublicClient** | Write | Boolean | Specifies whether this application is a public client (such as an installed application running on a mobile device). Default is false. | | | **ReplyURLs** | Write | StringArray[] | Specifies the URLs that user tokens are sent to for sign in, or the redirect URIs that OAuth 2.0 authorization codes and access tokens are sent to. | | @@ -39,6 +44,74 @@ | **Type** | Write | String | Type of permission. | `AppOnly`, `Delegated` | | **AdminConsentGranted** | Write | Boolean | Represented whether or not the Admin consent been granted on the app. | | +### MSFT_MicrosoftGraphPreAuthorizedApplication + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **AppId** | Write | String | The unique identifier for the client application. | | +| **PermissionIds** | Write | StringArray[] | The unique identifier for the scopes the client application is granted. | | + +### MSFT_MicrosoftGraphApiApplication + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **PreAuthorizedApplications** | Write | MSFT_MicrosoftGraphPreAuthorizedApplication[] | Lists the client applications that are preauthorized with the specified delegated permissions to access this application's APIs. Users aren't required to consent to any preauthorized application (for the permissions specified). However, any other permissions not listed in preAuthorizedApplications (requested through incremental consent for example) will require user consent. | | + +### MSFT_MicrosoftGraphAuthenticationBehaviors + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **BlockAzureADGraphAccess** | Write | Boolean | If false, allows the app to have extended access to Azure AD Graph until June 30, 2025 when Azure AD Graph is fully retired. For more information on Azure AD retirement updates, see June 2024 update on Azure AD Graph API retirement. | | +| **RemoveUnverifiedEmailClaim** | Write | Boolean | If true, removes the email claim from tokens sent to an application when the email address's domain can't be verified. | | +| **RequireClientServicePrincipal** | Write | Boolean | If true, requires multitenant applications to have a service principal in the resource tenant as part of authorization checks before they're granted access tokens. This property is only modifiable for multitenant resource applications that rely on access from clients without a service principal and had this behavior as set to false by Microsoft. Tenant administrators should respond to security advisories sent through Azure Health Service events and the Microsoft 365 message center. | | + +### MSFT_MicrosoftGraphKeyCredential + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **CustomKeyIdentifier** | Write | String | A 40-character binary type that can be used to identify the credential. Optional. When not provided in the payload, defaults to the thumbprint of the certificate. | | +| **DisplayName** | Write | String | Friendly name for the key. Optional. | | +| **EndDateTime** | Write | String | The date and time at which the credential expires. The DateTimeOffset type represents date and time information using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z. | | +| **KeyId** | Write | String | The unique identifier (GUID) for the key. | | +| **Key** | Write | String | The certificate's raw data in byte array converted to Base64 string. | | +| **StartDateTime** | Write | String | The date and time at which the credential becomes valid.The Timestamp type represents date and time information using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z. | | +| **Type** | Write | String | The type of key credential for example, Symmetric, AsymmetricX509Cert. | | +| **Usage** | Write | String | A string that describes the purpose for which the key can be used for example, Verify. | | + +### MSFT_MicrosoftGraphPasswordCredential + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **DisplayName** | Write | String | Friendly name for the password. Optional. | | +| **EndDateTime** | Write | String | The date and time at which the password expires represented using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z. Optional. | | +| **Hint** | Write | String | Contains the first three characters of the password. Read-only. | | +| **KeyId** | Write | String | The unique identifier for the password. | | +| **StartDateTime** | Write | String | The date and time at which the password becomes valid. The Timestamp type represents date and time information using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z. Optional. | | + +### MSFT_MicrosoftGraphAppRole + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **AllowedMemberTypes** | Write | StringArray[] | Specifies whether this app role can be assigned to users and groups (by setting to 'User'), to other application's (by setting to 'Application', or both (by setting to 'User', 'Application'). App roles supporting assignment to other applications' service principals are also known as application permissions. The 'Application' value is only supported for app roles defined on application entities. | | +| **Description** | Write | String | The description for the app role. This is displayed when the app role is being assigned and, if the app role functions as an application permission, during consent experiences. | | +| **DisplayName** | Write | String | Display name for the permission that appears in the app role assignment and consent experiences. | | +| **Id** | Write | String | Unique role identifier inside the appRoles collection. When creating a new app role, a new GUID identifier must be provided. | | +| **IsEnabled** | Write | Boolean | When creating or updating an app role, this must be set to true (which is the default). To delete a role, this must first be set to false. At that point, in a subsequent call, this role may be removed. | | +| **Origin** | Write | String | Specifies if the app role is defined on the application object or on the servicePrincipal entity. Must not be included in any POST or PATCH requests. Read-only. | | +| **Value** | Write | String | Specifies the value to include in the roles claim in ID tokens and access tokens authenticating an assigned user or service principal. Must not exceed 120 characters in length. Allowed characters are : ! # $ % & ' ( ) * + , - . / : = + _ } , and characters in the ranges 0-9, A-Z and a-z. Any other character, including the space character, aren't allowed. May not begin with .. | | + ## Description This resource configures an Azure Active Directory Application. From e02a772f05cb7477d873c27061981fe69c09edcf Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 13:13:26 +0000 Subject: [PATCH 352/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 9335c4e679..91818ac8a4 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -204,6 +204,166 @@ } ] }, + { + "ClassName": "MSFT_MicrosoftGraphPreAuthorizedApplication", + "Parameters": [ + { + "CIMType": "String", + "Name": "AppId", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "PermissionIds", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_MicrosoftGraphApiApplication", + "Parameters": [ + { + "CIMType": "MSFT_MicrosoftGraphPreAuthorizedApplication[]", + "Name": "PreAuthorizedApplications", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_MicrosoftGraphAuthenticationBehaviors", + "Parameters": [ + { + "CIMType": "Boolean", + "Name": "BlockAzureADGraphAccess", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "RemoveUnverifiedEmailClaim", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "RequireClientServicePrincipal", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_MicrosoftGraphKeyCredential", + "Parameters": [ + { + "CIMType": "String", + "Name": "CustomKeyIdentifier", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "EndDateTime", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "KeyId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Key", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "StartDateTime", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Type", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Usage", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_MicrosoftGraphPasswordCredential", + "Parameters": [ + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "EndDateTime", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Hint", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "KeyId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "StartDateTime", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_MicrosoftGraphAppRole", + "Parameters": [ + { + "CIMType": "String[]", + "Name": "AllowedMemberTypes", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Origin", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Value", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AADApplication", "Parameters": [ @@ -257,6 +417,31 @@ "Name": "KnownClientApplications", "Option": "Write" }, + { + "CIMType": "MSFT_MicrosoftGraphapiApplication", + "Name": "Api", + "Option": "Write" + }, + { + "CIMType": "MSFT_MicrosoftGraphauthenticationBehaviors", + "Name": "AuthenticationBehaviors", + "Option": "Write" + }, + { + "CIMType": "MSFT_MicrosoftGraphpasswordCredential[]", + "Name": "PasswordCredentials", + "Option": "Write" + }, + { + "CIMType": "MSFT_MicrosoftGraphkeyCredential[]", + "Name": "KeyCredentials", + "Option": "Write" + }, + { + "CIMType": "MSFT_MicrosoftGraphappRole[]", + "Name": "AppRoles", + "Option": "Write" + }, { "CIMType": "string", "Name": "LogoutURL", From c423da9bd0560dc313f2bfedaec7bb99c7cc4fcb Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 13:49:01 +0000 Subject: [PATCH 353/465] Updated Graph Permissions List --- Tests/QA/Graph.PermissionList.txt | Bin 5992 -> 5764 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index ab0533d4a562a696ceb8dde1d556c0239f1be4cc..a592902d7870e3cc7cedf983278e2144cc18d20d 100644 GIT binary patch delta 31 ncmaE%*P_ex|KG$1dXw!Kc{V<}#XZ?TlxOk-UZKqrya8MQG3pqr^amhI{DT-p(<;Wy1> Date: Fri, 27 Sep 2024 15:29:19 +0000 Subject: [PATCH 354/465] Updated Resources and Cmdlet documentation pages --- .../azure-ad/AADAuthenticationMethodPolicy.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/docs/resources/azure-ad/AADAuthenticationMethodPolicy.md b/docs/docs/resources/azure-ad/AADAuthenticationMethodPolicy.md index fd9fa85e4c..6f9800c0a1 100644 --- a/docs/docs/resources/azure-ad/AADAuthenticationMethodPolicy.md +++ b/docs/docs/resources/azure-ad/AADAuthenticationMethodPolicy.md @@ -10,6 +10,7 @@ | **PolicyVersion** | Write | String | The version of the policy in use. | | | **ReconfirmationInDays** | Write | UInt32 | Days before the user will be asked to reconfirm their method. | | | **RegistrationEnforcement** | Write | MSFT_MicrosoftGraphregistrationEnforcement | Enforce registration at sign-in time. This property can be used to remind users to set up targeted authentication methods. | | +| **ReportSuspiciousActivitySettings** | Write | MSFT_MicrosoftGraphreportSuspiciousActivitySettings | Allows users to report suspicious activities if they receive an authentication request that they did not initiate. | | | **SystemCredentialPreferences** | Write | MSFT_MicrosoftGraphsystemCredentialPreferences | Prompt users with their most-preferred credential for multifactor authentication. | | | **Id** | Write | String | The unique identifier for an entity. Read-only. | | | **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present` | @@ -87,6 +88,16 @@ | **IncludeTargets** | Write | MSFT_AADAuthenticationMethodPolicyIncludeTarget[] | Users and groups included in the preferred authentication method experience of the system. | | | **State** | Write | String | Indicates whether the feature is enabled or disabled. Possible values are: default, enabled, disabled, unknownFutureValue. The default value is used when the configuration hasn't been explicitly set, and uses the default behavior of Azure Active Directory for the setting. The default value is disabled. | `default`, `enabled`, `disabled`, `unknownFutureValue` | +### MSFT_MicrosoftGraphReportSuspiciousActivitySettings + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **IncludeTarget** | Write | MSFT_AADAuthenticationMethodPolicyIncludeTarget | Group IDs in scope for report suspicious activity. | | +| **State** | Write | String | Specifies the state of the reportSuspiciousActivitySettings object. | `default`, `enabled`, `disabled`, `unknownFutureValue` | +| **VoiceReportingCode** | Write | UInt32 | Specifies the number the user enters on their phone to report the MFA prompt as suspicious. | | + ## Description @@ -165,6 +176,14 @@ Configuration Example State = 'default' } }; + ReportSuspiciousActivitySettings = MSFT_MicrosoftGraphreportSuspiciousActivitySettings{ + VoiceReportingCode = 0 + IncludeTarget = MSFT_AADAuthenticationMethodPolicyIncludeTarget{ + Id = 'all_users' + TargetType = 'group' + } + State = 'default' + }; ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint From 579de5760b84b1461223b7934d77ba6934355b27 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 15:29:48 +0000 Subject: [PATCH 355/465] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Update.Tests.ps1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index a16837b9e2..04b4cafdf2 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -149,6 +149,14 @@ State = 'default' } }; + ReportSuspiciousActivitySettings = MSFT_MicrosoftGraphreportSuspiciousActivitySettings{ + VoiceReportingCode = 0 + IncludeTarget = MSFT_AADAuthenticationMethodPolicyIncludeTarget{ + Id = 'all_users' + TargetType = 'group' + } + State = 'default' + }; ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint From d6b592cf70b370b99a6a798420fd0c7916af1c5d Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 27 Sep 2024 15:31:13 +0000 Subject: [PATCH 356/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 91818ac8a4..9e3a40d0d6 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -819,6 +819,26 @@ } ] }, + { + "ClassName": "MSFT_MicrosoftGraphReportSuspiciousActivitySettings", + "Parameters": [ + { + "CIMType": "MSFT_AADAuthenticationMethodPolicyIncludeTarget", + "Name": "IncludeTarget", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "State", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "VoiceReportingCode", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_AADAuthenticationMethodPolicy", "Parameters": [ @@ -852,6 +872,11 @@ "Name": "RegistrationEnforcement", "Option": "Write" }, + { + "CIMType": "MSFT_MicrosoftGraphreportSuspiciousActivitySettings", + "Name": "ReportSuspiciousActivitySettings", + "Option": "Write" + }, { "CIMType": "MSFT_MicrosoftGraphsystemCredentialPreferences", "Name": "SystemCredentialPreferences", From e6d54cf7b8fb77f670a5d7dafbc6c6e06a77d5b6 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 27 Sep 2024 16:20:55 -0400 Subject: [PATCH 357/465] SCInsiderRiskPolicy - Initial Release --- .../MSFT_SCInsiderRiskPolicy.psm1 | 404 +++++++++++------- .../MSFT_SCInsiderRiskPolicy.schema.mof | 282 ++++++------ .../MSFT_SCInsiderRiskPolicy/readme.md | 4 +- .../MSFT_SCInsiderRiskPolicy/settings.json | 20 +- .../SCInsiderRiskPolicy/1-Create.ps1 | 140 +++++- .../SCInsiderRiskPolicy/2-Update.ps1 | 140 +++++- .../SCInsiderRiskPolicy/3-Remove.ps1 | 10 +- ...rosoft365DSC.SCInsiderRiskPolicy.Tests.ps1 | 112 +++-- Tests/Unit/Stubs/Microsoft365.psm1 | 381 +++++++++++++++++ 9 files changed, 1157 insertions(+), 336 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 index 1285bc70ea..051da6de2c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 @@ -8,6 +8,14 @@ function Get-TargetResource [System.String] $Name, + [Parameter(Mandatory = $true)] + [System.String] + $InsiderRiskScenario, + + [Parameter()] + [System.Boolean] + $Anonymization, + [Parameter()] [System.Boolean] $DLPUserRiskSync, @@ -553,19 +561,19 @@ function Get-TargetResource $SessionRecordingEnabled, [Parameter()] - [System.Boolean] + [System.String] $RecordingTimeframePreEventInSec, [Parameter()] - [System.Boolean] + [System.String] $RecordingTimeframePostEventInSec, [Parameter()] - [System.Boolean] + [System.String] $BandwidthCapInMb, [Parameter()] - [System.Boolean] + [System.String] $OfflineRecordingStorageLimitInMb, [Parameter()] @@ -626,8 +634,14 @@ function Get-TargetResource $instance = Get-InsiderRiskPolicy -Identity $Name } + if ($null -eq $instance) + { + return $nullResult + } + $results = @{ Name = $instance.Name + InsiderRiskScenario = $instance.InsiderRiskScenario Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -641,8 +655,8 @@ function Get-TargetResource { $SessionRecordingSettings = ConvertFrom-Json $instance.SessionRecordingSettings $forensicSettingsHash = @{ - ClipDeletionEnabled = [Boolean]$SessionRecordingSettings.ClipDeletionEnabled - SessionRecordingEnabled = [Boolean]$SessionRecordingSettings.Enabled + ClipDeletionEnabled = [Boolean]($SessionRecordingSettings.ClipDeletionEnabled) + SessionRecordingEnabled = [Boolean]($SessionRecordingSettings.Enabled) RecordingTimeframePreEventInSec = $SessionRecordingSettings.RecordingTimeframePreEventInSec RecordingTimeframePostEventInSec = $SessionRecordingSettings.RecordingTimeframePostEventInSec BandwidthCapInMb = $SessionRecordingSettings.BandwidthCapInMb @@ -651,136 +665,137 @@ function Get-TargetResource $results += $forensicSettingsHash } - if (-not [System.String]::IsNullOrEmpty($instance.TenantSettings)) + if (-not [System.String]::IsNullOrEmpty($instance.TenantSettings) -and $instance.TenantSettings.Length -gt 0) { $tenantSettings = ConvertFrom-Json $instance.TenantSettings[0] $tenantSettingsHash = @{ - DLPUserRiskSync = [Boolean]$tenantSettings.FeatureSettings.DLPUserRiskSync - OptInIRMDataExport = [Boolean]$tenantSettings.FeatureSettings.OptInIRMDataExport - RaiseAuditAlert = [Boolean]$tenantSettings.FeatureSettings.RaiseAuditAlert + Anonymization = [Boolean]($tenantSettings.FeatureSettings.Anonymization) + DLPUserRiskSync = [Boolean]($tenantSettings.FeatureSettings.DLPUserRiskSync) + OptInIRMDataExport = [Boolean]($tenantSettings.FeatureSettings.OptInIRMDataExport) + RaiseAuditAlert = [Boolean]($tenantSettings.FeatureSettings.RaiseAuditAlert) FileVolCutoffLimits = $tenantSettings.IntelligentDetections.FileVolCutoffLimits AlertVolume = $tenantSettings.IntelligentDetections.AlertVolume - AnomalyDetections = [Boolean]$tenantSettings.Indicators.AnomalyDetections - CopyToPersonalCloud = [Boolean]$tenantSettings.Indicators.CopyToPersonalCloud - CopyToUSB = [Boolean]$tenantSettings.Indicators.CopyToUSB - CumulativeExfiltrationDetector = [Boolean]$tenantSettings.Indicators.CumulativeExfiltrationDetector - EmailExternal = [Boolean]$tenantSettings.Indicators.EmailExternal - EmployeeAccessedEmployeePatientData = [Boolean]$tenantSettings.Indicators.EmployeeAccessedEmployeePatientData - EmployeeAccessedFamilyData = [Boolean]$tenantSettings.Indicators.EmployeeAccessedFamilyData - EmployeeAccessedHighVolumePatientData = [Boolean]$tenantSettings.Indicators.EmployeeAccessedHighVolumePatientData - EmployeeAccessedNeighbourData = [Boolean]$tenantSettings.Indicators.EmployeeAccessedNeighbourData - EmployeeAccessedRestrictedData = [Boolean]$tenantSettings.Indicators.EmployeeAccessedRestrictedData - EpoBrowseToChildAbuseSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToChildAbuseSites - EpoBrowseToCriminalActivitySites = [Boolean]$tenantSettings.Indicators.EpoBrowseToCriminalActivitySites - EpoBrowseToCultSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToCultSites - EpoBrowseToGamblingSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToGamblingSites - EpoBrowseToHackingSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToHackingSites - EpoBrowseToHateIntoleranceSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToHateIntoleranceSites - EpoBrowseToIllegalSoftwareSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToIllegalSoftwareSites - EpoBrowseToKeyloggerSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToKeyloggerSites - EpoBrowseToLlmSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToLlmSites - EpoBrowseToMalwareSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToMalwareSites - EpoBrowseToPhishingSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToPhishingSites - EpoBrowseToPornographySites = [Boolean]$tenantSettings.Indicators.EpoBrowseToPornographySites - EpoBrowseToUnallowedDomain = [Boolean]$tenantSettings.Indicators.EpoBrowseToUnallowedDomain - EpoBrowseToViolenceSites = [Boolean]$tenantSettings.Indicators.EpoBrowseToViolenceSites - EpoCopyToClipboardFromSensitiveFile = [Boolean]$tenantSettings.Indicators.EpoCopyToClipboardFromSensitiveFile - EpoCopyToNetworkShare = [Boolean]$tenantSettings.Indicators.EpoCopyToNetworkShare - EpoFileArchived = [Boolean]$tenantSettings.Indicators.EpoFileArchived - EpoFileCopiedToRemoteDesktopSession = [Boolean]$tenantSettings.Indicators.EpoFileCopiedToRemoteDesktopSession - EpoFileDeleted = [Boolean]$tenantSettings.Indicators.EpoFileDeleted - EpoFileDownloadedFromBlacklistedDomain = [Boolean]$tenantSettings.Indicators.EpoFileDownloadedFromBlacklistedDomain - EpoFileDownloadedFromEnterpriseDomain = [Boolean]$tenantSettings.Indicators.EpoFileDownloadedFromEnterpriseDomain - EpoFileRenamed = [Boolean]$tenantSettings.Indicators.EpoFileRenamed - EpoFileStagedToCentralLocation = [Boolean]$tenantSettings.Indicators.EpoFileStagedToCentralLocation - EpoHiddenFileCreated = [Boolean]$tenantSettings.Indicators.EpoHiddenFileCreated - EpoRemovableMediaMount = [Boolean]$tenantSettings.Indicators.EpoRemovableMediaMount - EpoSensitiveFileRead = [Boolean]$tenantSettings.Indicators.EpoSensitiveFileRead - Mcas3rdPartyAppDownload = [Boolean]$tenantSettings.Indicators.Mcas3rdPartyAppDownload - Mcas3rdPartyAppFileDelete = [Boolean]$tenantSettings.Indicators.Mcas3rdPartyAppFileDelete - Mcas3rdPartyAppFileSharing = [Boolean]$tenantSettings.Indicators.Mcas3rdPartyAppFileSharing - McasActivityFromInfrequentCountry = [Boolean]$tenantSettings.Indicators.McasActivityFromInfrequentCountry - McasImpossibleTravel = [Boolean]$tenantSettings.Indicators.McasImpossibleTravel - McasMultipleFailedLogins = [Boolean]$tenantSettings.Indicators.McasMultipleFailedLogins - McasMultipleStorageDeletion = [Boolean]$tenantSettings.Indicators.McasMultipleStorageDeletion - McasMultipleVMCreation = [Boolean]$tenantSettings.Indicators.McasMultipleVMCreation - McasMultipleVMDeletion = [Boolean]$tenantSettings.Indicators.McasMultipleVMDeletion - McasSuspiciousAdminActivities = [Boolean]$tenantSettings.Indicators.McasSuspiciousAdminActivities - McasSuspiciousCloudCreation = [Boolean]$tenantSettings.Indicators.McasSuspiciousCloudCreation - McasSuspiciousCloudTrailLoggingChange = [Boolean]$tenantSettings.Indicators.McasSuspiciousCloudTrailLoggingChange - McasTerminatedEmployeeActivity = [Boolean]$tenantSettings.Indicators.McasTerminatedEmployeeActivity - OdbDownload = [Boolean]$tenantSettings.Indicators.OdbDownload - OdbSyncDownload = [Boolean]$tenantSettings.Indicators.OdbSyncDownload - PeerCumulativeExfiltrationDetector = [Boolean]$tenantSettings.Indicators.PeerCumulativeExfiltrationDetector - PhysicalAccess = [Boolean]$tenantSettings.Indicators.PhysicalAccess - PotentialHighImpactUser = [Boolean]$tenantSettings.Indicators.PotentialHighImpactUser - Print = [Boolean]$tenantSettings.Indicators.Print - PriorityUserGroupMember = [Boolean]$tenantSettings.Indicators.PriorityUserGroupMember - SecurityAlertDefenseEvasion = [Boolean]$tenantSettings.Indicators.SecurityAlertDefenseEvasion - SecurityAlertUnwantedSoftware = [Boolean]$tenantSettings.Indicators.SecurityAlertUnwantedSoftware - SpoAccessRequest = [Boolean]$tenantSettings.Indicators.SpoAccessRequest - SpoApprovedAccess = [Boolean]$tenantSettings.Indicators.SpoApprovedAccess - SpoDownload = [Boolean]$tenantSettings.Indicators.SpoDownload - SpoDownloadV2 = [Boolean]$tenantSettings.Indicators.SpoDownloadV2 - SpoFileAccessed = [Boolean]$tenantSettings.Indicators.SpoFileAccessed - SpoFileDeleted = [Boolean]$tenantSettings.Indicators.SpoFileDeleted - SpoFileDeletedFromFirstStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFileDeletedFromFirstStageRecycleBin - SpoFileDeletedFromSecondStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFileDeletedFromSecondStageRecycleBin - SpoFileLabelDowngraded = [Boolean]$tenantSettings.Indicators.SpoFileLabelDowngraded - SpoFileLabelRemoved = [Boolean]$tenantSettings.Indicators.SpoFileLabelRemoved - SpoFileSharing = [Boolean]$tenantSettings.Indicators.SpoFileSharing - SpoFolderDeleted = [Boolean]$tenantSettings.Indicators.SpoFolderDeleted - SpoFolderDeletedFromFirstStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFolderDeletedFromFirstStageRecycleBin - SpoFolderDeletedFromSecondStageRecycleBin = [Boolean]$tenantSettings.Indicators.SpoFolderDeletedFromSecondStageRecycleBin - SpoFolderSharing = [Boolean]$tenantSettings.Indicators.SpoFolderSharing - SpoSiteExternalUserAdded = [Boolean]$tenantSettings.Indicators.SpoSiteExternalUserAdded - SpoSiteInternalUserAdded = [Boolean]$tenantSettings.Indicators.SpoSiteInternalUserAdded - SpoSiteLabelRemoved = [Boolean]$tenantSettings.Indicators.SpoSiteLabelRemoved - SpoSiteSharing = [Boolean]$tenantSettings.Indicators.SpoSiteSharing - SpoSyncDownload = [Boolean]$tenantSettings.Indicators.SpoSyncDownload - TeamsChannelFileSharedExternal = [Boolean]$tenantSettings.Indicators.TeamsChannelFileSharedExternal - TeamsChannelMemberAddedExternal = [Boolean]$tenantSettings.Indicators.TeamsChannelMemberAddedExternal - TeamsChatFileSharedExternal = [Boolean]$tenantSettings.Indicators.TeamsChatFileSharedExternal - TeamsFileDownload = [Boolean]$tenantSettings.Indicators.TeamsFileDownload - TeamsFolderSharedExternal = [Boolean]$tenantSettings.Indicators.TeamsFolderSharedExternal - TeamsMemberAddedExternal = [Boolean]$tenantSettings.Indicators.TeamsMemberAddedExternal - TeamsSensitiveMessage = [Boolean]$tenantSettings.Indicators.TeamsSensitiveMessage - UserHistory = [Boolean]$tenantSettings.Indicators.UserHistory - AWSS3BlockPublicAccessDisabled = [Boolean]$tenantSettings.ExtensibleIndicators.AWSS3BlockPublicAccessDisabled - AWSS3BucketDeleted = [Boolean]$tenantSettings.ExtensibleIndicators.AWSS3BucketDeleted - AWSS3PublicAccessEnabled = [Boolean]$tenantSettings.ExtensibleIndicators.AWSS3PublicAccessEnabled - AWSS3ServerLoggingDisabled = [Boolean]$tenantSettings.ExtensibleIndicators.AWSS3ServerLoggingDisabled - AzureElevateAccessToAllSubscriptions = [Boolean]$tenantSettings.ExtensibleIndicators.AzureElevateAccessToAllSubscriptions - AzureResourceThreatProtectionSettingsUpdated = [Boolean]$tenantSettings.ExtensibleIndicators.AzureResourceThreatProtectionSettingsUpdated - AzureSQLServerAuditingSettingsUpdated = [Boolean]$tenantSettings.ExtensibleIndicators.AzureSQLServerAuditingSettingsUpdated - AzureSQLServerFirewallRuleDeleted = [Boolean]$tenantSettings.ExtensibleIndicators.AzureSQLServerFirewallRuleDeleted - AzureSQLServerFirewallRuleUpdated = [Boolean]$tenantSettings.ExtensibleIndicators.AzureSQLServerFirewallRuleUpdated - AzureStorageAccountOrContainerDeleted = [Boolean]$tenantSettings.ExtensibleIndicators.AzureStorageAccountOrContainerDeleted - BoxContentAccess = [Boolean]$tenantSettings.ExtensibleIndicators.BoxContentAccess - BoxContentDelete = [Boolean]$tenantSettings.ExtensibleIndicators.BoxContentDelete - BoxContentDownload = [Boolean]$tenantSettings.ExtensibleIndicators.BoxContentDownload - BoxContentExternallyShared = [Boolean]$tenantSettings.ExtensibleIndicators.BoxContentExternallyShared - CCFinancialRegulatoryRiskyTextSent = [Boolean]$tenantSettings.ExtensibleIndicators.CCFinancialRegulatoryRiskyTextSent - CCInappropriateContentSent = [Boolean]$tenantSettings.ExtensibleIndicators.CCInappropriateContentSent - CCInappropriateImagesSent = [Boolean]$tenantSettings.ExtensibleIndicators.CCInappropriateImagesSent - DropboxContentAccess = [Boolean]$tenantSettings.ExtensibleIndicators.DropboxContentAccess - DropboxContentDelete = [Boolean]$tenantSettings.ExtensibleIndicators.DropboxContentDelete - DropboxContentDownload = [Boolean]$tenantSettings.ExtensibleIndicators.DropboxContentDownload - DropboxContentExternallyShared = [Boolean]$tenantSettings.ExtensibleIndicators.DropboxContentExternallyShared - GoogleDriveContentAccess = [Boolean]$tenantSettings.ExtensibleIndicators.GoogleDriveContentAccess - GoogleDriveContentDelete = [Boolean]$tenantSettings.ExtensibleIndicators.GoogleDriveContentDelete - GoogleDriveContentExternallyShared = [Boolean]$tenantSettings.ExtensibleIndicators.GoogleDriveContentExternallyShared - PowerBIDashboardsDeleted = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBIDashboardsDeleted - PowerBIReportsDeleted = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBIReportsDeleted - PowerBIReportsDownloaded = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBIReportsDownloaded - PowerBIReportsExported = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBIReportsExported - PowerBIReportsViewed = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBIReportsViewed - PowerBISemanticModelsDeleted = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBISemanticModelsDeleted - PowerBISensitivityLabelDowngradedForArtifacts = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBISensitivityLabelDowngradedForArtifacts - PowerBISensitivityLabelRemovedFromArtifacts = [Boolean]$tenantSettings.ExtensibleIndicators.PowerBISensitivityLabelRemovedFromArtifacts + AnomalyDetections = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'AnomalyDetections'}).Enabled + CopyToPersonalCloud = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'CopyToPersonalCloud'}).Enabled + CopyToUSB = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'CopyToUSB'}).Enabled + CumulativeExfiltrationDetector = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'CumulativeExfiltrationDetector'}).Enabled + EmailExternal = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EmailExternal'}).Enabled + EmployeeAccessedEmployeePatientData = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EmployeeAccessedEmployeePatientData'}).Enabled + EmployeeAccessedFamilyData = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EmployeeAccessedFamilyData'}).Enabled + EmployeeAccessedHighVolumePatientData = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EmployeeAccessedHighVolumePatientData'}).Enabled + EmployeeAccessedNeighbourData = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EmployeeAccessedNeighbourData'}).Enabled + EmployeeAccessedRestrictedData = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EmployeeAccessedRestrictedData'}).Enabled + EpoBrowseToChildAbuseSites = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoBrowseToChildAbuseSites'}).Enabled + EpoBrowseToCriminalActivitySites = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoBrowseToCriminalActivitySites'}).Enabled + EpoBrowseToCultSites = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoBrowseToCultSites'}).Enabled + EpoBrowseToGamblingSites = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoBrowseToGamblingSites'}).Enabled + EpoBrowseToHackingSites = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoBrowseToHackingSites'}).Enabled + EpoBrowseToHateIntoleranceSites = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoBrowseToHateIntoleranceSites'}).Enabled + EpoBrowseToIllegalSoftwareSites = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoBrowseToIllegalSoftwareSites'}).Enabled + EpoBrowseToKeyloggerSites = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoBrowseToKeyloggerSites'}).Enabled + EpoBrowseToLlmSites = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoBrowseToLlmSites'}).Enabled + EpoBrowseToMalwareSites = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoBrowseToMalwareSites'}).Enabled + EpoBrowseToPhishingSites = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoBrowseToPhishingSites'}).Enabled + EpoBrowseToPornographySites = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoBrowseToPornographySites'}).Enabled + EpoBrowseToUnallowedDomain = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoBrowseToUnallowedDomain'}).Enabled + EpoBrowseToViolenceSites = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoBrowseToViolenceSites'}).Enabled + EpoCopyToClipboardFromSensitiveFile = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoCopyToClipboardFromSensitiveFile'}).Enabled + EpoCopyToNetworkShare = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoCopyToNetworkShare'}).Enabled + EpoFileArchived = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoFileArchived'}).Enabled + EpoFileCopiedToRemoteDesktopSession = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoFileCopiedToRemoteDesktopSession'}).Enabled + EpoFileDeleted = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoFileDeleted'}).Enabled + EpoFileDownloadedFromBlacklistedDomain = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoFileDownloadedFromBlacklistedDomain'}).Enabled + EpoFileDownloadedFromEnterpriseDomain = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoFileDownloadedFromEnterpriseDomain'}).Enabled + EpoFileRenamed = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoFileRenamed'}).Enabled + EpoFileStagedToCentralLocation = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoFileStagedToCentralLocation'}).Enabled + EpoHiddenFileCreated = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoHiddenFileCreated'}).Enabled + EpoRemovableMediaMount = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoRemovableMediaMount'}).Enabled + EpoSensitiveFileRead = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'EpoSensitiveFileRead'}).Enabled + Mcas3rdPartyAppDownload = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'Mcas3rdPartyAppDownload'}).Enabled + Mcas3rdPartyAppFileDelete = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'Mcas3rdPartyAppFileDelete'}).Enabled + Mcas3rdPartyAppFileSharing = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'Mcas3rdPartyAppFileSharing'}).Enabled + McasActivityFromInfrequentCountry = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'McasActivityFromInfrequentCountry'}).Enabled + McasImpossibleTravel = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'McasImpossibleTravel'}).Enabled + McasMultipleFailedLogins = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'McasMultipleFailedLogins'}).Enabled + McasMultipleStorageDeletion = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'McasMultipleStorageDeletion'}).Enabled + McasMultipleVMCreation = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'McasMultipleVMCreation'}).Enabled + McasMultipleVMDeletion = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'McasMultipleVMDeletion'}).Enabled + McasSuspiciousAdminActivities = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'McasSuspiciousAdminActivities'}).Enabled + McasSuspiciousCloudCreation = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'McasSuspiciousCloudCreation'}).Enabled + McasSuspiciousCloudTrailLoggingChange = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'McasSuspiciousCloudTrailLoggingChange'}).Enabled + McasTerminatedEmployeeActivity = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'McasTerminatedEmployeeActivity'}).Enabled + OdbDownload = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'OdbDownload'}).Enabled + OdbSyncDownload = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'OdbSyncDownload'}).Enabled + PeerCumulativeExfiltrationDetector = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'PeerCumulativeExfiltrationDetector'}).Enabled + PhysicalAccess = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'PhysicalAccess'}).Enabled + PotentialHighImpactUser = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'PotentialHighImpactUser'}).Enabled + Print = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'Print'}).Enabled + PriorityUserGroupMember = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'PriorityUserGroupMember'}).Enabled + SecurityAlertDefenseEvasion = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SecurityAlertDefenseEvasion'}).Enabled + SecurityAlertUnwantedSoftware = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SecurityAlertUnwantedSoftware'}).Enabled + SpoAccessRequest = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoAccessRequest'}).Enabled + SpoApprovedAccess = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoApprovedAccess'}).Enabled + SpoDownload = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoDownload'}).Enabled + SpoDownloadV2 = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoDownloadV2'}).Enabled + SpoFileAccessed = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoFileAccessed'}).Enabled + SpoFileDeleted = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoFileDeleted'}).Enabled + SpoFileDeletedFromFirstStageRecycleBin = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoFileDeletedFromFirstStageRecycleBin'}).Enabled + SpoFileDeletedFromSecondStageRecycleBin = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoFileDeletedFromSecondStageRecycleBin'}).Enabled + SpoFileLabelDowngraded = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoFileLabelDowngraded'}).Enabled + SpoFileLabelRemoved = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoFileLabelRemoved'}).Enabled + SpoFileSharing = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoFileSharing'}).Enabled + SpoFolderDeleted = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoFolderDeleted'}).Enabled + SpoFolderDeletedFromFirstStageRecycleBin = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoFolderDeletedFromFirstStageRecycleBin'}).Enabled + SpoFolderDeletedFromSecondStageRecycleBin = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoFolderDeletedFromSecondStageRecycleBin'}).Enabled + SpoFolderSharing = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoFolderSharing'}).Enabled + SpoSiteExternalUserAdded = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoSiteExternalUserAdded'}).Enabled + SpoSiteInternalUserAdded = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoSiteInternalUserAdded'}).Enabled + SpoSiteLabelRemoved = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoSiteLabelRemoved'}).Enabled + SpoSiteSharing = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoSiteSharing'}).Enabled + SpoSyncDownload = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'SpoSyncDownload'}).Enabled + TeamsChannelFileSharedExternal = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'TeamsChannelFileSharedExternal'}).Enabled + TeamsChannelMemberAddedExternal = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'TeamsChannelMemberAddedExternal'}).Enabled + TeamsChatFileSharedExternal = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'TeamsChatFileSharedExternal'}).Enabled + TeamsFileDownload = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'TeamsFileDownload'}).Enabled + TeamsFolderSharedExternal = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'TeamsFolderSharedExternal'}).Enabled + TeamsMemberAddedExternal = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'TeamsMemberAddedExternal'}).Enabled + TeamsSensitiveMessage = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'TeamsSensitiveMessage'}).Enabled + UserHistory = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'UserHistory'}).Enabled + AWSS3BlockPublicAccessDisabled = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'AWSS3BlockPublicAccessDisabled'}).Enabled + AWSS3BucketDeleted = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'AWSS3BucketDeleted'}).Enabled + AWSS3PublicAccessEnabled = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'AWSS3PublicAccessEnabled'}).Enabled + AWSS3ServerLoggingDisabled = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'AWSS3ServerLoggingDisabled'}).Enabled + AzureElevateAccessToAllSubscriptions = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'AzureElevateAccessToAllSubscriptions'}).Enabled + AzureResourceThreatProtectionSettingsUpdated = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'AzureResourceThreatProtectionSettingsUpdated'}).Enabled + AzureSQLServerAuditingSettingsUpdated = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'AzureSQLServerAuditingSettingsUpdated'}).Enabled + AzureSQLServerFirewallRuleDeleted = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'AzureSQLServerFirewallRuleDeleted'}).Enabled + AzureSQLServerFirewallRuleUpdated = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'AzureSQLServerFirewallRuleUpdated'}).Enabled + AzureStorageAccountOrContainerDeleted = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'AzureStorageAccountOrContainerDeleted'}).Enabled + BoxContentAccess = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'BoxContentAccess'}).Enabled + BoxContentDelete = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'BoxContentDelete'}).Enabled + BoxContentDownload = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'BoxContentDownload'}).Enabled + BoxContentExternallyShared = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'BoxContentExternallyShared'}).Enabled + CCFinancialRegulatoryRiskyTextSent = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'CCFinancialRegulatoryRiskyTextSent'}).Enabled + CCInappropriateContentSent = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'CCInappropriateContentSent'}).Enabled + CCInappropriateImagesSent = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'CCInappropriateImagesSent'}).Enabled + DropboxContentAccess = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'DropboxContentAccess'}).Enabled + DropboxContentDelete = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'DropboxContentDelete'}).Enabled + DropboxContentDownload = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'DropboxContentDownload'}).Enabled + DropboxContentExternallyShared = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'DropboxContentExternallyShared'}).Enabled + GoogleDriveContentAccess = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'GoogleDriveContentAccess'}).Enabled + GoogleDriveContentDelete = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'GoogleDriveContentDelete'}).Enabled + GoogleDriveContentExternallyShared = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'GoogleDriveContentExternallyShared'}).Enabled + PowerBIDashboardsDeleted = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'PowerBIDashboardsDeleted'}).Enabled + PowerBIReportsDeleted = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'PowerBIReportsDeleted'}).Enabled + PowerBIReportsDownloaded = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'PowerBIReportsDownloaded'}).Enabled + PowerBIReportsExported = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'PowerBIReportsExported'}).Enabled + PowerBIReportsViewed = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'PowerBIReportsViewed'}).Enabled + PowerBISemanticModelsDeleted = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'PowerBISemanticModelsDeleted'}).Enabled + PowerBISensitivityLabelDowngradedForArtifacts = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'PowerBISensitivityLabelDowngradedForArtifacts'}).Enabled + PowerBISensitivityLabelRemovedFromArtifacts = ($tenantSettings.ExtensibleIndicators | Where-Object -FilterScript {$_.Name -eq 'PowerBISensitivityLabelRemovedFromArtifacts'}).Enabled HistoricTimeSpan = $tenantSettings.TimeSpan.HistoricTimeSpan InScopeTimeSpan = $tenantSettings.TimeSpan.InScopeTimeSpan - EnableTeam = [Boolean]$tenantSettings.FeatureSettings.EnableTeam + EnableTeam = [Boolean]($tenantSettings.FeatureSettings.EnableTeam) } $AnalyticsNewInsight = $tenantSettings.NotificationPreferences | Where-Object -FilterScript {$_.NotificationType -eq 'AnalyticsNewInsight'} @@ -846,6 +861,14 @@ function Set-TargetResource [System.String] $Name, + [Parameter(Mandatory = $true)] + [System.String] + $InsiderRiskScenario, + + [Parameter()] + [System.Boolean] + $Anonymization, + [Parameter()] [System.Boolean] $DLPUserRiskSync, @@ -1391,19 +1414,19 @@ function Set-TargetResource $SessionRecordingEnabled, [Parameter()] - [System.Boolean] + [System.String] $RecordingTimeframePreEventInSec, [Parameter()] - [System.Boolean] + [System.String] $RecordingTimeframePostEventInSec, [Parameter()] - [System.Boolean] + [System.String] $BandwidthCapInMb, [Parameter()] - [System.Boolean] + [System.String] $OfflineRecordingStorageLimitInMb, [Parameter()] @@ -1452,23 +1475,105 @@ function Set-TargetResource $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $indicatorsProperties = @('AnomalyDetections','CopyToPersonalCloud','CopyToUSB','CumulativeExfiltrationDetector', ` + 'EmailExternal','EmployeeAccessedEmployeePatientData','EmployeeAccessedFamilyData', ` + 'EmployeeAccessedHighVolumePatientData','EmployeeAccessedNeighbourData', ` + 'EmployeeAccessedRestrictedData','EpoBrowseToChildAbuseSites','EpoBrowseToCriminalActivitySites', ` + 'EpoBrowseToCultSites','EpoBrowseToGamblingSites','EpoBrowseToHackingSites', ` + 'EpoBrowseToHateIntoleranceSites','EpoBrowseToIllegalSoftwareSites','EpoBrowseToKeyloggerSites', ` + 'EpoBrowseToLlmSites','EpoBrowseToMalwareSites','EpoBrowseToPhishingSites', ` + 'EpoBrowseToPornographySites','EpoBrowseToUnallowedDomain','EpoBrowseToViolenceSites', ` + 'EpoCopyToClipboardFromSensitiveFile','EpoCopyToNetworkShare','EpoFileArchived', ` + 'EpoFileCopiedToRemoteDesktopSession','EpoFileDeleted','EpoFileDownloadedFromBlacklistedDomain', ` + 'EpoFileDownloadedFromEnterpriseDomain','EpoFileRenamed','EpoFileStagedToCentralLocation', ` + 'EpoHiddenFileCreated','EpoRemovableMediaMount','EpoSensitiveFileRead','Mcas3rdPartyAppDownload', ` + 'Mcas3rdPartyAppFileDelete','Mcas3rdPartyAppFileSharing','McasActivityFromInfrequentCountry', ` + 'McasImpossibleTravel','McasMultipleFailedLogins','McasMultipleStorageDeletion', ` + 'McasMultipleVMCreation','McasMultipleVMDeletion','McasSuspiciousAdminActivities', ` + 'McasSuspiciousCloudCreation','McasSuspiciousCloudTrailLoggingChange','McasTerminatedEmployeeActivity', ` + 'OdbDownload','OdbSyncDownload','PeerCumulativeExfiltrationDetector','PhysicalAccess', ` + 'PotentialHighImpactUser','Print','PriorityUserGroupMember','SecurityAlertDefenseEvasion', ` + 'SecurityAlertUnwantedSoftware','SpoAccessRequest','SpoApprovedAccess','SpoDownload','SpoDownloadV2', ` + 'SpoFileAccessed','SpoFileDeleted','SpoFileDeletedFromFirstStageRecycleBin', ` + 'SpoFileDeletedFromSecondStageRecycleBin','SpoFileLabelDowngraded','SpoFileLabelRemoved', ` + 'SpoFileSharing','SpoFolderDeleted','SpoFolderDeletedFromFirstStageRecycleBin', ` + 'SpoFolderDeletedFromSecondStageRecycleBin','SpoFolderSharing','SpoSiteExternalUserAdded', ` + 'SpoSiteInternalUserAdded','SpoSiteLabelRemoved','SpoSiteSharing','SpoSyncDownload', ` + 'TeamsChannelFileSharedExternal','TeamsChannelMemberAddedExternal','TeamsChatFileSharedExternal', ` + 'TeamsFileDownload','TeamsFolderSharedExternal','TeamsMemberAddedExternal','TeamsSensitiveMessage', ` + 'UserHistory') + + $indicatorValues = @() + foreach ($indicatorProperty in $indicatorsProperties) + { + if ($PSBoundParameters.ContainsKey($indicatorProperty)) + { + $indicatorValues += "{`"Name`":`"$indicatorProperty`",`"Type`":`"Insight`",`"Enabled`":$(($PSBoundParameters.$indicatorProperty).ToString().ToLower()),`"UseDefault`":true,`"ThresholdMode`":`"Default`"}" + } + } + + $extensibleIndicatorsProperties = @('AWSS3BlockPublicAccessDisabled','AWSS3BucketDeleted','AWSS3PublicAccessEnabled',` + 'AWSS3ServerLoggingDisabled','AzureElevateAccessToAllSubscriptions','AzureResourceThreatProtectionSettingsUpdated', ` + 'AzureSQLServerAuditingSettingsUpdated','AzureSQLServerFirewallRuleDeleted','AzureSQLServerFirewallRuleUpdated', ` + 'AzureStorageAccountOrContainerDeleted','BoxContentAccess','BoxContentDelete','BoxContentDownload','BoxContentExternallyShared', ` + 'CCFinancialRegulatoryRiskyTextSent','CCInappropriateContentSent','CCInappropriateImagesSent','DropboxContentAccess', ` + 'DropboxContentDelete','DropboxContentDownload','DropboxContentExternallyShared','GoogleDriveContentAccess', ` + 'GoogleDriveContentDelete','GoogleDriveContentExternallyShared','PowerBIDashboardsDeleted','PowerBIReportsDeleted', ` + 'PowerBIReportsDownloaded','PowerBIReportsExported','PowerBIReportsViewed','PowerBISemanticModelsDeleted', ` + 'PowerBISensitivityLabelDowngradedForArtifacts','PowerBISensitivityLabelRemovedFromArtifacts') + + $extensibleIndicatorsValues = @() + foreach ($extensibleIndicatorsProperty in $extensibleIndicatorsProperties) + { + if ($PSBoundParameters.ContainsKey($extensibleIndicatorsProperty)) + { + $extensibleIndicatorsValues += "{`"Name`":`"$extensibleIndicatorsProperty`",`"Type`":`"ExtensibleInsight`",`"Enabled`":$(($PSBoundParameters.$extensibleIndicatorsProperty).ToString().ToLower()),`"UseDefault`":true,`"ThresholdMode`":`"Default`"}" + } + } + + # Tenant Settings + $featureSettingsValue = "{`"Anonymization`":$($Anonymization.ToString().ToLower()), `"DLPUserRiskSync`":$($DLPUserRiskSync.ToString().ToLower()), `"OptInIRMDataExport`":$($OptInIRMDataExport.ToString().ToLower()), `"RaiseAuditAlert`":$($RaiseAuditAlert.ToString().ToLower()), `"EnableTeam`":$($EnableTeam.ToString().ToLower())}" + $intelligentDetectionValue = "{`"FileVolCutoffLimits`":`"$($FileVolCutoffLimits)`", `"AlertVolume`":`"$($AlertVolume)`"}" + $tenantSettingsValue = "{`"Region`":`"WW`", `"FeatureSettings`":$($featureSettingsValue), " + ` + "`"IntelligentDetections`":$($intelligentDetectionValue)}" + # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - ##TODO - Replace by the New cmdlet for the resource - New-Cmdlet @SetParameters + Write-Verbose -Message "Creating new Insider Risk Policy {$Name} with values:`r`nIndicators: $($indicatorValues)`r`n`r`nExtensibleIndicators: $($extensibleIndicatorsValues)`r`n`r`nTenantSettings: $($tenantSettingsValue)`r`n`r`nSessionRecordingSettings: $($sessionRecordingValues)" + New-InsiderRiskPolicy -Name $Name -InsiderRiskScenario $InsiderRiskScenario ` + -Indicators $indicatorValues ` + -ExtensibleIndicators $extensibleIndicatorsValues ` + -TenantSetting $tenantSettingsValue ` + -HistoricTimeSpan $HistoricTimeSpan ` + -InScopeTimeSpan $InScopeTimeSpan ` + -SessionRecordingSettings $sessionRecordingValues } # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - ##TODO - Replace by the Update/Set cmdlet for the resource - Set-cmdlet @SetParameters + Write-Verbose -Message "Updating existing Insider Risk Policy {$Name} with values:`r`nIndicators: $($indicatorValues)`r`n`r`nExtensibleIndicators: $($extensibleIndicatorsValues)`r`n`r`nTenantSettings: $($tenantSettingsValue)`r`n`r`nSessionRecordingSettings: $($sessionRecordingValues)" + + if ($InsiderRiskScenario -eq 'SessionRecordingSetting') + { + $sessionRecordingValues = "{`"RecordingMode`":`"EventDriven`", `"RecordingTimeframePreEventInSec`":$($RecordingTimeframePreEventInSec),`"RecordingTimeframePostEventInSec`":$($RecordingTimeframePostEventInSec),`"BandwidthCapInMb`":$($BandwidthCapInMb),`"OfflineRecordingStorageLimitInMb`":$($OfflineRecordingStorageLimitInMb),`"ClipDeletionEnabled`":$($ClipDeletionEnabled.ToString().ToLower()),`"Enabled`":$($SessionRecordingEnabled.ToString().ToLower()),`"FpsNumerator`":0,`"FpsDenominator`":0}" + Write-Verbose -Message 'Updating Session Recording Settings' + Set-InsiderRiskPolicy -Identity $Name -SessionRecordingSettings $sessionRecordingValues | Out-Null + } + else + { + Set-InsiderRiskPolicy -Identity $Name -Indicators $indicatorValues ` + -ExtensibleIndicators $extensibleIndicatorsValues ` + -TenantSetting $tenantSettingsValue ` + -HistoricTimeSpan $HistoricTimeSpan ` + -InScopeTimeSpan $InScopeTimeSpan + } } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - ##TODO - Replace by the Remove cmdlet for the resource - Remove-cmdlet @SetParameters + Write-Verbose -Message "Removing Insider Risk Policy {$Name}" + Remove-InsiderRiskPolicy -Identity $Name -Confirm:$false } } @@ -1482,6 +1587,14 @@ function Test-TargetResource [System.String] $Name, + [Parameter(Mandatory = $true)] + [System.String] + $InsiderRiskScenario, + + [Parameter()] + [System.Boolean] + $Anonymization, + [Parameter()] [System.Boolean] $DLPUserRiskSync, @@ -2027,19 +2140,19 @@ function Test-TargetResource $SessionRecordingEnabled, [Parameter()] - [System.Boolean] + [System.String] $RecordingTimeframePreEventInSec, [Parameter()] - [System.Boolean] + [System.String] $RecordingTimeframePostEventInSec, [Parameter()] - [System.Boolean] + [System.String] $BandwidthCapInMb, [Parameter()] - [System.Boolean] + [System.String] $OfflineRecordingStorageLimitInMb, [Parameter()] @@ -2167,10 +2280,15 @@ function Export-TargetResource } foreach ($config in $Script:exportedInstances) { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } $displayedKey = $config.Name Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline $params = @{ Name = $config.Name + InsiderRiskScenario = $config.InsiderRiskScenario Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof index 5cae80ebe7..2f219a3176 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof @@ -2,146 +2,148 @@ class MSFT_SCInsiderRiskPolicy : OMI_BaseResource { [Key, Description("Name of the insider risk policy.")] string Name; - [Write, Description("")] Boolean DLPUserRiskSync; - [Write, Description("")] Boolean OptInIRMDataExport; - [Write, Description("")] Boolean RaiseAuditAlert; - [Write, Description("")] String FileVolCutoffLimits; - [Write, Description("")] String AlertVolume; - [Write, Description("")] Boolean AnomalyDetections; - [Write, Description("")] Boolean CopyToPersonalCloud; - [Write, Description("")] Boolean CopyToUSB; - [Write, Description("")] Boolean CumulativeExfiltrationDetector; - [Write, Description("")] Boolean EmailExternal; - [Write, Description("")] Boolean EmployeeAccessedEmployeePatientData; - [Write, Description("")] Boolean EmployeeAccessedFamilyData; - [Write, Description("")] Boolean EmployeeAccessedHighVolumePatientData; - [Write, Description("")] Boolean EmployeeAccessedNeighbourData; - [Write, Description("")] Boolean EmployeeAccessedRestrictedData; - [Write, Description("")] Boolean EpoBrowseToChildAbuseSites; - [Write, Description("")] Boolean EpoBrowseToCriminalActivitySites; - [Write, Description("")] Boolean EpoBrowseToCultSites; - [Write, Description("")] Boolean EpoBrowseToGamblingSites; - [Write, Description("")] Boolean EpoBrowseToHackingSites; - [Write, Description("")] Boolean EpoBrowseToHateIntoleranceSites; - [Write, Description("")] Boolean EpoBrowseToIllegalSoftwareSites; - [Write, Description("")] Boolean EpoBrowseToKeyloggerSites; - [Write, Description("")] Boolean EpoBrowseToLlmSites; - [Write, Description("")] Boolean EpoBrowseToMalwareSites; - [Write, Description("")] Boolean EpoBrowseToPhishingSites; - [Write, Description("")] Boolean EpoBrowseToPornographySites; - [Write, Description("")] Boolean EpoBrowseToUnallowedDomain; - [Write, Description("")] Boolean EpoBrowseToViolenceSites; - [Write, Description("")] Boolean EpoCopyToClipboardFromSensitiveFile; - [Write, Description("")] Boolean EpoCopyToNetworkShare; - [Write, Description("")] Boolean EpoFileArchived; - [Write, Description("")] Boolean EpoFileCopiedToRemoteDesktopSession; - [Write, Description("")] Boolean EpoFileDeleted; - [Write, Description("")] Boolean EpoFileDownloadedFromBlacklistedDomain; - [Write, Description("")] Boolean EpoFileDownloadedFromEnterpriseDomain; - [Write, Description("")] Boolean EpoFileRenamed; - [Write, Description("")] Boolean EpoFileStagedToCentralLocation; - [Write, Description("")] Boolean EpoHiddenFileCreated; - [Write, Description("")] Boolean EpoRemovableMediaMount; - [Write, Description("")] Boolean EpoSensitiveFileRead; - [Write, Description("")] Boolean Mcas3rdPartyAppDownload; - [Write, Description("")] Boolean Mcas3rdPartyAppFileDelete; - [Write, Description("")] Boolean Mcas3rdPartyAppFileSharing; - [Write, Description("")] Boolean McasActivityFromInfrequentCountry; - [Write, Description("")] Boolean McasImpossibleTravel; - [Write, Description("")] Boolean McasMultipleFailedLogins; - [Write, Description("")] Boolean McasMultipleStorageDeletion; - [Write, Description("")] Boolean McasMultipleVMCreation; - [Write, Description("")] Boolean McasMultipleVMDeletion; - [Write, Description("")] Boolean McasSuspiciousAdminActivities; - [Write, Description("")] Boolean McasSuspiciousCloudCreation; - [Write, Description("")] Boolean McasSuspiciousCloudTrailLoggingChange; - [Write, Description("")] Boolean McasTerminatedEmployeeActivity; - [Write, Description("")] Boolean OdbDownload; - [Write, Description("")] Boolean OdbSyncDownload; - [Write, Description("")] Boolean PeerCumulativeExfiltrationDetector; - [Write, Description("")] Boolean PhysicalAccess; - [Write, Description("")] Boolean PotentialHighImpactUser; - [Write, Description("")] Boolean Print; - [Write, Description("")] Boolean PriorityUserGroupMember; - [Write, Description("")] Boolean SecurityAlertDefenseEvasion; - [Write, Description("")] Boolean SecurityAlertUnwantedSoftware; - [Write, Description("")] Boolean SpoAccessRequest; - [Write, Description("")] Boolean SpoApprovedAccess; - [Write, Description("")] Boolean SpoDownload; - [Write, Description("")] Boolean SpoDownloadV2; - [Write, Description("")] Boolean SpoFileAccessed; - [Write, Description("")] Boolean SpoFileDeleted; - [Write, Description("")] Boolean SpoFileDeletedFromFirstStageRecycleBin; - [Write, Description("")] Boolean SpoFileDeletedFromSecondStageRecycleBin; - [Write, Description("")] Boolean SpoFileLabelDowngraded; - [Write, Description("")] Boolean SpoFileLabelRemoved; - [Write, Description("")] Boolean SpoFileSharing; - [Write, Description("")] Boolean SpoFolderDeleted; - [Write, Description("")] Boolean SpoFolderDeletedFromFirstStageRecycleBin; - [Write, Description("")] Boolean SpoFolderDeletedFromSecondStageRecycleBin; - [Write, Description("")] Boolean SpoFolderSharing; - [Write, Description("")] Boolean SpoSiteExternalUserAdded; - [Write, Description("")] Boolean SpoSiteInternalUserAdded; - [Write, Description("")] Boolean SpoSiteLabelRemoved; - [Write, Description("")] Boolean SpoSiteSharing; - [Write, Description("")] Boolean SpoSyncDownload; - [Write, Description("")] Boolean TeamsChannelFileSharedExternal; - [Write, Description("")] Boolean TeamsChannelMemberAddedExternal; - [Write, Description("")] Boolean TeamsChatFileSharedExternal; - [Write, Description("")] Boolean TeamsFileDownload; - [Write, Description("")] Boolean TeamsFolderSharedExternal; - [Write, Description("")] Boolean TeamsMemberAddedExternal; - [Write, Description("")] Boolean TeamsSensitiveMessage; - [Write, Description("")] Boolean UserHistory; - [Write, Description("")] Boolean AWSS3BlockPublicAccessDisabled; - [Write, Description("")] Boolean AWSS3BucketDeleted; - [Write, Description("")] Boolean AWSS3PublicAccessEnabled; - [Write, Description("")] Boolean AWSS3ServerLoggingDisabled; - [Write, Description("")] Boolean AzureElevateAccessToAllSubscriptions; - [Write, Description("")] Boolean AzureResourceThreatProtectionSettingsUpdated; - [Write, Description("")] Boolean AzureSQLServerAuditingSettingsUpdated; - [Write, Description("")] Boolean AzureSQLServerFirewallRuleDeleted; - [Write, Description("")] Boolean AzureSQLServerFirewallRuleUpdated; - [Write, Description("")] Boolean AzureStorageAccountOrContainerDeleted; - [Write, Description("")] Boolean BoxContentAccess; - [Write, Description("")] Boolean BoxContentDelete; - [Write, Description("")] Boolean BoxContentDownload; - [Write, Description("")] Boolean BoxContentExternallyShared; - [Write, Description("")] Boolean CCFinancialRegulatoryRiskyTextSent; - [Write, Description("")] Boolean CCInappropriateContentSent; - [Write, Description("")] Boolean CCInappropriateImagesSent; - [Write, Description("")] Boolean DropboxContentAccess; - [Write, Description("")] Boolean DropboxContentDelete; - [Write, Description("")] Boolean DropboxContentDownload; - [Write, Description("")] Boolean DropboxContentExternallyShared; - [Write, Description("")] Boolean GoogleDriveContentAccess; - [Write, Description("")] Boolean GoogleDriveContentDelete; - [Write, Description("")] Boolean GoogleDriveContentExternallyShared; - [Write, Description("")] Boolean PowerBIDashboardsDeleted; - [Write, Description("")] Boolean PowerBIReportsDeleted; - [Write, Description("")] Boolean PowerBIReportsDownloaded; - [Write, Description("")] Boolean PowerBIReportsExported; - [Write, Description("")] Boolean PowerBIReportsViewed; - [Write, Description("")] Boolean PowerBISemanticModelsDeleted; - [Write, Description("")] Boolean PowerBISensitivityLabelDowngradedForArtifacts; - [Write, Description("")] Boolean PowerBISensitivityLabelRemovedFromArtifacts; - [Write, Description("")] String HistoricTimeSpan; - [Write, Description("")] String InScopeTimeSpan; - [Write, Description("")] Boolean EnableTeam; - [Write, Description("")] Boolean AnalyticsNewInsightEnabled; - [Write, Description("")] Boolean AnalyticsTurnedOffEnabled; - [Write, Description("")] Boolean HighSeverityAlertsEnabled; - [Write, Description("")] String HighSeverityAlertsRoleGroups[]; - [Write, Description("")] Boolean PoliciesHealthEnabled; - [Write, Description("")] String PoliciesHealthRoleGroups[]; - [Write, Description("")] Boolean NotificationDetailsEnabled; - [Write, Description("")] String NotificationDetailsRoleGroups[]; - [Write, Description("")] Boolean ClipDeletionEnabled; - [Write, Description("")] Boolean SessionRecordingEnabled; - [Write, Description("")] String RecordingTimeframePreEventInSec; - [Write, Description("")] String RecordingTimeframePostEventInSec; - [Write, Description("")] String BandwidthCapInMb; - [Write, Description("")] String OfflineRecordingStorageLimitInMb; + [Key, Description("Name of the scenario supported by the policy.")] string InsiderRiskScenario; + [Write, Description("Official documentation to come.")] Boolean Anonymization; + [Write, Description("Official documentation to come.")] Boolean DLPUserRiskSync; + [Write, Description("Official documentation to come.")] Boolean OptInIRMDataExport; + [Write, Description("Official documentation to come.")] Boolean RaiseAuditAlert; + [Write, Description("Official documentation to come.")] String FileVolCutoffLimits; + [Write, Description("Official documentation to come.")] String AlertVolume; + [Write, Description("Official documentation to come.")] Boolean AnomalyDetections; + [Write, Description("Official documentation to come.")] Boolean CopyToPersonalCloud; + [Write, Description("Official documentation to come.")] Boolean CopyToUSB; + [Write, Description("Official documentation to come.")] Boolean CumulativeExfiltrationDetector; + [Write, Description("Official documentation to come.")] Boolean EmailExternal; + [Write, Description("Official documentation to come.")] Boolean EmployeeAccessedEmployeePatientData; + [Write, Description("Official documentation to come.")] Boolean EmployeeAccessedFamilyData; + [Write, Description("Official documentation to come.")] Boolean EmployeeAccessedHighVolumePatientData; + [Write, Description("Official documentation to come.")] Boolean EmployeeAccessedNeighbourData; + [Write, Description("Official documentation to come.")] Boolean EmployeeAccessedRestrictedData; + [Write, Description("Official documentation to come.")] Boolean EpoBrowseToChildAbuseSites; + [Write, Description("Official documentation to come.")] Boolean EpoBrowseToCriminalActivitySites; + [Write, Description("Official documentation to come.")] Boolean EpoBrowseToCultSites; + [Write, Description("Official documentation to come.")] Boolean EpoBrowseToGamblingSites; + [Write, Description("Official documentation to come.")] Boolean EpoBrowseToHackingSites; + [Write, Description("Official documentation to come.")] Boolean EpoBrowseToHateIntoleranceSites; + [Write, Description("Official documentation to come.")] Boolean EpoBrowseToIllegalSoftwareSites; + [Write, Description("Official documentation to come.")] Boolean EpoBrowseToKeyloggerSites; + [Write, Description("Official documentation to come.")] Boolean EpoBrowseToLlmSites; + [Write, Description("Official documentation to come.")] Boolean EpoBrowseToMalwareSites; + [Write, Description("Official documentation to come.")] Boolean EpoBrowseToPhishingSites; + [Write, Description("Official documentation to come.")] Boolean EpoBrowseToPornographySites; + [Write, Description("Official documentation to come.")] Boolean EpoBrowseToUnallowedDomain; + [Write, Description("Official documentation to come.")] Boolean EpoBrowseToViolenceSites; + [Write, Description("Official documentation to come.")] Boolean EpoCopyToClipboardFromSensitiveFile; + [Write, Description("Official documentation to come.")] Boolean EpoCopyToNetworkShare; + [Write, Description("Official documentation to come.")] Boolean EpoFileArchived; + [Write, Description("Official documentation to come.")] Boolean EpoFileCopiedToRemoteDesktopSession; + [Write, Description("Official documentation to come.")] Boolean EpoFileDeleted; + [Write, Description("Official documentation to come.")] Boolean EpoFileDownloadedFromBlacklistedDomain; + [Write, Description("Official documentation to come.")] Boolean EpoFileDownloadedFromEnterpriseDomain; + [Write, Description("Official documentation to come.")] Boolean EpoFileRenamed; + [Write, Description("Official documentation to come.")] Boolean EpoFileStagedToCentralLocation; + [Write, Description("Official documentation to come.")] Boolean EpoHiddenFileCreated; + [Write, Description("Official documentation to come.")] Boolean EpoRemovableMediaMount; + [Write, Description("Official documentation to come.")] Boolean EpoSensitiveFileRead; + [Write, Description("Official documentation to come.")] Boolean Mcas3rdPartyAppDownload; + [Write, Description("Official documentation to come.")] Boolean Mcas3rdPartyAppFileDelete; + [Write, Description("Official documentation to come.")] Boolean Mcas3rdPartyAppFileSharing; + [Write, Description("Official documentation to come.")] Boolean McasActivityFromInfrequentCountry; + [Write, Description("Official documentation to come.")] Boolean McasImpossibleTravel; + [Write, Description("Official documentation to come.")] Boolean McasMultipleFailedLogins; + [Write, Description("Official documentation to come.")] Boolean McasMultipleStorageDeletion; + [Write, Description("Official documentation to come.")] Boolean McasMultipleVMCreation; + [Write, Description("Official documentation to come.")] Boolean McasMultipleVMDeletion; + [Write, Description("Official documentation to come.")] Boolean McasSuspiciousAdminActivities; + [Write, Description("Official documentation to come.")] Boolean McasSuspiciousCloudCreation; + [Write, Description("Official documentation to come.")] Boolean McasSuspiciousCloudTrailLoggingChange; + [Write, Description("Official documentation to come.")] Boolean McasTerminatedEmployeeActivity; + [Write, Description("Official documentation to come.")] Boolean OdbDownload; + [Write, Description("Official documentation to come.")] Boolean OdbSyncDownload; + [Write, Description("Official documentation to come.")] Boolean PeerCumulativeExfiltrationDetector; + [Write, Description("Official documentation to come.")] Boolean PhysicalAccess; + [Write, Description("Official documentation to come.")] Boolean PotentialHighImpactUser; + [Write, Description("Official documentation to come.")] Boolean Print; + [Write, Description("Official documentation to come.")] Boolean PriorityUserGroupMember; + [Write, Description("Official documentation to come.")] Boolean SecurityAlertDefenseEvasion; + [Write, Description("Official documentation to come.")] Boolean SecurityAlertUnwantedSoftware; + [Write, Description("Official documentation to come.")] Boolean SpoAccessRequest; + [Write, Description("Official documentation to come.")] Boolean SpoApprovedAccess; + [Write, Description("Official documentation to come.")] Boolean SpoDownload; + [Write, Description("Official documentation to come.")] Boolean SpoDownloadV2; + [Write, Description("Official documentation to come.")] Boolean SpoFileAccessed; + [Write, Description("Official documentation to come.")] Boolean SpoFileDeleted; + [Write, Description("Official documentation to come.")] Boolean SpoFileDeletedFromFirstStageRecycleBin; + [Write, Description("Official documentation to come.")] Boolean SpoFileDeletedFromSecondStageRecycleBin; + [Write, Description("Official documentation to come.")] Boolean SpoFileLabelDowngraded; + [Write, Description("Official documentation to come.")] Boolean SpoFileLabelRemoved; + [Write, Description("Official documentation to come.")] Boolean SpoFileSharing; + [Write, Description("Official documentation to come.")] Boolean SpoFolderDeleted; + [Write, Description("Official documentation to come.")] Boolean SpoFolderDeletedFromFirstStageRecycleBin; + [Write, Description("Official documentation to come.")] Boolean SpoFolderDeletedFromSecondStageRecycleBin; + [Write, Description("Official documentation to come.")] Boolean SpoFolderSharing; + [Write, Description("Official documentation to come.")] Boolean SpoSiteExternalUserAdded; + [Write, Description("Official documentation to come.")] Boolean SpoSiteInternalUserAdded; + [Write, Description("Official documentation to come.")] Boolean SpoSiteLabelRemoved; + [Write, Description("Official documentation to come.")] Boolean SpoSiteSharing; + [Write, Description("Official documentation to come.")] Boolean SpoSyncDownload; + [Write, Description("Official documentation to come.")] Boolean TeamsChannelFileSharedExternal; + [Write, Description("Official documentation to come.")] Boolean TeamsChannelMemberAddedExternal; + [Write, Description("Official documentation to come.")] Boolean TeamsChatFileSharedExternal; + [Write, Description("Official documentation to come.")] Boolean TeamsFileDownload; + [Write, Description("Official documentation to come.")] Boolean TeamsFolderSharedExternal; + [Write, Description("Official documentation to come.")] Boolean TeamsMemberAddedExternal; + [Write, Description("Official documentation to come.")] Boolean TeamsSensitiveMessage; + [Write, Description("Official documentation to come.")] Boolean UserHistory; + [Write, Description("Official documentation to come.")] Boolean AWSS3BlockPublicAccessDisabled; + [Write, Description("Official documentation to come.")] Boolean AWSS3BucketDeleted; + [Write, Description("Official documentation to come.")] Boolean AWSS3PublicAccessEnabled; + [Write, Description("Official documentation to come.")] Boolean AWSS3ServerLoggingDisabled; + [Write, Description("Official documentation to come.")] Boolean AzureElevateAccessToAllSubscriptions; + [Write, Description("Official documentation to come.")] Boolean AzureResourceThreatProtectionSettingsUpdated; + [Write, Description("Official documentation to come.")] Boolean AzureSQLServerAuditingSettingsUpdated; + [Write, Description("Official documentation to come.")] Boolean AzureSQLServerFirewallRuleDeleted; + [Write, Description("Official documentation to come.")] Boolean AzureSQLServerFirewallRuleUpdated; + [Write, Description("Official documentation to come.")] Boolean AzureStorageAccountOrContainerDeleted; + [Write, Description("Official documentation to come.")] Boolean BoxContentAccess; + [Write, Description("Official documentation to come.")] Boolean BoxContentDelete; + [Write, Description("Official documentation to come.")] Boolean BoxContentDownload; + [Write, Description("Official documentation to come.")] Boolean BoxContentExternallyShared; + [Write, Description("Official documentation to come.")] Boolean CCFinancialRegulatoryRiskyTextSent; + [Write, Description("Official documentation to come.")] Boolean CCInappropriateContentSent; + [Write, Description("Official documentation to come.")] Boolean CCInappropriateImagesSent; + [Write, Description("Official documentation to come.")] Boolean DropboxContentAccess; + [Write, Description("Official documentation to come.")] Boolean DropboxContentDelete; + [Write, Description("Official documentation to come.")] Boolean DropboxContentDownload; + [Write, Description("Official documentation to come.")] Boolean DropboxContentExternallyShared; + [Write, Description("Official documentation to come.")] Boolean GoogleDriveContentAccess; + [Write, Description("Official documentation to come.")] Boolean GoogleDriveContentDelete; + [Write, Description("Official documentation to come.")] Boolean GoogleDriveContentExternallyShared; + [Write, Description("Official documentation to come.")] Boolean PowerBIDashboardsDeleted; + [Write, Description("Official documentation to come.")] Boolean PowerBIReportsDeleted; + [Write, Description("Official documentation to come.")] Boolean PowerBIReportsDownloaded; + [Write, Description("Official documentation to come.")] Boolean PowerBIReportsExported; + [Write, Description("Official documentation to come.")] Boolean PowerBIReportsViewed; + [Write, Description("Official documentation to come.")] Boolean PowerBISemanticModelsDeleted; + [Write, Description("Official documentation to come.")] Boolean PowerBISensitivityLabelDowngradedForArtifacts; + [Write, Description("Official documentation to come.")] Boolean PowerBISensitivityLabelRemovedFromArtifacts; + [Write, Description("Official documentation to come.")] String HistoricTimeSpan; + [Write, Description("Official documentation to come.")] String InScopeTimeSpan; + [Write, Description("Official documentation to come.")] Boolean EnableTeam; + [Write, Description("Official documentation to come.")] Boolean AnalyticsNewInsightEnabled; + [Write, Description("Official documentation to come.")] Boolean AnalyticsTurnedOffEnabled; + [Write, Description("Official documentation to come.")] Boolean HighSeverityAlertsEnabled; + [Write, Description("Official documentation to come.")] String HighSeverityAlertsRoleGroups[]; + [Write, Description("Official documentation to come.")] Boolean PoliciesHealthEnabled; + [Write, Description("Official documentation to come.")] String PoliciesHealthRoleGroups[]; + [Write, Description("Official documentation to come.")] Boolean NotificationDetailsEnabled; + [Write, Description("Official documentation to come.")] String NotificationDetailsRoleGroups[]; + [Write, Description("Official documentation to come.")] Boolean ClipDeletionEnabled; + [Write, Description("Official documentation to come.")] Boolean SessionRecordingEnabled; + [Write, Description("Official documentation to come.")] String RecordingTimeframePreEventInSec; + [Write, Description("Official documentation to come.")] String RecordingTimeframePostEventInSec; + [Write, Description("Official documentation to come.")] String BandwidthCapInMb; + [Write, Description("Official documentation to come.")] String OfflineRecordingStorageLimitInMb; [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] 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; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/readme.md index 32e0e7fb27..eab9d9aa11 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/readme.md @@ -1,6 +1,6 @@ -# ResourceName +# SCInsiderRiskPolicy ## Description -##TODO - Provide a short description of what the resource is set to configure. +Configures Insider Risk Policies in Purview. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/settings.json index edf14b05e4..5738537aa8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/settings.json @@ -1,12 +1,12 @@ { - "resourceName": "ResourceName", - "description": "Description of what the resource is about.", + "resourceName": "SCInsiderRiskPolicy", + "description": "Configures Insider Risk Policies in Purview.", "roles": { "read": [ - "Role" + "Global Reader" ], "update": [ - "Role" + "Compliance Administrator" ] }, "permissions": { @@ -16,16 +16,8 @@ "update": [] }, "application": { - "read": [ - { - "name": "Permission for Monitoring and Export" - } - ], - "update": [ - { - "name": "Permission for deploying" - } - ] + "read": [], + "update": [] } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/1-Create.ps1 index b516274848..b4828f8b4a 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/1-Create.ps1 @@ -21,6 +21,144 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + SCInsiderRiskPolicy "SCInsiderRiskPolicy-IRM_Tenant_Setting" + { + Anonymization = $false + AlertVolume = "Medium"; + AnalyticsNewInsightEnabled = $False; + AnalyticsTurnedOffEnabled = $False; + AnomalyDetections = $False; + ApplicationId = $ApplicationId; + AWSS3BlockPublicAccessDisabled = $False; + AWSS3BucketDeleted = $False; + AWSS3PublicAccessEnabled = $False; + AWSS3ServerLoggingDisabled = $False; + AzureElevateAccessToAllSubscriptions = $False; + AzureResourceThreatProtectionSettingsUpdated = $False; + AzureSQLServerAuditingSettingsUpdated = $False; + AzureSQLServerFirewallRuleDeleted = $False; + AzureSQLServerFirewallRuleUpdated = $False; + AzureStorageAccountOrContainerDeleted = $False; + BoxContentAccess = $False; + BoxContentDelete = $False; + BoxContentDownload = $False; + BoxContentExternallyShared = $False; + CCFinancialRegulatoryRiskyTextSent = $False; + CCInappropriateContentSent = $False; + CCInappropriateImagesSent = $False; + CertificateThumbprint = $CertificateThumbprint; + CopyToPersonalCloud = $False; + CopyToUSB = $False; + CumulativeExfiltrationDetector = $True; + DLPUserRiskSync = $True; + DropboxContentAccess = $False; + DropboxContentDelete = $False; + DropboxContentDownload = $False; + DropboxContentExternallyShared = $False; + EmailExternal = $False; + EmployeeAccessedEmployeePatientData = $False; + EmployeeAccessedFamilyData = $False; + EmployeeAccessedHighVolumePatientData = $False; + EmployeeAccessedNeighbourData = $False; + EmployeeAccessedRestrictedData = $False; + EnableTeam = $True; + Ensure = "Present"; + EpoBrowseToChildAbuseSites = $False; + EpoBrowseToCriminalActivitySites = $False; + EpoBrowseToCultSites = $False; + EpoBrowseToGamblingSites = $False; + EpoBrowseToHackingSites = $False; + EpoBrowseToHateIntoleranceSites = $False; + EpoBrowseToIllegalSoftwareSites = $False; + EpoBrowseToKeyloggerSites = $False; + EpoBrowseToLlmSites = $False; + EpoBrowseToMalwareSites = $False; + EpoBrowseToPhishingSites = $False; + EpoBrowseToPornographySites = $False; + EpoBrowseToUnallowedDomain = $False; + EpoBrowseToViolenceSites = $False; + EpoCopyToClipboardFromSensitiveFile = $False; + EpoCopyToNetworkShare = $False; + EpoFileArchived = $False; + EpoFileCopiedToRemoteDesktopSession = $False; + EpoFileDeleted = $False; + EpoFileDownloadedFromBlacklistedDomain = $False; + EpoFileDownloadedFromEnterpriseDomain = $False; + EpoFileRenamed = $False; + EpoFileStagedToCentralLocation = $False; + EpoHiddenFileCreated = $False; + EpoRemovableMediaMount = $False; + EpoSensitiveFileRead = $False; + FileVolCutoffLimits = "59"; + GoogleDriveContentAccess = $False; + GoogleDriveContentDelete = $False; + GoogleDriveContentExternallyShared = $False; + HistoricTimeSpan = "89"; + InScopeTimeSpan = "30"; + InsiderRiskScenario = "TenantSetting"; + Mcas3rdPartyAppDownload = $False; + Mcas3rdPartyAppFileDelete = $False; + Mcas3rdPartyAppFileSharing = $False; + McasActivityFromInfrequentCountry = $False; + McasImpossibleTravel = $False; + McasMultipleFailedLogins = $False; + McasMultipleStorageDeletion = $False; + McasMultipleVMCreation = $True; + McasMultipleVMDeletion = $False; + McasSuspiciousAdminActivities = $False; + McasSuspiciousCloudCreation = $False; + McasSuspiciousCloudTrailLoggingChange = $False; + McasTerminatedEmployeeActivity = $False; + Name = "IRM_Tenant_Setting"; + NotificationDetailsEnabled = $True; + OdbDownload = $False; + OdbSyncDownload = $False; + OptInIRMDataExport = $True; + PeerCumulativeExfiltrationDetector = $False; + PhysicalAccess = $False; + PotentialHighImpactUser = $False; + PowerBIDashboardsDeleted = $False; + PowerBIReportsDeleted = $False; + PowerBIReportsDownloaded = $False; + PowerBIReportsExported = $False; + PowerBIReportsViewed = $False; + PowerBISemanticModelsDeleted = $False; + PowerBISensitivityLabelDowngradedForArtifacts = $False; + PowerBISensitivityLabelRemovedFromArtifacts = $False; + Print = $False; + PriorityUserGroupMember = $False; + RaiseAuditAlert = $True; + SecurityAlertDefenseEvasion = $False; + SecurityAlertUnwantedSoftware = $False; + SpoAccessRequest = $False; + SpoApprovedAccess = $False; + SpoDownload = $False; + SpoDownloadV2 = $False; + SpoFileAccessed = $False; + SpoFileDeleted = $False; + SpoFileDeletedFromFirstStageRecycleBin = $False; + SpoFileDeletedFromSecondStageRecycleBin = $False; + SpoFileLabelDowngraded = $False; + SpoFileLabelRemoved = $False; + SpoFileSharing = $True; + SpoFolderDeleted = $False; + SpoFolderDeletedFromFirstStageRecycleBin = $False; + SpoFolderDeletedFromSecondStageRecycleBin = $False; + SpoFolderSharing = $False; + SpoSiteExternalUserAdded = $False; + SpoSiteInternalUserAdded = $False; + SpoSiteLabelRemoved = $False; + SpoSiteSharing = $False; + SpoSyncDownload = $False; + TeamsChannelFileSharedExternal = $False; + TeamsChannelMemberAddedExternal = $False; + TeamsChatFileSharedExternal = $False; + TeamsFileDownload = $False; + TeamsFolderSharedExternal = $False; + TeamsMemberAddedExternal = $False; + TeamsSensitiveMessage = $False; + TenantId = $TenantId; + UserHistory = $False; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/2-Update.ps1 index b516274848..d3ba78ab1c 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/2-Update.ps1 @@ -21,6 +21,144 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + SCInsiderRiskPolicy "SCInsiderRiskPolicy-IRM_Tenant_Setting" + { + Anonymization = $false + AlertVolume = "Medium"; + AnalyticsNewInsightEnabled = $False; + AnalyticsTurnedOffEnabled = $False; + AnomalyDetections = $False; + ApplicationId = $ApplicationId; + AWSS3BlockPublicAccessDisabled = $False; + AWSS3BucketDeleted = $False; + AWSS3PublicAccessEnabled = $False; + AWSS3ServerLoggingDisabled = $False; + AzureElevateAccessToAllSubscriptions = $False; + AzureResourceThreatProtectionSettingsUpdated = $False; + AzureSQLServerAuditingSettingsUpdated = $False; + AzureSQLServerFirewallRuleDeleted = $False; + AzureSQLServerFirewallRuleUpdated = $False; + AzureStorageAccountOrContainerDeleted = $False; + BoxContentAccess = $False; + BoxContentDelete = $False; + BoxContentDownload = $False; + BoxContentExternallyShared = $False; + CCFinancialRegulatoryRiskyTextSent = $False; + CCInappropriateContentSent = $False; + CCInappropriateImagesSent = $False; + CertificateThumbprint = $CertificateThumbprint; + CopyToPersonalCloud = $False; + CopyToUSB = $False; + CumulativeExfiltrationDetector = $True; + DLPUserRiskSync = $True; + DropboxContentAccess = $False; + DropboxContentDelete = $False; + DropboxContentDownload = $False; + DropboxContentExternallyShared = $False; + EmailExternal = $False; + EmployeeAccessedEmployeePatientData = $False; + EmployeeAccessedFamilyData = $False; + EmployeeAccessedHighVolumePatientData = $False; + EmployeeAccessedNeighbourData = $False; + EmployeeAccessedRestrictedData = $False; + EnableTeam = $True; + Ensure = "Present"; + EpoBrowseToChildAbuseSites = $False; + EpoBrowseToCriminalActivitySites = $False; + EpoBrowseToCultSites = $False; + EpoBrowseToGamblingSites = $False; + EpoBrowseToHackingSites = $False; + EpoBrowseToHateIntoleranceSites = $False; + EpoBrowseToIllegalSoftwareSites = $False; + EpoBrowseToKeyloggerSites = $False; + EpoBrowseToLlmSites = $False; + EpoBrowseToMalwareSites = $False; + EpoBrowseToPhishingSites = $False; + EpoBrowseToPornographySites = $False; + EpoBrowseToUnallowedDomain = $False; + EpoBrowseToViolenceSites = $False; + EpoCopyToClipboardFromSensitiveFile = $False; + EpoCopyToNetworkShare = $False; + EpoFileArchived = $False; + EpoFileCopiedToRemoteDesktopSession = $False; + EpoFileDeleted = $False; + EpoFileDownloadedFromBlacklistedDomain = $False; + EpoFileDownloadedFromEnterpriseDomain = $False; + EpoFileRenamed = $False; + EpoFileStagedToCentralLocation = $False; + EpoHiddenFileCreated = $False; + EpoRemovableMediaMount = $False; + EpoSensitiveFileRead = $False; + FileVolCutoffLimits = "59"; + GoogleDriveContentAccess = $False; + GoogleDriveContentDelete = $False; + GoogleDriveContentExternallyShared = $False; + HistoricTimeSpan = "89"; + InScopeTimeSpan = "30"; + InsiderRiskScenario = "TenantSetting"; + Mcas3rdPartyAppDownload = $False; + Mcas3rdPartyAppFileDelete = $False; + Mcas3rdPartyAppFileSharing = $False; + McasActivityFromInfrequentCountry = $False; + McasImpossibleTravel = $False; + McasMultipleFailedLogins = $False; + McasMultipleStorageDeletion = $False; + McasMultipleVMCreation = $True; + McasMultipleVMDeletion = $False; + McasSuspiciousAdminActivities = $False; + McasSuspiciousCloudCreation = $False; + McasSuspiciousCloudTrailLoggingChange = $False; + McasTerminatedEmployeeActivity = $False; + Name = "IRM_Tenant_Setting"; + NotificationDetailsEnabled = $True; + OdbDownload = $False; + OdbSyncDownload = $False; + OptInIRMDataExport = $True; + PeerCumulativeExfiltrationDetector = $False; + PhysicalAccess = $False; + PotentialHighImpactUser = $False; + PowerBIDashboardsDeleted = $False; + PowerBIReportsDeleted = $False; + PowerBIReportsDownloaded = $False; + PowerBIReportsExported = $False; + PowerBIReportsViewed = $False; + PowerBISemanticModelsDeleted = $False; + PowerBISensitivityLabelDowngradedForArtifacts = $False; + PowerBISensitivityLabelRemovedFromArtifacts = $False; + Print = $False; + PriorityUserGroupMember = $False; + RaiseAuditAlert = $True; + SecurityAlertDefenseEvasion = $False; + SecurityAlertUnwantedSoftware = $False; + SpoAccessRequest = $False; + SpoApprovedAccess = $False; + SpoDownload = $False; + SpoDownloadV2 = $False; + SpoFileAccessed = $False; + SpoFileDeleted = $False; + SpoFileDeletedFromFirstStageRecycleBin = $False; + SpoFileDeletedFromSecondStageRecycleBin = $False; + SpoFileLabelDowngraded = $False; + SpoFileLabelRemoved = $False; + SpoFileSharing = $True; + SpoFolderDeleted = $False; + SpoFolderDeletedFromFirstStageRecycleBin = $False; + SpoFolderDeletedFromSecondStageRecycleBin = $False; + SpoFolderSharing = $False; + SpoSiteExternalUserAdded = $False; + SpoSiteInternalUserAdded = $False; + SpoSiteLabelRemoved = $False; + SpoSiteSharing = $False; + SpoSyncDownload = $False; + TeamsChannelFileSharedExternal = $False; + TeamsChannelMemberAddedExternal = $False; + TeamsChatFileSharedExternal = $True; # Drift + TeamsFileDownload = $False; + TeamsFolderSharedExternal = $False; + TeamsMemberAddedExternal = $False; + TeamsSensitiveMessage = $False; + TenantId = $TenantId; + UserHistory = $False; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/3-Remove.ps1 index b516274848..cd6854e02e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SCInsiderRiskPolicy/3-Remove.ps1 @@ -21,6 +21,14 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + SCInsiderRiskPolicy "SCInsiderRiskPolicy-IRM_Tenant_Setting" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + InsiderRiskScenario = "TenantSetting"; + Name = "IRM_Tenant_Setting"; + TenantId = $TenantId; + } } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskPolicy.Tests.ps1 index f3ddc7d594..a70f94592a 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCInsiderRiskPolicy.Tests.ps1 @@ -35,7 +35,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets + Mock -CommandName Set-InsiderRiskPolicy -MockWith {} + Mock -CommandName New-InsiderRiskPolicy -MockWith {} + Mock -CommandName Remove-InsiderRiskPolicy -MockWith {} # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { @@ -47,13 +49,23 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + Anonymization = $false + AlertVolume = "Medium"; + AnalyticsNewInsightEnabled = $False; + AnalyticsTurnedOffEnabled = $False; + AnomalyDetections = $False; + AzureStorageAccountOrContainerDeleted = $False; + CCInappropriateContentSent = $False; + EnableTeam = $True; + InsiderRiskScenario = "TenantSetting"; + Mcas3rdPartyAppDownload = $False; + Name = "IRM_Tenant_Setting"; + NotificationDetailsEnabled = $True; + Ensure = 'Present' + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-InsiderRiskPolicy -MockWith { return $null } } @@ -65,24 +77,35 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should create a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one Set-TargetResource @testParams - Should -Invoke -CommandName New-Cmdlet -Exactly 1 + Should -Invoke -CommandName New-InsiderRiskPolicy -Exactly 1 } } Context -Name "The instance exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Absent' - Credential = $Credential; + Anonymization = $false + AlertVolume = "Medium"; + AnalyticsNewInsightEnabled = $False; + AnalyticsTurnedOffEnabled = $False; + AnomalyDetections = $False; + AzureStorageAccountOrContainerDeleted = $False; + CCInappropriateContentSent = $False; + EnableTeam = $True; + InsiderRiskScenario = "TenantSetting"; + Mcas3rdPartyAppDownload = $False; + Name = "IRM_Tenant_Setting"; + NotificationDetailsEnabled = $True; + Ensure = 'Absent' + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-InsiderRiskPolicy -MockWith { return @{ - + TenantSetting = @( + '{"Region":"WW","IndicatorVersion":"1.1","Indicators":[{"Name":"AnomalyDetections","Enabled":false},{"Name":"CopyToPersonalCloud","Enabled":false},{"Name":"CopyToUSB","Enabled":false},{"Name":"CumulativeExfiltrationDetector","Enabled":true},{"Name":"EmailExternal","Enabled":false},{"Name":"EmployeeAccessedEmployeePatientData","Enabled":false},{"Name":"EmployeeAccessedFamilyData","Enabled":false},{"Name":"EmployeeAccessedHighVolumePatientData","Enabled":false},{"Name":"EmployeeAccessedNeighbourData","Enabled":false},{"Name":"EmployeeAccessedRestrictedData","Enabled":false},{"Name":"EpoBrowseToChildAbuseSites","Enabled":false},{"Name":"EpoBrowseToCriminalActivitySites","Enabled":false},{"Name":"EpoBrowseToCultSites","Enabled":false},{"Name":"EpoBrowseToGamblingSites","Enabled":false},{"Name":"EpoBrowseToHackingSites","Enabled":false},{"Name":"EpoBrowseToHateIntoleranceSites","Enabled":false},{"Name":"EpoBrowseToIllegalSoftwareSites","Enabled":false},{"Name":"EpoBrowseToKeyloggerSites","Enabled":false},{"Name":"EpoBrowseToLlmSites","Enabled":false},{"Name":"EpoBrowseToMalwareSites","Enabled":false},{"Name":"EpoBrowseToPhishingSites","Enabled":false},{"Name":"EpoBrowseToPornographySites","Enabled":false},{"Name":"EpoBrowseToUnallowedDomain","Enabled":false},{"Name":"EpoBrowseToViolenceSites","Enabled":false},{"Name":"EpoCopyToClipboardFromSensitiveFile","Enabled":false},{"Name":"EpoCopyToNetworkShare","Enabled":false},{"Name":"EpoFileArchived","Enabled":false},{"Name":"EpoFileCopiedToRemoteDesktopSession","Enabled":false},{"Name":"EpoFileDeleted","Enabled":false},{"Name":"EpoFileDownloadedFromBlacklistedDomain","Enabled":false},{"Name":"EpoFileDownloadedFromEnterpriseDomain","Enabled":false},{"Name":"EpoFileRenamed","Enabled":false},{"Name":"EpoFileStagedToCentralLocation","Enabled":false},{"Name":"EpoHiddenFileCreated","Enabled":false},{"Name":"EpoRemovableMediaMount","Enabled":false},{"Name":"EpoSensitiveFileRead","Enabled":false},{"Name":"Mcas3rdPartyAppDownload","Enabled":false},{"Name":"Mcas3rdPartyAppFileDelete","Enabled":false},{"Name":"Mcas3rdPartyAppFileSharing","Enabled":false},{"Name":"McasActivityFromInfrequentCountry","Enabled":false},{"Name":"McasImpossibleTravel","Enabled":false},{"Name":"McasMultipleFailedLogins","Enabled":false},{"Name":"McasMultipleStorageDeletion","Enabled":false},{"Name":"McasMultipleVMCreation","Enabled":true},{"Name":"McasMultipleVMDeletion","Enabled":false},{"Name":"McasSuspiciousAdminActivities","Enabled":false},{"Name":"McasSuspiciousCloudCreation","Enabled":false},{"Name":"McasSuspiciousCloudTrailLoggingChange","Enabled":false},{"Name":"McasTerminatedEmployeeActivity","Enabled":false},{"Name":"OdbDownload","Enabled":false},{"Name":"OdbSyncDownload","Enabled":false},{"Name":"PeerCumulativeExfiltrationDetector","Enabled":false},{"Name":"PhysicalAccess","Enabled":false},{"Name":"PotentialHighImpactUser","Enabled":false},{"Name":"Print","Enabled":false},{"Name":"PriorityUserGroupMember","Enabled":false},{"Name":"SecurityAlertDefenseEvasion","Enabled":false},{"Name":"SecurityAlertUnwantedSoftware","Enabled":false},{"Name":"SpoAccessRequest","Enabled":false},{"Name":"SpoApprovedAccess","Enabled":false},{"Name":"SpoDownload","Enabled":false},{"Name":"SpoDownloadV2","Enabled":false},{"Name":"SpoFileAccessed","Enabled":false},{"Name":"SpoFileDeleted","Enabled":false},{"Name":"SpoFileDeletedFromFirstStageRecycleBin","Enabled":false},{"Name":"SpoFileDeletedFromSecondStageRecycleBin","Enabled":false},{"Name":"SpoFileLabelDowngraded","Enabled":false},{"Name":"SpoFileLabelRemoved","Enabled":false},{"Name":"SpoFileSharing","Enabled":true},{"Name":"SpoFolderDeleted","Enabled":false},{"Name":"SpoFolderDeletedFromFirstStageRecycleBin","Enabled":false},{"Name":"SpoFolderDeletedFromSecondStageRecycleBin","Enabled":false},{"Name":"SpoFolderSharing","Enabled":false},{"Name":"SpoSiteExternalUserAdded","Enabled":false},{"Name":"SpoSiteInternalUserAdded","Enabled":false},{"Name":"SpoSiteLabelRemoved","Enabled":false},{"Name":"SpoSiteSharing","Enabled":false},{"Name":"SpoSyncDownload","Enabled":false},{"Name":"TeamsChannelFileSharedExternal","Enabled":false},{"Name":"TeamsChannelMemberAddedExternal","Enabled":false},{"Name":"TeamsChatFileSharedExternal","Enabled":false},{"Name":"TeamsFileDownload","Enabled":false},{"Name":"TeamsFolderSharedExternal","Enabled":false},{"Name":"TeamsMemberAddedExternal","Enabled":false},{"Name":"TeamsSensitiveMessage","Enabled":false},{"Name":"UserHistory","Enabled":false}],"ExtensibleIndicators":[{"Name":"AWSS3BlockPublicAccessDisabled","Enabled":false},{"Name":"AWSS3BucketDeleted","Enabled":false},{"Name":"AWSS3PublicAccessEnabled","Enabled":false},{"Name":"AWSS3ServerLoggingDisabled","Enabled":false},{"Name":"AzureElevateAccessToAllSubscriptions","Enabled":false},{"Name":"AzureResourceThreatProtectionSettingsUpdated","Enabled":false},{"Name":"AzureSQLServerAuditingSettingsUpdated","Enabled":false},{"Name":"AzureSQLServerFirewallRuleDeleted","Enabled":false},{"Name":"AzureSQLServerFirewallRuleUpdated","Enabled":false},{"Name":"AzureStorageAccountOrContainerDeleted","Enabled":false},{"Name":"BoxContentAccess","Enabled":false},{"Name":"BoxContentDelete","Enabled":false},{"Name":"BoxContentDownload","Enabled":false},{"Name":"BoxContentExternallyShared","Enabled":false},{"Name":"CCFinancialRegulatoryRiskyTextSent","Enabled":false},{"Name":"CCInappropriateContentSent","Enabled":false},{"Name":"CCInappropriateImagesSent","Enabled":false},{"Name":"DropboxContentAccess","Enabled":false},{"Name":"DropboxContentDelete","Enabled":false},{"Name":"DropboxContentDownload","Enabled":false},{"Name":"DropboxContentExternallyShared","Enabled":false},{"Name":"GoogleDriveContentAccess","Enabled":false},{"Name":"GoogleDriveContentDelete","Enabled":false},{"Name":"GoogleDriveContentExternallyShared","Enabled":false},{"Name":"PowerBIDashboardsDeleted","Enabled":false},{"Name":"PowerBIReportsDeleted","Enabled":false},{"Name":"PowerBIReportsDownloaded","Enabled":false},{"Name":"PowerBIReportsExported","Enabled":false},{"Name":"PowerBIReportsViewed","Enabled":false},{"Name":"PowerBISemanticModelsDeleted","Enabled":false},{"Name":"PowerBISensitivityLabelDowngradedForArtifacts","Enabled":false},{"Name":"PowerBISensitivityLabelRemovedFromArtifacts","Enabled":false}],"TimeSpan":{"InScopeTimeSpan":"30","HistoricTimeSpan":"89","FutureTerminationWindow":"5","PastTerminationWindow":"5","PostTerminationActivity":"False"},"IntelligentDetections":{"FileVolCutoffLimits":"59","AlertVolume":"Medium"},"FeatureSettings":{"Anonymization":"false","DLPUserRiskSync":"true","OptInIRMDataExport":"true","RaiseAuditAlert":"true","EnableTeam":"true"},"NotificationPreferences":null,"DynamicRiskPreventionSettings":null,"InterpretedSettings":null}' + ) } } } @@ -94,23 +117,28 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should remove the instance from the Set method' { - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-InsiderRiskPolicy -Exactly 1 } } Context -Name "The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + AnomalyDetections = $False; + InsiderRiskScenario = "TenantSetting"; + Name = "IRM_Tenant_Setting"; + Ensure = 'Present' + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-InsiderRiskPolicy -MockWith { return @{ - + Name = "IRM_Tenant_Setting" + InsiderRiskScenario = "TenantSetting" + TenantSettings = @( + '{"Region":"WW","IndicatorVersion":"1.1","Indicators":[{"Name":"AnomalyDetections","Enabled":false},{"Name":"CumulativeExfiltrationDetector","Enabled":true},{"Name":"EmailExternal","Enabled":false},{"Name":"EmployeeAccessedEmployeePatientData","Enabled":false},{"Name":"EmployeeAccessedFamilyData","Enabled":false},{"Name":"EmployeeAccessedHighVolumePatientData","Enabled":false},{"Name":"EmployeeAccessedNeighbourData","Enabled":false},{"Name":"EmployeeAccessedRestrictedData","Enabled":false},{"Name":"EpoBrowseToChildAbuseSites","Enabled":false},{"Name":"EpoBrowseToCriminalActivitySites","Enabled":false},{"Name":"EpoBrowseToCultSites","Enabled":false},{"Name":"EpoBrowseToGamblingSites","Enabled":false},{"Name":"EpoBrowseToHackingSites","Enabled":false},{"Name":"EpoBrowseToHateIntoleranceSites","Enabled":false},{"Name":"EpoBrowseToIllegalSoftwareSites","Enabled":false},{"Name":"EpoBrowseToKeyloggerSites","Enabled":false},{"Name":"EpoBrowseToLlmSites","Enabled":false},{"Name":"EpoBrowseToMalwareSites","Enabled":false},{"Name":"EpoBrowseToPhishingSites","Enabled":false},{"Name":"EpoBrowseToPornographySites","Enabled":false},{"Name":"EpoBrowseToUnallowedDomain","Enabled":false},{"Name":"EpoBrowseToViolenceSites","Enabled":false},{"Name":"EpoCopyToClipboardFromSensitiveFile","Enabled":false},{"Name":"EpoCopyToNetworkShare","Enabled":false},{"Name":"EpoFileArchived","Enabled":false},{"Name":"EpoFileCopiedToRemoteDesktopSession","Enabled":false},{"Name":"EpoFileDeleted","Enabled":false},{"Name":"EpoFileDownloadedFromBlacklistedDomain","Enabled":false},{"Name":"EpoFileDownloadedFromEnterpriseDomain","Enabled":false},{"Name":"EpoFileRenamed","Enabled":false},{"Name":"EpoFileStagedToCentralLocation","Enabled":false},{"Name":"EpoHiddenFileCreated","Enabled":false},{"Name":"EpoRemovableMediaMount","Enabled":false},{"Name":"EpoSensitiveFileRead","Enabled":false},{"Name":"Mcas3rdPartyAppDownload","Enabled":false},{"Name":"Mcas3rdPartyAppFileDelete","Enabled":false},{"Name":"Mcas3rdPartyAppFileSharing","Enabled":false},{"Name":"McasActivityFromInfrequentCountry","Enabled":false},{"Name":"McasImpossibleTravel","Enabled":false},{"Name":"McasMultipleFailedLogins","Enabled":false},{"Name":"McasMultipleStorageDeletion","Enabled":false},{"Name":"McasMultipleVMCreation","Enabled":true},{"Name":"McasMultipleVMDeletion","Enabled":false},{"Name":"McasSuspiciousAdminActivities","Enabled":false},{"Name":"McasSuspiciousCloudCreation","Enabled":false},{"Name":"McasSuspiciousCloudTrailLoggingChange","Enabled":false},{"Name":"McasTerminatedEmployeeActivity","Enabled":false},{"Name":"OdbDownload","Enabled":false},{"Name":"OdbSyncDownload","Enabled":false},{"Name":"PeerCumulativeExfiltrationDetector","Enabled":false},{"Name":"PhysicalAccess","Enabled":false},{"Name":"PotentialHighImpactUser","Enabled":false},{"Name":"Print","Enabled":false},{"Name":"PriorityUserGroupMember","Enabled":false},{"Name":"SecurityAlertDefenseEvasion","Enabled":false},{"Name":"SecurityAlertUnwantedSoftware","Enabled":false},{"Name":"SpoAccessRequest","Enabled":false},{"Name":"SpoApprovedAccess","Enabled":false},{"Name":"SpoDownload","Enabled":false},{"Name":"SpoDownloadV2","Enabled":false},{"Name":"SpoFileAccessed","Enabled":false},{"Name":"SpoFileDeleted","Enabled":false},{"Name":"SpoFileDeletedFromFirstStageRecycleBin","Enabled":false},{"Name":"SpoFileDeletedFromSecondStageRecycleBin","Enabled":false},{"Name":"SpoFileLabelDowngraded","Enabled":false},{"Name":"SpoFileLabelRemoved","Enabled":false},{"Name":"SpoFileSharing","Enabled":true},{"Name":"SpoFolderDeleted","Enabled":false},{"Name":"SpoFolderDeletedFromFirstStageRecycleBin","Enabled":false},{"Name":"SpoFolderDeletedFromSecondStageRecycleBin","Enabled":false},{"Name":"SpoFolderSharing","Enabled":false},{"Name":"SpoSiteExternalUserAdded","Enabled":false},{"Name":"SpoSiteInternalUserAdded","Enabled":false},{"Name":"SpoSiteLabelRemoved","Enabled":false},{"Name":"SpoSiteSharing","Enabled":false},{"Name":"SpoSyncDownload","Enabled":false},{"Name":"TeamsChannelFileSharedExternal","Enabled":false},{"Name":"TeamsChannelMemberAddedExternal","Enabled":false},{"Name":"TeamsChatFileSharedExternal","Enabled":false},{"Name":"TeamsFileDownload","Enabled":false},{"Name":"TeamsFolderSharedExternal","Enabled":false},{"Name":"TeamsMemberAddedExternal","Enabled":false},{"Name":"TeamsSensitiveMessage","Enabled":false},{"Name":"UserHistory","Enabled":false}],"ExtensibleIndicators":[{"Name":"AWSS3BlockPublicAccessDisabled","Enabled":false},{"Name":"AWSS3BucketDeleted","Enabled":false},{"Name":"AWSS3PublicAccessEnabled","Enabled":false},{"Name":"AWSS3ServerLoggingDisabled","Enabled":false},{"Name":"AzureElevateAccessToAllSubscriptions","Enabled":false},{"Name":"AzureResourceThreatProtectionSettingsUpdated","Enabled":false},{"Name":"AzureSQLServerAuditingSettingsUpdated","Enabled":false},{"Name":"AzureSQLServerFirewallRuleDeleted","Enabled":false},{"Name":"AzureSQLServerFirewallRuleUpdated","Enabled":false},{"Name":"AzureStorageAccountOrContainerDeleted","Enabled":false},{"Name":"BoxContentAccess","Enabled":false},{"Name":"BoxContentDelete","Enabled":false},{"Name":"BoxContentDownload","Enabled":false},{"Name":"BoxContentExternallyShared","Enabled":false},{"Name":"CCFinancialRegulatoryRiskyTextSent","Enabled":false},{"Name":"CCInappropriateContentSent","Enabled":false},{"Name":"CCInappropriateImagesSent","Enabled":false},{"Name":"DropboxContentAccess","Enabled":false},{"Name":"DropboxContentDelete","Enabled":false},{"Name":"DropboxContentDownload","Enabled":false},{"Name":"DropboxContentExternallyShared","Enabled":false},{"Name":"GoogleDriveContentAccess","Enabled":false},{"Name":"GoogleDriveContentDelete","Enabled":false},{"Name":"GoogleDriveContentExternallyShared","Enabled":false},{"Name":"PowerBIDashboardsDeleted","Enabled":false},{"Name":"PowerBIReportsDeleted","Enabled":false},{"Name":"PowerBIReportsDownloaded","Enabled":false},{"Name":"PowerBIReportsExported","Enabled":false},{"Name":"PowerBIReportsViewed","Enabled":false},{"Name":"PowerBISemanticModelsDeleted","Enabled":false},{"Name":"PowerBISensitivityLabelDowngradedForArtifacts","Enabled":false},{"Name":"PowerBISensitivityLabelRemovedFromArtifacts","Enabled":false}],"TimeSpan":{"InScopeTimeSpan":"30","HistoricTimeSpan":"89","FutureTerminationWindow":"5","PastTerminationWindow":"5","PostTerminationActivity":"False"},"IntelligentDetections":{"FileVolCutoffLimits":"59","AlertVolume":"Medium"},"FeatureSettings":{"Anonymization":"false","DLPUserRiskSync":"true","OptInIRMDataExport":"true","RaiseAuditAlert":"true","EnableTeam":"true"},"NotificationPreferences":null,"DynamicRiskPreventionSettings":null,"InterpretedSettings":null}' + ) } } } @@ -123,15 +151,29 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + Anonymization = $false + AlertVolume = "Medium"; + AnalyticsNewInsightEnabled = $False; + AnalyticsTurnedOffEnabled = $False; + AnomalyDetections = $False; + AzureStorageAccountOrContainerDeleted = $True; #Drift + CCInappropriateContentSent = $False; + EnableTeam = $True; + InsiderRiskScenario = "TenantSetting"; + Mcas3rdPartyAppDownload = $False; + Name = "IRM_Tenant_Setting"; + NotificationDetailsEnabled = $True; + Ensure = 'Present' + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { - return @{ - + Mock -CommandName Get-InsiderRiskPolicy -MockWith { + return @{ + Name = "IRM_Tenant_Setting" + InsiderRiskScenario = "TenantSetting" + TenantSettings = @( + '{"Region":"WW","IndicatorVersion":"1.1","Indicators":[{"Name":"AnomalyDetections","Enabled":false},{"Name":"CopyToPersonalCloud","Enabled":false},{"Name":"CopyToUSB","Enabled":false},{"Name":"CumulativeExfiltrationDetector","Enabled":true},{"Name":"EmailExternal","Enabled":false},{"Name":"EmployeeAccessedEmployeePatientData","Enabled":false},{"Name":"EmployeeAccessedFamilyData","Enabled":false},{"Name":"EmployeeAccessedHighVolumePatientData","Enabled":false},{"Name":"EmployeeAccessedNeighbourData","Enabled":false},{"Name":"EmployeeAccessedRestrictedData","Enabled":false},{"Name":"EpoBrowseToChildAbuseSites","Enabled":false},{"Name":"EpoBrowseToCriminalActivitySites","Enabled":false},{"Name":"EpoBrowseToCultSites","Enabled":false},{"Name":"EpoBrowseToGamblingSites","Enabled":false},{"Name":"EpoBrowseToHackingSites","Enabled":false},{"Name":"EpoBrowseToHateIntoleranceSites","Enabled":false},{"Name":"EpoBrowseToIllegalSoftwareSites","Enabled":false},{"Name":"EpoBrowseToKeyloggerSites","Enabled":false},{"Name":"EpoBrowseToLlmSites","Enabled":false},{"Name":"EpoBrowseToMalwareSites","Enabled":false},{"Name":"EpoBrowseToPhishingSites","Enabled":false},{"Name":"EpoBrowseToPornographySites","Enabled":false},{"Name":"EpoBrowseToUnallowedDomain","Enabled":false},{"Name":"EpoBrowseToViolenceSites","Enabled":false},{"Name":"EpoCopyToClipboardFromSensitiveFile","Enabled":false},{"Name":"EpoCopyToNetworkShare","Enabled":false},{"Name":"EpoFileArchived","Enabled":false},{"Name":"EpoFileCopiedToRemoteDesktopSession","Enabled":false},{"Name":"EpoFileDeleted","Enabled":false},{"Name":"EpoFileDownloadedFromBlacklistedDomain","Enabled":false},{"Name":"EpoFileDownloadedFromEnterpriseDomain","Enabled":false},{"Name":"EpoFileRenamed","Enabled":false},{"Name":"EpoFileStagedToCentralLocation","Enabled":false},{"Name":"EpoHiddenFileCreated","Enabled":false},{"Name":"EpoRemovableMediaMount","Enabled":false},{"Name":"EpoSensitiveFileRead","Enabled":false},{"Name":"Mcas3rdPartyAppDownload","Enabled":false},{"Name":"Mcas3rdPartyAppFileDelete","Enabled":false},{"Name":"Mcas3rdPartyAppFileSharing","Enabled":false},{"Name":"McasActivityFromInfrequentCountry","Enabled":false},{"Name":"McasImpossibleTravel","Enabled":false},{"Name":"McasMultipleFailedLogins","Enabled":false},{"Name":"McasMultipleStorageDeletion","Enabled":false},{"Name":"McasMultipleVMCreation","Enabled":true},{"Name":"McasMultipleVMDeletion","Enabled":false},{"Name":"McasSuspiciousAdminActivities","Enabled":false},{"Name":"McasSuspiciousCloudCreation","Enabled":false},{"Name":"McasSuspiciousCloudTrailLoggingChange","Enabled":false},{"Name":"McasTerminatedEmployeeActivity","Enabled":false},{"Name":"OdbDownload","Enabled":false},{"Name":"OdbSyncDownload","Enabled":false},{"Name":"PeerCumulativeExfiltrationDetector","Enabled":false},{"Name":"PhysicalAccess","Enabled":false},{"Name":"PotentialHighImpactUser","Enabled":false},{"Name":"Print","Enabled":false},{"Name":"PriorityUserGroupMember","Enabled":false},{"Name":"SecurityAlertDefenseEvasion","Enabled":false},{"Name":"SecurityAlertUnwantedSoftware","Enabled":false},{"Name":"SpoAccessRequest","Enabled":false},{"Name":"SpoApprovedAccess","Enabled":false},{"Name":"SpoDownload","Enabled":false},{"Name":"SpoDownloadV2","Enabled":false},{"Name":"SpoFileAccessed","Enabled":false},{"Name":"SpoFileDeleted","Enabled":false},{"Name":"SpoFileDeletedFromFirstStageRecycleBin","Enabled":false},{"Name":"SpoFileDeletedFromSecondStageRecycleBin","Enabled":false},{"Name":"SpoFileLabelDowngraded","Enabled":false},{"Name":"SpoFileLabelRemoved","Enabled":false},{"Name":"SpoFileSharing","Enabled":true},{"Name":"SpoFolderDeleted","Enabled":false},{"Name":"SpoFolderDeletedFromFirstStageRecycleBin","Enabled":false},{"Name":"SpoFolderDeletedFromSecondStageRecycleBin","Enabled":false},{"Name":"SpoFolderSharing","Enabled":false},{"Name":"SpoSiteExternalUserAdded","Enabled":false},{"Name":"SpoSiteInternalUserAdded","Enabled":false},{"Name":"SpoSiteLabelRemoved","Enabled":false},{"Name":"SpoSiteSharing","Enabled":false},{"Name":"SpoSyncDownload","Enabled":false},{"Name":"TeamsChannelFileSharedExternal","Enabled":false},{"Name":"TeamsChannelMemberAddedExternal","Enabled":false},{"Name":"TeamsChatFileSharedExternal","Enabled":false},{"Name":"TeamsFileDownload","Enabled":false},{"Name":"TeamsFolderSharedExternal","Enabled":false},{"Name":"TeamsMemberAddedExternal","Enabled":false},{"Name":"TeamsSensitiveMessage","Enabled":false},{"Name":"UserHistory","Enabled":false}],"ExtensibleIndicators":[{"Name":"AWSS3BlockPublicAccessDisabled","Enabled":false},{"Name":"AWSS3BucketDeleted","Enabled":false},{"Name":"AWSS3PublicAccessEnabled","Enabled":false},{"Name":"AWSS3ServerLoggingDisabled","Enabled":false},{"Name":"AzureElevateAccessToAllSubscriptions","Enabled":false},{"Name":"AzureResourceThreatProtectionSettingsUpdated","Enabled":false},{"Name":"AzureSQLServerAuditingSettingsUpdated","Enabled":false},{"Name":"AzureSQLServerFirewallRuleDeleted","Enabled":false},{"Name":"AzureSQLServerFirewallRuleUpdated","Enabled":false},{"Name":"AzureStorageAccountOrContainerDeleted","Enabled":false},{"Name":"BoxContentAccess","Enabled":false},{"Name":"BoxContentDelete","Enabled":false},{"Name":"BoxContentDownload","Enabled":false},{"Name":"BoxContentExternallyShared","Enabled":false},{"Name":"CCFinancialRegulatoryRiskyTextSent","Enabled":false},{"Name":"CCInappropriateContentSent","Enabled":false},{"Name":"CCInappropriateImagesSent","Enabled":false},{"Name":"DropboxContentAccess","Enabled":false},{"Name":"DropboxContentDelete","Enabled":false},{"Name":"DropboxContentDownload","Enabled":false},{"Name":"DropboxContentExternallyShared","Enabled":false},{"Name":"GoogleDriveContentAccess","Enabled":false},{"Name":"GoogleDriveContentDelete","Enabled":false},{"Name":"GoogleDriveContentExternallyShared","Enabled":false},{"Name":"PowerBIDashboardsDeleted","Enabled":false},{"Name":"PowerBIReportsDeleted","Enabled":false},{"Name":"PowerBIReportsDownloaded","Enabled":false},{"Name":"PowerBIReportsExported","Enabled":false},{"Name":"PowerBIReportsViewed","Enabled":false},{"Name":"PowerBISemanticModelsDeleted","Enabled":false},{"Name":"PowerBISensitivityLabelDowngradedForArtifacts","Enabled":false},{"Name":"PowerBISensitivityLabelRemovedFromArtifacts","Enabled":false}],"TimeSpan":{"InScopeTimeSpan":"30","HistoricTimeSpan":"89","FutureTerminationWindow":"5","PastTerminationWindow":"5","PostTerminationActivity":"False"},"IntelligentDetections":{"FileVolCutoffLimits":"59","AlertVolume":"Medium"},"FeatureSettings":{"Anonymization":"false","DLPUserRiskSync":"true","OptInIRMDataExport":"true","RaiseAuditAlert":"true","EnableTeam":"true"},"NotificationPreferences":null,"DynamicRiskPreventionSettings":null,"InterpretedSettings":null}' + ) } } } @@ -146,8 +188,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the Set method' { Set-TargetResource @testParams - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + Should -Invoke -CommandName Set-InsiderRiskPolicy -Exactly 1 } } @@ -159,10 +200,13 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-InsiderRiskPolicy -MockWith { return @{ - + Name = "IRM_Tenant_Setting" + InsiderRiskScenario = "TenantSetting" + TenantSettings = @( + '{"Region":"WW","IndicatorVersion":"1.1","Indicators":[{"Name":"AnomalyDetections","Enabled":false},{"Name":"CopyToPersonalCloud","Enabled":false},{"Name":"CopyToUSB","Enabled":false},{"Name":"CumulativeExfiltrationDetector","Enabled":true},{"Name":"EmailExternal","Enabled":false},{"Name":"EmployeeAccessedEmployeePatientData","Enabled":false},{"Name":"EmployeeAccessedFamilyData","Enabled":false},{"Name":"EmployeeAccessedHighVolumePatientData","Enabled":false},{"Name":"EmployeeAccessedNeighbourData","Enabled":false},{"Name":"EmployeeAccessedRestrictedData","Enabled":false},{"Name":"EpoBrowseToChildAbuseSites","Enabled":false},{"Name":"EpoBrowseToCriminalActivitySites","Enabled":false},{"Name":"EpoBrowseToCultSites","Enabled":false},{"Name":"EpoBrowseToGamblingSites","Enabled":false},{"Name":"EpoBrowseToHackingSites","Enabled":false},{"Name":"EpoBrowseToHateIntoleranceSites","Enabled":false},{"Name":"EpoBrowseToIllegalSoftwareSites","Enabled":false},{"Name":"EpoBrowseToKeyloggerSites","Enabled":false},{"Name":"EpoBrowseToLlmSites","Enabled":false},{"Name":"EpoBrowseToMalwareSites","Enabled":false},{"Name":"EpoBrowseToPhishingSites","Enabled":false},{"Name":"EpoBrowseToPornographySites","Enabled":false},{"Name":"EpoBrowseToUnallowedDomain","Enabled":false},{"Name":"EpoBrowseToViolenceSites","Enabled":false},{"Name":"EpoCopyToClipboardFromSensitiveFile","Enabled":false},{"Name":"EpoCopyToNetworkShare","Enabled":false},{"Name":"EpoFileArchived","Enabled":false},{"Name":"EpoFileCopiedToRemoteDesktopSession","Enabled":false},{"Name":"EpoFileDeleted","Enabled":false},{"Name":"EpoFileDownloadedFromBlacklistedDomain","Enabled":false},{"Name":"EpoFileDownloadedFromEnterpriseDomain","Enabled":false},{"Name":"EpoFileRenamed","Enabled":false},{"Name":"EpoFileStagedToCentralLocation","Enabled":false},{"Name":"EpoHiddenFileCreated","Enabled":false},{"Name":"EpoRemovableMediaMount","Enabled":false},{"Name":"EpoSensitiveFileRead","Enabled":false},{"Name":"Mcas3rdPartyAppDownload","Enabled":false},{"Name":"Mcas3rdPartyAppFileDelete","Enabled":false},{"Name":"Mcas3rdPartyAppFileSharing","Enabled":false},{"Name":"McasActivityFromInfrequentCountry","Enabled":false},{"Name":"McasImpossibleTravel","Enabled":false},{"Name":"McasMultipleFailedLogins","Enabled":false},{"Name":"McasMultipleStorageDeletion","Enabled":false},{"Name":"McasMultipleVMCreation","Enabled":true},{"Name":"McasMultipleVMDeletion","Enabled":false},{"Name":"McasSuspiciousAdminActivities","Enabled":false},{"Name":"McasSuspiciousCloudCreation","Enabled":false},{"Name":"McasSuspiciousCloudTrailLoggingChange","Enabled":false},{"Name":"McasTerminatedEmployeeActivity","Enabled":false},{"Name":"OdbDownload","Enabled":false},{"Name":"OdbSyncDownload","Enabled":false},{"Name":"PeerCumulativeExfiltrationDetector","Enabled":false},{"Name":"PhysicalAccess","Enabled":false},{"Name":"PotentialHighImpactUser","Enabled":false},{"Name":"Print","Enabled":false},{"Name":"PriorityUserGroupMember","Enabled":false},{"Name":"SecurityAlertDefenseEvasion","Enabled":false},{"Name":"SecurityAlertUnwantedSoftware","Enabled":false},{"Name":"SpoAccessRequest","Enabled":false},{"Name":"SpoApprovedAccess","Enabled":false},{"Name":"SpoDownload","Enabled":false},{"Name":"SpoDownloadV2","Enabled":false},{"Name":"SpoFileAccessed","Enabled":false},{"Name":"SpoFileDeleted","Enabled":false},{"Name":"SpoFileDeletedFromFirstStageRecycleBin","Enabled":false},{"Name":"SpoFileDeletedFromSecondStageRecycleBin","Enabled":false},{"Name":"SpoFileLabelDowngraded","Enabled":false},{"Name":"SpoFileLabelRemoved","Enabled":false},{"Name":"SpoFileSharing","Enabled":true},{"Name":"SpoFolderDeleted","Enabled":false},{"Name":"SpoFolderDeletedFromFirstStageRecycleBin","Enabled":false},{"Name":"SpoFolderDeletedFromSecondStageRecycleBin","Enabled":false},{"Name":"SpoFolderSharing","Enabled":false},{"Name":"SpoSiteExternalUserAdded","Enabled":false},{"Name":"SpoSiteInternalUserAdded","Enabled":false},{"Name":"SpoSiteLabelRemoved","Enabled":false},{"Name":"SpoSiteSharing","Enabled":false},{"Name":"SpoSyncDownload","Enabled":false},{"Name":"TeamsChannelFileSharedExternal","Enabled":false},{"Name":"TeamsChannelMemberAddedExternal","Enabled":false},{"Name":"TeamsChatFileSharedExternal","Enabled":false},{"Name":"TeamsFileDownload","Enabled":false},{"Name":"TeamsFolderSharedExternal","Enabled":false},{"Name":"TeamsMemberAddedExternal","Enabled":false},{"Name":"TeamsSensitiveMessage","Enabled":false},{"Name":"UserHistory","Enabled":false}],"ExtensibleIndicators":[{"Name":"AWSS3BlockPublicAccessDisabled","Enabled":false},{"Name":"AWSS3BucketDeleted","Enabled":false},{"Name":"AWSS3PublicAccessEnabled","Enabled":false},{"Name":"AWSS3ServerLoggingDisabled","Enabled":false},{"Name":"AzureElevateAccessToAllSubscriptions","Enabled":false},{"Name":"AzureResourceThreatProtectionSettingsUpdated","Enabled":false},{"Name":"AzureSQLServerAuditingSettingsUpdated","Enabled":false},{"Name":"AzureSQLServerFirewallRuleDeleted","Enabled":false},{"Name":"AzureSQLServerFirewallRuleUpdated","Enabled":false},{"Name":"AzureStorageAccountOrContainerDeleted","Enabled":false},{"Name":"BoxContentAccess","Enabled":false},{"Name":"BoxContentDelete","Enabled":false},{"Name":"BoxContentDownload","Enabled":false},{"Name":"BoxContentExternallyShared","Enabled":false},{"Name":"CCFinancialRegulatoryRiskyTextSent","Enabled":false},{"Name":"CCInappropriateContentSent","Enabled":false},{"Name":"CCInappropriateImagesSent","Enabled":false},{"Name":"DropboxContentAccess","Enabled":false},{"Name":"DropboxContentDelete","Enabled":false},{"Name":"DropboxContentDownload","Enabled":false},{"Name":"DropboxContentExternallyShared","Enabled":false},{"Name":"GoogleDriveContentAccess","Enabled":false},{"Name":"GoogleDriveContentDelete","Enabled":false},{"Name":"GoogleDriveContentExternallyShared","Enabled":false},{"Name":"PowerBIDashboardsDeleted","Enabled":false},{"Name":"PowerBIReportsDeleted","Enabled":false},{"Name":"PowerBIReportsDownloaded","Enabled":false},{"Name":"PowerBIReportsExported","Enabled":false},{"Name":"PowerBIReportsViewed","Enabled":false},{"Name":"PowerBISemanticModelsDeleted","Enabled":false},{"Name":"PowerBISensitivityLabelDowngradedForArtifacts","Enabled":false},{"Name":"PowerBISensitivityLabelRemovedFromArtifacts","Enabled":false}],"TimeSpan":{"InScopeTimeSpan":"30","HistoricTimeSpan":"89","FutureTerminationWindow":"5","PastTerminationWindow":"5","PostTerminationActivity":"False"},"IntelligentDetections":{"FileVolCutoffLimits":"59","AlertVolume":"Medium"},"FeatureSettings":{"Anonymization":"false","DLPUserRiskSync":"true","OptInIRMDataExport":"true","RaiseAuditAlert":"true","EnableTeam":"true"},"NotificationPreferences":null,"DynamicRiskPreventionSettings":null,"InterpretedSettings":null}' + ) } } } diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index c1cfaf92b3..cae92f1dde 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -70346,6 +70346,387 @@ function Get-MgBetaDirectoryObject } #endregion #region SecurityComplianceCenter +function Get-InsiderRiskPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Boolean] + $MetaDataOnly, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $DistributionDetail + ) +} +function New-InsiderRiskPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Boolean] + $IsCustom, + + [Parameter()] + [System.Object] + $ExchangeLocationException, + + [Parameter()] + [System.Object] + $Indicators, + + [Parameter()] + [System.Object] + $ExtensibleIndicators, + + [Parameter()] + [System.Object] + $ModernGroupLocationException, + + [Parameter()] + [System.String] + $CCPolicySdsId, + + [Parameter()] + [System.Boolean] + $Enabled, + + [Parameter()] + [System.Object] + $ExtensibleTriggerInsightGroups, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Object] + $UserMailList, + + [Parameter()] + [System.Object] + $PolicyRBACScopes, + + [Parameter()] + [System.Object] + $ExchangeLocation, + + [Parameter()] + [System.Object] + $FileExtensions, + + [Parameter()] + [System.Boolean] + $OptInDrpForDlp, + + [Parameter()] + [System.Int32] + $UseDefaultTemplate, + + [Parameter()] + [System.Boolean] + $IsPriorityContentOnlyScoring, + + [Parameter()] + [System.Object] + $Triggers, + + [Parameter()] + [System.Object] + $SharepointSites, + + [Parameter()] + [System.String] + $Comment, + + [Parameter()] + [System.Object] + $TeamsSites, + + [Parameter()] + [System.Int32] + $HistoricTimeSpan, + + [Parameter()] + [System.Int32] + $PastTerminationWindow, + + [Parameter()] + [System.Object] + $MLClassifierTypes, + + [Parameter()] + [System.Object] + $ModernGroupLocation, + + [Parameter()] + [System.Object] + $InsiderRiskScenario, + + [Parameter()] + [System.String] + $SessionRecordingSettings, + + [Parameter()] + [System.Object] + $DlpPolicy, + + [Parameter()] + [System.Int32] + $FutureTerminationWindow, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Boolean] + $PostTerminationActivity, + + [Parameter()] + [System.Object] + $IrmAdaptiveScopeLocation, + + [Parameter()] + [System.Object] + $CustomTags, + + [Parameter()] + [System.String] + $CCPolicyName, + + [Parameter()] + [System.Object] + $TriggerInsightGroups, + + [Parameter()] + [System.String] + $TenantSetting, + + [Parameter()] + [System.Object] + $SensitivityLabels, + + [Parameter()] + [System.Object] + $DlpSensitiveTypes, + + [Parameter()] + [System.Int32] + $InScopeTimeSpan, + + [Parameter()] + [System.Int32] + $SchemaVersion + ) +} +function Remove-InsiderRiskPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ForceDeletion + ) +} +function Set-InsiderRiskPolicy +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Boolean] + $IsCustom, + + [Parameter()] + [System.Object] + $Indicators, + + [Parameter()] + [System.String] + $TurnOnAnalytics, + + [Parameter()] + [System.Object] + $AddExchangeLocationException, + + [Parameter()] + [System.String] + $SessionRecordingSettings, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.String] + $CCPolicyName, + + [Parameter()] + [System.Object] + $RemoveExchangeLocationException, + + [Parameter()] + [System.String] + $CCPolicySdsId, + + [Parameter()] + [System.Boolean] + $Enabled, + + [Parameter()] + [System.Object] + $ExtensibleTriggerInsightGroups, + + [Parameter()] + [System.Object] + $AddExchangeLocation, + + [Parameter()] + [System.Object] + $PolicyRBACScopes, + + [Parameter()] + [System.Object] + $FileExtensions, + + [Parameter()] + [System.Boolean] + $OptInDrpForDlp, + + [Parameter()] + [System.Object] + $RemoveIrmAdaptiveScopeLocation, + + [Parameter()] + [System.Object] + $RemoveModernGroupLocationException, + + [Parameter()] + [System.Object] + $AddModernGroupLocationException, + + [Parameter()] + [System.Object] + $DlpPolicy, + + [Parameter()] + [System.Boolean] + $IsPriorityContentOnlyScoring, + + [Parameter()] + [System.Object] + $Triggers, + + [Parameter()] + [System.Object] + $AddModernGroupLocation, + + [Parameter()] + [System.String] + $Comment, + + [Parameter()] + [System.Object] + $TeamsSites, + + [Parameter()] + [System.Int32] + $HistoricTimeSpan, + + [Parameter()] + [System.String] + $TurnOnDLPUserRiskSync, + + [Parameter()] + [System.Object] + $RemoveModernGroupLocation, + + [Parameter()] + [System.Object] + $MLClassifierTypes, + + [Parameter()] + [System.Object] + $ExtensibleIndicators, + + [Parameter()] + [System.Object] + $AddIrmAdaptiveScopeLocation, + + [Parameter()] + [System.Int32] + $FutureTerminationWindow, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Boolean] + $PostTerminationActivity, + + [Parameter()] + [System.Object] + $RemoveExchangeLocation, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $RetryDistribution, + + [Parameter()] + [System.Object] + $SharepointSites, + + [Parameter()] + [System.Object] + $CustomTags, + + [Parameter()] + [System.Object] + $AddUserMailList, + + [Parameter()] + [System.Object] + $TriggerInsightGroups, + + [Parameter()] + [System.String] + $TenantSetting, + + [Parameter()] + [System.Object] + $SensitivityLabels, + + [Parameter()] + [System.Object] + $DlpSensitiveTypes, + + [Parameter()] + [System.Int32] + $InScopeTimeSpan, + + [Parameter()] + [System.Int32] + $SchemaVersion, + + [Parameter()] + [System.Int32] + $PastTerminationWindow + ) +} + function Get-AdminAuditLogConfig { [CmdletBinding()] From 3a8636ca76081b73a2be74e507e6f7235d635fe8 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 27 Sep 2024 16:21:00 -0400 Subject: [PATCH 358/465] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3726babc4c..085825dc0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,8 @@ * Initial release. * SCInsiderRiskEntityList * Initial release. +* SCInsiderRiskPolicy + * Initial release. * SCRoleGroup * Fixes an issue with creation without specifying Displayname * Fixes an issue with Drifts because of returned Role format From fb2dc8d9d7e644f70d8a4f76226c97ea60444199 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 27 Sep 2024 16:23:23 -0700 Subject: [PATCH 359/465] addressed the comments. --- .../MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 | 6 ++++-- .../MSFT_IntuneAppCategories.schema.mof | 4 ++-- .../Examples/Resources/IntuneAppCategory/1-Create.ps1 | 1 + .../Examples/Resources/IntuneAppCategory/2-Update.ps1 | 5 ++++- .../Examples/Resources/IntuneAppCategory/3-Remove.ps1 | 2 ++ 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 index ae3403f681..211d061d50 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 @@ -75,7 +75,7 @@ function Get-TargetResource if ($null -eq $instance) { - Write-Verbose -Message "Could not find by Id {$Id}." + Write-Verbose -Message "Could not find MobileAppCategory by Id {$Id}." if (-Not [string]::IsNullOrEmpty($DisplayName)) { @@ -87,7 +87,7 @@ function Get-TargetResource if ($null -eq $instance) { - Write-Verbose -Message "Could not find by DisplayName {$DisplayName}." + Write-Verbose -Message "Could not find MobileAppCategory by DisplayName {$DisplayName}." return $nullResult } } @@ -344,6 +344,8 @@ function Export-TargetResource Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline $params = @{ Id = $config.Id + DisplayName = $config.DisplayName + Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof index b4e30581a5..5385b5cf69 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof @@ -1,8 +1,8 @@ [ClassVersion("1.0.0.0"), FriendlyName("IntuneAppCategories")] class MSFT_IntuneAppCategories : OMI_BaseResource { - [Key, Description("The unique identifier for an entity. Read-only.")] String Id; - [Required, Description("The name of the app category.")] String DisplayName; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; + [Key, Description("The name of the app category.")] String DisplayName; [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 index f692f74739..04adeaa55e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 @@ -24,5 +24,6 @@ Configuration Example { Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; DisplayName = "Books & Reference"; + Ensure = "Present"; } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 index b516274848..04adeaa55e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 @@ -18,9 +18,12 @@ Configuration Example [System.String] $CertificateThumbprint ) + Import-DscResource -ModuleName Microsoft365DSC node localhost { - + Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Books & Reference"; + Ensure = "Present"; } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 index 1357c5eb7a..c3dc576a85 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 @@ -18,10 +18,12 @@ Configuration Example [System.String] $CertificateThumbprint ) + Import-DscResource -ModuleName Microsoft365DSC node localhost { Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; DisplayName = "Books & Reference"; + Ensure = "Absent"; } } From 256230fe99bd74ddd071d9f59638e58561373407 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Fri, 27 Sep 2024 16:23:44 -0700 Subject: [PATCH 360/465] addressed other comments. --- .../MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 | 1 + .../DSCResources/MSFT_IntuneAppCategories/readme.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 index 211d061d50..9d62124a4f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 @@ -197,6 +197,7 @@ function Set-TargetResource Remove-MgBetaDeviceAppManagementMobileAppCategory @SetParameters } } + function Test-TargetResource { [CmdletBinding()] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/readme.md index cef6d76862..6a45c9566d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/readme.md @@ -3,4 +3,4 @@ ## Description -Configures a resource for navigation property for Intune mobile app categories. +Configures a resource for navigation property for Intune mobile app categories. Default app categories cannot be renamed. From ffecab3c47d20042b6a1a847eb6f68631fc2f3c0 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Sat, 28 Sep 2024 13:56:42 -0400 Subject: [PATCH 361/465] Update Graph.PermissionList.txt --- Tests/QA/Graph.PermissionList.txt | Bin 5764 -> 2915 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index a592902d7870e3cc7cedf983278e2144cc18d20d..46a5b6035285765ec72b72082e457ce9a67fbfb1 100644 GIT binary patch literal 2915 zcma)8&5qk35WZLHn`CpT+PmXyS1UDIE6%oO7A6i_3>J`V(^u=EkJMM_*f?Q~?QD6cqzVwowmnDPCv(nA1L7N7=AIZcx@&y=Y;9fCy% zSiiGJ=X0a?vO2bV8cp`Q2^mN!$;ae@aULE#Pj4E;>b%IB=EA$%LTx;(!M%FZghP&R zu{8=Z=VYa?H;;R*ta)=_ON`JrjH-*5oAg9t&J<|DY+x*g%N28yC$^5d$PY|wP|Gza z=pUswZJ>Sun;gIQmEgV96*=9MgB(toqbTxtnVc91%o^u*pqcj17=*%_y;M*hn8nQq z`CS;1#B4Ej2|V-O%9msNI(tmmVdCWPp>7G{F;CKAA`TBZk{scpXdC^Cc@PEIT4HV( z{a`T)N%Yrnk{n_n$eL=kpbgWk3Z+$YD;t_gfi{Df7s5m*51xu#z4HPyRhue}Ve^vV z5+X?4INbzpUUa+4NUEmCyL#sZO0ex4kOt6oyHsfmBa+er_r{*dYY$8l&@FINV^0xX zXQR=$FsBei$ka@dcDj!12)fr^devnX$)L97N6dpY$7Y#Zz?5Eu#dRjcWrDxMaGk)q zq%C*&u`eN$X4QqdV-aJ7KMEW-(x1C(6n%s1IFp`8e6khO@>g=ak#(BD)C%ia3_1j* zCjNm4#>F#EMkEq14fw7tyG)BdmB^b@(E6-dExG${2JM4Fz8YK4us4!p!!>*V>C5Lw z?Qk}$n3PmwXM~BK0!)L=do(E~?D4vV!C6Xjez1;%cF-ag6oekpHFu^m&cQkA?f3Z) zogR7ghc;WnS78JGV8nzTqKxe`W9*(dQJ8DR!FU?4)Ec9*g~nJv4rTk3xL2~0FH&Jj zm;33{#!Sby6!Q$vn>w3x&A7sbeE2)+pF#KYWFHuCc|Cm@4*Hr|}_tW-`K7RNI Dr-VI! literal 5764 zcmb_gU2hUW6ur+T{uA04qwiZN$5h&TP4}JG(UmsylPf zxpTi~|NJgwAzN8XiSJP=ImisZYk8EVeA1_toXZ&hn_=g<6tcl*fWKYjz5sU(++_`6 zg{Mn=w)mDSmsu~bq{RzLh)t9-{LH)R3cfxryR3w@YL| ze6H>iHXF0^0d^bVTp=!EbbE)5M$a=|rqH`oD^;jSE)qr>7tCc^Yob>U$dZ)5| zG+=c*{L7fwBW>9gTg6X$IcT<)YiPkb%Sq&b`Nd{W@5)2vygLWO79T$g_}ZO{jpv-X z7`8^_o@pJnPiU=MNLN}b*?HJ0z5Okp1Re{Ab(h_J4~q}g2d+vFv?BWzp1FQch~@lh zGyWOyS?PHL;r!+9BdM+#@N?vvneE9c%rAk<-f5v^x5)UBb7VQaP>65w)KY!|CZGh4LO!oOrr%-zbxtaCf-jR`N#P$y>RG zM!YA{uDo6N{A;(%6nZT1wPZMz@fPSN@47|%@3*`=0*||w+I2p?Zry0(o>jm950I5M zlapaA`|3|y7Vt3VN=~II+4_0@k3Mxw-Y)K;g{v*`TLo4puF;2i`Z+AdUcF}INaxvz z(dqANBh`%^+>V#Fy>&ad_fd@PJrMcM=Xsu6EMx3t1Yc={t#Ix;d>L)5(wyjN+XXrv zcf|;o*mJ$ewRW(h@LeObk#@_A!HM<^Mj9hNr(fqv#5O1pLwsX9g=Tz*XZIHB Z&hC}Y9ShUHkBRfc^PR4pBD|JY@)r@#F>n9? From a6521a9f4959018fd21ba88f32814ef8385ea576 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Sat, 28 Sep 2024 13:56:52 -0400 Subject: [PATCH 362/465] Fixes --- .github/workflows/Scheduled - Generate Permission List.yml | 2 +- Tests/TestHarness.psm1 | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Scheduled - Generate Permission List.yml b/.github/workflows/Scheduled - Generate Permission List.yml index e9695f17ed..6d02dc3383 100644 --- a/.github/workflows/Scheduled - Generate Permission List.yml +++ b/.github/workflows/Scheduled - Generate Permission List.yml @@ -27,7 +27,7 @@ jobs: - name: Install Dependencies shell: powershell run: | - Import-Module './Modules/Microsoft365DSC/Microsoft365DSC.psd1' -Force; + Import-Module './Modules/Microsoft365DSC/Microsoft365DSC.psd1' -Force; Import-Module './Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1' -Force; Update-M365DSCModule - name: Get Permissions List diff --git a/Tests/TestHarness.psm1 b/Tests/TestHarness.psm1 index a1ccd89269..44a6eb95ee 100644 --- a/Tests/TestHarness.psm1 +++ b/Tests/TestHarness.psm1 @@ -167,7 +167,8 @@ function Get-M365DSCAllGraphPermissionsList 'Channel.Delete.All', ` 'ChannelSettings.ReadWrite.All', ` 'ChannelMember.ReadWrite.All', ` - 'ChannelSettings.Read.All') + 'ChannelSettings.Read.All', + 'EntitlementManagement.Read.All') $roles = $allPermissions | Select-Object -Unique | Sort-Object -Descending:$false return $roles } From 75fcbb1f9f2949522448a62c4d12f747af3a761a Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sat, 28 Sep 2024 18:34:59 +0000 Subject: [PATCH 363/465] Updated Graph Permissions List --- Tests/QA/Graph.PermissionList.txt | Bin 2915 -> 5764 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index 46a5b6035285765ec72b72082e457ce9a67fbfb1..a592902d7870e3cc7cedf983278e2144cc18d20d 100644 GIT binary patch literal 5764 zcmb_gU2hUW6ur+T{uA04qwiZN$5h&TP4}JG(UmsylPf zxpTi~|NJgwAzN8XiSJP=ImisZYk8EVeA1_toXZ&hn_=g<6tcl*fWKYjz5sU(++_`6 zg{Mn=w)mDSmsu~bq{RzLh)t9-{LH)R3cfxryR3w@YL| ze6H>iHXF0^0d^bVTp=!EbbE)5M$a=|rqH`oD^;jSE)qr>7tCc^Yob>U$dZ)5| zG+=c*{L7fwBW>9gTg6X$IcT<)YiPkb%Sq&b`Nd{W@5)2vygLWO79T$g_}ZO{jpv-X z7`8^_o@pJnPiU=MNLN}b*?HJ0z5Okp1Re{Ab(h_J4~q}g2d+vFv?BWzp1FQch~@lh zGyWOyS?PHL;r!+9BdM+#@N?vvneE9c%rAk<-f5v^x5)UBb7VQaP>65w)KY!|CZGh4LO!oOrr%-zbxtaCf-jR`N#P$y>RG zM!YA{uDo6N{A;(%6nZT1wPZMz@fPSN@47|%@3*`=0*||w+I2p?Zry0(o>jm950I5M zlapaA`|3|y7Vt3VN=~II+4_0@k3Mxw-Y)K;g{v*`TLo4puF;2i`Z+AdUcF}INaxvz z(dqANBh`%^+>V#Fy>&ad_fd@PJrMcM=Xsu6EMx3t1Yc={t#Ix;d>L)5(wyjN+XXrv zcf|;o*mJ$ewRW(h@LeObk#@_A!HM<^Mj9hNr(fqv#5O1pLwsX9g=Tz*XZIHB Z&hC}Y9ShUHkBRfc^PR4pBD|JY@)r@#F>n9? literal 2915 zcma)8&5qk35WZLHn`CpT+PmXyS1UDIE6%oO7A6i_3>J`V(^u=EkJMM_*f?Q~?QD6cqzVwowmnDPCv(nA1L7N7=AIZcx@&y=Y;9fCy% zSiiGJ=X0a?vO2bV8cp`Q2^mN!$;ae@aULE#Pj4E;>b%IB=EA$%LTx;(!M%FZghP&R zu{8=Z=VYa?H;;R*ta)=_ON`JrjH-*5oAg9t&J<|DY+x*g%N28yC$^5d$PY|wP|Gza z=pUswZJ>Sun;gIQmEgV96*=9MgB(toqbTxtnVc91%o^u*pqcj17=*%_y;M*hn8nQq z`CS;1#B4Ej2|V-O%9msNI(tmmVdCWPp>7G{F;CKAA`TBZk{scpXdC^Cc@PEIT4HV( z{a`T)N%Yrnk{n_n$eL=kpbgWk3Z+$YD;t_gfi{Df7s5m*51xu#z4HPyRhue}Ve^vV z5+X?4INbzpUUa+4NUEmCyL#sZO0ex4kOt6oyHsfmBa+er_r{*dYY$8l&@FINV^0xX zXQR=$FsBei$ka@dcDj!12)fr^devnX$)L97N6dpY$7Y#Zz?5Eu#dRjcWrDxMaGk)q zq%C*&u`eN$X4QqdV-aJ7KMEW-(x1C(6n%s1IFp`8e6khO@>g=ak#(BD)C%ia3_1j* zCjNm4#>F#EMkEq14fw7tyG)BdmB^b@(E6-dExG${2JM4Fz8YK4us4!p!!>*V>C5Lw z?Qk}$n3PmwXM~BK0!)L=do(E~?D4vV!C6Xjez1;%cF-ag6oekpHFu^m&cQkA?f3Z) zogR7ghc;WnS78JGV8nzTqKxe`W9*(dQJ8DR!FU?4)Ec9*g~nJv4rTk3xL2~0FH&Jj zm;33{#!Sby6!Q$vn>w3x&A7sbeE2)+pF#KYWFHuCc|Cm@4*Hr|}_tW-`K7RNI Dr-VI! From c6bd8cb2e980d2c62b3dfa940366bc1cd04f7978 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Sat, 28 Sep 2024 15:11:02 -0400 Subject: [PATCH 364/465] Fix --- .../settings.json | 6 ------ Tests/QA/Graph.PermissionList.txt | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementAccessPackage/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementAccessPackage/settings.json index e3121136dc..e6f044849a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementAccessPackage/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADEntitlementManagementAccessPackage/settings.json @@ -18,9 +18,6 @@ } ], "update": [ - { - "name": "EntitlementManagement.Read.All" - }, { "name": "EntitlementManagement.ReadWrite.All" } @@ -33,9 +30,6 @@ } ], "update": [ - { - "name": "EntitlementManagement.Read.All" - }, { "name": "EntitlementManagement.ReadWrite.All" } diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index 46a5b60352..25d445a159 100644 --- a/Tests/QA/Graph.PermissionList.txt +++ b/Tests/QA/Graph.PermissionList.txt @@ -1 +1 @@ -AdministrativeUnit.Read.All,AdministrativeUnit.ReadWrite.All,Agreement.Read.All,AppCatalog.ReadWrite.All,AppCertTrustConfiguration.Read.All,AppCertTrustConfiguration.ReadWrite.All,Application.Read.All,Application.ReadWrite.All,Application.ReadWrite.OwnedBy,Application-RemoteDesktopConfig.ReadWrite.All,AppRoleAssignment.ReadWrite.All,BrowserSiteLists.Read.All,BrowserSiteLists.ReadWrite.All,Calendars.Read,Calendars.ReadBasic,Calendars.ReadWrite,Channel.Delete.All,ChannelMember.ReadWrite.All,ChannelSettings.Read.All,ChannelSettings.ReadWrite.All,CloudPC.Read.All,CloudPC.ReadWrite.All,CrossTenantUserProfileSharing.Read.All,CrossTenantUserProfileSharing.ReadWrite.All,CustomSecAttributeDefinition.Read.All,CustomSecAttributeDefinition.ReadWrite.All,CustomSecAttributeProvisioning.Read.All,CustomSecAttributeProvisioning.ReadWrite.All,DelegatedPermissionGrant.ReadWrite.All,Device.Read.All,Device.ReadWrite.All,DeviceManagement.Scripts.Read.All,DeviceManagement.Scripts.ReadWrite.All,DeviceManagementApps.Read.All,DeviceManagementApps.ReadWrite.All,DeviceManagementConfiguration.Read.All,DeviceManagementConfiguration.ReadWrite.All,DeviceManagementManagedDevices.Read.All,DeviceManagementManagedDevices.ReadWrite.All,DeviceManagementRBAC.Read.All,DeviceManagementRBAC.ReadWrite.All,DeviceManagementServiceConfig.Read.All,DeviceManagementServiceConfig.ReadWrite.All,Directory.Read.All,Directory.ReadWrite.All,DirectoryRecommendations.Read.All,DirectoryRecommendations.ReadWrite.All,Domain.Read.All,Domain.ReadWrite.All,EntitlementManagement.ReadWrite.All,Group.Create,Group.Read.All,Group.ReadWrite.All,Group-Conversation.Read.All,Group-Conversation.ReadWrite.All,GroupMember.Read.All,GroupMember.ReadWrite.All,IdentityProvider.Read.All,IdentityProvider.ReadWrite.All,Organization.Read.All,Organization.ReadWrite.All,OrganizationalBranding.Read.All,OrganizationalBranding.ReadWrite.All,OrgContact.Read.All,OrgSettings-AppsAndServices.Read.All,OrgSettings-DynamicsVoice.Read.All,OrgSettings-Forms.Read.All,OrgSettings-Microsoft365Install.Read.All,OrgSettings-Todo.Read.All,PeopleSettings.Read.All,PeopleSettings.ReadWrite.All,Policy.Read.All,Policy.Read.ApplicationConfiguration,Policy.Read.ConditionalAccess,Policy.ReadWrite.ApplicationConfiguration,Policy.ReadWrite.AuthenticationMethod,Policy.ReadWrite.Authorization,Policy.ReadWrite.ConditionalAccess,ProfilePhoto.Read.All,ProfilePhoto.ReadWrite.All,ReportSettings.Read.All,RoleEligibilitySchedule.Read.Directory,RoleManagement.Read.All,RoleManagement.Read.CloudPC,RoleManagement.Read.Directory,RoleManagement.Read.Exchange,RoleManagement.ReadWrite.CloudPC,RoleManagement.ReadWrite.Directory,RoleManagement.ReadWrite.Exchange,RoleManagementPolicy.Read.Directory,SharePointTenantSettings.Read.All,Synchronization.Read.All,Synchronization.ReadWrite.All,Tasks.Read.All,TeamSettings.ReadWrite.All,User.Read.All,User.ReadWrite.All,EntitlementManagement.Read.All +AdministrativeUnit.Read.All,AdministrativeUnit.ReadWrite.All,Agreement.Read.All,AppCatalog.ReadWrite.All,AppCertTrustConfiguration.Read.All,AppCertTrustConfiguration.ReadWrite.All,Application.Read.All,Application.ReadWrite.All,Application.ReadWrite.OwnedBy,Application-RemoteDesktopConfig.ReadWrite.All,AppRoleAssignment.ReadWrite.All,BrowserSiteLists.Read.All,BrowserSiteLists.ReadWrite.All,Calendars.Read,Calendars.ReadBasic,Calendars.ReadWrite,Channel.Delete.All,ChannelMember.ReadWrite.All,ChannelSettings.Read.All,ChannelSettings.ReadWrite.All,CloudPC.Read.All,CloudPC.ReadWrite.All,CrossTenantUserProfileSharing.Read.All,CrossTenantUserProfileSharing.ReadWrite.All,CustomSecAttributeDefinition.Read.All,CustomSecAttributeDefinition.ReadWrite.All,CustomSecAttributeProvisioning.Read.All,CustomSecAttributeProvisioning.ReadWrite.All,DelegatedPermissionGrant.ReadWrite.All,Device.Read.All,Device.ReadWrite.All,DeviceManagement.Scripts.Read.All,DeviceManagement.Scripts.ReadWrite.All,DeviceManagementApps.Read.All,DeviceManagementApps.ReadWrite.All,DeviceManagementConfiguration.Read.All,DeviceManagementConfiguration.ReadWrite.All,DeviceManagementManagedDevices.Read.All,DeviceManagementManagedDevices.ReadWrite.All,DeviceManagementRBAC.Read.All,DeviceManagementRBAC.ReadWrite.All,DeviceManagementServiceConfig.Read.All,DeviceManagementServiceConfig.ReadWrite.All,Directory.Read.All,Directory.ReadWrite.All,DirectoryRecommendations.Read.All,DirectoryRecommendations.ReadWrite.All,Domain.Read.All,Domain.ReadWrite.All,EntitlementManagement.ReadWrite.All,Group.Create,Group.Read.All,Group.ReadWrite.All,Group-Conversation.Read.All,Group-Conversation.ReadWrite.All,GroupMember.Read.All,GroupMember.ReadWrite.All,IdentityProvider.Read.All,IdentityProvider.ReadWrite.All,Organization.Read.All,Organization.ReadWrite.All,OrganizationalBranding.Read.All,OrganizationalBranding.ReadWrite.All,OrgContact.Read.All,OrgSettings-AppsAndServices.Read.All,OrgSettings-DynamicsVoice.Read.All,OrgSettings-Forms.Read.All,OrgSettings-Microsoft365Install.Read.All,OrgSettings-Todo.Read.All,PeopleSettings.Read.All,PeopleSettings.ReadWrite.All,Policy.Read.All,Policy.Read.ApplicationConfiguration,Policy.Read.ConditionalAccess,Policy.ReadWrite.ApplicationConfiguration,Policy.ReadWrite.AuthenticationMethod,Policy.ReadWrite.Authorization,Policy.ReadWrite.ConditionalAccess,ProfilePhoto.Read.All,ProfilePhoto.ReadWrite.All,ReportSettings.Read.All,RoleEligibilitySchedule.Read.Directory,RoleManagement.Read.All,RoleManagement.Read.CloudPC,RoleManagement.Read.Directory,RoleManagement.Read.Exchange,RoleManagement.ReadWrite.CloudPC,RoleManagement.ReadWrite.Directory,RoleManagement.ReadWrite.Exchange,RoleManagementPolicy.Read.Directory,SharePointTenantSettings.Read.All,Synchronization.Read.All,Synchronization.ReadWrite.All,Tasks.Read.All,TeamSettings.ReadWrite.All,User.Read.All,User.ReadWrite.All,EntitlementManagement.Read.All, From 340467841acd88f1275c25ff8e441c177815c195 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Sat, 28 Sep 2024 15:11:22 -0400 Subject: [PATCH 365/465] Update Graph.PermissionList.txt --- Tests/QA/Graph.PermissionList.txt | Bin 5764 -> 2885 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index a592902d7870e3cc7cedf983278e2144cc18d20d..ad071c60377121e32eb5788612ec627eca149e15 100644 GIT binary patch literal 2885 zcma)8&5qk35WZLHn`CpT+PmXyS1UDIE6%oO7A6i_3>J`V(^u=EkJMM_*f?Q~?QD6cqzVwowmnDPCv(nA1L7N7=AIZcx@&y=Y;9fCy% zSiiGJ=X0a?vO2bV8cp`Q2^mN!$;ae@aULE#Pj4E;>b%IB=EA$%LTx;(!M%FZghP&R zu{8=Z=VYa?H;;R*ta)=_ON`JrjH-*5oAg9t&J<|DY+x*g%N28yC$^5d$PY|wP|Gza z=pUswZJ>Sun;gIQmEgV96*=9MgB(toqbTxtnVc91%o^u*pqcj17=*%_y;M*hn8nQq z`CS;1#B4Ej2|V-O%9msNI(tmmVdCWPp>7G{F;CKAA`TBZk{scpXdC^Cc@PEIT4HV( z{a`T)N%Yrnk{n_n$eL=kpbgWk3Z+$YD;t_gfi{Df7s5m*51xu#z4HPyRhue}Ve^vV z5+X?4INbzpUUa+4NUEmCyL#sZO0ex4kOt6oyHsfmBa+er_r{*dYY$8l&@FINV^0xX zXQR=$FsBei$ka@dcDj!12)fr^devnX$)L97N6dpY$7Y#Zz?5Eu#dRjcWrDxMaGk)q zq%C*&u`eN$X4QqdV-aJ7KMEW-(x1C(6n%s1IFp`8e6khO@>g=ak#(BD)C%ia3_1j* zCjNm4#>F#EMkEq14fw7tyG)BdmB^b@(E6-dExG${2JM4Fz8YK4us4!p!!>*V>C5Lw z?Qk}$n3PmwXM~BK0!)L=do(E~?D4vV!C6Xjez1;%cF-ag6oekpHFu^m&cQkA?f3Z) zogR7ghc;WnS78JGV8nzTqKxe`W9*(dQJ8DR!FU?4)Ec9*g~nJv4rTk3xL2~0FH&Jj zm;33{#!Sby6!Q$vn>w3x&A7sbeE2)+pF#KYWFHuCc|Cm@4*Hr|3{O}L{UNQ&( literal 5764 zcmb_gU2hUW6ur+T{uA04qwiZN$5h&TP4}JG(UmsylPf zxpTi~|NJgwAzN8XiSJP=ImisZYk8EVeA1_toXZ&hn_=g<6tcl*fWKYjz5sU(++_`6 zg{Mn=w)mDSmsu~bq{RzLh)t9-{LH)R3cfxryR3w@YL| ze6H>iHXF0^0d^bVTp=!EbbE)5M$a=|rqH`oD^;jSE)qr>7tCc^Yob>U$dZ)5| zG+=c*{L7fwBW>9gTg6X$IcT<)YiPkb%Sq&b`Nd{W@5)2vygLWO79T$g_}ZO{jpv-X z7`8^_o@pJnPiU=MNLN}b*?HJ0z5Okp1Re{Ab(h_J4~q}g2d+vFv?BWzp1FQch~@lh zGyWOyS?PHL;r!+9BdM+#@N?vvneE9c%rAk<-f5v^x5)UBb7VQaP>65w)KY!|CZGh4LO!oOrr%-zbxtaCf-jR`N#P$y>RG zM!YA{uDo6N{A;(%6nZT1wPZMz@fPSN@47|%@3*`=0*||w+I2p?Zry0(o>jm950I5M zlapaA`|3|y7Vt3VN=~II+4_0@k3Mxw-Y)K;g{v*`TLo4puF;2i`Z+AdUcF}INaxvz z(dqANBh`%^+>V#Fy>&ad_fd@PJrMcM=Xsu6EMx3t1Yc={t#Ix;d>L)5(wyjN+XXrv zcf|;o*mJ$ewRW(h@LeObk#@_A!HM<^Mj9hNr(fqv#5O1pLwsX9g=Tz*XZIHB Z&hC}Y9ShUHkBRfc^PR4pBD|JY@)r@#F>n9? From b8058b69bda48dbd2266e69872d4800f2d17d1b9 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Sat, 28 Sep 2024 15:24:01 -0400 Subject: [PATCH 366/465] Update MSFT_SCInsiderRiskPolicy.schema.mof --- .../MSFT_SCInsiderRiskPolicy.schema.mof | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof index 2f219a3176..84a02dc923 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof @@ -144,7 +144,7 @@ class MSFT_SCInsiderRiskPolicy : OMI_BaseResource [Write, Description("Official documentation to come.")] String RecordingTimeframePostEventInSec; [Write, Description("Official documentation to come.")] String BandwidthCapInMb; [Write, Description("Official documentation to come.")] String OfflineRecordingStorageLimitInMb; - [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] 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; From e60652ee7b02af615b766fbe0460d8e9e2b6f84f Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sat, 28 Sep 2024 19:46:18 +0000 Subject: [PATCH 367/465] Updated Resources and Cmdlet documentation pages --- .../AADEntitlementManagementAccessPackage.md | 4 +- .../SCInsiderRiskPolicy.md | 561 ++++++++++++++++++ 2 files changed, 563 insertions(+), 2 deletions(-) create mode 100644 docs/docs/resources/security-compliance/SCInsiderRiskPolicy.md diff --git a/docs/docs/resources/azure-ad/AADEntitlementManagementAccessPackage.md b/docs/docs/resources/azure-ad/AADEntitlementManagementAccessPackage.md index 0c50a322d3..5cd3b23e28 100644 --- a/docs/docs/resources/azure-ad/AADEntitlementManagementAccessPackage.md +++ b/docs/docs/resources/azure-ad/AADEntitlementManagementAccessPackage.md @@ -52,7 +52,7 @@ To authenticate with the Microsoft Graph API, this resource required the followi - **Update** - - EntitlementManagement.Read.All, EntitlementManagement.ReadWrite.All + - EntitlementManagement.ReadWrite.All #### Application permissions @@ -62,7 +62,7 @@ To authenticate with the Microsoft Graph API, this resource required the followi - **Update** - - EntitlementManagement.Read.All, EntitlementManagement.ReadWrite.All + - EntitlementManagement.ReadWrite.All ## Examples diff --git a/docs/docs/resources/security-compliance/SCInsiderRiskPolicy.md b/docs/docs/resources/security-compliance/SCInsiderRiskPolicy.md new file mode 100644 index 0000000000..863077a28d --- /dev/null +++ b/docs/docs/resources/security-compliance/SCInsiderRiskPolicy.md @@ -0,0 +1,561 @@ +# SCInsiderRiskPolicy + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Name** | Key | String | Name of the insider risk policy. | | +| **InsiderRiskScenario** | Key | String | Name of the scenario supported by the policy. | | +| **Anonymization** | Write | Boolean | Official documentation to come. | | +| **DLPUserRiskSync** | Write | Boolean | Official documentation to come. | | +| **OptInIRMDataExport** | Write | Boolean | Official documentation to come. | | +| **RaiseAuditAlert** | Write | Boolean | Official documentation to come. | | +| **FileVolCutoffLimits** | Write | String | Official documentation to come. | | +| **AlertVolume** | Write | String | Official documentation to come. | | +| **AnomalyDetections** | Write | Boolean | Official documentation to come. | | +| **CopyToPersonalCloud** | Write | Boolean | Official documentation to come. | | +| **CopyToUSB** | Write | Boolean | Official documentation to come. | | +| **CumulativeExfiltrationDetector** | Write | Boolean | Official documentation to come. | | +| **EmailExternal** | Write | Boolean | Official documentation to come. | | +| **EmployeeAccessedEmployeePatientData** | Write | Boolean | Official documentation to come. | | +| **EmployeeAccessedFamilyData** | Write | Boolean | Official documentation to come. | | +| **EmployeeAccessedHighVolumePatientData** | Write | Boolean | Official documentation to come. | | +| **EmployeeAccessedNeighbourData** | Write | Boolean | Official documentation to come. | | +| **EmployeeAccessedRestrictedData** | Write | Boolean | Official documentation to come. | | +| **EpoBrowseToChildAbuseSites** | Write | Boolean | Official documentation to come. | | +| **EpoBrowseToCriminalActivitySites** | Write | Boolean | Official documentation to come. | | +| **EpoBrowseToCultSites** | Write | Boolean | Official documentation to come. | | +| **EpoBrowseToGamblingSites** | Write | Boolean | Official documentation to come. | | +| **EpoBrowseToHackingSites** | Write | Boolean | Official documentation to come. | | +| **EpoBrowseToHateIntoleranceSites** | Write | Boolean | Official documentation to come. | | +| **EpoBrowseToIllegalSoftwareSites** | Write | Boolean | Official documentation to come. | | +| **EpoBrowseToKeyloggerSites** | Write | Boolean | Official documentation to come. | | +| **EpoBrowseToLlmSites** | Write | Boolean | Official documentation to come. | | +| **EpoBrowseToMalwareSites** | Write | Boolean | Official documentation to come. | | +| **EpoBrowseToPhishingSites** | Write | Boolean | Official documentation to come. | | +| **EpoBrowseToPornographySites** | Write | Boolean | Official documentation to come. | | +| **EpoBrowseToUnallowedDomain** | Write | Boolean | Official documentation to come. | | +| **EpoBrowseToViolenceSites** | Write | Boolean | Official documentation to come. | | +| **EpoCopyToClipboardFromSensitiveFile** | Write | Boolean | Official documentation to come. | | +| **EpoCopyToNetworkShare** | Write | Boolean | Official documentation to come. | | +| **EpoFileArchived** | Write | Boolean | Official documentation to come. | | +| **EpoFileCopiedToRemoteDesktopSession** | Write | Boolean | Official documentation to come. | | +| **EpoFileDeleted** | Write | Boolean | Official documentation to come. | | +| **EpoFileDownloadedFromBlacklistedDomain** | Write | Boolean | Official documentation to come. | | +| **EpoFileDownloadedFromEnterpriseDomain** | Write | Boolean | Official documentation to come. | | +| **EpoFileRenamed** | Write | Boolean | Official documentation to come. | | +| **EpoFileStagedToCentralLocation** | Write | Boolean | Official documentation to come. | | +| **EpoHiddenFileCreated** | Write | Boolean | Official documentation to come. | | +| **EpoRemovableMediaMount** | Write | Boolean | Official documentation to come. | | +| **EpoSensitiveFileRead** | Write | Boolean | Official documentation to come. | | +| **Mcas3rdPartyAppDownload** | Write | Boolean | Official documentation to come. | | +| **Mcas3rdPartyAppFileDelete** | Write | Boolean | Official documentation to come. | | +| **Mcas3rdPartyAppFileSharing** | Write | Boolean | Official documentation to come. | | +| **McasActivityFromInfrequentCountry** | Write | Boolean | Official documentation to come. | | +| **McasImpossibleTravel** | Write | Boolean | Official documentation to come. | | +| **McasMultipleFailedLogins** | Write | Boolean | Official documentation to come. | | +| **McasMultipleStorageDeletion** | Write | Boolean | Official documentation to come. | | +| **McasMultipleVMCreation** | Write | Boolean | Official documentation to come. | | +| **McasMultipleVMDeletion** | Write | Boolean | Official documentation to come. | | +| **McasSuspiciousAdminActivities** | Write | Boolean | Official documentation to come. | | +| **McasSuspiciousCloudCreation** | Write | Boolean | Official documentation to come. | | +| **McasSuspiciousCloudTrailLoggingChange** | Write | Boolean | Official documentation to come. | | +| **McasTerminatedEmployeeActivity** | Write | Boolean | Official documentation to come. | | +| **OdbDownload** | Write | Boolean | Official documentation to come. | | +| **OdbSyncDownload** | Write | Boolean | Official documentation to come. | | +| **PeerCumulativeExfiltrationDetector** | Write | Boolean | Official documentation to come. | | +| **PhysicalAccess** | Write | Boolean | Official documentation to come. | | +| **PotentialHighImpactUser** | Write | Boolean | Official documentation to come. | | +| **Print** | Write | Boolean | Official documentation to come. | | +| **PriorityUserGroupMember** | Write | Boolean | Official documentation to come. | | +| **SecurityAlertDefenseEvasion** | Write | Boolean | Official documentation to come. | | +| **SecurityAlertUnwantedSoftware** | Write | Boolean | Official documentation to come. | | +| **SpoAccessRequest** | Write | Boolean | Official documentation to come. | | +| **SpoApprovedAccess** | Write | Boolean | Official documentation to come. | | +| **SpoDownload** | Write | Boolean | Official documentation to come. | | +| **SpoDownloadV2** | Write | Boolean | Official documentation to come. | | +| **SpoFileAccessed** | Write | Boolean | Official documentation to come. | | +| **SpoFileDeleted** | Write | Boolean | Official documentation to come. | | +| **SpoFileDeletedFromFirstStageRecycleBin** | Write | Boolean | Official documentation to come. | | +| **SpoFileDeletedFromSecondStageRecycleBin** | Write | Boolean | Official documentation to come. | | +| **SpoFileLabelDowngraded** | Write | Boolean | Official documentation to come. | | +| **SpoFileLabelRemoved** | Write | Boolean | Official documentation to come. | | +| **SpoFileSharing** | Write | Boolean | Official documentation to come. | | +| **SpoFolderDeleted** | Write | Boolean | Official documentation to come. | | +| **SpoFolderDeletedFromFirstStageRecycleBin** | Write | Boolean | Official documentation to come. | | +| **SpoFolderDeletedFromSecondStageRecycleBin** | Write | Boolean | Official documentation to come. | | +| **SpoFolderSharing** | Write | Boolean | Official documentation to come. | | +| **SpoSiteExternalUserAdded** | Write | Boolean | Official documentation to come. | | +| **SpoSiteInternalUserAdded** | Write | Boolean | Official documentation to come. | | +| **SpoSiteLabelRemoved** | Write | Boolean | Official documentation to come. | | +| **SpoSiteSharing** | Write | Boolean | Official documentation to come. | | +| **SpoSyncDownload** | Write | Boolean | Official documentation to come. | | +| **TeamsChannelFileSharedExternal** | Write | Boolean | Official documentation to come. | | +| **TeamsChannelMemberAddedExternal** | Write | Boolean | Official documentation to come. | | +| **TeamsChatFileSharedExternal** | Write | Boolean | Official documentation to come. | | +| **TeamsFileDownload** | Write | Boolean | Official documentation to come. | | +| **TeamsFolderSharedExternal** | Write | Boolean | Official documentation to come. | | +| **TeamsMemberAddedExternal** | Write | Boolean | Official documentation to come. | | +| **TeamsSensitiveMessage** | Write | Boolean | Official documentation to come. | | +| **UserHistory** | Write | Boolean | Official documentation to come. | | +| **AWSS3BlockPublicAccessDisabled** | Write | Boolean | Official documentation to come. | | +| **AWSS3BucketDeleted** | Write | Boolean | Official documentation to come. | | +| **AWSS3PublicAccessEnabled** | Write | Boolean | Official documentation to come. | | +| **AWSS3ServerLoggingDisabled** | Write | Boolean | Official documentation to come. | | +| **AzureElevateAccessToAllSubscriptions** | Write | Boolean | Official documentation to come. | | +| **AzureResourceThreatProtectionSettingsUpdated** | Write | Boolean | Official documentation to come. | | +| **AzureSQLServerAuditingSettingsUpdated** | Write | Boolean | Official documentation to come. | | +| **AzureSQLServerFirewallRuleDeleted** | Write | Boolean | Official documentation to come. | | +| **AzureSQLServerFirewallRuleUpdated** | Write | Boolean | Official documentation to come. | | +| **AzureStorageAccountOrContainerDeleted** | Write | Boolean | Official documentation to come. | | +| **BoxContentAccess** | Write | Boolean | Official documentation to come. | | +| **BoxContentDelete** | Write | Boolean | Official documentation to come. | | +| **BoxContentDownload** | Write | Boolean | Official documentation to come. | | +| **BoxContentExternallyShared** | Write | Boolean | Official documentation to come. | | +| **CCFinancialRegulatoryRiskyTextSent** | Write | Boolean | Official documentation to come. | | +| **CCInappropriateContentSent** | Write | Boolean | Official documentation to come. | | +| **CCInappropriateImagesSent** | Write | Boolean | Official documentation to come. | | +| **DropboxContentAccess** | Write | Boolean | Official documentation to come. | | +| **DropboxContentDelete** | Write | Boolean | Official documentation to come. | | +| **DropboxContentDownload** | Write | Boolean | Official documentation to come. | | +| **DropboxContentExternallyShared** | Write | Boolean | Official documentation to come. | | +| **GoogleDriveContentAccess** | Write | Boolean | Official documentation to come. | | +| **GoogleDriveContentDelete** | Write | Boolean | Official documentation to come. | | +| **GoogleDriveContentExternallyShared** | Write | Boolean | Official documentation to come. | | +| **PowerBIDashboardsDeleted** | Write | Boolean | Official documentation to come. | | +| **PowerBIReportsDeleted** | Write | Boolean | Official documentation to come. | | +| **PowerBIReportsDownloaded** | Write | Boolean | Official documentation to come. | | +| **PowerBIReportsExported** | Write | Boolean | Official documentation to come. | | +| **PowerBIReportsViewed** | Write | Boolean | Official documentation to come. | | +| **PowerBISemanticModelsDeleted** | Write | Boolean | Official documentation to come. | | +| **PowerBISensitivityLabelDowngradedForArtifacts** | Write | Boolean | Official documentation to come. | | +| **PowerBISensitivityLabelRemovedFromArtifacts** | Write | Boolean | Official documentation to come. | | +| **HistoricTimeSpan** | Write | String | Official documentation to come. | | +| **InScopeTimeSpan** | Write | String | Official documentation to come. | | +| **EnableTeam** | Write | Boolean | Official documentation to come. | | +| **AnalyticsNewInsightEnabled** | Write | Boolean | Official documentation to come. | | +| **AnalyticsTurnedOffEnabled** | Write | Boolean | Official documentation to come. | | +| **HighSeverityAlertsEnabled** | Write | Boolean | Official documentation to come. | | +| **HighSeverityAlertsRoleGroups** | Write | StringArray[] | Official documentation to come. | | +| **PoliciesHealthEnabled** | Write | Boolean | Official documentation to come. | | +| **PoliciesHealthRoleGroups** | Write | StringArray[] | Official documentation to come. | | +| **NotificationDetailsEnabled** | Write | Boolean | Official documentation to come. | | +| **NotificationDetailsRoleGroups** | Write | StringArray[] | Official documentation to come. | | +| **ClipDeletionEnabled** | Write | Boolean | Official documentation to come. | | +| **SessionRecordingEnabled** | Write | Boolean | Official documentation to come. | | +| **RecordingTimeframePreEventInSec** | Write | String | Official documentation to come. | | +| **RecordingTimeframePostEventInSec** | Write | String | Official documentation to come. | | +| **BandwidthCapInMb** | Write | String | Official documentation to come. | | +| **OfflineRecordingStorageLimitInMb** | Write | String | Official documentation to come. | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Absent`, `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Configures Insider Risk Policies in Purview. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCInsiderRiskPolicy "SCInsiderRiskPolicy-IRM_Tenant_Setting" + { + Anonymization = $false + AlertVolume = "Medium"; + AnalyticsNewInsightEnabled = $False; + AnalyticsTurnedOffEnabled = $False; + AnomalyDetections = $False; + ApplicationId = $ApplicationId; + AWSS3BlockPublicAccessDisabled = $False; + AWSS3BucketDeleted = $False; + AWSS3PublicAccessEnabled = $False; + AWSS3ServerLoggingDisabled = $False; + AzureElevateAccessToAllSubscriptions = $False; + AzureResourceThreatProtectionSettingsUpdated = $False; + AzureSQLServerAuditingSettingsUpdated = $False; + AzureSQLServerFirewallRuleDeleted = $False; + AzureSQLServerFirewallRuleUpdated = $False; + AzureStorageAccountOrContainerDeleted = $False; + BoxContentAccess = $False; + BoxContentDelete = $False; + BoxContentDownload = $False; + BoxContentExternallyShared = $False; + CCFinancialRegulatoryRiskyTextSent = $False; + CCInappropriateContentSent = $False; + CCInappropriateImagesSent = $False; + CertificateThumbprint = $CertificateThumbprint; + CopyToPersonalCloud = $False; + CopyToUSB = $False; + CumulativeExfiltrationDetector = $True; + DLPUserRiskSync = $True; + DropboxContentAccess = $False; + DropboxContentDelete = $False; + DropboxContentDownload = $False; + DropboxContentExternallyShared = $False; + EmailExternal = $False; + EmployeeAccessedEmployeePatientData = $False; + EmployeeAccessedFamilyData = $False; + EmployeeAccessedHighVolumePatientData = $False; + EmployeeAccessedNeighbourData = $False; + EmployeeAccessedRestrictedData = $False; + EnableTeam = $True; + Ensure = "Present"; + EpoBrowseToChildAbuseSites = $False; + EpoBrowseToCriminalActivitySites = $False; + EpoBrowseToCultSites = $False; + EpoBrowseToGamblingSites = $False; + EpoBrowseToHackingSites = $False; + EpoBrowseToHateIntoleranceSites = $False; + EpoBrowseToIllegalSoftwareSites = $False; + EpoBrowseToKeyloggerSites = $False; + EpoBrowseToLlmSites = $False; + EpoBrowseToMalwareSites = $False; + EpoBrowseToPhishingSites = $False; + EpoBrowseToPornographySites = $False; + EpoBrowseToUnallowedDomain = $False; + EpoBrowseToViolenceSites = $False; + EpoCopyToClipboardFromSensitiveFile = $False; + EpoCopyToNetworkShare = $False; + EpoFileArchived = $False; + EpoFileCopiedToRemoteDesktopSession = $False; + EpoFileDeleted = $False; + EpoFileDownloadedFromBlacklistedDomain = $False; + EpoFileDownloadedFromEnterpriseDomain = $False; + EpoFileRenamed = $False; + EpoFileStagedToCentralLocation = $False; + EpoHiddenFileCreated = $False; + EpoRemovableMediaMount = $False; + EpoSensitiveFileRead = $False; + FileVolCutoffLimits = "59"; + GoogleDriveContentAccess = $False; + GoogleDriveContentDelete = $False; + GoogleDriveContentExternallyShared = $False; + HistoricTimeSpan = "89"; + InScopeTimeSpan = "30"; + InsiderRiskScenario = "TenantSetting"; + Mcas3rdPartyAppDownload = $False; + Mcas3rdPartyAppFileDelete = $False; + Mcas3rdPartyAppFileSharing = $False; + McasActivityFromInfrequentCountry = $False; + McasImpossibleTravel = $False; + McasMultipleFailedLogins = $False; + McasMultipleStorageDeletion = $False; + McasMultipleVMCreation = $True; + McasMultipleVMDeletion = $False; + McasSuspiciousAdminActivities = $False; + McasSuspiciousCloudCreation = $False; + McasSuspiciousCloudTrailLoggingChange = $False; + McasTerminatedEmployeeActivity = $False; + Name = "IRM_Tenant_Setting"; + NotificationDetailsEnabled = $True; + OdbDownload = $False; + OdbSyncDownload = $False; + OptInIRMDataExport = $True; + PeerCumulativeExfiltrationDetector = $False; + PhysicalAccess = $False; + PotentialHighImpactUser = $False; + PowerBIDashboardsDeleted = $False; + PowerBIReportsDeleted = $False; + PowerBIReportsDownloaded = $False; + PowerBIReportsExported = $False; + PowerBIReportsViewed = $False; + PowerBISemanticModelsDeleted = $False; + PowerBISensitivityLabelDowngradedForArtifacts = $False; + PowerBISensitivityLabelRemovedFromArtifacts = $False; + Print = $False; + PriorityUserGroupMember = $False; + RaiseAuditAlert = $True; + SecurityAlertDefenseEvasion = $False; + SecurityAlertUnwantedSoftware = $False; + SpoAccessRequest = $False; + SpoApprovedAccess = $False; + SpoDownload = $False; + SpoDownloadV2 = $False; + SpoFileAccessed = $False; + SpoFileDeleted = $False; + SpoFileDeletedFromFirstStageRecycleBin = $False; + SpoFileDeletedFromSecondStageRecycleBin = $False; + SpoFileLabelDowngraded = $False; + SpoFileLabelRemoved = $False; + SpoFileSharing = $True; + SpoFolderDeleted = $False; + SpoFolderDeletedFromFirstStageRecycleBin = $False; + SpoFolderDeletedFromSecondStageRecycleBin = $False; + SpoFolderSharing = $False; + SpoSiteExternalUserAdded = $False; + SpoSiteInternalUserAdded = $False; + SpoSiteLabelRemoved = $False; + SpoSiteSharing = $False; + SpoSyncDownload = $False; + TeamsChannelFileSharedExternal = $False; + TeamsChannelMemberAddedExternal = $False; + TeamsChatFileSharedExternal = $False; + TeamsFileDownload = $False; + TeamsFolderSharedExternal = $False; + TeamsMemberAddedExternal = $False; + TeamsSensitiveMessage = $False; + TenantId = $TenantId; + UserHistory = $False; + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCInsiderRiskPolicy "SCInsiderRiskPolicy-IRM_Tenant_Setting" + { + Anonymization = $false + AlertVolume = "Medium"; + AnalyticsNewInsightEnabled = $False; + AnalyticsTurnedOffEnabled = $False; + AnomalyDetections = $False; + ApplicationId = $ApplicationId; + AWSS3BlockPublicAccessDisabled = $False; + AWSS3BucketDeleted = $False; + AWSS3PublicAccessEnabled = $False; + AWSS3ServerLoggingDisabled = $False; + AzureElevateAccessToAllSubscriptions = $False; + AzureResourceThreatProtectionSettingsUpdated = $False; + AzureSQLServerAuditingSettingsUpdated = $False; + AzureSQLServerFirewallRuleDeleted = $False; + AzureSQLServerFirewallRuleUpdated = $False; + AzureStorageAccountOrContainerDeleted = $False; + BoxContentAccess = $False; + BoxContentDelete = $False; + BoxContentDownload = $False; + BoxContentExternallyShared = $False; + CCFinancialRegulatoryRiskyTextSent = $False; + CCInappropriateContentSent = $False; + CCInappropriateImagesSent = $False; + CertificateThumbprint = $CertificateThumbprint; + CopyToPersonalCloud = $False; + CopyToUSB = $False; + CumulativeExfiltrationDetector = $True; + DLPUserRiskSync = $True; + DropboxContentAccess = $False; + DropboxContentDelete = $False; + DropboxContentDownload = $False; + DropboxContentExternallyShared = $False; + EmailExternal = $False; + EmployeeAccessedEmployeePatientData = $False; + EmployeeAccessedFamilyData = $False; + EmployeeAccessedHighVolumePatientData = $False; + EmployeeAccessedNeighbourData = $False; + EmployeeAccessedRestrictedData = $False; + EnableTeam = $True; + Ensure = "Present"; + EpoBrowseToChildAbuseSites = $False; + EpoBrowseToCriminalActivitySites = $False; + EpoBrowseToCultSites = $False; + EpoBrowseToGamblingSites = $False; + EpoBrowseToHackingSites = $False; + EpoBrowseToHateIntoleranceSites = $False; + EpoBrowseToIllegalSoftwareSites = $False; + EpoBrowseToKeyloggerSites = $False; + EpoBrowseToLlmSites = $False; + EpoBrowseToMalwareSites = $False; + EpoBrowseToPhishingSites = $False; + EpoBrowseToPornographySites = $False; + EpoBrowseToUnallowedDomain = $False; + EpoBrowseToViolenceSites = $False; + EpoCopyToClipboardFromSensitiveFile = $False; + EpoCopyToNetworkShare = $False; + EpoFileArchived = $False; + EpoFileCopiedToRemoteDesktopSession = $False; + EpoFileDeleted = $False; + EpoFileDownloadedFromBlacklistedDomain = $False; + EpoFileDownloadedFromEnterpriseDomain = $False; + EpoFileRenamed = $False; + EpoFileStagedToCentralLocation = $False; + EpoHiddenFileCreated = $False; + EpoRemovableMediaMount = $False; + EpoSensitiveFileRead = $False; + FileVolCutoffLimits = "59"; + GoogleDriveContentAccess = $False; + GoogleDriveContentDelete = $False; + GoogleDriveContentExternallyShared = $False; + HistoricTimeSpan = "89"; + InScopeTimeSpan = "30"; + InsiderRiskScenario = "TenantSetting"; + Mcas3rdPartyAppDownload = $False; + Mcas3rdPartyAppFileDelete = $False; + Mcas3rdPartyAppFileSharing = $False; + McasActivityFromInfrequentCountry = $False; + McasImpossibleTravel = $False; + McasMultipleFailedLogins = $False; + McasMultipleStorageDeletion = $False; + McasMultipleVMCreation = $True; + McasMultipleVMDeletion = $False; + McasSuspiciousAdminActivities = $False; + McasSuspiciousCloudCreation = $False; + McasSuspiciousCloudTrailLoggingChange = $False; + McasTerminatedEmployeeActivity = $False; + Name = "IRM_Tenant_Setting"; + NotificationDetailsEnabled = $True; + OdbDownload = $False; + OdbSyncDownload = $False; + OptInIRMDataExport = $True; + PeerCumulativeExfiltrationDetector = $False; + PhysicalAccess = $False; + PotentialHighImpactUser = $False; + PowerBIDashboardsDeleted = $False; + PowerBIReportsDeleted = $False; + PowerBIReportsDownloaded = $False; + PowerBIReportsExported = $False; + PowerBIReportsViewed = $False; + PowerBISemanticModelsDeleted = $False; + PowerBISensitivityLabelDowngradedForArtifacts = $False; + PowerBISensitivityLabelRemovedFromArtifacts = $False; + Print = $False; + PriorityUserGroupMember = $False; + RaiseAuditAlert = $True; + SecurityAlertDefenseEvasion = $False; + SecurityAlertUnwantedSoftware = $False; + SpoAccessRequest = $False; + SpoApprovedAccess = $False; + SpoDownload = $False; + SpoDownloadV2 = $False; + SpoFileAccessed = $False; + SpoFileDeleted = $False; + SpoFileDeletedFromFirstStageRecycleBin = $False; + SpoFileDeletedFromSecondStageRecycleBin = $False; + SpoFileLabelDowngraded = $False; + SpoFileLabelRemoved = $False; + SpoFileSharing = $True; + SpoFolderDeleted = $False; + SpoFolderDeletedFromFirstStageRecycleBin = $False; + SpoFolderDeletedFromSecondStageRecycleBin = $False; + SpoFolderSharing = $False; + SpoSiteExternalUserAdded = $False; + SpoSiteInternalUserAdded = $False; + SpoSiteLabelRemoved = $False; + SpoSiteSharing = $False; + SpoSyncDownload = $False; + TeamsChannelFileSharedExternal = $False; + TeamsChannelMemberAddedExternal = $False; + TeamsChatFileSharedExternal = $True; # Drift + TeamsFileDownload = $False; + TeamsFolderSharedExternal = $False; + TeamsMemberAddedExternal = $False; + TeamsSensitiveMessage = $False; + TenantId = $TenantId; + UserHistory = $False; + } + } +} +``` + +### Example 3 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCInsiderRiskPolicy "SCInsiderRiskPolicy-IRM_Tenant_Setting" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + InsiderRiskScenario = "TenantSetting"; + Name = "IRM_Tenant_Setting"; + TenantId = $TenantId; + } + } +} +``` + From 985db922cd64b28d3743f6e55e766e4f60f8604c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sat, 28 Sep 2024 19:48:28 +0000 Subject: [PATCH 368/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 755 ++++++++++++++++++ 1 file changed, 755 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 9e3a40d0d6..4f93884879 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -40329,6 +40329,761 @@ } ] }, + { + "ClassName": "MSFT_SCInsiderRiskPolicy", + "Parameters": [ + { + "CIMType": "string", + "Name": "Name", + "Option": "Key" + }, + { + "CIMType": "string", + "Name": "InsiderRiskScenario", + "Option": "Key" + }, + { + "CIMType": "Boolean", + "Name": "Anonymization", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "DLPUserRiskSync", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "OptInIRMDataExport", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "RaiseAuditAlert", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "FileVolCutoffLimits", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AlertVolume", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AnomalyDetections", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "CopyToPersonalCloud", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "CopyToUSB", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "CumulativeExfiltrationDetector", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EmailExternal", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EmployeeAccessedEmployeePatientData", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EmployeeAccessedFamilyData", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EmployeeAccessedHighVolumePatientData", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EmployeeAccessedNeighbourData", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EmployeeAccessedRestrictedData", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoBrowseToChildAbuseSites", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoBrowseToCriminalActivitySites", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoBrowseToCultSites", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoBrowseToGamblingSites", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoBrowseToHackingSites", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoBrowseToHateIntoleranceSites", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoBrowseToIllegalSoftwareSites", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoBrowseToKeyloggerSites", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoBrowseToLlmSites", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoBrowseToMalwareSites", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoBrowseToPhishingSites", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoBrowseToPornographySites", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoBrowseToUnallowedDomain", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoBrowseToViolenceSites", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoCopyToClipboardFromSensitiveFile", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoCopyToNetworkShare", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoFileArchived", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoFileCopiedToRemoteDesktopSession", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoFileDeleted", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoFileDownloadedFromBlacklistedDomain", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoFileDownloadedFromEnterpriseDomain", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoFileRenamed", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoFileStagedToCentralLocation", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoHiddenFileCreated", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoRemovableMediaMount", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EpoSensitiveFileRead", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "Mcas3rdPartyAppDownload", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "Mcas3rdPartyAppFileDelete", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "Mcas3rdPartyAppFileSharing", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "McasActivityFromInfrequentCountry", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "McasImpossibleTravel", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "McasMultipleFailedLogins", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "McasMultipleStorageDeletion", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "McasMultipleVMCreation", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "McasMultipleVMDeletion", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "McasSuspiciousAdminActivities", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "McasSuspiciousCloudCreation", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "McasSuspiciousCloudTrailLoggingChange", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "McasTerminatedEmployeeActivity", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "OdbDownload", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "OdbSyncDownload", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PeerCumulativeExfiltrationDetector", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PhysicalAccess", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PotentialHighImpactUser", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "Print", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PriorityUserGroupMember", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SecurityAlertDefenseEvasion", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SecurityAlertUnwantedSoftware", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoAccessRequest", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoApprovedAccess", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoDownload", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoDownloadV2", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoFileAccessed", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoFileDeleted", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoFileDeletedFromFirstStageRecycleBin", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoFileDeletedFromSecondStageRecycleBin", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoFileLabelDowngraded", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoFileLabelRemoved", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoFileSharing", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoFolderDeleted", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoFolderDeletedFromFirstStageRecycleBin", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoFolderDeletedFromSecondStageRecycleBin", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoFolderSharing", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoSiteExternalUserAdded", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoSiteInternalUserAdded", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoSiteLabelRemoved", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoSiteSharing", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SpoSyncDownload", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "TeamsChannelFileSharedExternal", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "TeamsChannelMemberAddedExternal", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "TeamsChatFileSharedExternal", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "TeamsFileDownload", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "TeamsFolderSharedExternal", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "TeamsMemberAddedExternal", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "TeamsSensitiveMessage", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "UserHistory", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AWSS3BlockPublicAccessDisabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AWSS3BucketDeleted", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AWSS3PublicAccessEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AWSS3ServerLoggingDisabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AzureElevateAccessToAllSubscriptions", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AzureResourceThreatProtectionSettingsUpdated", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AzureSQLServerAuditingSettingsUpdated", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AzureSQLServerFirewallRuleDeleted", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AzureSQLServerFirewallRuleUpdated", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AzureStorageAccountOrContainerDeleted", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "BoxContentAccess", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "BoxContentDelete", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "BoxContentDownload", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "BoxContentExternallyShared", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "CCFinancialRegulatoryRiskyTextSent", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "CCInappropriateContentSent", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "CCInappropriateImagesSent", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "DropboxContentAccess", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "DropboxContentDelete", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "DropboxContentDownload", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "DropboxContentExternallyShared", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "GoogleDriveContentAccess", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "GoogleDriveContentDelete", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "GoogleDriveContentExternallyShared", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PowerBIDashboardsDeleted", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PowerBIReportsDeleted", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PowerBIReportsDownloaded", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PowerBIReportsExported", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PowerBIReportsViewed", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PowerBISemanticModelsDeleted", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PowerBISensitivityLabelDowngradedForArtifacts", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PowerBISensitivityLabelRemovedFromArtifacts", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "HistoricTimeSpan", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "InScopeTimeSpan", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "EnableTeam", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AnalyticsNewInsightEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AnalyticsTurnedOffEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "HighSeverityAlertsEnabled", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "HighSeverityAlertsRoleGroups", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "PoliciesHealthEnabled", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "PoliciesHealthRoleGroups", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "NotificationDetailsEnabled", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "NotificationDetailsRoleGroups", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ClipDeletionEnabled", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "SessionRecordingEnabled", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "RecordingTimeframePreEventInSec", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "RecordingTimeframePostEventInSec", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "BandwidthCapInMb", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "OfflineRecordingStorageLimitInMb", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_SCLabelSetting", "Parameters": [ From 8a29a895a3700912d4abea95fd26ecb61d601b21 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sat, 28 Sep 2024 20:23:28 +0000 Subject: [PATCH 369/465] Updated Graph Permissions List --- Tests/QA/Graph.PermissionList.txt | Bin 2911 -> 5826 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index be9a8de07f5a87bd0d6100a773b2ecf91e0ac662..826113f235a6a0d9238e46bc09b5d42a131a610f 100644 GIT binary patch literal 5826 zcmb_gU2hsO5ZvcV{U;y zTCKo7eX{Uz=Jd=G^jPLrzGKaE`0qk~swZi$=X_`C^EGTnuU+EV%QyVJQEvoG2HV9P zAxelngwzTM6)^T{|Jv}mC4T`wZJ_TS(mNSF#n4CmGFJDd=kjGNMn)QStzn-DIAe~U z#$jso0`s}LDQtQSC9rbdJ)~;&#|o>Vor&MxDeYM|7+=dBzIW0318Uf#ZMl)+a&Onz z0r9#{m$2EmJ0D=T0oE1bB1X4o*l6@T<7EuJYqe5?jN~F=pmD*yOlytQip(%vna%ui zG+RrTTQ=|r?K?$`H~3JOJJ`bS9cs!9OY5iheg7#>m1C7^=&bn&-59^r@0caKSKN(f zY3gHt0bkQ@j3dT4tCPzc)a(P^aL2^eB8A2kO@U!W1lbP9yO3^_dx9v7tJVlC^!OH9 z+50MHI}M{mqY9dA3pF{EEz#h#TH9rv9JCTGV^7R9_xgw^^I{%eiKau;>MD^{yR3I8 zTcQE8+wR|vi9OP_yJD;OPA><|)^Z6gm}l9E?9jj1?CDu~sO)#AU|8ehdjX%jQ?c=! zGZ(|wh};v+!}bcTaSQ26b0sSeE2X!;z|WC8&TRK(q5BD3_Dl=?8dZ?-$JlES?V+;recb;A zo_raL@fN78!0Z8jby%-^?kNoHyV<*wd!~_Z_i`!LFP+AHqfD+p-r#)P$QyYl zZ{->q@svfo@@(SwUx>7n9%JY+!(+*?r{fvY_3dqome04mI{=S6)!J1eJ#L+c`K|wrexde`9J!!F?lw*hZZik#CH%Sc@U31%ZaJN~E?JW>_WAuEVTP#D&WdvVoge|b{J3NdwW@(-W zXxkYo9%sb}mzcA|yU@Y({@st{R%OrLHNOw`a3as=d5Ml!@E^F+SGQDGj z@)g7=r>!NG1uR|sjm2DZ2P+D1D!ChJx4ak}Y0Y4yG2(OTb*@Bgg9^5I5dA}rFP-)-%V{Pv^~7U2?U}$@W`aNi*s1&LyArZlA>`!9?t2ed_Jcw+ zQcLG8^YRR@TKeS7q9Jvm<*eUSC3 z+tX;W-(AQ^N=ZH?kBsy1;CcDbAXb+}(Y9CK!wwqbVGZuxn>HMBdW)S=P&g-ReY<(w zYh}%c16yH)eqmHyyj<23i6v8@1+#&%7%x}MNuJnx>Y_X{twAlIzQrF~kIR`nMGAFSu<7G->ATVp3+kzhV%!)*PgQ>c}i^M#!JSh$Lo@4QI(A z27;`qRtMTJ&FWBE6}PgbnG|RJbbFHnK)-hecKzT2frQy7ty7PvR|LSB1h%0PF(O@lo}^qq}H&TR zB<*w^*Aeunz4WTjERsQ8%a52RYfkO5w16qS2#ecHh|2{3fZ;lWbxB+9@l#(yCe5l3 zbK*p^g3f?E`D2$Y;j6F# ze>5VahbUu*%$T|}Ckk_Ido-TLE49X`?4UK)Pea-LBp#Kl<(pKP(iJ~~IH_Sktgl7C z=wL~$_6eV}4}&?&xv%*6m*Zceh8#6q<&Jg$+}$8RW_F<|5LLRL18j}dK71;s5v(qn pA1#jVw61fG_#k`c-buCWf#DZ}e2F5m`^UtZxUC{!zMuAQ^dI|#J1YPH From 8144f5d4b763f0f4cbc4190b8fc2977e8d716874 Mon Sep 17 00:00:00 2001 From: ritikmit <88980817+ritikmit@users.noreply.github.com> Date: Mon, 30 Sep 2024 10:52:26 +0530 Subject: [PATCH 370/465] Update settings.json --- .../MSFT_AADAuthenticationMethodPolicyHardware/settings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/settings.json index b3604ceaec..be5ed21940 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyHardware/settings.json @@ -1,6 +1,6 @@ { - "resourceName": "AADAuthenticationMethodPolicySoftware", - "description": "This resource configures an Azure AD Authentication Method Policy Software.", + "resourceName": "AADAuthenticationMethodPolicyHardware", + "description": "This resource configures an Azure AD Authentication Method Policy Hardware.", "roles": { "read": [ "Security Reader" From e2d798e6c6a7f8a4fb94e38f1b571ef3689e488e Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Mon, 30 Sep 2024 10:54:33 +0530 Subject: [PATCH 371/465] Added changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d42af4e80..f572cd9bfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* AADAuthenticationMethodPolicyHardware + * Initial release. * AADEntitlementManagementSettings * Initial release. * AADPasswordRuleSettings From 3bc3fbe6b33d8717c01c8b43d0a27b2c4d1fc02e Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Mon, 30 Sep 2024 12:35:27 +0530 Subject: [PATCH 372/465] Added EXODnssecForVerifiedDomain resource --- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 4 +++ Tests/Unit/Stubs/Microsoft365.psm1 | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 3882742237..55612426e0 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -3769,6 +3769,10 @@ function Get-M365DSCExportContentForResource { $primaryKey = $Results.OrganizationName } + elseif ($Keys.Contains('DomainName')) + { + $primaryKey = $Results.DomainName + } if ([String]::IsNullOrEmpty($primaryKey) -and ` -not $Keys.Contains('IsSingleInstance')) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index cae92f1dde..204a864638 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -547,6 +547,35 @@ function Set-EmailTenantSettings ) } +function Get-DnssecStatusForVerifiedDomain +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $DomainName + ) +} + +function Enable-DnssecForVerifiedDomain +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $DomainName + ) +} + +function Disable-DnssecForVerifiedDomain +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $DomainName + ) +} function Get-MailboxIRMAccess { From afbd9e4a34bb8dde4bbb02281a8f0b4c2fe40d3c Mon Sep 17 00:00:00 2001 From: "Ritik Mittal (from Dev Box)" Date: Mon, 30 Sep 2024 12:37:10 +0530 Subject: [PATCH 373/465] Adding more files --- CHANGELOG.md | 2 + .../MSFT_EXODnssecForVerifiedDomain.psm1 | 334 ++++++++++++++++++ ...MSFT_EXODnssecForVerifiedDomain.schema.mof | 13 + .../MSFT_EXODnssecForVerifiedDomain/readme.md | 6 + .../settings.json | 32 ++ .../EXODnssecForVerifiedDomain/1-Create.ps1 | 33 ++ .../EXODnssecForVerifiedDomain/2-Update.ps1 | 33 ++ ...65DSC.EXODnssecForVerifiedDomain.Tests.ps1 | 168 +++++++++ 8 files changed, 621 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/MSFT_EXODnssecForVerifiedDomain.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/MSFT_EXODnssecForVerifiedDomain.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXODnssecForVerifiedDomain/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXODnssecForVerifiedDomain/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODnssecForVerifiedDomain.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b33239401..44f5e3fa9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,8 @@ * Initial release. * EXOArcConfig * Initial Release. +* EXODnssecForVerifiedDomain + * Initial Release. * EXOEmailTenantSettings * Initial Release. * EXOFocusedInbox diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/MSFT_EXODnssecForVerifiedDomain.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/MSFT_EXODnssecForVerifiedDomain.psm1 new file mode 100644 index 0000000000..3c39679718 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/MSFT_EXODnssecForVerifiedDomain.psm1 @@ -0,0 +1,334 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $DomainName, + + [Parameter()] + [System.String] + $DnssecFeatureStatus, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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.DnssecFeatureStatus = 'Unknown' + + try + { + $instance = Get-DnssecStatusForVerifiedDomain -DomainName $DomainName -ErrorAction Stop + if ('Unknown' -eq $instance.DnssecFeatureStatus.ToString()) + { + return $nullResult + } + + $results = @{ + DomainName = $DomainName + DnssecFeatureStatus = $instance.DnssecFeatureStatus.ToString() + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $DomainName, + + [Parameter()] + [System.String] + $DnssecFeatureStatus, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # Enable + if ($DnssecFeatureStatus -eq 'Enabled' -and $currentInstance.DnssecFeatureStatus -eq 'Disabled') + { + Enable-DnssecForVerifiedDomain -DomainName $setParameters.DomainName + } + # Disable + elseif ($DnssecFeatureStatus -eq 'Disabled' -and $currentInstance.DnssecFeatureStatus -eq 'Enabled') + { + Disable-DnssecForVerifiedDomain -DomainName $setParameters.DomainName + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $DomainName, + + [Parameter()] + [System.String] + $DnssecFeatureStatus, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-AcceptedDomain -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + DomainName = $config.DomainName + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_EXODnssecForVerifiedDomain/MSFT_EXODnssecForVerifiedDomain.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/MSFT_EXODnssecForVerifiedDomain.schema.mof new file mode 100644 index 0000000000..40def183ce --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/MSFT_EXODnssecForVerifiedDomain.schema.mof @@ -0,0 +1,13 @@ +[ClassVersion("1.0.0.0"), FriendlyName("EXODnssecForVerifiedDomain")] +class MSFT_EXODnssecForVerifiedDomain : OMI_BaseResource +{ + [Key, Description("DomainName parameter specifies the accepted domain in the Exchange Online organization where you want to view information about DNSSEC")] String DomainName; + [Write, Description("Status of the DnsSec for the given Domain Name."), ValueMap{"Enabled","Disabled","Unknown"}, Values{"Enabled","Disabled","Unknown"}] string DnssecFeatureStatus; + + [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/readme.md new file mode 100644 index 0000000000..3ce7d651bb --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/readme.md @@ -0,0 +1,6 @@ + +# EXODnssecForVerifiedDomain + +## Description + +DNSSec status for a verified domain. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/settings.json new file mode 100644 index 0000000000..4af6412f08 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "EXODnssecForVerifiedDomain", + "description": "This resource configures the DnsSec status for a verified domain.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXODnssecForVerifiedDomain/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXODnssecForVerifiedDomain/1-Create.ps1 new file mode 100644 index 0000000000..09e66b14c1 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXODnssecForVerifiedDomain/1-Create.ps1 @@ -0,0 +1,33 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXODnssecForVerifiedDomain "EXODnssecForVerifiedDomain-nik-charlebois.com" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + DnssecFeatureStatus = "Enabled"; + DomainName = "nik-charlebois.com"; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXODnssecForVerifiedDomain/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXODnssecForVerifiedDomain/2-Update.ps1 new file mode 100644 index 0000000000..09e66b14c1 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXODnssecForVerifiedDomain/2-Update.ps1 @@ -0,0 +1,33 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXODnssecForVerifiedDomain "EXODnssecForVerifiedDomain-nik-charlebois.com" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + DnssecFeatureStatus = "Enabled"; + DomainName = "nik-charlebois.com"; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODnssecForVerifiedDomain.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODnssecForVerifiedDomain.Tests.ps1 new file mode 100644 index 0000000000..9b35a77676 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODnssecForVerifiedDomain.Tests.ps1 @@ -0,0 +1,168 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Enable-DnssecForVerifiedDomain -MockWith { + return $null + } + + Mock -CommandName Disable-DnssecForVerifiedDomain -MockWith { + return $null + } + + # 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 instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + DomainName = 'test.com' + DnssecFeatureStatus = 'Enabled' + Credential = $Credential; + } + + Mock -CommandName Get-DnssecStatusForVerifiedDomain -MockWith { + return @{ + DomainName = 'test.com' + DnssecFeatureStatus = 'Enabled' + Credential = $Credential; + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state - Enable" -Fixture { + BeforeAll { + $testParams = @{ + DomainName = 'test.com' + DnssecFeatureStatus = 'Enabled' + Credential = $Credential; + } + + Mock -CommandName Get-DnssecStatusForVerifiedDomain -MockWith { + return @{ + DomainName = 'test.com' + DnssecFeatureStatus = 'Disabled' + Credential = $Credential; + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).DnssecFeatureStatus | Should -Be 'Disabled' + } + + 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 Enable-DnssecForVerifiedDomain -Exactly 1 + } + } + + Context -Name "The instance exists and values are NOT in the desired state - Disable" -Fixture { + BeforeAll { + $testParams = @{ + DomainName = 'test.com' + DnssecFeatureStatus = 'Disabled' + Credential = $Credential; + } + + Mock -CommandName Get-DnssecStatusForVerifiedDomain -MockWith { + return @{ + DomainName = 'test.com' + DnssecFeatureStatus = 'Enabled' + Credential = $Credential; + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).DnssecFeatureStatus | Should -Be 'Enabled' + } + + 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 Disable-DnssecForVerifiedDomain -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-DnssecStatusForVerifiedDomain -MockWith { + return @{ + DomainName = 'test.com' + DnssecFeatureStatus = 'Enabled' + Credential = $Credential; + } + } + + Mock -CommandName Get-AcceptedDomain -MockWith { + return @{ + DomainName = 'test.com' + Credential = $Credential; + } + } + } + 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 84deaff2e7274767bcbf3b9d0000e06375e86d19 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 30 Sep 2024 07:11:25 +0000 Subject: [PATCH 374/465] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index a73d8c8c5e..b77b1a29db 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -249,6 +249,14 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXODnssecForVerifiedDomain 'EXODnssecForVerifiedDomain-nik-charlebois.com' + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + DnssecFeatureStatus = "Enabled"; + DomainName = "nik-charlebois.com"; + } EXOEmailAddressPolicy 'ConfigureEmailAddressPolicy' { Name = "Integration Policy" From 9ae80de3d9d050360203d8e5bc11908480bd5165 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 30 Sep 2024 07:11:40 +0000 Subject: [PATCH 375/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 4f93884879..6a4d9d1920 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -8339,6 +8339,51 @@ } ] }, + { + "ClassName": "MSFT_EXODnssecForVerifiedDomain", + "Parameters": [ + { + "CIMType": "String", + "Name": "DomainName", + "Option": "Key" + }, + { + "CIMType": "string", + "Name": "DnssecFeatureStatus", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_EXOEmailAddressPolicy", "Parameters": [ From c3ca4dd1f70d92c1729f15765d1937e7304467c9 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 30 Sep 2024 07:11:55 +0000 Subject: [PATCH 376/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index 1ad7ba24e4..f62b9934f7 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -360,6 +360,14 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } + EXODnssecForVerifiedDomain 'EXODnssecForVerifiedDomain-nik-charlebois.com' + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + DnssecFeatureStatus = "Enabled"; + DomainName = "nik-charlebois.com"; + } EXOEmailAddressPolicy 'ConfigureEmailAddressPolicy' { Name = "Integration Policy" From 917037098721579197cf1d8728f0a3003c478117 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 30 Sep 2024 11:03:21 +0000 Subject: [PATCH 377/465] Updated Resources and Cmdlet documentation pages --- .../exchange/EXODnssecForVerifiedDomain.md | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 docs/docs/resources/exchange/EXODnssecForVerifiedDomain.md diff --git a/docs/docs/resources/exchange/EXODnssecForVerifiedDomain.md b/docs/docs/resources/exchange/EXODnssecForVerifiedDomain.md new file mode 100644 index 0000000000..ec46f78c50 --- /dev/null +++ b/docs/docs/resources/exchange/EXODnssecForVerifiedDomain.md @@ -0,0 +1,120 @@ +# EXODnssecForVerifiedDomain + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **DomainName** | Key | String | DomainName parameter specifies the accepted domain in the Exchange Online organization where you want to view information about DNSSEC | | +| **DnssecFeatureStatus** | Write | String | Status of the DnsSec for the given Domain Name. | `Enabled`, `Disabled`, `Unknown` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +DNSSec status for a verified domain. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - Permission for Monitoring and Export + +- **Update** + + - Permission for deploying + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXODnssecForVerifiedDomain "EXODnssecForVerifiedDomain-nik-charlebois.com" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + DnssecFeatureStatus = "Enabled"; + DomainName = "nik-charlebois.com"; + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + EXODnssecForVerifiedDomain "EXODnssecForVerifiedDomain-nik-charlebois.com" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + DnssecFeatureStatus = "Enabled"; + DomainName = "nik-charlebois.com"; + } + } +} +``` + From 45faac3b48207c2bc69eddd928523c42fd90dc64 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 30 Sep 2024 11:04:45 +0000 Subject: [PATCH 378/465] Updated Resources and Cmdlet documentation pages --- .../AADAuthenticationMethodPolicyHardware.md | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 docs/docs/resources/azure-ad/AADAuthenticationMethodPolicyHardware.md diff --git a/docs/docs/resources/azure-ad/AADAuthenticationMethodPolicyHardware.md b/docs/docs/resources/azure-ad/AADAuthenticationMethodPolicyHardware.md new file mode 100644 index 0000000000..cfed4b1402 --- /dev/null +++ b/docs/docs/resources/azure-ad/AADAuthenticationMethodPolicyHardware.md @@ -0,0 +1,163 @@ +# AADAuthenticationMethodPolicyHardware + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **ExcludeTargets** | Write | MSFT_AADAuthenticationMethodPolicyHardwareExcludeTarget[] | Displayname of the groups of users that are excluded from a policy. | | +| **IncludeTargets** | Write | MSFT_AADAuthenticationMethodPolicyHardwareIncludeTarget[] | Displayname of the groups of users that are included from a policy. | | +| **State** | Write | String | The state of the policy. Possible values are: enabled, disabled. | `enabled`, `disabled` | +| **Id** | Key | String | The unique identifier for an entity. Read-only. | | +| **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_AADAuthenticationMethodPolicyHardwareExcludeTarget + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Id** | Write | String | The object identifier of an Azure AD group. | | +| **TargetType** | Write | String | The type of the authentication method target. Possible values are: group and unknownFutureValue. | `user`, `group`, `unknownFutureValue` | + +### MSFT_AADAuthenticationMethodPolicyHardwareIncludeTarget + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Id** | Write | String | The object identifier of an Azure AD group. | | +| **TargetType** | Write | String | The type of the authentication method target. Possible values are: group and unknownFutureValue. | `user`, `group`, `unknownFutureValue` | + + +# AADAuthenticationMethodPolicySoftware + +## Description + +Azure AD Authentication Method Policy Hardware + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - Policy.ReadWrite.AuthenticationMethod, Policy.Read.All + +- **Update** + + - Policy.ReadWrite.AuthenticationMethod, Policy.Read.All + +#### Application permissions + +- **Read** + + - Policy.ReadWrite.AuthenticationMethod, Policy.Read.All + +- **Update** + + - Policy.ReadWrite.AuthenticationMethod, Policy.Read.All + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + Node localhost + { + AADAuthenticationMethodPolicyHardware "AADAuthenticationMethodPolicyHardware-HardwareOath" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Present"; + ExcludeTargets = @( + MSFT_AADAuthenticationMethodPolicyHardwareExcludeTarget{ + Id = 'Executives' + TargetType = 'group' + } + MSFT_AADAuthenticationMethodPolicyHardwareExcludeTarget{ + Id = 'Paralegals' + TargetType = 'group' + } + ); + Id = "HardwareOath"; + IncludeTargets = @( + MSFT_AADAuthenticationMethodPolicyHardwareIncludeTarget{ + Id = 'Legal Team' + TargetType = 'group' + } + ); + State = "enabled"; # Updated Property + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + Node localhost + { + AADAuthenticationMethodPolicyHardware "AADAuthenticationMethodPolicyHardware-HardwareOath" + { + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + Ensure = "Absent"; + Id = "HardwareOath"; + } + } +} +``` + From d0474ecb0add31042de7470e961eef73bab0132b Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 30 Sep 2024 17:48:46 +0530 Subject: [PATCH 379/465] Initial commit --- .../MSFT_AADApplication.psm1 | 105 +++++++++++++++++- .../MSFT_AADApplication.schema.mof | 17 +++ 2 files changed, 121 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 7f98342cac..636e27a4db 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -60,6 +60,10 @@ function Get-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $OptionalClaims, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $Api, @@ -206,6 +210,52 @@ function Get-TargetResource $complexAuthenticationBehaviors = $null } + $complexOptionalClaims = @{} + $complexAccessToken = @() + foreach ($currentAccessToken in $AADApp.optionalClaims.accessToken) + { + $myAccessToken = @{} + $myAccessToken.Add('Essential', $currentAccessToken.essential) + $myAccessToken.Add('Name', $currentAccessToken.name) + $myAccessToken.Add('Source', $currentAccessToken.source) + if ($myAccessToken.values.Where({$null -ne $_}).Count -gt 0) + { + $complexAccessToken += $myAccessToken + } + } + $complexOptionalClaims.Add('AccessToken',$complexAccessToken) + $complexIdToken = @() + foreach ($currentIdToken in $AADApp.optionalClaims.idToken) + { + $myIdToken = @{} + $myIdToken.Add('Essential', $currentIdToken.essential) + $myIdToken.Add('Name', $currentIdToken.name) + $myIdToken.Add('Source', $currentIdToken.source) + if ($myIdToken.values.Where({$null -ne $_}).Count -gt 0) + { + $complexIdToken += $myIdToken + } + } + $complexOptionalClaims.Add('IdToken',$complexIdToken) + $complexSaml2Token = @() + foreach ($currentSaml2Token in $AADApp.optionalClaims.saml2Token) + { + $mySaml2Token = @{} + $mySaml2Token.Add('Essential', $currentSaml2Token.essential) + $mySaml2Token.Add('Name', $currentSaml2Token.name) + $mySaml2Token.Add('Source', $currentSaml2Token.source) + if ($mySaml2Token.values.Where({$null -ne $_}).Count -gt 0) + { + $complexSaml2Token += $mySaml2Token + } + } + $complexOptionalClaims.Add('Saml2Token',$complexSaml2Token) + if ($complexOptionalClaims.values.Where({$null -ne $_}).Count -eq 0) + { + $complexOptionalClaims = $null + } + + $complexApi = @{} $complexPreAuthorizedApplications = @() foreach ($currentPreAuthorizedApplications in $AADApp.api.preAuthorizedApplications) @@ -344,6 +394,7 @@ function Get-TargetResource Owners = $OwnersValues ObjectId = $AADApp.Id AppId = $AADApp.AppId + OptionalClaims = $complexOptionalClaims Api = $complexApi AuthenticationBehaviors = $complexAuthenticationBehaviors KeyCredentials = $complexKeyCredentials @@ -443,6 +494,10 @@ function Set-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $OptionalClaims, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $Api, @@ -944,6 +999,10 @@ function Test-TargetResource [System.String[]] $Owners, + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance] + $OptionalClaims, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $Api, @@ -1241,6 +1300,47 @@ function Export-TargetResource } } + + if ($null -ne $Results.OptionalClaims) + { + $complexMapping = @( + @{ + Name = 'OptionalClaims' + CimInstanceName = 'MicrosoftGraphOptionalClaims' + IsRequired = $False + } + @{ + Name = 'AccessToken' + CimInstanceName = 'MicrosoftGraphOptionalClaim' + IsRequired = $False + } + @{ + Name = 'IdToken' + CimInstanceName = 'MicrosoftGraphOptionalClaim' + IsRequired = $False + } + @{ + Name = 'Saml2Token' + CimInstanceName = 'MicrosoftGraphOptionalClaim' + IsRequired = $False + } + ) + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.OptionalClaims ` + -CIMInstanceName 'MicrosoftGraphoptionalClaims' ` + -ComplexTypeMapping $complexMapping + + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.OptionalClaims = $complexTypeStringResult + } + else + { + $Results.Remove('OptionalClaims') | Out-Null + } + } + + if ($null -ne $Results.KeyCredentials) { $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` @@ -1302,7 +1402,10 @@ function Export-TargetResource $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock ` -ParameterName 'Permissions' } - + if ($Results.OptionalClaims) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "OptionalClaims" -IsCIMArray:$False + } if ($Results.AuthenticationBehaviors) { $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "AuthenticationBehaviors" -IsCIMArray:$False diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof index 0f537deaaa..c78c43016d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof @@ -7,6 +7,22 @@ class MSFT_AADApplicationPermission [Write, Description("Represented whether or not the Admin consent been granted on the app.")] Boolean AdminConsentGranted; }; +[ClassVersion("1.0.0")] +class MSFT_MicrosoftGraphOptionalClaims +{ + [Write, Description("The optional claims returned in the JWT access token."), EmbeddedInstance("MSFT_MicrosoftGraphOptionalClaim")] String AccessToken[]; + [Write, Description("The optional claims returned in the JWT ID token."), EmbeddedInstance("MSFT_MicrosoftGraphOptionalClaim")] String IdToken[]; + [Write, Description("The optional claims returned in the SAML token."), EmbeddedInstance("MSFT_MicrosoftGraphOptionalClaim")] String Saml2Token[]; +}; + +[ClassVersion("1.0.0")] +class MSFT_MicrosoftGraphOptionalClaim +{ + [Write, Description("If the value is true, the claim specified by the client is necessary to ensure a smooth authorization experience for the specific task requested by the end user. The default value is false.")] Boolean Essential; + [Write, Description("The name of the optional claim.")] String Name; + [Write, Description("The source (directory object) of the claim. There are predefined claims and user-defined claims from extension properties. If the source value is null, the claim is a predefined optional claim. If the source value is user, the value in the name property is the extension property from the user object.")] String Source; +}; + [ClassVersion("1.0.0")] class MSFT_MicrosoftGraphPreAuthorizedApplication { @@ -76,6 +92,7 @@ class MSFT_AADApplication : OMI_BaseResource [Write, Description("User-defined URI(s) that uniquely identify a Web application within its Azure AD tenant, or within a verified custom domain.")] string IdentifierUris[]; [Write, Description("Specifies the fallback application type as public client, such as an installed application running on a mobile device. The default value is false, which means the fallback application type is confidential client such as web app. There are certain scenarios where Microsoft Entra ID cannot determine the client application type (for example, ROPC flow where it is configured without specifying a redirect URI). In those cases, Microsoft Entra ID will interpret the application type based on the value of this property.")] Boolean IsFallbackPublicClient; [Write, Description("Client applications that are tied to this resource application.")] string KnownClientApplications[]; + [Write, Description("Application developers can configure optional claims in their Microsoft Entra applications to specify the claims that are sent to their application by the Microsoft security token service. For more information, see How to: Provide optional claims to your app."), EmbeddedInstance("MSFT_MicrosoftGraphoptionalClaims")] String OptionalClaims; [Write, Description("Specifies settings for an application that implements a web API."), EmbeddedInstance("MSFT_MicrosoftGraphapiApplication")] String Api; [Write, Description("The collection of breaking change behaviors related to token issuance that are configured for the application. Authentication behaviors are unset by default (null) and must be explicitly enabled or disabled. Nullable. Returned only on $select. For more information about authentication behaviors, see Manage application authenticationBehaviors to avoid unverified use of email claims for user identification or authorization."), EmbeddedInstance("MSFT_MicrosoftGraphauthenticationBehaviors")] String AuthenticationBehaviors; [Write, Description("The collection of password credentials associated with the application. Not nullable."), EmbeddedInstance("MSFT_MicrosoftGraphpasswordCredential")] String PasswordCredentials[]; From 5c6af3211abf928cc063a53365c12a3666f108fc Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 30 Sep 2024 08:35:19 -0400 Subject: [PATCH 380/465] Update MSFT_SCInsiderRiskPolicy.psm1 --- .../MSFT_SCInsiderRiskPolicy.psm1 | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 index 051da6de2c..d39fceba62 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 @@ -668,11 +668,36 @@ function Get-TargetResource if (-not [System.String]::IsNullOrEmpty($instance.TenantSettings) -and $instance.TenantSettings.Length -gt 0) { $tenantSettings = ConvertFrom-Json $instance.TenantSettings[0] + + $DLPUserRiskSyncValue = $null + if (-not [System.String]::IsNullOrEmpty($tenantSettings.FeatureSettings.DLPUserRiskSync)) + { + $DLPUserRiskSyncValue = [Boolean]::Parse($tenantSettings.FeatureSettings.DLPUserRiskSync) + } + + $AnonymizationValue = $null + if (-not [System.String]::IsNullOrEmpty($tenantSettings.FeatureSettings.Anonymization)) + { + $AnonymizationValue = [Boolean]::Parse($tenantSettings.FeatureSettings.Anonymization) + } + + $OptInIRMDataExportValue = $null + if (-not [System.String]::IsNullOrEmpty($tenantSettings.FeatureSettings.OptInIRMDataExport)) + { + $OptInIRMDataExportValue = [Boolean]::Parse($tenantSettings.FeatureSettings.OptInIRMDataExport) + } + + $RaiseAuditAlertValue = $null + if (-not [System.String]::IsNullOrEmpty($tenantSettings.FeatureSettings.RaiseAuditAlert)) + { + $RaiseAuditAlertValue = [Boolean]::Parse($tenantSettings.FeatureSettings.RaiseAuditAlert) + } + $tenantSettingsHash = @{ - Anonymization = [Boolean]($tenantSettings.FeatureSettings.Anonymization) - DLPUserRiskSync = [Boolean]($tenantSettings.FeatureSettings.DLPUserRiskSync) - OptInIRMDataExport = [Boolean]($tenantSettings.FeatureSettings.OptInIRMDataExport) - RaiseAuditAlert = [Boolean]($tenantSettings.FeatureSettings.RaiseAuditAlert) + Anonymization = $AnonymizationValue + DLPUserRiskSync = $DLPUserRiskSyncValue + OptInIRMDataExport = $OptInIRMDataExportValue + RaiseAuditAlert = $RaiseAuditAlertValue FileVolCutoffLimits = $tenantSettings.IntelligentDetections.FileVolCutoffLimits AlertVolume = $tenantSettings.IntelligentDetections.AlertVolume AnomalyDetections = ($tenantSettings.Indicators | Where-Object -FilterScript {$_.Name -eq 'AnomalyDetections'}).Enabled From ac13812ca7b1d3bda65f62615e9e0c3913c789ed Mon Sep 17 00:00:00 2001 From: "Kartikeya Saxena (from Dev Box)" Date: Mon, 30 Sep 2024 18:45:33 +0530 Subject: [PATCH 381/465] Added UTs --- CHANGELOG.md | 1 + .../Microsoft365DSC.AADApplication.Tests.ps1 | 48 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6760e1370e..7eb4ebe53b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Added AppRoles * Added AuthenticationBehavior * Added KeyCredentials + * Added OptionalClaims * Added PaswordCredentials * Added PreAuthorizationApplications * AADAuthenticationMethodPolicy diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 index eafea2820d..55637d70cd 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 @@ -212,6 +212,30 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { DisplayName = 'anexas_test_2' } -ClientOnly ) + OptionalClaims = New-CimInstance -ClassName MSFT_MicrosoftGraphoptionalClaims -Property @{ + Saml2Token = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_MicrosoftGraphOptionalClaim -Property @{ + Name = 'groups' + Essential = $False + } -ClientOnly + ) + AccessToken = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_MicrosoftGraphOptionalClaim -Property @{ + Name = 'groups' + Essential = $False + } -ClientOnly + ) + IdToken = [CimInstance[]]@( + New-CimInstance -ClassName MSFT_MicrosoftGraphOptionalClaim -Property @{ + Name = 'acrs' + Essential = $False + } -ClientOnly + New-CimInstance -ClassName MSFT_MicrosoftGraphOptionalClaim -Property @{ + Name = 'groups' + Essential = $False + } -ClientOnly + ) + } -ClientOnly AuthenticationBehaviors = New-CimInstance -ClassName MSFT_MicrosoftGraphAuthenticationBehaviors -Property @{ blockAzureADGraphAccess = $false removeUnverifiedEmailClaim = $true @@ -249,6 +273,30 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $AADApp | Add-Member -MemberType NoteProperty -Name Description -Value 'App description' $AADApp | Add-Member -MemberType NoteProperty -Name GroupMembershipClaims -Value 0 $AADApp | Add-Member -MemberType NoteProperty -Name SignInAudience -Value 'AzureADMyOrg' + $AADApp | Add-Member -MemberType NoteProperty -Name OptionalClaims -Value @{ + Saml2Token = @( + @{ + Name = 'groups' + Essential = $False + } + ) + AccessToken = @( + @{ + Name = 'groups' + Essential = $False + } + ) + IdToken = @( + @{ + Name = 'acrs' + Essential = $False + } + @{ + Name = 'groups' + Essential = $False + } + ) + } $AADApp | Add-Member -MemberType NoteProperty -Name Web -Value @{ HomepageUrl = 'https://app.contoso.com' LogoutURL = 'https://app.contoso.com/logout' From 76e83705e4fcddea697d1963989c2efb9d024cf4 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 30 Sep 2024 09:17:35 -0400 Subject: [PATCH 382/465] Fixes --- .../settings.json | 16 ++--- .../MSFT_SCInsiderRiskPolicy.psm1 | 60 ++++++++++++++++--- .../MSFT_SCInsiderRiskPolicy.schema.mof | 1 + 3 files changed, 56 insertions(+), 21 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/settings.json index 4af6412f08..a6aeb81b3a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODnssecForVerifiedDomain/settings.json @@ -3,10 +3,10 @@ "description": "This resource configures the DnsSec status for a verified domain.", "roles": { "read": [ - "Role" + "Global Reader" ], "update": [ - "Role" + "Exchange Administrator" ] }, "permissions": { @@ -16,16 +16,8 @@ "update": [] }, "application": { - "read": [ - { - "name": "Permission for Monitoring and Export" - } - ], - "update": [ - { - "name": "Permission for deploying" - } - ] + "read": [], + "update": [] } } } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 index d39fceba62..18ecc85eb7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 @@ -576,6 +576,10 @@ function Get-TargetResource [System.String] $OfflineRecordingStorageLimitInMb, + [Parameter()] + [System.Boolean] + $AdaptiveProtectionEnabled, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -859,6 +863,21 @@ function Get-TargetResource $tenantSettingsHash.Add('NotificationDetailsEnabled', $false) } + $AdaptiveProtectionEnabledValue = $false + if ($null -ne $tenantSettings.DynamicRiskPreventionSettings -and ` + $null -ne $tenantSettings.DynamicRiskPreventionSettings.DynamicRiskScenarioSettings) + { + if ($tenantSettings.DynamicRiskPreventionSettings.DynamicRiskScenarioSettings.ActivationStatus -eq 0) + { + $AdaptiveProtectionEnabledValue = $true + } + else + { + $AdaptiveProtectionEnabledValue = $false + } + } + $tenantSettingsHash.Add('AdaptiveProtectionEnabled', $AdaptiveProtectionEnabledValue) + $results += $tenantSettingsHash } @@ -1454,6 +1473,10 @@ function Set-TargetResource [System.String] $OfflineRecordingStorageLimitInMb, + [Parameter()] + [System.Boolean] + $AdaptiveProtectionEnabled, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -1538,14 +1561,14 @@ function Set-TargetResource } $extensibleIndicatorsProperties = @('AWSS3BlockPublicAccessDisabled','AWSS3BucketDeleted','AWSS3PublicAccessEnabled',` - 'AWSS3ServerLoggingDisabled','AzureElevateAccessToAllSubscriptions','AzureResourceThreatProtectionSettingsUpdated', ` - 'AzureSQLServerAuditingSettingsUpdated','AzureSQLServerFirewallRuleDeleted','AzureSQLServerFirewallRuleUpdated', ` - 'AzureStorageAccountOrContainerDeleted','BoxContentAccess','BoxContentDelete','BoxContentDownload','BoxContentExternallyShared', ` - 'CCFinancialRegulatoryRiskyTextSent','CCInappropriateContentSent','CCInappropriateImagesSent','DropboxContentAccess', ` - 'DropboxContentDelete','DropboxContentDownload','DropboxContentExternallyShared','GoogleDriveContentAccess', ` - 'GoogleDriveContentDelete','GoogleDriveContentExternallyShared','PowerBIDashboardsDeleted','PowerBIReportsDeleted', ` - 'PowerBIReportsDownloaded','PowerBIReportsExported','PowerBIReportsViewed','PowerBISemanticModelsDeleted', ` - 'PowerBISensitivityLabelDowngradedForArtifacts','PowerBISensitivityLabelRemovedFromArtifacts') + 'AWSS3ServerLoggingDisabled','AzureElevateAccessToAllSubscriptions','AzureResourceThreatProtectionSettingsUpdated', ` + 'AzureSQLServerAuditingSettingsUpdated','AzureSQLServerFirewallRuleDeleted','AzureSQLServerFirewallRuleUpdated', ` + 'AzureStorageAccountOrContainerDeleted','BoxContentAccess','BoxContentDelete','BoxContentDownload','BoxContentExternallyShared', ` + 'CCFinancialRegulatoryRiskyTextSent','CCInappropriateContentSent','CCInappropriateImagesSent','DropboxContentAccess', ` + 'DropboxContentDelete','DropboxContentDownload','DropboxContentExternallyShared','GoogleDriveContentAccess', ` + 'GoogleDriveContentDelete','GoogleDriveContentExternallyShared','PowerBIDashboardsDeleted','PowerBIReportsDeleted', ` + 'PowerBIReportsDownloaded','PowerBIReportsExported','PowerBIReportsViewed','PowerBISemanticModelsDeleted', ` + 'PowerBISensitivityLabelDowngradedForArtifacts','PowerBISensitivityLabelRemovedFromArtifacts') $extensibleIndicatorsValues = @() foreach ($extensibleIndicatorsProperty in $extensibleIndicatorsProperties) @@ -1559,8 +1582,23 @@ function Set-TargetResource # Tenant Settings $featureSettingsValue = "{`"Anonymization`":$($Anonymization.ToString().ToLower()), `"DLPUserRiskSync`":$($DLPUserRiskSync.ToString().ToLower()), `"OptInIRMDataExport`":$($OptInIRMDataExport.ToString().ToLower()), `"RaiseAuditAlert`":$($RaiseAuditAlert.ToString().ToLower()), `"EnableTeam`":$($EnableTeam.ToString().ToLower())}" $intelligentDetectionValue = "{`"FileVolCutoffLimits`":`"$($FileVolCutoffLimits)`", `"AlertVolume`":`"$($AlertVolume)`"}" + + $tenantSettingsValue = "{`"Region`":`"WW`", `"FeatureSettings`":$($featureSettingsValue), " + ` - "`"IntelligentDetections`":$($intelligentDetectionValue)}" + "`"IntelligentDetections`":$($intelligentDetectionValue)" + if ($null -ne $AdaptiveProtectionEnabled) + { + Write-Verbose -Message "Adding Adaptive Protection setting to the set parameters." + $AdaptiveProtectionActivatonStatus = 1 + if ($AdaptiveProtectionEnabled) + { + $AdaptiveProtectionActivatonStatus = 0 + } + $dynamicRiskPreventionSettings = "{`"ProfileInScopeTimeSpan`":7, `"LoopbackTimeSpan`":7, `"DynamicRiskScenarioSettings`":[{`"ActivationStatus`":$AdaptiveProtectionActivatonStatus}]}" + $tenantSettingsValue += ", `"DynamicRiskPreventionSettings`":$dynamicRiskPreventionSettings" + } + + $tenantSettingsValue += "}" # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') @@ -2180,6 +2218,10 @@ function Test-TargetResource [System.String] $OfflineRecordingStorageLimitInMb, + [Parameter()] + [System.Boolean] + $AdaptiveProtectionEnabled, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof index 84a02dc923..4f91c8eea5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof @@ -144,6 +144,7 @@ class MSFT_SCInsiderRiskPolicy : OMI_BaseResource [Write, Description("Official documentation to come.")] String RecordingTimeframePostEventInSec; [Write, Description("Official documentation to come.")] String BandwidthCapInMb; [Write, Description("Official documentation to come.")] String OfflineRecordingStorageLimitInMb; + [Write, Description("Determines if Adaptive Protection is enabled for Purview.")] Boolean AdaptiveProtectionEnabled; [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] 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 bacbfb6d7cabc8a7ad787e65af3db13917a749e2 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 30 Sep 2024 13:32:50 +0000 Subject: [PATCH 383/465] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/exchange/EXODnssecForVerifiedDomain.md | 4 ++-- .../docs/resources/security-compliance/SCInsiderRiskPolicy.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/docs/resources/exchange/EXODnssecForVerifiedDomain.md b/docs/docs/resources/exchange/EXODnssecForVerifiedDomain.md index ec46f78c50..1464320d25 100644 --- a/docs/docs/resources/exchange/EXODnssecForVerifiedDomain.md +++ b/docs/docs/resources/exchange/EXODnssecForVerifiedDomain.md @@ -38,11 +38,11 @@ To authenticate with the Microsoft Graph API, this resource required the followi - **Read** - - Permission for Monitoring and Export + - None - **Update** - - Permission for deploying + - None ## Examples diff --git a/docs/docs/resources/security-compliance/SCInsiderRiskPolicy.md b/docs/docs/resources/security-compliance/SCInsiderRiskPolicy.md index 863077a28d..fbf9c1a9dd 100644 --- a/docs/docs/resources/security-compliance/SCInsiderRiskPolicy.md +++ b/docs/docs/resources/security-compliance/SCInsiderRiskPolicy.md @@ -147,6 +147,7 @@ | **RecordingTimeframePostEventInSec** | Write | String | Official documentation to come. | | | **BandwidthCapInMb** | Write | String | Official documentation to come. | | | **OfflineRecordingStorageLimitInMb** | Write | String | Official documentation to come. | | +| **AdaptiveProtectionEnabled** | Write | Boolean | Determines if Adaptive Protection is enabled for Purview. | | | **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Absent`, `Present` | | **Credential** | Write | PSCredential | Credentials of the workload's Admin | | | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | From fefe286ed878711d1c9ba9ecb015a06af62990ca Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 30 Sep 2024 13:36:39 +0000 Subject: [PATCH 384/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 18d8dad1ff..c92a049539 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -41187,6 +41187,11 @@ "Name": "OfflineRecordingStorageLimitInMb", "Option": "Write" }, + { + "CIMType": "Boolean", + "Name": "AdaptiveProtectionEnabled", + "Option": "Write" + }, { "CIMType": "string", "Name": "Ensure", From e65035e707193b6d3c7c09a4bb2f02eea4823a04 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 30 Sep 2024 14:30:30 +0000 Subject: [PATCH 385/465] Updated Resources and Cmdlet documentation pages --- .../docs/resources/azure-ad/AADApplication.md | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/docs/resources/azure-ad/AADApplication.md b/docs/docs/resources/azure-ad/AADApplication.md index 857f6513b8..3ad2464b54 100644 --- a/docs/docs/resources/azure-ad/AADApplication.md +++ b/docs/docs/resources/azure-ad/AADApplication.md @@ -14,6 +14,7 @@ | **IdentifierUris** | Write | StringArray[] | User-defined URI(s) that uniquely identify a Web application within its Azure AD tenant, or within a verified custom domain. | | | **IsFallbackPublicClient** | Write | Boolean | Specifies the fallback application type as public client, such as an installed application running on a mobile device. The default value is false, which means the fallback application type is confidential client such as web app. There are certain scenarios where Microsoft Entra ID cannot determine the client application type (for example, ROPC flow where it is configured without specifying a redirect URI). In those cases, Microsoft Entra ID will interpret the application type based on the value of this property. | | | **KnownClientApplications** | Write | StringArray[] | Client applications that are tied to this resource application. | | +| **OptionalClaims** | Write | MSFT_MicrosoftGraphoptionalClaims | Application developers can configure optional claims in their Microsoft Entra applications to specify the claims that are sent to their application by the Microsoft security token service. For more information, see How to: Provide optional claims to your app. | | | **Api** | Write | MSFT_MicrosoftGraphapiApplication | Specifies settings for an application that implements a web API. | | | **AuthenticationBehaviors** | Write | MSFT_MicrosoftGraphauthenticationBehaviors | The collection of breaking change behaviors related to token issuance that are configured for the application. Authentication behaviors are unset by default (null) and must be explicitly enabled or disabled. Nullable. Returned only on $select. For more information about authentication behaviors, see Manage application authenticationBehaviors to avoid unverified use of email claims for user identification or authorization. | | | **PasswordCredentials** | Write | MSFT_MicrosoftGraphpasswordCredential[] | The collection of password credentials associated with the application. Not nullable. | | @@ -44,6 +45,26 @@ | **Type** | Write | String | Type of permission. | `AppOnly`, `Delegated` | | **AdminConsentGranted** | Write | Boolean | Represented whether or not the Admin consent been granted on the app. | | +### MSFT_MicrosoftGraphOptionalClaims + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **AccessToken** | Write | MSFT_MicrosoftGraphOptionalClaim[] | The optional claims returned in the JWT access token. | | +| **IdToken** | Write | MSFT_MicrosoftGraphOptionalClaim[] | The optional claims returned in the JWT ID token. | | +| **Saml2Token** | Write | MSFT_MicrosoftGraphOptionalClaim[] | The optional claims returned in the SAML token. | | + +### MSFT_MicrosoftGraphOptionalClaim + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Essential** | Write | Boolean | If the value is true, the claim specified by the client is necessary to ensure a smooth authorization experience for the specific task requested by the end user. The default value is false. | | +| **Name** | Write | String | The name of the optional claim. | | +| **Source** | Write | String | The source (directory object) of the claim. There are predefined claims and user-defined claims from extension properties. If the source value is null, the claim is a predefined optional claim. If the source value is user, the value in the name property is the extension property from the user object. | | + ### MSFT_MicrosoftGraphPreAuthorizedApplication #### Parameters From 40561dc1f1911f95986312d7fe3de206ea536038 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 30 Sep 2024 14:32:42 +0000 Subject: [PATCH 386/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index c92a049539..f5f4fea5ad 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -204,6 +204,46 @@ } ] }, + { + "ClassName": "MSFT_MicrosoftGraphOptionalClaims", + "Parameters": [ + { + "CIMType": "MSFT_MicrosoftGraphOptionalClaim[]", + "Name": "AccessToken", + "Option": "Write" + }, + { + "CIMType": "MSFT_MicrosoftGraphOptionalClaim[]", + "Name": "IdToken", + "Option": "Write" + }, + { + "CIMType": "MSFT_MicrosoftGraphOptionalClaim[]", + "Name": "Saml2Token", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_MicrosoftGraphOptionalClaim", + "Parameters": [ + { + "CIMType": "Boolean", + "Name": "Essential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Name", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Source", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_MicrosoftGraphPreAuthorizedApplication", "Parameters": [ @@ -417,6 +457,11 @@ "Name": "KnownClientApplications", "Option": "Write" }, + { + "CIMType": "MSFT_MicrosoftGraphoptionalClaims", + "Name": "OptionalClaims", + "Option": "Write" + }, { "CIMType": "MSFT_MicrosoftGraphapiApplication", "Name": "Api", From 63d01e31c4c03e0cfced9d8c5803994b4449849c Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 30 Sep 2024 11:42:44 -0400 Subject: [PATCH 387/465] Added properties --- .../MSFT_SCInsiderRiskPolicy.psm1 | 338 +++++++++++++++++- .../MSFT_SCInsiderRiskPolicy.schema.mof | 24 ++ 2 files changed, 361 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 index 18ecc85eb7..baac85f2b7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.psm1 @@ -580,6 +580,102 @@ function Get-TargetResource [System.Boolean] $AdaptiveProtectionEnabled, + [Parameter()] + [System.UInt32] + $AdaptiveProtectionHighProfileSourceType, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionHighProfileConfirmedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionHighProfileGeneratedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionHighProfileInsightSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionHighProfileInsightCount, + + [Parameter()] + [System.String[]] + $AdaptiveProtectionHighProfileInsightTypes, + + [Parameter()] + [System.Boolean] + $AdaptiveProtectionHighProfileConfirmedIssue, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionMediumProfileSourceType, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionMediumProfileConfirmedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionMediumProfileGeneratedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionMediumProfileInsightSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionMediumProfileInsightCount, + + [Parameter()] + [System.String[]] + $AdaptiveProtectionMediumProfileInsightTypes, + + [Parameter()] + [System.Boolean] + $AdaptiveProtectionMediumProfileConfirmedIssue, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionLowProfileSourceType, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionLowProfileConfirmedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionLowProfileGeneratedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionLowProfileInsightSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionLowProfileInsightCount, + + [Parameter()] + [System.String[]] + $AdaptiveProtectionLowProfileInsightTypes, + + [Parameter()] + [System.Boolean] + $AdaptiveProtectionLowProfileConfirmedIssue, + + [Parameter()] + [System.UInt32] + $ProfileInscopeTimeSpan, + + [Parameter()] + [System.UInt32] + $LookbackTimeSpan, + + [Parameter()] + [System.Boolean] + $RetainSeverityAfterTriage, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -863,6 +959,7 @@ function Get-TargetResource $tenantSettingsHash.Add('NotificationDetailsEnabled', $false) } + # Adaptive Protection $AdaptiveProtectionEnabledValue = $false if ($null -ne $tenantSettings.DynamicRiskPreventionSettings -and ` $null -ne $tenantSettings.DynamicRiskPreventionSettings.DynamicRiskScenarioSettings) @@ -875,6 +972,49 @@ function Get-TargetResource { $AdaptiveProtectionEnabledValue = $false } + + # High Profile + if ($null -ne $tenantSettings.DynamicRiskPreventionSettings.DynamicRiskScenarioSettings.HighProfile) + { + $highProfile = $tenantSettings.DynamicRiskPreventionSettings.DynamicRiskScenarioSettings.HighProfile + $tenantSettingsHash.Add('AdaptiveProtectionHighProfileSourceType', $highProfile.ProfileSourceType) + $tenantSettingsHash.Add('AdaptiveProtectionHighProfileConfirmedIssueSeverity', $highProfile.ConfirmedIssueSeverity) + $tenantSettingsHash.Add('AdaptiveProtectionHighProfileGeneratedIssueSeverity', $highProfile.GeneratedIssueSeverity) + $tenantSettingsHash.Add('AdaptiveProtectionHighProfileInsightSeverity', $highProfile.InsightSeverity) + $tenantSettingsHash.Add('AdaptiveProtectionHighProfileInsightCount', $highProfile.InsightCount) + $tenantSettingsHash.Add('AdaptiveProtectionHighProfileInsightTypes', [Array]($highProfile.InsightTypes)) + $tenantSettingsHash.Add('AdaptiveProtectionHighProfileConfirmedIssue', $highProfile.ConfirmedIssue) + } + + # Medium Profile + if ($null -ne $tenantSettings.DynamicRiskPreventionSettings.DynamicRiskScenarioSettings.MediumProfile) + { + $mediumProfile = $tenantSettings.DynamicRiskPreventionSettings.DynamicRiskScenarioSettings.MediumProfile + $tenantSettingsHash.Add('AdaptiveProtectionMediumProfileSourceType', $mediumProfile.ProfileSourceType) + $tenantSettingsHash.Add('AdaptiveProtectionMediumProfileConfirmedIssueSeverity', $mediumProfile.ConfirmedIssueSeverity) + $tenantSettingsHash.Add('AdaptiveProtectionMediumProfileGeneratedIssueSeverity', $mediumProfile.GeneratedIssueSeverity) + $tenantSettingsHash.Add('AdaptiveProtectionMediumProfileInsightSeverity', $mediumProfile.InsightSeverity) + $tenantSettingsHash.Add('AdaptiveProtectionMediumProfileInsightCount', $mediumProfile.InsightCount) + $tenantSettingsHash.Add('AdaptiveProtectionMediumProfileInsightTypes', [Array]($mediumProfile.InsightTypes)) + $tenantSettingsHash.Add('AdaptiveProtectionMediumProfileConfirmedIssue', $mediumProfile.ConfirmedIssue) + } + + # Low Profile + if ($null -ne $tenantSettings.DynamicRiskPreventionSettings.DynamicRiskScenarioSettings.LowProfile) + { + $lowProfile = $tenantSettings.DynamicRiskPreventionSettings.DynamicRiskScenarioSettings.LowProfile + $tenantSettingsHash.Add('AdaptiveProtectionLowProfileSourceType', $lowProfile.ProfileSourceType) + $tenantSettingsHash.Add('AdaptiveProtectionLowProfileConfirmedIssueSeverity', $lowProfile.ConfirmedIssueSeverity) + $tenantSettingsHash.Add('AdaptiveProtectionLowProfileGeneratedIssueSeverity', $lowProfile.GeneratedIssueSeverity) + $tenantSettingsHash.Add('AdaptiveProtectionLowProfileInsightSeverity', $lowProfile.InsightSeverity) + $tenantSettingsHash.Add('AdaptiveProtectionLowProfileInsightCount', $lowProfile.InsightCount) + $tenantSettingsHash.Add('AdaptiveProtectionLowProfileInsightTypes', [Array]($lowProfile.InsightTypes)) + $tenantSettingsHash.Add('AdaptiveProtectionLowProfileConfirmedIssue', $lowProfile.ConfirmedIssue) + } + + $tenantSettingsHash.Add('ProfileInScopeTimeSpan', $tenantSettings.DynamicRiskPreventionSettings.ProfileInScopeTimeSpan) + $tenantSettingsHash.Add('LookbackTimeSpan', $tenantSettings.DynamicRiskPreventionSettings.LookbackTimeSpan) + $tenantSettingsHash.Add('RetainSeverityAfterTriage', $tenantSettings.DynamicRiskPreventionSettings.RetainSeverityAfterTriage) } $tenantSettingsHash.Add('AdaptiveProtectionEnabled', $AdaptiveProtectionEnabledValue) @@ -1477,6 +1617,102 @@ function Set-TargetResource [System.Boolean] $AdaptiveProtectionEnabled, + [Parameter()] + [System.UInt32] + $AdaptiveProtectionHighProfileSourceType, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionHighProfileConfirmedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionHighProfileGeneratedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionHighProfileInsightSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionHighProfileInsightCount, + + [Parameter()] + [System.String[]] + $AdaptiveProtectionHighProfileInsightTypes, + + [Parameter()] + [System.Boolean] + $AdaptiveProtectionHighProfileConfirmedIssue, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionMediumProfileSourceType, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionMediumProfileConfirmedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionMediumProfileGeneratedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionMediumProfileInsightSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionMediumProfileInsightCount, + + [Parameter()] + [System.String[]] + $AdaptiveProtectionMediumProfileInsightTypes, + + [Parameter()] + [System.Boolean] + $AdaptiveProtectionMediumProfileConfirmedIssue, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionLowProfileSourceType, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionLowProfileConfirmedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionLowProfileGeneratedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionLowProfileInsightSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionLowProfileInsightCount, + + [Parameter()] + [System.String[]] + $AdaptiveProtectionLowProfileInsightTypes, + + [Parameter()] + [System.Boolean] + $AdaptiveProtectionLowProfileConfirmedIssue, + + [Parameter()] + [System.UInt32] + $ProfileInscopeTimeSpan, + + [Parameter()] + [System.UInt32] + $LookbackTimeSpan, + + [Parameter()] + [System.Boolean] + $RetainSeverityAfterTriage, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -1594,7 +1830,11 @@ function Set-TargetResource { $AdaptiveProtectionActivatonStatus = 0 } - $dynamicRiskPreventionSettings = "{`"ProfileInScopeTimeSpan`":7, `"LoopbackTimeSpan`":7, `"DynamicRiskScenarioSettings`":[{`"ActivationStatus`":$AdaptiveProtectionActivatonStatus}]}" + $dynamicRiskPreventionSettings = "{`"RetainSeverityAfterTriage`":$($RetainSeverityAfterTriage.ToString().ToLower()),`"ProfileInScopeTimeSpan`":$($ProfileInscopeTimeSpan), `"LookbackTimeSpan`":$($LookbackTimeSpan), `"DynamicRiskScenarioSettings`":[{`"ActivationStatus`":$AdaptiveProtectionActivatonStatus" + $dynamicRiskPreventionSettings += ", `"HighProfile`":{`"ProfileSourceType`":$($AdaptiveProtectionHighProfileSourceType), `"ConfirmedIssueSeverity`":$($AdaptiveProtectionHighProfileConfirmedIssueSeverity), `"GeneratedIssueSeverity`":$($AdaptiveProtectionHighProfileGeneratedIssueSeverity), `"InsightSeverity`": $($AdaptiveProtectionHighProfileInsightSeverity), `"InsightCount`": $($AdaptiveProtectionHighProfileInsightCount), `"InsightTypes`": [`"$($AdaptiveProtectionHighProfileInsightTypes -join '","')`"], `"ConfirmedIssue`": $($AdaptiveProtectionHighProfileConfirmedIssue.ToString().ToLower())}" + $dynamicRiskPreventionSettings += ", `"MediumProfile`":{`"ProfileSourceType`":$($AdaptiveProtectionMediumProfileSourceType), `"ConfirmedIssueSeverity`":$($AdaptiveProtectionMediumProfileConfirmedIssueSeverity), `"GeneratedIssueSeverity`":$($AdaptiveProtectionMediumProfileGeneratedIssueSeverity), `"InsightSeverity`": $($AdaptiveProtectionMediumProfileInsightSeverity), `"InsightCount`": $($AdaptiveProtectionMediumProfileInsightCount), `"InsightTypes`": [`"$($AdaptiveProtectionMediumProfileInsightTypes -join '","')`"], `"ConfirmedIssue`": $($AdaptiveProtectionMediumProfileConfirmedIssue.ToString().ToLower())}" + $dynamicRiskPreventionSettings += ", `"LowProfile`":{`"ProfileSourceType`":$($AdaptiveProtectionLowProfileSourceType), `"ConfirmedIssueSeverity`":$($AdaptiveProtectionLowProfileConfirmedIssueSeverity), `"GeneratedIssueSeverity`":$($AdaptiveProtectionLowProfileGeneratedIssueSeverity), `"InsightSeverity`": $($AdaptiveProtectionLowProfileInsightSeverity), `"InsightCount`": $($AdaptiveProtectionLowProfileInsightCount), `"InsightTypes`": [`"$($AdaptiveProtectionLowProfileInsightTypes -join '","')`"], `"ConfirmedIssue`": $($AdaptiveProtectionLowProfileConfirmedIssue.ToString().ToLower())}" + $dynamicRiskPreventionSettings += '}]}' $tenantSettingsValue += ", `"DynamicRiskPreventionSettings`":$dynamicRiskPreventionSettings" } @@ -2222,6 +2462,102 @@ function Test-TargetResource [System.Boolean] $AdaptiveProtectionEnabled, + [Parameter()] + [System.UInt32] + $AdaptiveProtectionHighProfileSourceType, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionHighProfileConfirmedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionHighProfileGeneratedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionHighProfileInsightSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionHighProfileInsightCount, + + [Parameter()] + [System.String[]] + $AdaptiveProtectionHighProfileInsightTypes, + + [Parameter()] + [System.Boolean] + $AdaptiveProtectionHighProfileConfirmedIssue, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionMediumProfileSourceType, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionMediumProfileConfirmedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionMediumProfileGeneratedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionMediumProfileInsightSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionMediumProfileInsightCount, + + [Parameter()] + [System.String[]] + $AdaptiveProtectionMediumProfileInsightTypes, + + [Parameter()] + [System.Boolean] + $AdaptiveProtectionMediumProfileConfirmedIssue, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionLowProfileSourceType, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionLowProfileConfirmedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionLowProfileGeneratedIssueSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionLowProfileInsightSeverity, + + [Parameter()] + [System.UInt32] + $AdaptiveProtectionLowProfileInsightCount, + + [Parameter()] + [System.String[]] + $AdaptiveProtectionLowProfileInsightTypes, + + [Parameter()] + [System.Boolean] + $AdaptiveProtectionLowProfileConfirmedIssue, + + [Parameter()] + [System.UInt32] + $ProfileInscopeTimeSpan, + + [Parameter()] + [System.UInt32] + $LookbackTimeSpan, + + [Parameter()] + [System.Boolean] + $RetainSeverityAfterTriage, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof index 4f91c8eea5..dccbecd928 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCInsiderRiskPolicy/MSFT_SCInsiderRiskPolicy.schema.mof @@ -145,6 +145,30 @@ class MSFT_SCInsiderRiskPolicy : OMI_BaseResource [Write, Description("Official documentation to come.")] String BandwidthCapInMb; [Write, Description("Official documentation to come.")] String OfflineRecordingStorageLimitInMb; [Write, Description("Determines if Adaptive Protection is enabled for Purview.")] Boolean AdaptiveProtectionEnabled; + [Write, Description("Official documentation to come.")] UInt32 AdaptiveProtectionHighProfileSourceType; + [Write, Description("Official documentation to come.")] UInt32 AdaptiveProtectionHighProfileConfirmedIssueSeverity; + [Write, Description("Official documentation to come.")] UInt32 AdaptiveProtectionHighProfileGeneratedIssueSeverity; + [Write, Description("Official documentation to come.")] UInt32 AdaptiveProtectionHighProfileInsightSeverity; + [Write, Description("Official documentation to come.")] UInt32 AdaptiveProtectionHighProfileInsightCount; + [Write, Description("Official documentation to come.")] String AdaptiveProtectionHighProfileInsightTypes[]; + [Write, Description("Official documentation to come.")] Boolean AdaptiveProtectionHighProfileConfirmedIssue; + [Write, Description("Official documentation to come.")] UInt32 AdaptiveProtectionMediumProfileSourceType; + [Write, Description("Official documentation to come.")] UInt32 AdaptiveProtectionMediumProfileConfirmedIssueSeverity; + [Write, Description("Official documentation to come.")] UInt32 AdaptiveProtectionMediumProfileGeneratedIssueSeverity; + [Write, Description("Official documentation to come.")] UInt32 AdaptiveProtectionMediumProfileInsightSeverity; + [Write, Description("Official documentation to come.")] UInt32 AdaptiveProtectionMediumProfileInsightCount; + [Write, Description("Official documentation to come.")] String AdaptiveProtectionMediumProfileInsightTypes[]; + [Write, Description("Official documentation to come.")] Boolean AdaptiveProtectionMediumProfileConfirmedIssue; + [Write, Description("Official documentation to come.")] UInt32 AdaptiveProtectionLowProfileSourceType; + [Write, Description("Official documentation to come.")] UInt32 AdaptiveProtectionLowProfileConfirmedIssueSeverity; + [Write, Description("Official documentation to come.")] UInt32 AdaptiveProtectionLowProfileGeneratedIssueSeverity; + [Write, Description("Official documentation to come.")] UInt32 AdaptiveProtectionLowProfileInsightSeverity; + [Write, Description("Official documentation to come.")] UInt32 AdaptiveProtectionLowProfileInsightCount; + [Write, Description("Official documentation to come.")] String AdaptiveProtectionLowProfileInsightTypes[]; + [Write, Description("Official documentation to come.")] Boolean AdaptiveProtectionLowProfileConfirmedIssue; + [Write, Description("Official documentation to come.")] Boolean RetainSeverityAfterTriage; + [Write, Description("Official documentation to come.")] UInt32 LookbackTimeSpan; + [Write, Description("Official documentation to come.")] UInt32 ProfileInScopeTimeSpan; [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] 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 eea64f7de6d575209871c0ad1d7562befae83536 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 30 Sep 2024 15:58:36 +0000 Subject: [PATCH 388/465] Updated Resources and Cmdlet documentation pages --- .../SCInsiderRiskPolicy.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/docs/resources/security-compliance/SCInsiderRiskPolicy.md b/docs/docs/resources/security-compliance/SCInsiderRiskPolicy.md index fbf9c1a9dd..960b48328f 100644 --- a/docs/docs/resources/security-compliance/SCInsiderRiskPolicy.md +++ b/docs/docs/resources/security-compliance/SCInsiderRiskPolicy.md @@ -148,6 +148,30 @@ | **BandwidthCapInMb** | Write | String | Official documentation to come. | | | **OfflineRecordingStorageLimitInMb** | Write | String | Official documentation to come. | | | **AdaptiveProtectionEnabled** | Write | Boolean | Determines if Adaptive Protection is enabled for Purview. | | +| **AdaptiveProtectionHighProfileSourceType** | Write | UInt32 | Official documentation to come. | | +| **AdaptiveProtectionHighProfileConfirmedIssueSeverity** | Write | UInt32 | Official documentation to come. | | +| **AdaptiveProtectionHighProfileGeneratedIssueSeverity** | Write | UInt32 | Official documentation to come. | | +| **AdaptiveProtectionHighProfileInsightSeverity** | Write | UInt32 | Official documentation to come. | | +| **AdaptiveProtectionHighProfileInsightCount** | Write | UInt32 | Official documentation to come. | | +| **AdaptiveProtectionHighProfileInsightTypes** | Write | StringArray[] | Official documentation to come. | | +| **AdaptiveProtectionHighProfileConfirmedIssue** | Write | Boolean | Official documentation to come. | | +| **AdaptiveProtectionMediumProfileSourceType** | Write | UInt32 | Official documentation to come. | | +| **AdaptiveProtectionMediumProfileConfirmedIssueSeverity** | Write | UInt32 | Official documentation to come. | | +| **AdaptiveProtectionMediumProfileGeneratedIssueSeverity** | Write | UInt32 | Official documentation to come. | | +| **AdaptiveProtectionMediumProfileInsightSeverity** | Write | UInt32 | Official documentation to come. | | +| **AdaptiveProtectionMediumProfileInsightCount** | Write | UInt32 | Official documentation to come. | | +| **AdaptiveProtectionMediumProfileInsightTypes** | Write | StringArray[] | Official documentation to come. | | +| **AdaptiveProtectionMediumProfileConfirmedIssue** | Write | Boolean | Official documentation to come. | | +| **AdaptiveProtectionLowProfileSourceType** | Write | UInt32 | Official documentation to come. | | +| **AdaptiveProtectionLowProfileConfirmedIssueSeverity** | Write | UInt32 | Official documentation to come. | | +| **AdaptiveProtectionLowProfileGeneratedIssueSeverity** | Write | UInt32 | Official documentation to come. | | +| **AdaptiveProtectionLowProfileInsightSeverity** | Write | UInt32 | Official documentation to come. | | +| **AdaptiveProtectionLowProfileInsightCount** | Write | UInt32 | Official documentation to come. | | +| **AdaptiveProtectionLowProfileInsightTypes** | Write | StringArray[] | Official documentation to come. | | +| **AdaptiveProtectionLowProfileConfirmedIssue** | Write | Boolean | Official documentation to come. | | +| **RetainSeverityAfterTriage** | Write | Boolean | Official documentation to come. | | +| **LookbackTimeSpan** | Write | UInt32 | Official documentation to come. | | +| **ProfileInScopeTimeSpan** | Write | UInt32 | Official documentation to come. | | | **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Absent`, `Present` | | **Credential** | Write | PSCredential | Credentials of the workload's Admin | | | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | From 77956ee24f2fba85e61fbcfb0e693c021bf12df5 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 30 Sep 2024 16:00:33 +0000 Subject: [PATCH 389/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index f5f4fea5ad..d715b93298 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -41237,6 +41237,126 @@ "Name": "AdaptiveProtectionEnabled", "Option": "Write" }, + { + "CIMType": "UInt32", + "Name": "AdaptiveProtectionHighProfileSourceType", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AdaptiveProtectionHighProfileConfirmedIssueSeverity", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AdaptiveProtectionHighProfileGeneratedIssueSeverity", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AdaptiveProtectionHighProfileInsightSeverity", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AdaptiveProtectionHighProfileInsightCount", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AdaptiveProtectionHighProfileInsightTypes", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AdaptiveProtectionHighProfileConfirmedIssue", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AdaptiveProtectionMediumProfileSourceType", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AdaptiveProtectionMediumProfileConfirmedIssueSeverity", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AdaptiveProtectionMediumProfileGeneratedIssueSeverity", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AdaptiveProtectionMediumProfileInsightSeverity", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AdaptiveProtectionMediumProfileInsightCount", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AdaptiveProtectionMediumProfileInsightTypes", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AdaptiveProtectionMediumProfileConfirmedIssue", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AdaptiveProtectionLowProfileSourceType", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AdaptiveProtectionLowProfileConfirmedIssueSeverity", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AdaptiveProtectionLowProfileGeneratedIssueSeverity", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AdaptiveProtectionLowProfileInsightSeverity", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "AdaptiveProtectionLowProfileInsightCount", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AdaptiveProtectionLowProfileInsightTypes", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "AdaptiveProtectionLowProfileConfirmedIssue", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "RetainSeverityAfterTriage", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "LookbackTimeSpan", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "ProfileInScopeTimeSpan", + "Option": "Write" + }, { "CIMType": "string", "Name": "Ensure", From d6c27824528337bcd4661f386f31bfad3fd9b932 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Mon, 30 Sep 2024 13:10:32 -0700 Subject: [PATCH 390/465] get, update, remove worked. --- .../MSFT_IntuneAppCategories.psm1 | 33 ++++++++++++++----- .../MSFT_IntuneAppCategories.schema.mof | 5 +-- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 index 9d62124a4f..b3cfae2a73 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 @@ -6,7 +6,7 @@ function Get-TargetResource ( #region Intune params - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Id, @@ -37,6 +37,10 @@ function Get-TargetResource [System.String] $CertificateThumbprint, + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + [Parameter()] [Switch] $ManagedIdentity, @@ -100,6 +104,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret ManagedIdentity = $ManagedIdentity.IsPresent AccessTokens = $AccessTokens } @@ -125,7 +130,7 @@ function Set-TargetResource ( #region Intune params - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Id, @@ -156,6 +161,10 @@ function Set-TargetResource [System.String] $CertificateThumbprint, + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + [Parameter()] [Switch] $ManagedIdentity, @@ -189,12 +198,13 @@ function Set-TargetResource # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - Update-MgBetaDeviceAppManagementMobileAppCategory @SetParameters + Update-MgBetaDeviceAppManagementMobileAppCategory -MobileAppCategoryId $currentInstance.Id @SetParameters } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - Remove-MgBetaDeviceAppManagementMobileAppCategory @SetParameters + Remove-MgBetaDeviceAppManagementMobileAppCategory -MobileAppCategoryId $currentInstance.Id -Confirm:$false + #Remove-MgBetaDeviceAppManagementMobileAppCategory @SetParameters - didn't work as it didn't find -Id param } } @@ -206,7 +216,7 @@ function Test-TargetResource ( #region Intune params - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Id, @@ -237,6 +247,10 @@ function Test-TargetResource [System.String] $CertificateThumbprint, + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + [Parameter()] [Switch] $ManagedIdentity, @@ -292,14 +306,14 @@ function Export-TargetResource [System.String] $TenantId, - [Parameter()] - [System.Management.Automation.PSCredential] - $ApplicationSecret, - [Parameter()] [System.String] $CertificateThumbprint, + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + [Parameter()] [Switch] $ManagedIdentity, @@ -351,6 +365,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ApplicationSecret = $ApplicationSecret ManagedIdentity = $ManagedIdentity.IsPresent AccessTokens = $AccessTokens } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof index 5385b5cf69..6c44219ba5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof @@ -1,14 +1,15 @@ [ClassVersion("1.0.0.0"), FriendlyName("IntuneAppCategories")] class MSFT_IntuneAppCategories : OMI_BaseResource { - [Write, Description("The unique identifier for an entity. Read-only.")] String Id; [Key, Description("The name of the app category.")] String DisplayName; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; - [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; + [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; [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; [Write, Description("Access token used for authentication.")] String AccessTokens[]; }; From 492154b66f1b4c4f24a9f57fb9ebf76b9e25b3bc Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 30 Sep 2024 16:34:19 -0400 Subject: [PATCH 391/465] Get-SCRecordReviewNotificationTemplateConfig --- CHANGELOG.md | 2 + ...ecordReviewNotificationTemplateConfig.psm1 | 381 ++++++++++++++++++ ...eviewNotificationTemplateConfig.schema.mof | 15 + .../readme.md | 6 + .../settings.json | 16 + .../2-Update.ps1 | 36 ++ ...ReviewNotificationTemplateConfig.Tests.ps1 | 113 ++++++ Tests/Unit/Stubs/Microsoft365.psm1 | 31 ++ 8 files changed, 600 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCRecordReviewNotificationTemplateConfig/MSFT_SCRecordReviewNotificationTemplateConfig.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCRecordReviewNotificationTemplateConfig/MSFT_SCRecordReviewNotificationTemplateConfig.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCRecordReviewNotificationTemplateConfig/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCRecordReviewNotificationTemplateConfig/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCRecordReviewNotificationTemplateConfig/2-Update.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCRecordReviewNotificationTemplateConfig.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eb4ebe53b..fc881df5f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,6 +80,8 @@ * Initial release. * SCInsiderRiskPolicy * Initial release. +* SCRecordReviewNotificationTemplateConfig + * Initial release. * SCRoleGroup * Fixes an issue with creation without specifying Displayname * Fixes an issue with Drifts because of returned Role format diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCRecordReviewNotificationTemplateConfig/MSFT_SCRecordReviewNotificationTemplateConfig.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRecordReviewNotificationTemplateConfig/MSFT_SCRecordReviewNotificationTemplateConfig.psm1 new file mode 100644 index 0000000000..0c53f3c54a --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRecordReviewNotificationTemplateConfig/MSFT_SCRecordReviewNotificationTemplateConfig.psm1 @@ -0,0 +1,381 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [ValidateSet('Yes')] + [System.String] + $IsSingleInstance, + + [Parameter()] + [System.Boolean] + $IsCustomizedNotificationTemplate, + + [Parameter()] + [System.Boolean] + $IsCustomizedReminderTemplate, + + [Parameter()] + [System.String] + $CustomizedNotificationDataString, + + [Parameter()] + [System.String] + $CustomizedReminderDataString, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + 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 + try + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances[0] + } + else + { + $instance = Get-RecordReviewNotificationTemplateConfig -ErrorAction Stop + } + if ($null -eq $instance) + { + throw "Couldn't retrieve the Record Management Disposition settings" + } + + $results = @{ + IsSingleInstance = 'Yes' + IsCustomizedNotificationTemplate = $instance.IsCustomizedNotificationTemplate + IsCustomizedReminderTemplate = $instance.IsCustomizedReminderTemplate + CustomizedNotificationDataString = $instance.CustomizedNotificationDataString + CustomizedReminderDataString = $instance.CustomizedReminderDataString + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [ValidateSet('Yes')] + [System.String] + $IsSingleInstance, + + [Parameter()] + [System.Boolean] + $IsCustomizedNotificationTemplate, + + [Parameter()] + [System.Boolean] + $IsCustomizedReminderTemplate, + + [Parameter()] + [System.String] + $CustomizedNotificationDataString, + + [Parameter()] + [System.String] + $CustomizedReminderDataString, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 'Updating the Records Management Disposition settings for Purview' + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $setParameters.Remove('IsSingleInstance') | Out-Null + Set-RecordReviewNotificationTemplateConfig @setParameters +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [ValidateSet('Yes')] + [System.String] + $IsSingleInstance, + + [Parameter()] + [System.Boolean] + $IsCustomizedNotificationTemplate, + + [Parameter()] + [System.Boolean] + $IsCustomizedReminderTemplate, + + [Parameter()] + [System.String] + $CustomizedNotificationDataString, + + [Parameter()] + [System.String] + $CustomizedReminderDataString, + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $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 + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-RecordReviewNotificationTemplateConfig -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $config.Name + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + IsSingleInstance = 'Yes' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_SCRecordReviewNotificationTemplateConfig/MSFT_SCRecordReviewNotificationTemplateConfig.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRecordReviewNotificationTemplateConfig/MSFT_SCRecordReviewNotificationTemplateConfig.schema.mof new file mode 100644 index 0000000000..1713a5828f --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRecordReviewNotificationTemplateConfig/MSFT_SCRecordReviewNotificationTemplateConfig.schema.mof @@ -0,0 +1,15 @@ +[ClassVersion("1.0.0.0"), FriendlyName("SCRecordReviewNotificationTemplateConfig")] +class MSFT_SCRecordReviewNotificationTemplateConfig : OMI_BaseResource +{ + [Key, Description("Specifies the resource is a single instance, the value must be 'Yes'"),ValueMap{"Yes"},Values{"Yes"}] String IsSingleInstance; + [Write, Description("The CustomizedNotificationDataString parameter specifies the customized review notification text to use. If the value contains spaces, enclose the value in quotation marks.")] String CustomizedNotificationDataString; + [Write, Description("The CustomizedReminderDataString parameter specifies the customized review reminder text to use. If the value contains spaces, enclose the value in quotation marks.")] String CustomizedReminderDataString; + [Write, Description("The IsCustomizedNotificationTemplate switch specifies whether to use a customized review notification instead of the system default notification.")] Boolean IsCustomizedNotificationTemplate; + [Write, Description("The IsCustomizedReminderTemplate switch specifies whether to use a customized review reminder instead of the system default reminder.")] Boolean IsCustomizedReminderTemplate; + [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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCRecordReviewNotificationTemplateConfig/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRecordReviewNotificationTemplateConfig/readme.md new file mode 100644 index 0000000000..ae0f575028 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRecordReviewNotificationTemplateConfig/readme.md @@ -0,0 +1,6 @@ + +# SCRecordReviewNotificationTemplateConfig + +## Description + +Configures Purview Records Management disposition settings. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCRecordReviewNotificationTemplateConfig/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRecordReviewNotificationTemplateConfig/settings.json new file mode 100644 index 0000000000..410be122f2 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCRecordReviewNotificationTemplateConfig/settings.json @@ -0,0 +1,16 @@ +{ + "resourceName": "SCRecordReviewNotificationTemplateConfig", + "description": "Configures Purview Records Management disposition settings.", + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCRecordReviewNotificationTemplateConfig/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCRecordReviewNotificationTemplateConfig/2-Update.ps1 new file mode 100644 index 0000000000..f0e255b64d --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCRecordReviewNotificationTemplateConfig/2-Update.ps1 @@ -0,0 +1,36 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCRecordReviewNotificationTemplateConfig "SCRecordReviewNotificationTemplateConfig" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + CustomizedNotificationDataString = "This is my Notification Message"; + CustomizedReminderDataString = "This is my reminder message"; + IsCustomizedNotificationTemplate = $True; + IsCustomizedReminderTemplate = $True; + IsSingleInstance = "Yes"; + TenantId = $TenantId; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCRecordReviewNotificationTemplateConfig.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCRecordReviewNotificationTemplateConfig.Tests.ps1 new file mode 100644 index 0000000000..f25c01c095 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCRecordReviewNotificationTemplateConfig.Tests.ps1 @@ -0,0 +1,113 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Get-RecordReviewNotificationTemplateConfig -MockWith { + return @{ + IsCustomizedNotificationTemplate = $true + IsCustomizedReminderTemplate = $true + CustomizedNotificationDataString = "This is my Notification Message"; + CustomizedReminderDataString = "This is my reminder message"; + } + } + + Mock -CommandName Set-RecordReviewNotificationTemplateConfig -MockWith { + } + + # 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 instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + CustomizedNotificationDataString = "This is my Notification Message"; + CustomizedReminderDataString = "This is my reminder message"; + IsCustomizedNotificationTemplate = $True; + IsCustomizedReminderTemplate = $True; + IsSingleInstance = "Yes"; + Credential = $Credential; + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + CustomizedNotificationDataString = "This is my Notification Message"; + CustomizedReminderDataString = "This is my reminder message"; + IsCustomizedNotificationTemplate = $False; # drift + IsCustomizedReminderTemplate = $True; + IsSingleInstance = "Yes"; + Credential = $Credential; + } + } + + 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-RecordReviewNotificationTemplateConfig -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 204a864638..6b94f469ef 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -70756,6 +70756,37 @@ function Set-InsiderRiskPolicy ) } +function Get-RecordReviewNotificationTemplateConfig +{ + [CmdletBinding()] + param( + + ) +} + +function Set-RecordReviewNotificationTemplateConfig +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Boolean] + $IsCustomizedReminderTemplate, + + [Parameter()] + [System.String] + $CustomizedNotificationDataString, + + [Parameter()] + [System.String] + $CustomizedReminderDataString, + + [Parameter()] + [System.Boolean] + $IsCustomizedNotificationTemplate + ) +} + + function Get-AdminAuditLogConfig { [CmdletBinding()] From 33da1b25afb237a1c8a3d6193c75f8ec1c4d5f72 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 30 Sep 2024 20:48:58 +0000 Subject: [PATCH 392/465] Updated Resources and Cmdlet documentation pages --- ...CRecordReviewNotificationTemplateConfig.md | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 docs/docs/resources/security-compliance/SCRecordReviewNotificationTemplateConfig.md diff --git a/docs/docs/resources/security-compliance/SCRecordReviewNotificationTemplateConfig.md b/docs/docs/resources/security-compliance/SCRecordReviewNotificationTemplateConfig.md new file mode 100644 index 0000000000..db06db4c26 --- /dev/null +++ b/docs/docs/resources/security-compliance/SCRecordReviewNotificationTemplateConfig.md @@ -0,0 +1,90 @@ +# SCRecordReviewNotificationTemplateConfig + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **IsSingleInstance** | Key | String | Specifies the resource is a single instance, the value must be 'Yes' | `Yes` | +| **CustomizedNotificationDataString** | Write | String | The CustomizedNotificationDataString parameter specifies the customized review notification text to use. If the value contains spaces, enclose the value in quotation marks. | | +| **CustomizedReminderDataString** | Write | String | The CustomizedReminderDataString parameter specifies the customized review reminder text to use. If the value contains spaces, enclose the value in quotation marks. | | +| **IsCustomizedNotificationTemplate** | Write | Boolean | The IsCustomizedNotificationTemplate switch specifies whether to use a customized review notification instead of the system default notification. | | +| **IsCustomizedReminderTemplate** | Write | Boolean | The IsCustomizedReminderTemplate switch specifies whether to use a customized review reminder instead of the system default reminder. | | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Configures Purview Records Management disposition settings. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SCRecordReviewNotificationTemplateConfig "SCRecordReviewNotificationTemplateConfig" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + CustomizedNotificationDataString = "This is my Notification Message"; + CustomizedReminderDataString = "This is my reminder message"; + IsCustomizedNotificationTemplate = $True; + IsCustomizedReminderTemplate = $True; + IsSingleInstance = "Yes"; + TenantId = $TenantId; + } + } +} +``` + From 7294ab7beba269c0b633be0fe3193b764e08ff40 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 30 Sep 2024 20:51:08 +0000 Subject: [PATCH 393/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index d715b93298..e0a5d13661 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -41709,6 +41709,66 @@ } ] }, + { + "ClassName": "MSFT_SCRecordReviewNotificationTemplateConfig", + "Parameters": [ + { + "CIMType": "String", + "Name": "IsSingleInstance", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "CustomizedNotificationDataString", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CustomizedReminderDataString", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsCustomizedNotificationTemplate", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "IsCustomizedReminderTemplate", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_SCRetentionCompliancePolicy", "Parameters": [ From 2b9936868a336edf2826f69c7a62b5419240e4e6 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Mon, 30 Sep 2024 14:04:16 -0700 Subject: [PATCH 394/465] updated some tests. --- .../Resources/IntuneAppCategory/1-Create.ps1 | 2 +- .../Resources/IntuneAppCategory/2-Update.ps1 | 2 +- .../Resources/IntuneAppCategory/3-Remove.ps1 | 2 +- ...icrosoft365DSC.IntuneAppCategory.Tests.ps1 | 5 +++-- Tests/Unit/Stubs/Microsoft365.psm1 | 20 ++++++++++++++++--- 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 index 04adeaa55e..50de51708c 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 @@ -23,7 +23,7 @@ Configuration Example node localhost { Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Books & Reference"; + DisplayName = "Custom Books & Reference"; Ensure = "Present"; } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 index 04adeaa55e..aab5cae4c6 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 @@ -23,7 +23,7 @@ Configuration Example node localhost { Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Books & Reference"; + DisplayName = "Custom Books & Reference updated"; Ensure = "Present"; } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 index c3dc576a85..cac96fb063 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 @@ -23,7 +23,7 @@ Configuration Example node localhost { Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Books & Reference"; + DisplayName = "Custom Books & Reference"; Ensure = "Absent"; } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 index 4097fc5c5d..189da98a56 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 @@ -52,7 +52,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $Script:ExportMode = $false } - # Test contexts + #Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ @@ -172,7 +173,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { return @{ Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Books & Reference"; + DisplayName = "Custom Books & Reference sample category"; } } } diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 11385cd7cb..824ff71c85 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -37636,12 +37636,26 @@ function Update-MgBetaTeamChannelTab #region Microsoft.Graph.deviceManagement -function Get-MgBetaDeviceAppManagementMobileAppCategory +function New-MgBetaDeviceAppManagementMobileAppCategory { [CmdletBinding()] param( + [Parameter()] + [System.String] + $Id, + [Parameter(Mandatory = $true)] [System.String] + $DisplayName + ) +} + +function Get-MgBetaDeviceAppManagementMobileAppCategory +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] $Id, [Parameter(Mandatory = $true)] @@ -37654,7 +37668,7 @@ function Update-MgBetaDeviceAppManagementMobileAppCategory { [CmdletBinding()] param( - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Id, @@ -37668,7 +37682,7 @@ function Remove-MgBetaDeviceAppManagementMobileAppCategory { [CmdletBinding()] param( - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Id, From cc06f2e5e24f89486714f8af192e0c539150064a Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Mon, 30 Sep 2024 17:52:20 -0700 Subject: [PATCH 395/465] Changed the resource name to singular. Made Display name is mandatory param. Some UTs working locally. --- .../MSFT_IntuneAppCategory.psm1} | 7 +- .../MSFT_IntuneAppCategory.schema.mof} | 4 +- .../readme.md | 2 +- .../settings.json | 2 +- .../Resources/IntuneAppCategory/1-Create.ps1 | 2 +- .../Resources/IntuneAppCategory/2-Update.ps1 | 2 +- .../Resources/IntuneAppCategory/3-Remove.ps1 | 2 +- ...icrosoft365DSC.IntuneAppCategory.Tests.ps1 | 78 ++++++++++--------- ...osoft365DSC.IntuneDeviceCategory.Tests.ps1 | 24 +++--- 9 files changed, 64 insertions(+), 59 deletions(-) rename Modules/Microsoft365DSC/DSCResources/{MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 => MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.psm1} (98%) rename Modules/Microsoft365DSC/DSCResources/{MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof => MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof} (91%) rename Modules/Microsoft365DSC/DSCResources/{MSFT_IntuneAppCategories => MSFT_IntuneAppCategory}/readme.md (86%) rename Modules/Microsoft365DSC/DSCResources/{MSFT_IntuneAppCategories => MSFT_IntuneAppCategory}/settings.json (95%) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.psm1 similarity index 98% rename from Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 rename to Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.psm1 index b3cfae2a73..553e4d0183 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.psm1 @@ -70,12 +70,15 @@ function Get-TargetResource try { + $instance = null if ($null -ne $Script:exportedInstances -and $Script:ExportMode) { $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} } - else { - $instance = Get-MgBetaDeviceAppManagementMobileAppCategory -MobileAppCategoryId $Id -ErrorAction Stop + + if ($null -eq $instance) + { + $instance = Get-MgBetaDeviceAppManagementMobileAppCategory -MobileAppCategoryId $Id -ErrorAction Stop if ($null -eq $instance) { diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof similarity index 91% rename from Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof rename to Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof index 6c44219ba5..676bc98242 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/MSFT_IntuneAppCategories.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.schema.mof @@ -1,5 +1,5 @@ -[ClassVersion("1.0.0.0"), FriendlyName("IntuneAppCategories")] -class MSFT_IntuneAppCategories : OMI_BaseResource +[ClassVersion("1.0.0.0"), FriendlyName("IntuneAppCategory")] +class MSFT_IntuneAppCategory : OMI_BaseResource { [Key, Description("The name of the app category.")] String DisplayName; [Write, Description("The unique identifier for an entity. Read-only.")] String Id; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/readme.md similarity index 86% rename from Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/readme.md rename to Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/readme.md index 6a45c9566d..bf34aa3b26 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/readme.md @@ -1,5 +1,5 @@ -# IntuneAppCategories +# IntuneAppCategory ## Description diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/settings.json similarity index 95% rename from Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/settings.json rename to Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/settings.json index 9fff933f93..cd9e8d4d50 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategories/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/settings.json @@ -1,5 +1,5 @@ { - "resourceName": "IntuneAppCategories", + "resourceName": "IntuneAppCategory", "description": "Configures a resource for navigation property for Intune mobile app categories.", "permissions": { "graph": { diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 index 50de51708c..63f2756cf6 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 @@ -22,7 +22,7 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; DisplayName = "Custom Books & Reference"; Ensure = "Present"; } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 index aab5cae4c6..f37a514980 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 @@ -22,7 +22,7 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; DisplayName = "Custom Books & Reference updated"; Ensure = "Present"; } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 index cac96fb063..f0274ea05b 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 @@ -22,7 +22,7 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; DisplayName = "Custom Books & Reference"; Ensure = "Absent"; } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 index 189da98a56..4d329f384a 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 @@ -54,13 +54,13 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { #Test contexts - Context -Name "The instance should exist but it DOES NOT" -Fixture { + Context -Name '1. The instance should exist but it DOES NOT' -Fixture { BeforeAll { $testParams = @{ - Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Books & Reference"; + Id = 'f1fc9fe2-728d-4867-9a72-a61e18f8c606' + DisplayName = 'Books & Reference' Ensure = 'Present' - Credential = $Credential; + Credential = $Credential } Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { @@ -68,117 +68,119 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } - It 'Should return Values from the Get method' { + It '1.1 Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' } - It 'Should return false from the Test method' { + It '1.2 Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - It 'Should create a new instance from the Set method' { + It '1.3 Should create a new instance from the Set method' { Set-TargetResource @testParams Should -Invoke -CommandName New-MgBetaDeviceAppManagementMobileAppCategory -Exactly 1 } } - Context -Name "The instance exists but it SHOULD NOT" -Fixture { + Context -Name '2. The instance exists but it SHOULD NOT' -Fixture { BeforeAll { $testParams = @{ - Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Books & Reference"; - Ensure = 'Absent' - Credential = $Credential; + Id = 'f1fc9fe2-728d-4867-9a72-a61e18f8c606' + DisplayName = 'Books & Reference' + Ensure = 'Present' + Credential = $Credential } Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { return @{ - Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Books & Reference"; + Id = 'f1fc9fe2-728d-4867-9a72-a61e18f8c606' + DisplayName = 'Books & Reference' } } } - It 'Should return Values from the Get method' { + It '2.1 Should return values from the Get method' { + + $kjl = $testParams (Get-TargetResource @testParams).Ensure | Should -Be 'Present' } - It 'Should return false from the Test method' { + It '2.2 Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - It 'Should remove the instance from the Set method' { + It '2.3 Should remove the instance from the Set method' { Set-TargetResource @testParams Should -Invoke -CommandName Remove-MgBetaDeviceAppManagementMobileAppCategory -Exactly 1 } } - Context -Name "The instance exists and values are already in the desired state" -Fixture { + Context -Name '3. The instance exists and values are already in the desired state' -Fixture { BeforeAll { $testParams = @{ - Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Books & Reference"; + Id = 'f1fc9fe2-728d-4867-9a72-a61e18f8c606' + DisplayName = 'Books & Reference' Ensure = 'Present' - Credential = $Credential; + Credential = $Credential } Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { return @{ - Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Books & Reference"; + Id = 'f1fc9fe2-728d-4867-9a72-a61e18f8c606' + DisplayName = 'Books & Reference' } } } - It 'Should return true from the Test method' { + It '3.0 Should return true from the Test method' { Test-TargetResource @testParams | Should -Be $true } } - Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + Context -Name '4. The instance exists and values are NOT in the desired state' -Fixture { BeforeAll { $testParams = @{ - Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Books & Reference"; + Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606" + DisplayName = "Books & Reference" Ensure = 'Present' - Credential = $Credential; + Credential = $Credential } Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { return @{ - Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Books & Reference"; + Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606" + DisplayName = "Books & Reference" } } } - It 'Should return Values from the Get method' { + It '4.1 Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Present' } - It 'Should return false from the Test method' { + It '4.2 Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - It 'Should call the Set method' { + It '4.3 Should call the Set method' { Set-TargetResource @testParams Should -Invoke -CommandName Update-MgBetaDeviceAppManagementMobileAppCategory -Exactly 1 } } - Context -Name 'ReverseDSC Tests' -Fixture { + Context -Name '5. ReverseDSC Tests' -Fixture { BeforeAll { $Global:CurrentModeIsExport = $true $Global:PartialExportFileName = "$(New-Guid).partial.ps1" $testParams = @{ - Credential = $Credential; + Credential = $Credential } Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { return @{ - Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Books & Reference sample category"; + Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606" + DisplayName = "Books & Reference" } } } - It 'Should Reverse Engineer resource from the Export method' { + It '5.1 Should Reverse Engineer resource from the Export method' { $result = Export-TargetResource @testParams $result | Should -Not -BeNullOrEmpty } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceCategory.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceCategory.Tests.ps1 index 45d4c1bbc7..86aeb31a54 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceCategory.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceCategory.Tests.ps1 @@ -77,19 +77,19 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } - Context -Name 'When the policy already exists and is NOT in the Desired State' -Fixture { + Context -Name 'When the policy exists and it SHOULD NOT' -Fixture { BeforeAll { $testParams = @{ DisplayName = 'Test Category' Description = 'Test Definition' - Ensure = 'Present' + Ensure = 'Absent' Credential = $Credential } Mock -CommandName Get-MgBetaDeviceManagementDeviceCategory -MockWith { return @{ DisplayName = 'Test Category' - Description = 'Different Value' + Description = 'Test Definition' Id = '12345-12345-12345-12345-12345' } } @@ -99,13 +99,13 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { (Get-TargetResource @testParams).Ensure | Should -Be 'Present' } - It 'Should return false from the Test method' { + It 'Should return true from the Test method' { Test-TargetResource @testParams | Should -Be $false } - It 'Should update the category from the Set method' { + It 'Should remove the category from the Set method' { Set-TargetResource @testParams - Should -Invoke -CommandName Update-MgBetaDeviceManagementDeviceCategory -Exactly 1 + Should -Invoke -CommandName Remove-MgBetaDeviceManagementDeviceCategory -Exactly 1 } } @@ -132,19 +132,19 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } - Context -Name 'When the policy exists and it SHOULD NOT' -Fixture { + Context -Name 'When the policy already exists and is NOT in the Desired State' -Fixture { BeforeAll { $testParams = @{ DisplayName = 'Test Category' Description = 'Test Definition' - Ensure = 'Absent' + Ensure = 'Present' Credential = $Credential } Mock -CommandName Get-MgBetaDeviceManagementDeviceCategory -MockWith { return @{ DisplayName = 'Test Category' - Description = 'Test Definition' + Description = 'Different Value' Id = '12345-12345-12345-12345-12345' } } @@ -154,13 +154,13 @@ 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 } - It 'Should remove the category from the Set method' { + It 'Should update the category from the Set method' { Set-TargetResource @testParams - Should -Invoke -CommandName Remove-MgBetaDeviceManagementDeviceCategory -Exactly 1 + Should -Invoke -CommandName Update-MgBetaDeviceManagementDeviceCategory -Exactly 1 } } From 7f3bac78a7360f9c70107318f3e384354855ea28 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Mon, 30 Sep 2024 20:50:52 -0700 Subject: [PATCH 396/465] changed logs change. --- CHANGELOG.md | 2 ++ .../Resources/IntuneAppCategory/1-Create.ps1 | 2 +- .../Resources/IntuneAppCategory/2-Update.ps1 | 2 +- .../Resources/IntuneAppCategory/3-Remove.ps1 | 2 +- ...icrosoft365DSC.IntuneAppCategory.Tests.ps1 | 32 +++++++++---------- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d42af4e80..b1e1d8f4f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* IntuneAppCategory + * Initial release. * AADEntitlementManagementSettings * Initial release. * AADPasswordRuleSettings diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 index 63f2756cf6..aaeaa15cb1 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 @@ -23,7 +23,7 @@ Configuration Example node localhost { Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Books & Reference"; + DisplayName = "Custom Data Management"; Ensure = "Present"; } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 index f37a514980..62e08806c9 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 @@ -23,7 +23,7 @@ Configuration Example node localhost { Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Books & Reference updated"; + DisplayName = "Custom Data Management updated"; Ensure = "Present"; } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 index f0274ea05b..c75c649e10 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 @@ -23,7 +23,7 @@ Configuration Example node localhost { Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Books & Reference"; + DisplayName = "Custom Data Management"; Ensure = "Absent"; } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 index 4d329f384a..3eb5b9cf7f 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 @@ -57,8 +57,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name '1. The instance should exist but it DOES NOT' -Fixture { BeforeAll { $testParams = @{ - Id = 'f1fc9fe2-728d-4867-9a72-a61e18f8c606' - DisplayName = 'Books & Reference' + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' Ensure = 'Present' Credential = $Credential } @@ -83,16 +83,16 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name '2. The instance exists but it SHOULD NOT' -Fixture { BeforeAll { $testParams = @{ - Id = 'f1fc9fe2-728d-4867-9a72-a61e18f8c606' - DisplayName = 'Books & Reference' + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' Ensure = 'Present' Credential = $Credential } Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { return @{ - Id = 'f1fc9fe2-728d-4867-9a72-a61e18f8c606' - DisplayName = 'Books & Reference' + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' } } } @@ -114,16 +114,16 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name '3. The instance exists and values are already in the desired state' -Fixture { BeforeAll { $testParams = @{ - Id = 'f1fc9fe2-728d-4867-9a72-a61e18f8c606' - DisplayName = 'Books & Reference' + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' Ensure = 'Present' Credential = $Credential } Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { return @{ - Id = 'f1fc9fe2-728d-4867-9a72-a61e18f8c606' - DisplayName = 'Books & Reference' + Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' + DisplayName = 'Data Management' } } } @@ -136,16 +136,16 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name '4. The instance exists and values are NOT in the desired state' -Fixture { BeforeAll { $testParams = @{ - Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606" - DisplayName = "Books & Reference" + Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" + DisplayName = "Data Management" Ensure = 'Present' Credential = $Credential } Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { return @{ - Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606" - DisplayName = "Books & Reference" + Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" + DisplayName = "Data Management" } } } @@ -174,8 +174,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { return @{ - Id = "f1fc9fe2-728d-4867-9a72-a61e18f8c606" - DisplayName = "Books & Reference" + Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" + DisplayName = "Data Management" } } } From 5a6680c439ae1d00a5a1cc05940b3fa693f3fc1d Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Tue, 1 Oct 2024 10:50:35 +0200 Subject: [PATCH 397/465] Removed code that purports to assign licenses to a new group but is never executed due to an unassigned variable. Any licenses are assigned afterwards when Ensure equals 'Present'. Expanded unit-tests to include AssignedLicenses --- .../MSFT_AADGroup/MSFT_AADGroup.psm1 | 4 - .../Microsoft365DSC.AADGroup.Tests.ps1 | 387 ++++++++++++++++-- 2 files changed, 362 insertions(+), 29 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 index b5540084ee..a342d7d613 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 @@ -591,10 +591,6 @@ function Set-TargetResource -Source $MyInvocation.MyCommand.ModuleName } } - if ($assignedLicensesGUIDs.Length -gt 0) - { - Set-MgGroupLicense -GroupId $currentGroup.Id -AddLicenses $licensesToAdd -RemoveLicenses @() - } } if ($Ensure -eq 'Present') { diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADGroup.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADGroup.Tests.ps1 index 87431e0b50..ea04994692 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADGroup.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADGroup.Tests.ps1 @@ -36,8 +36,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgGroupMember -MockWith { } - Mock -CommandName Get-MgBetaGroupMember -MockWith { - } Mock -CommandName Get-MgGroup -MockWith { } @@ -53,12 +51,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgGroupOwner -MockWith { } - Mock -CommandName Get-MgBetaGroupMemberOf -MockWith { - } - - Mock -CommandName Get-MgBetaGroupOwner -MockWith { - } - Mock -CommandName Invoke-MgGraphRequest -MockWith { } @@ -74,15 +66,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName New-MgGroupOwnerByRef -MockWith { } - Mock -CommandName New-MgGroupMember -MockWith { } - - Mock -CommandName New-MgBetaGroupOwnerByRef -MockWith { + Mock -CommandName New-MgGroupMember -MockWith { } - - Mock -CommandName New-MgBetaGroupMemberByRef -MockWith { - } - - Mock -CommandName New-MgBetaGroupMember -MockWith {} Mock -CommandName New-MgBetaDirectoryRoleMemberByRef -MockWith { } @@ -96,6 +81,12 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Remove-MgBetaDirectoryRoleMemberDirectoryObjectByRef -MockWith { } + Mock -CommandName Invoke-MgGraphRequest -MockWith { + } + + Mock -CommandName Set-MgGroupLicense -MockWith { + } + # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { } @@ -255,7 +246,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { GroupTypes = @() } } - Mock -CommandName Get-MgBetaGroupMemberOf -MockWith { + Mock -CommandName Get-MgGroupMemberOf -MockWith { return @{ AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.group' @@ -282,7 +273,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return Values from the Get method' { Get-TargetResource @testParams Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 - Should -Invoke -CommandName 'Get-MgBetaGroupMemberOf' -Exactly 1 + Should -Invoke -CommandName 'Get-MgGroupMemberOf' -Exactly 1 } It 'Should return true from the Test method' { @@ -323,7 +314,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { IsAssignableToRole = $true } } - Mock -CommandName Get-MgBetaGroupMemberOf -MockWith { + Mock -CommandName Get-MgGroupMemberOf -MockWith { return @{ AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.directoryRole' @@ -336,7 +327,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return Values from the Get method' { Get-TargetResource @testParams Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 - Should -Invoke -CommandName 'Get-MgBEtaGroupMemberOf' -Exactly 1 + Should -Invoke -CommandName 'Get-MgGroupMemberOf' -Exactly 1 } It 'Should return true from the Test method' { @@ -444,7 +435,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return Values from the Get method' { Get-TargetResource @testParams Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 - Should -Invoke -CommandName 'Get-MgBetaGroupMemberOf' -Exactly 1 + Should -Invoke -CommandName 'Get-MgGroupMemberOf' -Exactly 1 } It 'Should return false from the Test method' { @@ -554,7 +545,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } - Mock -CommandName New-MgBetaGroupMemberByRef -MockWith { + Mock -CommandName New-MgGroupMemberByRef -MockWith { } } @@ -570,7 +561,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the Set method' { Set-TargetResource @testParams Should -Invoke -CommandName 'Get-MgGroup' -Exactly 2 - Should -Invoke -CommandName 'New-MgBetaGroupMemberByRef' -Exactly 1 + Should -Invoke -CommandName 'New-MgGroupMemberByRef' -Exactly 1 #Should -Invoke -CommandName 'Remove-MgGroupMemberDirectoryObjectByRef' -Exactly 1 } } @@ -608,7 +599,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { IsAssignableToRole = $true } } - Mock -CommandName Get-MgBEtaGroupMemberOf -MockWith { + Mock -CommandName Get-MgGroupMemberOf -MockWith { return @{ AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.directoryRole' @@ -627,7 +618,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return Values from the Get method' { Get-TargetResource @testParams Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 - Should -Invoke -CommandName 'Get-MgBetaGroupMemberOf' -Exactly 1 + Should -Invoke -CommandName 'Get-MgGroupMemberOf' -Exactly 1 } It 'Should return false from the Test method' { @@ -642,6 +633,352 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } + Context -Name "The Group does not exist and must be created and assigned a license. Values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + DisplayName = 'DSCGroup' + ID = '12345-12345-12345-12345' + Description = 'Microsoft DSC Group' + SecurityEnabled = $True + MailEnabled = $false + GroupTypes = @() + MailNickname = 'M365DSC' + AssignedLicenses = @( + (New-CimInstance -ClassName MSFT_AADGroupLicense -Property @{ + DisabledPlans = [string[]]@() + SkuId = 'AAD_PREMIUM_P2' + } -ClientOnly) + ) + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return 'Credentials' + } + + Mock -CommandName Get-MgGroup -MockWith { + } + + Mock -CommandName Get-MgBetaSubscribedSku -MockWith { + return [pscustomobject]@{ + ServicePlans = @( + @{ + ServicePlanId = '56789-56789-56789-56789' + ServicePlanName = 'Something_P2' + } + ) + SkuId = '12345-12345-12345-12345' + SkuPartNumber = 'AAD_PREMIUM_P2' + } + } + } + + It 'Should return Values from the Get method' { + Get-TargetResource @testParams + Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 + } + + 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 'New-MgGroup' -Exactly 1 + Should -Invoke -CommandName 'Set-MgGroupLicense' -Exactly 1 + } + } + + Context -Name "The Group exists and has been assigned the correct license. Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + DisplayName = 'DSCGroup' + ID = '12345-12345-12345-12345' + Description = 'Microsoft DSC Group' + SecurityEnabled = $True + MailEnabled = $false + GroupTypes = @() + MailNickname = 'M365DSC' + AssignedLicenses = @( + (New-CimInstance -ClassName MSFT_AADGroupLicense -Property @{ + DisabledPlans = [string[]]@() + SkuId = 'AAD_PREMIUM_P2' + } -ClientOnly) + ) + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return 'Credentials' + } + + Mock -CommandName Get-MgGroup -MockWith { + return @{ + DisplayName = 'DSCGroup' + ID = '12345-12345-12345-12345' + Description = 'Microsoft DSC Group' + SecurityEnabled = $True + MailEnabled = $false + GroupTypes = @() + MailNickname = 'M365DSC' + IsAssignableToRole = $false + } + } + + Mock -CommandName Invoke-MgGraphRequest -MockWith { + return @{ + value = @{ + DisabledPlans = @() + SkuId = '12345-12345-12345' + } + } + } + + Mock -CommandName Get-MgBetaSubscribedSku -MockWith { + return [pscustomobject]@{ + ServicePlans = @( + @{ + ServicePlanId = '67890-67890-67890' + ServicePlanName = 'Something_P2' + } + ) + SkuId = '12345-12345-12345' + SkuPartNumber = 'AAD_PREMIUM_P2' + } + } + } + + It 'Should return Values from the Get method' { + Get-TargetResource @testParams + Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 + Should -Invoke -CommandName 'Invoke-MgGraphRequest' -Exactly 1 + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + Context -Name "The Group exists and has been assigned the correct license but DisabledPlans differ. Values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + DisplayName = 'DSCGroup' + ID = '12345-12345-12345-12345' + Description = 'Microsoft DSC Group' + SecurityEnabled = $True + MailEnabled = $false + GroupTypes = @() + MailNickname = 'M365DSC' + AssignedLicenses = @( + (New-CimInstance -ClassName MSFT_AADGroupLicense -Property @{ + DisabledPlans = [string[]]@() + SkuId = 'AAD_PREMIUM_P2' # is really the SkuPartNumber + } -ClientOnly) + ) + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return 'Credentials' + } + + Mock -CommandName Get-MgGroup -MockWith { + return @{ + DisplayName = 'DSCGroup' + ID = '12345-12345-12345-12345' + Description = 'Microsoft DSC Group' + SecurityEnabled = $True + MailEnabled = $false + GroupTypes = @() + MailNickname = 'M365DSC' + IsAssignableToRole = $false + } + } + + Mock -CommandName Invoke-MgGraphRequest -MockWith { + return @{ + value = @{ + DisabledPlans = @('56789-56789-56789-56789') + SkuId = '23456-23456-23456-23456' + } + } + } + + Mock -CommandName Get-MgBetaSubscribedSku -MockWith { + return [pscustomobject]@{ + ServicePlans = @( + @{ + ServicePlanId = '56789-56789-56789-56789' + ServicePlanName = 'AAD_PREMIUM' + }, + @{ + ServicePlanId = '67890-67890-67890-67890' + ServicePlanName = 'AAD_PREMIUM_P2' + } + ) + SkuId = '23456-23456-23456-23456' + SkuPartNumber = 'AAD_PREMIUM_P2' + } + } + } + + It 'Should return Values from the Get method' { + Get-TargetResource @testParams + Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 + Should -Invoke -CommandName 'Invoke-MgGraphRequest' -Exactly 1 + } + + 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 'Update-MgGroup' -Exactly 1 + Should -Invoke -CommandName 'Set-MgGroupLicense' -Exactly 1 + } + } + Context -Name "The Group exists and is not assigned a license but it should be. Values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + DisplayName = 'DSCGroup' + ID = '12345-12345-12345-12345' + Description = 'Microsoft DSC Group' + SecurityEnabled = $True + MailEnabled = $false + GroupTypes = @() + MailNickname = 'M365DSC' + AssignedLicenses = @( + (New-CimInstance -ClassName MSFT_AADGroupLicense -Property @{ + DisabledPlans = [string[]]@() + SkuId = 'AAD_PREMIUM_P2' + } -ClientOnly) + ) + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return 'Credentials' + } + + Mock -CommandName Get-MgGroup -MockWith { + return @{ + DisplayName = 'DSCGroup' + ID = '12345-12345-12345-12345' + Description = 'Microsoft DSC Group' + SecurityEnabled = $True + MailEnabled = $false + GroupTypes = @() + MailNickname = 'M365DSC' + IsAssignableToRole = $false + } + } + + Mock -CommandName Get-MgBetaSubscribedSku -MockWith { + return [pscustomobject]@{ + ServicePlans = @( + @{ + ServicePlanId = '67890-67890-67890' + ServicePlanName = 'Something_P2' + } + ) + SkuId = '12345-12345-12345' + SkuPartNumber = 'AAD_PREMIUM_P2' + } + } + } + + It 'Should return Values from the Get method' { + Get-TargetResource @testParams + Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 + Should -Invoke -CommandName 'Invoke-MgGraphRequest' -Exactly 1 + } + + 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 'Get-MgGroup' -Exactly 1 + Should -Invoke -CommandName 'Set-MgGroupLicense' -Exactly 1 + } + } + Context -Name "The Group Exists and is assigned a license but it shouldn't be. Values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + DisplayName = 'DSCGroup' + ID = '12345-12345-12345-12345' + Description = 'Microsoft DSC Group' + SecurityEnabled = $True + MailEnabled = $false + GroupTypes = @() + MailNickname = 'M365DSC' + AssignedLicenses = @() + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return 'Credentials' + } + + Mock -CommandName Get-MgGroup -MockWith { + return @{ + DisplayName = 'DSCGroup' + ID = '12345-12345-12345-12345' + Description = 'Microsoft DSC Group' + SecurityEnabled = $True + MailEnabled = $false + GroupTypes = @() + MailNickname = 'M365DSC' + IsAssignableToRole = $false + } + } + + Mock -CommandName Invoke-MgGraphRequest -MockWith { + return @{ + value = @{ + DisabledPlans = @() + SkuId = '12345-12345-12345' + } + } + } + + Mock -CommandName Get-MgBetaSubscribedSku -MockWith { + return [pscustomobject]@{ + ServicePlans = @( + @{ + ServicePlanId = '67890-67890-67890' + ServicePlanName = 'Something_P2' + } + ) + SkuId = '12345-12345-12345' + SkuPartNumber = 'AAD_PREMIUM_P2' + } + } + } + + It 'Should return Values from the Get method' { + Get-TargetResource @testParams + Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 + Should -Invoke -CommandName 'Invoke-MgGraphRequest' -Exactly 1 + } + + 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 'Get-MgGroup' -Exactly 1 + Should -Invoke -CommandName 'Set-MgGroupLicense' -Exactly 1 + } + } + Context -Name 'ReverseDSC Tests' -Fixture { BeforeAll { $Global:CurrentModeIsExport = $true From e646ff7236a9cc7d5d477b4691319141d10b12e7 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 1 Oct 2024 13:35:01 +0000 Subject: [PATCH 398/465] Updated Resources and Cmdlet documentation pages --- .../security-compliance/SCSensitivityLabel.md | 193 ++++++++++++++++++ 1 file changed, 193 insertions(+) diff --git a/docs/docs/resources/security-compliance/SCSensitivityLabel.md b/docs/docs/resources/security-compliance/SCSensitivityLabel.md index 6731ac0fff..6d2c1e8fe0 100644 --- a/docs/docs/resources/security-compliance/SCSensitivityLabel.md +++ b/docs/docs/resources/security-compliance/SCSensitivityLabel.md @@ -48,6 +48,7 @@ | **SiteAndGroupProtectionEnabled** | Write | Boolean | The SiteAndGroupProtectionEnabled parameter enables or disables the Site and Group Protection action for the labels. | | | **SiteAndGroupProtectionPrivacy** | Write | String | The SiteAndGroupProtectionPrivacy parameter specifies the privacy level for the label. | `Public`, `Private`, `Unspecified` | | **SiteAndGroupExternalSharingControlType** | Write | String | The SiteAndGroupExternalSharingControlType parameter specifies the external user sharing setting for the label. | `ExternalUserAndGuestSharing`, `ExternalUserSharingOnly`, `ExistingExternalUserSharingOnly`, `Disabled` | +| **AutoLabelingSettings** | Write | MSFT_SCSLAutoLabelingSettings | The AutoLabelingSettings parameter specifies the conditions for label to be automatically applied to files and emails. | | | **Credential** | Write | PSCredential | Credentials of the Exchange Global Admin | | | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | @@ -56,6 +57,49 @@ | **CertificatePath** | Write | String | Path to certificate used in service principal usually a PFX file. | | | **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | +### MSFT_SCSLSensitiveInformationType + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **name** | Required | String | Name of the Sensitive Information Type | | +| **confidencelevel** | Write | String | Confidence level value for the Sensitive Information | `Low`, `Medium`, `High` | +| **classifiertype** | Write | String | Type of Classifier value for the Sensitive Information | | +| **mincount** | Write | String | Minimum Count value for the Sensitive Information | | +| **maxcount** | Write | String | Maximum Count value for the Sensitive Information | | + +### MSFT_SCSLTrainableClassifiers + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **name** | Required | String | Name of the Trainable Classifier | | +| **id** | Write | String | Id of the Trainable Classifier | | + +### MSFT_SCSLSensitiveInformationGroup + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **SensitiveInformationType** | Write | MSFT_SCSLSensitiveInformationType[] | Sensitive Information Content Types | | +| **TrainableClassifier** | Write | MSFT_SCSLTrainableClassifiers[] | Trainable Classifiers | | +| **Name** | Required | String | Name of the group | | +| **Operator** | Required | String | How to process the Sensitive Information Types and Trainable Classifiers | `And`, `Or` | + +### MSFT_SCSLAutoLabelingSettings + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Groups** | Required | MSFT_SCSLSensitiveInformationGroup[] | Groups of sensitive information types. | | +| **Operator** | Required | String | How to process the various groups | `And`, `Or` | +| **PolicyTip** | Write | String | Display this message to users when the label is applied | | +| **AutoApplyType** | Required | String | Specifies what to do when content matches the conditions | `Automatic`, `Recommend` | + ### MSFT_SCLabelSetting #### Parameters @@ -207,3 +251,152 @@ Configuration Example } ``` +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter(Mandatory = $true)] + [PSCredential] + $Credscredential + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + SCSensitivityLabel 'ConfigureSensitivityLabel' + { + Name = 'DemoLabel' + Comment = 'Demo Label comment' + ToolTip = 'Demo tool tip' + DisplayName = 'Demo Label' + ApplyContentMarkingFooterAlignment = 'Center' + ApplyContentMarkingFooterEnabled = $true + ApplyContentMarkingFooterFontColor = '#FF0000' + ApplyContentMarkingFooterFontSize = 10 + ApplyContentMarkingFooterMargin = 5 + ApplyContentMarkingFooterText = 'Demo footer text' + ApplyContentMarkingHeaderAlignment = 'Center' + ApplyContentMarkingHeaderEnabled = $true + ApplyContentMarkingHeaderFontColor = '#FF0000' + ApplyContentMarkingHeaderFontSize = 10 + ApplyContentMarkingHeaderMargin = 5 + ApplyContentMarkingHeaderText = 'demo header text' + ApplyWaterMarkingEnabled = $true + ApplyWaterMarkingFontColor = '#FF0000' + ApplyWaterMarkingFontSize = 10 + ApplyWaterMarkingLayout = 'Diagonal' + ApplyWaterMarkingText = 'demo watermark' + SiteAndGroupProtectionAllowAccessToGuestUsers = $true + SiteAndGroupProtectionAllowEmailFromGuestUsers = $true + SiteAndGroupProtectionAllowFullAccess = $true + SiteAndGroupProtectionAllowLimitedAccess = $true + SiteAndGroupProtectionBlockAccess = $true + SiteAndGroupProtectionEnabled = $true + SiteAndGroupProtectionPrivacy = 'Private' + LocaleSettings = @( + MSFT_SCLabelLocaleSettings + { + LocaleKey = 'DisplayName' + LabelSettings = @( + MSFT_SCLabelSetting + { + Key = 'en-us' + Value = 'English Display Names' + } + MSFT_SCLabelSetting + { + Key = 'fr-fr' + Value = "Nom da'ffichage francais" + } + ) + } + MSFT_SCLabelLocaleSettings + { + LocaleKey = 'StopColor' + LabelSettings = @( + MSFT_SCLabelSetting + { + Key = 'en-us' + Value = 'RedGreen' + } + MSFT_SCLabelSetting + { + Key = 'fr-fr' + Value = 'Rouge' + } + ) + } + ) + AdvancedSettings = @( + MSFT_SCLabelSetting + { + Key = 'AllowedLevel' + Value = @('Sensitive', 'Classified') + } + MSFT_SCLabelSetting + { + Key = 'LabelStatus' + Value = 'Enabled' + } + ) + AutoLabelingSettings = MSFT_SCSLAutoLabelingSettings + { + Operator = 'And' + AutoApplyType = 'Recommend' + PolicyTip = 'My Perfect Test Tip!' + Groups = @( + MSFT_SCSLSensitiveInformationGroup + { + Name = 'Group1' + Operator = 'Or' + SensitiveInformationType = @( + MSFT_SCSLSensitiveInformationType + { + name = 'ABA Routing Number' + confidencelevel = 'High' + maxcount = -1 + mincount = 1 + } + ) + TrainableClassifier = @( + MSFT_SCSLTrainableClassifiers + { + name = 'Legal Affairs' + } + ) + } + MSFT_SCSLSensitiveInformationGroup + { + Name = 'Group2' + Operator = 'And' + SensitiveInformationType = @( + MSFT_SCSLSensitiveInformationType + { + name = 'All Full Names' + confidencelevel = 'High' + maxcount = 100 + mincount = 10 + } + ) + TrainableClassifier = @( + MSFT_SCSLTrainableClassifiers + { + name = 'Threat' + } + ) + } + ) + } + ParentId = 'Personal' + Ensure = 'Present' + Credential = $Credscredential + } + } +} +``` + From b93aa101c212b4c04023072b7912c0fb77c9ae6b Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 1 Oct 2024 13:37:27 +0000 Subject: [PATCH 399/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index e0a5d13661..273fb20cdc 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -42264,6 +42264,101 @@ } ] }, + { + "ClassName": "MSFT_SCSLSensitiveInformationType", + "Parameters": [ + { + "CIMType": "String", + "Name": "name", + "Option": "Required" + }, + { + "CIMType": "String", + "Name": "confidencelevel", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "classifiertype", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "mincount", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "maxcount", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_SCSLTrainableClassifiers", + "Parameters": [ + { + "CIMType": "String", + "Name": "name", + "Option": "Required" + }, + { + "CIMType": "String", + "Name": "id", + "Option": "Write" + } + ] + }, + { + "ClassName": "MSFT_SCSLSensitiveInformationGroup", + "Parameters": [ + { + "CIMType": "MSFT_SCSLSensitiveInformationType[]", + "Name": "SensitiveInformationType", + "Option": "Write" + }, + { + "CIMType": "MSFT_SCSLTrainableClassifiers[]", + "Name": "TrainableClassifier", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Name", + "Option": "Required" + }, + { + "CIMType": "String", + "Name": "Operator", + "Option": "Required" + } + ] + }, + { + "ClassName": "MSFT_SCSLAutoLabelingSettings", + "Parameters": [ + { + "CIMType": "MSFT_SCSLSensitiveInformationGroup[]", + "Name": "Groups", + "Option": "Required" + }, + { + "CIMType": "String", + "Name": "Operator", + "Option": "Required" + }, + { + "CIMType": "String", + "Name": "PolicyTip", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AutoApplyType", + "Option": "Required" + } + ] + }, { "ClassName": "MSFT_SCLabelLocaleSettings", "Parameters": [ @@ -42502,6 +42597,11 @@ "Name": "SiteAndGroupExternalSharingControlType", "Option": "Write" }, + { + "CIMType": "MSFT_SCSLAutoLabelingSettings", + "Name": "AutoLabelingSettings", + "Option": "Write" + }, { "CIMType": "MSFT_Credential", "Name": "Credential", From c22bd3dd4dfa7d6903a43a62b294d6bf4f5a680b Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 1 Oct 2024 10:17:45 -0400 Subject: [PATCH 400/465] O365ExternalConnection - Initial Release --- CHANGELOG.md | 1 + .../MSFT_O365ExternalConnection.psm1 | 410 ++++++++++++++++++ .../MSFT_O365ExternalConnection.schema.mof | 14 + .../MSFT_O365ExternalConnection/readme.md | 6 + .../MSFT_O365ExternalConnection/settings.json | 32 ++ .../Dependencies/Manifest.psd1 | 4 + .../O365ExternalConnection/1-Create.ps1 | 26 ++ .../O365ExternalConnection/2-Update.ps1 | 26 ++ .../O365ExternalConnection/3-Remove.ps1 | 26 ++ ...oft365DSC.O365ExternalConnection.Tests.ps1 | 177 ++++++++ .../MSFT_ResourceName/MSFT_ResourceName.psm1 | 5 + 11 files changed, 727 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.O365ExternalConnection.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index fc881df5f0..d5862c363f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -96,6 +96,7 @@ * Added dependencies on Az.Accounts, Az.Resources and Az.SecurityInsights * Updated DSCParser to version 2.0.0.9. * Updated MSCloudLoginAssistant to version 1.1.25. + * Added dependency on Microsoft.Graph.Beta.Search. # 1.24.904.1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.psm1 new file mode 100644 index 0000000000..4bae420f7e --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.psm1 @@ -0,0 +1,410 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String[]] + $authorizedAppIds, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + if (-not [System.String]::IsNullOrEmpty($Id)) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} + } + + if ($null -eq $instance) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Name -eq $Name} + } + } + else + { + if (-not [System.String]::IsNullOrEmpty($Id)) + { + $instance = Get-MgBetaExternalConnection -ExternalConnectionId $Id -ErrorAction SilentlyContinue + } + if ($null -eq $instance) + { + $instance = Get-MgBetaExternalConnection -Filter "Name eq '$Name'" + } + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + Name = $instance.Name + Id = $instance.id + Description = $instance.Description + AuthorizedAppIds = [Array] $instance.authorizedAppIds + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String[]] + $authorizedAppIds, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + ##TODO - Replace by the New cmdlet for the resource + New-Cmdlet @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Update/Set cmdlet for the resource + Set-cmdlet @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Remove cmdlet for the resource + Remove-cmdlet @SetParameters + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String[]] + $authorizedAppIds, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -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 + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-MgBetaExternalConnection-ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + $displayedKey = $config.Id + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Name = $config.Name + Id = $config.Id + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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_O365ExternalConnection/MSFT_O365ExternalConnection.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.schema.mof new file mode 100644 index 0000000000..92ead2adaf --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.schema.mof @@ -0,0 +1,14 @@ +[ClassVersion("1.0.0.0"), FriendlyName("O365ExternalConnection")] +class MSFT_O365ExternalConnection : OMI_BaseResource +{ + [Key, Description("")] String PrimaryKey; + [Write, Description("")] String OtherProperties; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] 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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/readme.md new file mode 100644 index 0000000000..32e0e7fb27 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/readme.md @@ -0,0 +1,6 @@ + +# ResourceName + +## Description + +##TODO - Provide a short description of what the resource is set to configure. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/settings.json new file mode 100644 index 0000000000..edf14b05e4 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName": "ResourceName", + "description": "Description of what the resource is about.", + "roles": { + "read": [ + "Role" + ], + "update": [ + "Role" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Permission for Monitoring and Export" + } + ], + "update": [ + { + "name": "Permission for deploying" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 2a27e01195..956ea10abd 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -64,6 +64,10 @@ ModuleName = 'Microsoft.Graph.Beta.Reports' RequiredVersion = '2.23.0' }, + @{ + ModuleName = 'Microsoft.Graph.Beta.Search' + RequiredVersion = '2.23.0' + }, @{ ModuleName = 'Microsoft.Graph.Beta.Teams' RequiredVersion = '2.23.0' diff --git a/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/1-Create.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/1-Create.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/2-Update.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/3-Remove.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/3-Remove.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.O365ExternalConnection.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.O365ExternalConnection.Tests.ps1 new file mode 100644 index 0000000000..f3ddc7d594 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.O365ExternalConnection.Tests.ps1 @@ -0,0 +1,177 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -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 a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Set-TargetResource @testParams + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 remove the instance from the Set method' { + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + 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 + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.psm1 b/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.psm1 index 0990631700..b3846eb047 100644 --- a/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.psm1 +++ b/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.psm1 @@ -319,6 +319,11 @@ function Export-TargetResource } foreach ($config in $Script:exportedInstances) { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + $displayedKey = $config.Id Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline $params = @{ From d7162eb3bbd6795d384013ecdcf73a318fe9a8b5 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 1 Oct 2024 11:11:27 -0400 Subject: [PATCH 401/465] Updates --- .../MSFT_O365ExternalConnection.psm1 | 61 ++- .../MSFT_O365ExternalConnection.schema.mof | 7 +- .../MSFT_O365ExternalConnection/readme.md | 4 +- .../MSFT_O365ExternalConnection/settings.json | 17 +- .../O365ExternalConnection/1-Create.ps1 | 12 +- .../O365ExternalConnection/2-Update.ps1 | 12 +- .../O365ExternalConnection/3-Remove.ps1 | 12 +- .../Modules/M365DSCStubsUtility.psm1 | 1 + ...oft365DSC.O365ExternalConnection.Tests.ps1 | 90 +++- Tests/Unit/Stubs/Microsoft365.psm1 | 484 ++++++++++++++++++ .../Microsoft365DSC.ResourceName.Tests.ps1 | 1 + 11 files changed, 642 insertions(+), 59 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.psm1 index 4bae420f7e..fd8834c6c3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.psm1 @@ -18,7 +18,7 @@ function Get-TargetResource [Parameter()] [System.String[]] - $authorizedAppIds, + $AuthorizedAppIds, [Parameter()] [ValidateSet('Present', 'Absent')] @@ -97,11 +97,25 @@ function Get-TargetResource return $nullResult } + $AuthorizedAppIdsValue = @() + foreach ($app in $instance.Configuration.AuthorizedAppIds) + { + $appInstance = Get-MgApplication -Filter "AppId eq '$app'" -ErrorAction SilentlyContinue + if ($null -ne $appInstance) + { + $AuthorizedAppIdsValue += $appInstance.DisplayName + } + else + { + throw "Could not find referenced application {$app} in the tenant." + } + } + $results = @{ Name = $instance.Name Id = $instance.id Description = $instance.Description - AuthorizedAppIds = [Array] $instance.authorizedAppIds + AuthorizedAppIds = $AuthorizedAppIdsValue Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -144,7 +158,7 @@ function Set-TargetResource [Parameter()] [System.String[]] - $authorizedAppIds, + $AuthorizedAppIds, [Parameter()] [ValidateSet('Present', 'Absent')] @@ -192,23 +206,48 @@ function Set-TargetResource $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $AuthorizedAppIdsValue = @() + if ($null -ne $AuthorizedAppIds) + { + foreach ($app in $AuthorizedAppIds) + { + $app = Get-MgApplication -Filter "DisplayName eq '$app'" -ErrorAction SilentlyContinue + if ($null -ne $app) + { + $AuthorizedAppIdsValue += $app.AppId + } + else + { + throw "Could not find referenced application {$app} in the tenant." + } + } + } + $body = @{ + id = $Id + name = $Name + description = $Description + configuration = @{ + AuthorizedAppIds = $AuthorizedAppIdsValue + } + } # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { - ##TODO - Replace by the New cmdlet for the resource - New-Cmdlet @SetParameters + Write-Verbose -Message "Creating new external connection {$Name}" + New-MgBetaExternalConnection -BodyParameter $body } # UPDATE elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { - ##TODO - Replace by the Update/Set cmdlet for the resource - Set-cmdlet @SetParameters + Write-Verbose -Message "Updating new external connection {$Name}" + $body.Remove('Id') | Out-Null + Update-MgBetaExternalConnection -ExternalConnectionId $currentInstance.Id -BodyParameter $body } # REMOVE elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { - ##TODO - Replace by the Remove cmdlet for the resource - Remove-cmdlet @SetParameters + Write-Verbose -Message "Removing external connection {$Name}" + Remove-MgBetaExternalConnection -ExternalConnectionId $currentInstance.Id -Confirm:$false } } @@ -232,7 +271,7 @@ function Test-TargetResource [Parameter()] [System.String[]] - $authorizedAppIds, + $AuthorizedAppIds, [Parameter()] [ValidateSet('Present', 'Absent')] @@ -345,7 +384,7 @@ function Export-TargetResource try { $Script:ExportMode = $true - [array] $Script:exportedInstances = Get-MgBetaExternalConnection-ErrorAction Stop + [array] $Script:exportedInstances = Get-MgBetaExternalConnection -ErrorAction Stop $i = 1 $dscContent = '' diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.schema.mof index 92ead2adaf..f4bc419014 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.schema.mof @@ -1,9 +1,10 @@ [ClassVersion("1.0.0.0"), FriendlyName("O365ExternalConnection")] class MSFT_O365ExternalConnection : OMI_BaseResource { - [Key, Description("")] String PrimaryKey; - [Write, Description("")] String OtherProperties; - + [Key, Description("The name of the external connector.")] String Name; + [Write, Description("The unique identifier of the external connector.")] String Id; + [Write, Description("The description of the external connector.")] String Description; + [Write, Description("A collection of application IDs for registered Microsoft Entra apps that are allowed to manage the externalConnection and to index content in the externalConnection.")] String AuthorizedAppIds[]; [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] 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; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/readme.md index 32e0e7fb27..f7509cc64a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/readme.md @@ -1,6 +1,6 @@ -# ResourceName +# O365ExternalConnection ## Description -##TODO - Provide a short description of what the resource is set to configure. +Configures external connectors in Microsoft 365. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/settings.json index edf14b05e4..d6e2971178 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/settings.json @@ -1,14 +1,7 @@ { - "resourceName": "ResourceName", - "description": "Description of what the resource is about.", - "roles": { - "read": [ - "Role" - ], - "update": [ - "Role" - ] - }, + "resourceName": "O365ExternalConnection", + "description": "Configures external connectors in Microsoft 365.", + "roles": {}, "permissions": { "graph": { "delegated": { @@ -18,12 +11,12 @@ "application": { "read": [ { - "name": "Permission for Monitoring and Export" + "name": "ExternalConnection.Read.All" } ], "update": [ { - "name": "Permission for deploying" + "name": "ExternalConnection.ReadWrite.All" } ] } diff --git a/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/1-Create.ps1 index b516274848..5e052ad0e2 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/1-Create.ps1 @@ -21,6 +21,16 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + O365ExternalConnection "O365ExternalConnection-Contoso HR" + { + ApplicationId = $ApplicationId; + AuthorizedAppIds = @("MyApp"); + CertificateThumbprint = $CertificateThumbprint; + Description = "Connection to index Contoso HR system"; + Ensure = "Present"; + Id = "contosohr"; + Name = "Contoso HR Nik"; + TenantId = $TenantId; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/2-Update.ps1 index b516274848..36bcc28d21 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/2-Update.ps1 @@ -21,6 +21,16 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + O365ExternalConnection "O365ExternalConnection-Contoso HR" + { + ApplicationId = $ApplicationId; + AuthorizedAppIds = @("MyApp", "MySecondApp"); # Drift + CertificateThumbprint = $CertificateThumbprint; + Description = "Connection to index Contoso HR system"; + Ensure = "Present"; + Id = "contosohr"; + Name = "Contoso HR Nik"; + TenantId = $TenantId; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/3-Remove.ps1 index b516274848..ad9474a857 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/O365ExternalConnection/3-Remove.ps1 @@ -21,6 +21,16 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + O365ExternalConnection "O365ExternalConnection-Contoso HR" + { + ApplicationId = $ApplicationId; + AuthorizedAppIds = @("MyApp"); + CertificateThumbprint = $CertificateThumbprint; + Description = "Connection to index Contoso HR system"; + Ensure = "Absent"; + Id = "contosohr"; + Name = "Contoso HR Nik"; + TenantId = $TenantId; + } } } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCStubsUtility.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCStubsUtility.psm1 index 8a98b55211..e843fe0807 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCStubsUtility.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCStubsUtility.psm1 @@ -60,6 +60,7 @@ function New-M365DSCStubFiles @{Name = 'MicrosoftGraph'; ModuleName = 'Microsoft.Graph.Beta.Identity.DirectoryManagement'}, @{Name = 'MicrosoftGraph'; ModuleName = 'Microsoft.Graph.Beta.Identity.Governance'}, @{Name = 'MicrosoftGraph'; ModuleName = 'Microsoft.Graph.Beta.Identity.SignIns'}, + @{Name = 'MicrosoftGraph'; ModuleName = 'Microsoft.Graph.Beta.Search'}, @{Name = 'MicrosoftGraph'; ModuleName = 'Microsoft.Graph.Beta.Teams'}, @{Name = 'MicrosoftGraph'; ModuleName = 'Microsoft.Graph.DeviceManagement.Administration'}, @{Name = 'MicrosoftGraph'; ModuleName = 'Microsoft.Graph.DirectoryObjects'}, diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.O365ExternalConnection.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.O365ExternalConnection.Tests.ps1 index f3ddc7d594..2b855bff9f 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.O365ExternalConnection.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.O365ExternalConnection.Tests.ps1 @@ -35,7 +35,16 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets + Mock -CommandName Update-MgBetaExternalConnection -MockWith{} + Mock -CommandName New-MgBetaExternalConnection -MockWith{} + Mock -CommandName Remove-MgBetaExternalConnection -MockWith{} + + Mock -CommandName Get-MgApplication -MockWith { + return @{ + DisplayName = 'MyApp' + AppId = "12345-12345-12345-12345-12345" + } + } # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { @@ -47,13 +56,15 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' + AuthorizedAppIds = @("MyApp"); + Description = "Connection to index Contoso HR system"; + Ensure = "Present"; + Id = "contosohr"; + Name = "Contoso HR"; Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaExternalConnection -MockWith { return $null } } @@ -65,24 +76,30 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should create a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one Set-TargetResource @testParams - Should -Invoke -CommandName New-Cmdlet -Exactly 1 + Should -Invoke -CommandName New-MgBetaExternalConnection -Exactly 1 } } Context -Name "The instance exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Absent' + AuthorizedAppIds = @("MyApp"); + Description = "Connection to index Contoso HR system"; + Ensure = "Absent"; + Id = "contosohr"; + Name = "Contoso HR"; Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaExternalConnection -MockWith { return @{ - + Name = 'Contoso Hr' + Id = "contosohr" + Description = 'Connection to index Contoso HR system' + Configuration = @{ + AuthorizedAppIds = @('12345-12345-12345-12345-12345') + } } } } @@ -94,23 +111,30 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should remove the instance from the Set method' { - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaExternalConnection -Exactly 1 } } Context -Name "The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' + AuthorizedAppIds = @("MyApp"); + Description = "Connection to index Contoso HR system"; + Ensure = "Absent"; + Id = "contosohr"; + Name = "Contoso HR"; Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaExternalConnection -MockWith { return @{ - + Name = 'Contoso Hr' + Id = "contosohr" + Description = 'Connection to index Contoso HR system' + Configuration = @{ + AuthorizedAppIds = @('12345-12345-12345-12345-12345') + } } } } @@ -123,15 +147,22 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' + AuthorizedAppIds = @("MyApp"); + Description = "Connection to index Contoso HR system"; + Ensure = "Present"; + Id = "contosohr"; + Name = "Contoso HR Nik"; # drift Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaExternalConnection -MockWith { return @{ - + Name = 'Contoso Hr' + Id = "contosohr" + Description = 'Connection to index Contoso HR system' + Configuration = @{ + AuthorizedAppIds = @('12345-12345-12345-12345-12345') + } } } } @@ -146,8 +177,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the Set method' { Set-TargetResource @testParams - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + Should -Invoke -CommandName Update-MgBetaExternalConnection -Exactly 1 } } @@ -159,10 +189,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance Mock -CommandName Get-Cmdlet -MockWith { return @{ - + Name = 'Contoso Hr' + Id = "contosohr" + Description = 'Connection to index Contoso HR system' + Configuration = @{ + AuthorizedAppIds = @('12345-12345-12345-12345-12345') + } } } } diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 853e8db965..e79c895ab1 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -94157,3 +94157,487 @@ function Update-MgBetaPolicyFeatureRolloutPolicy #endregion +#region Microsoft.Graph.Beta.Search +function Get-MgBetaExternal +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Get-MgBetaExternalConnection +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $CountVariable, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.String] + $ExternalConnectionId, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function New-MgBetaExternalConnection +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $Schema, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String] + $ConnectorId, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $Groups, + + [Parameter()] + [PSObject] + $Items, + + [Parameter()] + [PSObject] + $SearchSettings, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.String] + $EnabledContentExperiences, + + [Parameter()] + [System.String] + $State, + + [Parameter()] + [PSObject] + $ComplianceSettings, + + [Parameter()] + [PSObject] + $Quota, + + [Parameter()] + [PSObject] + $ActivitySettings, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Int64] + $IngestedItemsCount, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [PSObject] + $Operations, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $Configuration, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +function Remove-MgBetaExternalConnection +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.String] + $IfMatch, + + [Parameter()] + [System.String] + $ExternalConnectionId, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Update-MgBetaExternal +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [PSObject] + $Connections, + + [Parameter()] + [PSObject] + $IndustryData, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $HttpPipelineAppend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $AuthorizationSystems, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break + ) +} +function Update-MgBetaExternalConnection +{ + [CmdletBinding()] + param( + [Parameter()] + [PSObject] + $Schema, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [PSObject] + $Groups, + + [Parameter()] + [PSObject] + $Items, + + [Parameter()] + [PSObject] + $SearchSettings, + + [Parameter()] + [PSObject] + $HttpPipelinePrepend, + + [Parameter()] + [System.String] + $EnabledContentExperiences, + + [Parameter()] + [System.String] + $ExternalConnectionId, + + [Parameter()] + [System.String] + $State, + + [Parameter()] + [PSObject] + $ComplianceSettings, + + [Parameter()] + [PSObject] + $Quota, + + [Parameter()] + [PSObject] + $ActivitySettings, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.String] + $ConnectorId, + + [Parameter()] + [System.Int64] + $IngestedItemsCount, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [PSObject] + $Operations, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [PSObject] + $Configuration, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject] + $HttpPipelineAppend + ) +} +#endregion diff --git a/dev-package/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 b/dev-package/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 index f3ddc7d594..780e0f343d 100644 --- a/dev-package/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 +++ b/dev-package/Tests/Unit/Microsoft365DSC/Microsoft365DSC.ResourceName.Tests.ps1 @@ -94,6 +94,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should remove the instance from the Set method' { + Set-TargetResource @testParams ##TODO - Replace the Remove-Cmdlet by the appropriate one Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 } From 1b895d6f8c58294a1ae944d2a281f9887a958908 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 1 Oct 2024 11:14:16 -0400 Subject: [PATCH 402/465] PR ready for merge --- CHANGELOG.md | 2 ++ .../Microsoft365DSC.O365ExternalConnection.Tests.ps1 | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3314cf2c01..a79cd4fe31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,8 @@ * Update export logic to target more specific policy types. * Prevent thrown exception to be caught by exception handler. FIXES [#5088](https://github.com/microsoft/Microsoft365DSC/issues/5088) +* O365ExternalConnection + * Initial release. * SCDeviceConditionalAccessRule * Initial release. * SCDeviceConfigurationRule diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.O365ExternalConnection.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.O365ExternalConnection.Tests.ps1 index 2b855bff9f..f3dac80dd4 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.O365ExternalConnection.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.O365ExternalConnection.Tests.ps1 @@ -121,7 +121,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $testParams = @{ AuthorizedAppIds = @("MyApp"); Description = "Connection to index Contoso HR system"; - Ensure = "Absent"; + Ensure = "Present"; Id = "contosohr"; Name = "Contoso HR"; Credential = $Credential; @@ -189,7 +189,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential; } - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Get-MgBetaExternalConnection -MockWith { return @{ Name = 'Contoso Hr' Id = "contosohr" From 6d81727ca40fa42620754cad751b626dbafa56c4 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 1 Oct 2024 11:41:32 -0400 Subject: [PATCH 403/465] Fixes --- .../MSFT_O365ExternalConnection.schema.mof | 2 +- .../DSCResources/MSFT_ResourceName/MSFT_ResourceName.schema.mof | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.schema.mof index f4bc419014..b3f888c603 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/MSFT_O365ExternalConnection.schema.mof @@ -5,7 +5,7 @@ class MSFT_O365ExternalConnection : OMI_BaseResource [Write, Description("The unique identifier of the external connector.")] String Id; [Write, Description("The description of the external connector.")] String Description; [Write, Description("A collection of application IDs for registered Microsoft Entra apps that are allowed to manage the externalConnection and to index content in the externalConnection.")] String AuthorizedAppIds[]; - [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] 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; diff --git a/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.schema.mof b/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.schema.mof index be6b06c877..fe8aabccae 100644 --- a/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.schema.mof +++ b/dev-package/Modules/Microsoft365DSC/DSCResources/MSFT_ResourceName/MSFT_ResourceName.schema.mof @@ -4,7 +4,7 @@ class MSFT_ResourceName : OMI_BaseResource [Key, Description("")] String PrimaryKey; [Write, Description("")] String OtherProperties; - [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] 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; From 3156b0a4e13c2ece1a175173855308ca39629b46 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 1 Oct 2024 11:59:41 -0400 Subject: [PATCH 404/465] Update Graph.PermissionList.txt --- Tests/QA/Graph.PermissionList.txt | Bin 5826 -> 5950 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index 826113f235a6a0d9238e46bc09b5d42a131a610f..7f3779a43e9e867bf837fb382d040ce492c277ce 100644 GIT binary patch delta 78 zcmX@4yH9V!KC#IUxLG7C7)lsY8HyP47!nzB7@QgMfvh~BNb+PwK3Qp32Hf%s8P!>M H8Mqh#Lpc&z delta 12 Tcmdm|cSv``J~0+v1}+8wAE^U- From f9be8b5f0769366970a98dc544f20cf725e8ab98 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 1 Oct 2024 16:19:06 +0000 Subject: [PATCH 405/465] Updated Resources and Cmdlet documentation pages --- .../office365/O365ExternalConnection.md | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 docs/docs/resources/office365/O365ExternalConnection.md diff --git a/docs/docs/resources/office365/O365ExternalConnection.md b/docs/docs/resources/office365/O365ExternalConnection.md new file mode 100644 index 0000000000..2f2c8b3ddd --- /dev/null +++ b/docs/docs/resources/office365/O365ExternalConnection.md @@ -0,0 +1,168 @@ +# O365ExternalConnection + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Name** | Key | String | The name of the external connector. | | +| **Id** | Write | String | The unique identifier of the external connector. | | +| **Description** | Write | String | The description of the external connector. | | +| **AuthorizedAppIds** | Write | StringArray[] | A collection of application IDs for registered Microsoft Entra apps that are allowed to manage the externalConnection and to index content in the externalConnection. | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Absent`, `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Configures external connectors in Microsoft 365. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - ExternalConnection.Read.All + +- **Update** + + - ExternalConnection.ReadWrite.All + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + O365ExternalConnection "O365ExternalConnection-Contoso HR" + { + ApplicationId = $ApplicationId; + AuthorizedAppIds = @("MyApp"); + CertificateThumbprint = $CertificateThumbprint; + Description = "Connection to index Contoso HR system"; + Ensure = "Present"; + Id = "contosohr"; + Name = "Contoso HR Nik"; + TenantId = $TenantId; + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + O365ExternalConnection "O365ExternalConnection-Contoso HR" + { + ApplicationId = $ApplicationId; + AuthorizedAppIds = @("MyApp", "MySecondApp"); # Drift + CertificateThumbprint = $CertificateThumbprint; + Description = "Connection to index Contoso HR system"; + Ensure = "Present"; + Id = "contosohr"; + Name = "Contoso HR Nik"; + TenantId = $TenantId; + } + } +} +``` + +### Example 3 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + O365ExternalConnection "O365ExternalConnection-Contoso HR" + { + ApplicationId = $ApplicationId; + AuthorizedAppIds = @("MyApp"); + CertificateThumbprint = $CertificateThumbprint; + Description = "Connection to index Contoso HR system"; + Ensure = "Absent"; + Id = "contosohr"; + Name = "Contoso HR Nik"; + TenantId = $TenantId; + } + } +} +``` + From efbb9bc960134f0f1de93f32b1586bbeb252081f Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Tue, 1 Oct 2024 09:20:07 -0700 Subject: [PATCH 406/465] All UTs working. --- .../MSFT_IntuneAppCategory.psm1 | 5 +++-- ...Microsoft365DSC.IntuneAppCategory.Tests.ps1 | 6 ++---- Tests/Unit/Stubs/Microsoft365.psm1 | 18 +++++++++--------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.psm1 index 553e4d0183..bb74801759 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppCategory/MSFT_IntuneAppCategory.psm1 @@ -70,7 +70,7 @@ function Get-TargetResource try { - $instance = null + $instance = $null if ($null -ne $Script:exportedInstances -and $Script:ExportMode) { $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} @@ -192,6 +192,8 @@ function Set-TargetResource $currentInstance = Get-TargetResource @PSBoundParameters $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $setParameters.remove('Id') | Out-Null + $setParameters.remove('Ensure') | Out-Null # CREATE if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') @@ -207,7 +209,6 @@ function Set-TargetResource elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { Remove-MgBetaDeviceAppManagementMobileAppCategory -MobileAppCategoryId $currentInstance.Id -Confirm:$false - #Remove-MgBetaDeviceAppManagementMobileAppCategory @SetParameters - didn't work as it didn't find -Id param } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 index 3eb5b9cf7f..ba70ad5206 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppCategory.Tests.ps1 @@ -85,7 +85,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $testParams = @{ Id = '046e0b16-76ce-4b49-bf1b-1cc5bd94fb47' DisplayName = 'Data Management' - Ensure = 'Present' + Ensure = 'Absent' Credential = $Credential } @@ -98,8 +98,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It '2.1 Should return values from the Get method' { - - $kjl = $testParams (Get-TargetResource @testParams).Ensure | Should -Be 'Present' } It '2.2 Should return false from the Test method' { @@ -145,7 +143,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgBetaDeviceAppManagementMobileAppCategory -MockWith { return @{ Id = "046e0b16-76ce-4b49-bf1b-1cc5bd94fb47" - DisplayName = "Data Management" + DisplayName = "Data Management 1" #drift } } } diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 824ff71c85..5d363cb954 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -37644,7 +37644,7 @@ function New-MgBetaDeviceAppManagementMobileAppCategory [System.String] $Id, - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $DisplayName ) @@ -37656,9 +37656,9 @@ function Get-MgBetaDeviceAppManagementMobileAppCategory param( [Parameter()] [System.String] - $Id, + $MobileAppCategoryId, - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $DisplayName ) @@ -37670,9 +37670,9 @@ function Update-MgBetaDeviceAppManagementMobileAppCategory param( [Parameter()] [System.String] - $Id, + $MobileAppCategoryId, - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $DisplayName ) @@ -37684,11 +37684,11 @@ function Remove-MgBetaDeviceAppManagementMobileAppCategory param( [Parameter()] [System.String] - $Id, + $MobileAppCategoryId, - [Parameter(Mandatory = $true)] - [System.String] - $DisplayName + [Parameter()] + [System.Boolean] + $Confirm ) } From 54c9a57794093b47aa0a24e0faf5c962aa59996c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 1 Oct 2024 16:21:02 +0000 Subject: [PATCH 407/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 273fb20cdc..58be3d4bb1 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -36709,6 +36709,66 @@ } ] }, + { + "ClassName": "MSFT_O365ExternalConnection", + "Parameters": [ + { + "CIMType": "String", + "Name": "Name", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AuthorizedAppIds", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_O365Group", "Parameters": [ From 0048d354b1d18907609361d7a296c178215ec06c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 1 Oct 2024 16:55:12 +0000 Subject: [PATCH 408/465] Updated Graph Permissions List --- Tests/QA/Graph.PermissionList.txt | Bin 5950 -> 5826 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index 7f3779a43e9e867bf837fb382d040ce492c277ce..826113f235a6a0d9238e46bc09b5d42a131a610f 100644 GIT binary patch delta 12 Tcmdm|cSv``J~0+v1}+8wAE^U- delta 78 zcmX@4yH9V!KC#IUxLG7C7)lsY8HyP47!nzB7@QgMfvh~BNb+PwK3Qp32Hf%s8P!>M H8Mqh#Lpc&z From 7c6495f01acdd0e391b25e351f21f48c109cc436 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Tue, 1 Oct 2024 19:35:29 +0100 Subject: [PATCH 409/465] Add missing permissions --- .../DSCResources/MSFT_O365ExternalConnection/settings.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/settings.json index d6e2971178..72e0ff2579 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_O365ExternalConnection/settings.json @@ -10,11 +10,17 @@ }, "application": { "read": [ + { + "name": "Application.Read.All" + }, { "name": "ExternalConnection.Read.All" } ], "update": [ + { + "name": "Application.Read.All" + }, { "name": "ExternalConnection.ReadWrite.All" } From 3b039a87f84da76778db30829e77c64ee95c631b Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Tue, 1 Oct 2024 19:56:39 +0100 Subject: [PATCH 410/465] Updated Graph Permissions List --- Tests/QA/Graph.PermissionList.txt | Bin 5826 -> 5948 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index 826113f235a6a0d9238e46bc09b5d42a131a610f..e5bb7560ddbbfa45fd9098cdcd7a317badb77f2f 100644 GIT binary patch delta 80 zcmX@4yGL(B29LBWLj^+#Ln=cNLmopSLk@#8Lq3p|2NX%3tjH&eSAHR*`s5s5uFXX} G0bBqZvJ*l8 delta 16 Ycmdm^cSv_b2G8U@yj+{#@C0xH06aDZX#fBK From ebcca7ac2d1f10f8b9e318fe0e6c9e4cc116da78 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 1 Oct 2024 15:17:39 -0400 Subject: [PATCH 411/465] SentinelWatchlist --- .../MSFT_SentinelSetting.psm1 | 2 + .../MSFT_SentinelWatchlist.psm1 | 640 ++++++++++++++++++ .../MSFT_SentinelWatchlist.schema.mof | 24 + .../MSFT_SentinelWatchlist/readme.md | 6 + .../MSFT_SentinelWatchlist/settings.json | 20 + .../Resources/SentinelWatchlist/1-Create.ps1 | 26 + .../Resources/SentinelWatchlist/2-Update.ps1 | 26 + .../Resources/SentinelWatchlist/3-Remove.ps1 | 26 + ...icrosoft365DSC.SentinelWatchlist.Tests.ps1 | 178 +++++ 9 files changed, 948 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelWatchlist.Tests.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/MSFT_SentinelSetting.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/MSFT_SentinelSetting.psm1 index 21c39097df..5d13b0e142 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/MSFT_SentinelSetting.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelSetting/MSFT_SentinelSetting.psm1 @@ -433,9 +433,11 @@ function Export-TargetResource } $displayedKey = $config.Name Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $SubscriptionId = $config.ResourceId.Split('/')[2] $params = @{ ResourceGroupName = $config.ResourceGroupName WorkspaceName = $config.Name + SubscriptionId = $SubscriptionId Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.psm1 new file mode 100644 index 0000000000..fd67a21020 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.psm1 @@ -0,0 +1,640 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $SubscriptionId, + + [Parameter(Mandatory = $true)] + [System.String] + $ResourceGroupName, + + [Parameter(Mandatory = $true)] + [System.String] + $WorkspaceName, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $SourceType, + + [Parameter()] + [System.String] + $ItemsSearchKey, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DefaultDuration, + + [Parameter()] + [System.String] + $Alias, + + [Parameter()] + [System.Uint32] + $NumberOfLinesToSkip, + + [Parameter()] + [System.String] + $RawContent, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'Azure' ` + -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 + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + if (-not [System.String]::IsNullOrEmpty($Id)) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.properties.watchListId -eq $Id} + } + + if ($null -eq $instance) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.name -eq $Name} + } + } + else + { + $watchLists = Get-M365DSCSentinelWatchlist -SubscriptionId $SubscriptionId ` + -ResourceGroupName $ResourceName ` + -WorkspaceName $workspaceName + + if (-not [System.String]::IsNullOrEmpty($Id)) + { + $instance = $watchLists | Where-Object -FilterScript {$_.properties.watchListId -eq $Id} + } + + if ($null -eq $instance) + { + $instance = $watchLists | Where-Object -FilterScript {$_.name -eq $Name} + } + } + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + SubscriptionId = $SubscriptionId + ResourceGroupName = $ResourceGroupName + WorkspaceName = $WorkspaceName + Name = $instance.Name + Id = $instance.properties.watchlistId + DisplayName = $instance.properties.displayName + SourceType = $instance.properties.sourceType + ItemsSearchKey = $instance.properties.itemsSearchKey + Description = $instance.properties.description + DefaultDuration = $instance.properties.defaultDuration + Alias = $instance.properties.watchListAlias + NumberOfLinesToSkip = $instance.properties.numberOfLinesToSkip + RawContent = $RawContent + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $SubscriptionId, + + [Parameter(Mandatory = $true)] + [System.String] + $ResourceGroupName, + + [Parameter(Mandatory = $true)] + [System.String] + $WorkspaceName, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $SourceType, + + [Parameter()] + [System.String] + $ItemsSearchKey, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DefaultDuration, + + [Parameter()] + [System.String] + $Alias, + + [Parameter()] + [System.Uint32] + $NumberOfLinesToSkip, + + [Parameter()] + [System.String] + $RawContent, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + ##TODO - Replace by the New cmdlet for the resource + New-Cmdlet @SetParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Update/Set cmdlet for the resource + Set-cmdlet @SetParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + ##TODO - Replace by the Remove cmdlet for the resource + Remove-cmdlet @SetParameters + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $SubscriptionId, + + [Parameter(Mandatory = $true)] + [System.String] + $ResourceGroupName, + + [Parameter(Mandatory = $true)] + [System.String] + $WorkspaceName, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.String] + $SourceType, + + [Parameter()] + [System.String] + $ItemsSearchKey, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DefaultDuration, + + [Parameter()] + [System.String] + $Alias, + + [Parameter()] + [System.Uint32] + $NumberOfLinesToSkip, + + [Parameter()] + [System.String] + $RawContent, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'Azure' ` + -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 + { + $Script:ExportMode = $true + $workspaces = Get-AzResource -ResourceType 'Microsoft.OperationalInsights/workspaces' + $Script:exportedInstances = @() + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($workspace in $workspaces) + { + Write-Host " |---[$i/$($workspaces.Length)] $($workspace.Name)" -NoNewline + $subscriptionId = $workspace.ResourceId.Split('/')[2] + $resourceGroupName = $workspace.ResourceGroupName + $workspaceName = $workspace.Name + + $currentWatchLists = Get-M365DSCSentinelWatchlist -SubscriptionId $subscriptionId ` + -ResourceGroupName $resourceGroupName ` + -WorkspaceName $workspaceName + + $j = 1 + if ($currentWatchLists.Length -eq 0 ) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + + foreach ($watchList in $currentWatchLists) + { + $Script:exportedInstances += $watchList + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $watchList.Name + Write-Host " |---[$j/$($currentWatchLists.Length)] $displayedKey" -NoNewline + $params = @{ + SubscriptionId = $subscriptionId + ResourceGroupName = $resourceGroupName + WorkspaceName = $workspaceName + Name = $watchList.Name + Id = $watchlist.properties.watchlistId + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $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 + $j++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + $i++ + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +function Get-M365DSCSentinelWatchlist +{ + [CmdletBinding()] + [OutputType([Array])] + param( + [Parameter()] + [System.String] + $SubscriptionId, + + [Parameter()] + [System.String] + $ResourceGroupName, + + [Parameter()] + [System.String] + $WorkspaceName + ) + + try + { + $uri = $Global:MSCloudLoginConnectionProfile.Azure.HostUrl + "/subscriptions/$($SubscriptionId)/resourceGroups/$($ResourceGroupName)/" + $uri += "providers/Microsoft.OperationalInsights/workspaces/$($WorkspaceName)/providers/Microsoft.SecurityInsights/watchlists?api-version=2022-06-01-preview" + $response = Invoke-AzRest -Uri $uri -Method Get + $result = ConvertFrom-Json $response.Content + return $result.value + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + throw $_ + } +} + +function New-M365DSCSentinelWatchlist +{ + [CmdletBinding()] + [OutputType([Array])] + param( + [Parameter()] + [System.String] + $SubscriptionId, + + [Parameter()] + [System.String] + $ResourceGroupName, + + [Parameter()] + [System.String] + $WorkspaceName, + + [Parameter()] + [System.Collections.Hashtable] + $Body + ) + + try + { + $uri = $Global:MSCloudLoginConnectionProfile.Azure.HostUrl + "/subscriptions/$($SubscriptionId)/resourceGroups/$($ResourceGroupName)/" + $uri += "providers/Microsoft.OperationalInsights/workspaces/$($WorkspaceName)/providers/Microsoft.SecurityInsights/watchlists?api-version=2022-06-01-preview" + $response = Invoke-AzRest -Uri $uri -Method PUT + $result = ConvertFrom-Json $response.Content + return $result.value + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + throw $_ + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.schema.mof new file mode 100644 index 0000000000..d228bab204 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.schema.mof @@ -0,0 +1,24 @@ +[ClassVersion("1.0.0.0"), FriendlyName("SentinelWatchlist")] +class MSFT_SentinelWatchlist : OMI_BaseResource +{ + [Key, Description("")] Name; + [Write, Description("")] String SubscriptionId; + [Write, Description("")] String ResourceGroupName; + [Write, Description("")] String WorkspaceName; + [Write, Description("")] String Id; + [Write, Description("")] String DisplayName; + [Write, Description("")] String SourceType; + [Write, Description("")] String ItemsSearchKey; + [Write, Description("")] String Description; + [Write, Description("")] String DefaultDuration; + [Write, Description("")] String Alias; + [Write, Description("")] UInt32 NumberOfLinesToSkip; + [Write, Description("")] String RawContent; + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] 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("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/readme.md new file mode 100644 index 0000000000..42dff9161f --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/readme.md @@ -0,0 +1,6 @@ + +# SentinelWatchlist + +## Description + +Configures watchlists in Azure Sentinel. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/settings.json new file mode 100644 index 0000000000..1c5e4917fd --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/settings.json @@ -0,0 +1,20 @@ +{ + "resourceName": "SentinelWatchlist", + "description": "Configures watchlists in Azure Sentinel.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/1-Create.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/1-Create.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/2-Update.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/2-Update.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/3-Remove.ps1 new file mode 100644 index 0000000000..b516274848 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/3-Remove.ps1 @@ -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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelWatchlist.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelWatchlist.Tests.ps1 new file mode 100644 index 0000000000..780e0f343d --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelWatchlist.Tests.ps1 @@ -0,0 +1,178 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + ##TODO - Mock any Remove/Set/New cmdlets + + # 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 instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return $null + Mock -CommandName Get-Cmdlet -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 a new instance from the Set method' { + ##TODO - Replace the New-Cmdlet by the appropriate one + Set-TargetResource @testParams + Should -Invoke -CommandName New-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Absent' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 remove the instance from the Set method' { + Set-TargetResource @testParams + ##TODO - Replace the Remove-Cmdlet by the appropriate one + Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return the desired values + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + ##TODO - Add Parameters + Ensure = 'Present' + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return a drift + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + + 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 + ##TODO - Replace the Update-Cmdlet by the appropriate one + Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + ##TODO - Mock the Get-Cmdlet to return an instance + Mock -CommandName Get-Cmdlet -MockWith { + return @{ + + } + } + } + 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 74dfdf660879de1582c9c1669de6ca784c808ce3 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Tue, 1 Oct 2024 20:31:10 +0100 Subject: [PATCH 412/465] Fix Unit Tests --- .../Resources/EXOMailTips/1-Create.ps1 | 39 ------------------- .../Resources/EXOMailTips/2-Update.ps1 | 1 - .../Resources/EXOMailTips/3-Remove.ps1 | 34 ---------------- 3 files changed, 74 deletions(-) delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/1-Create.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/3-Remove.ps1 diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/1-Create.ps1 deleted file mode 100644 index 9111f3ae5c..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/1-Create.ps1 +++ /dev/null @@ -1,39 +0,0 @@ -<# -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()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - Import-DscResource -ModuleName Microsoft365DSC - - node localhost - { - EXOMailTips 'OrgWideMailTips' - { - IsSingleInstance = 'Yes' - MailTipsAllTipsEnabled = $True - MailTipsGroupMetricsEnabled = $True - #MailTipsLargeAudienceThreshold = 100 - MailTipsMailboxSourcedTipsEnabled = $True - MailTipsExternalRecipientsTipsEnabled = $True - Ensure = "Present" - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/2-Update.ps1 index 77b38d9db2..f2a92980e9 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/2-Update.ps1 @@ -30,7 +30,6 @@ Configuration Example #MailTipsLargeAudienceThreshold = 100 MailTipsMailboxSourcedTipsEnabled = $True MailTipsExternalRecipientsTipsEnabled = $True - Ensure = "Present" ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/3-Remove.ps1 deleted file mode 100644 index ec8fa0c4ab..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailTips/3-Remove.ps1 +++ /dev/null @@ -1,34 +0,0 @@ -<# -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()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - Import-DscResource -ModuleName Microsoft365DSC - - node localhost - { - EXOMailTips 'OrgWideMailTips' - { - IsSingleInstance = 'Yes' - Ensure = "Absent" - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - } - } -} From c037e885d557a8225fecb6a208c726f40a8b3896 Mon Sep 17 00:00:00 2001 From: Kajalp1079 Date: Tue, 1 Oct 2024 12:39:37 -0700 Subject: [PATCH 413/465] fixing syntax error for examples. --- .../Examples/Resources/IntuneAppCategory/1-Create.ps1 | 9 ++++++--- .../Examples/Resources/IntuneAppCategory/2-Update.ps1 | 9 ++++++--- .../Examples/Resources/IntuneAppCategory/3-Remove.ps1 | 9 ++++++--- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 index aaeaa15cb1..c86b8d401e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/1-Create.ps1 @@ -22,8 +22,11 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Data Management"; - Ensure = "Present"; + IntuneAppCategory "IntuneAppCategory-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management"; + Ensure = "Present"; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 index 62e08806c9..9568256f2c 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/2-Update.ps1 @@ -22,8 +22,11 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Data Management updated"; - Ensure = "Present"; + IntuneAppCategory "IntuneAppCategory-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management updated"; + Ensure = "Present"; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 index c75c649e10..b3e94d9b6f 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAppCategory/3-Remove.ps1 @@ -22,8 +22,11 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; - DisplayName = "Custom Data Management"; - Ensure = "Absent"; + IntuneAppCategory "IntuneAppCategory-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management"; + Ensure = "Absent"; + } } } From fc847ccbf14528039044881d722205d7b5808f17 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Tue, 1 Oct 2024 20:40:18 +0100 Subject: [PATCH 414/465] Updated Graph permission list to fix Unit Tests --- Tests/QA/Graph.PermissionList.txt | Bin 5826 -> 5948 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index 826113f235a6a0d9238e46bc09b5d42a131a610f..e63c6c5f2a47b66b1473568b2c965eae5ce0708a 100644 GIT binary patch delta 80 zcmX@4yGL(B6OXhjLj^+#Ln=cNLmopSLk@#8Lq3p|2NX%3tjH&eSAHR*`s5s5uFX9> GW?TRxgcDo< delta 12 Tcmdm^cSv_b6VK*9JPup{C2|EF From d03450feae59b68f79fe065e7154694fe0574e74 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Tue, 1 Oct 2024 20:42:19 +0100 Subject: [PATCH 415/465] Updated Graph permission list to fix Unit Tests --- Tests/QA/Graph.PermissionList.txt | Bin 5826 -> 5948 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index 826113f235a6a0d9238e46bc09b5d42a131a610f..e63c6c5f2a47b66b1473568b2c965eae5ce0708a 100644 GIT binary patch delta 80 zcmX@4yGL(B6OXhjLj^+#Ln=cNLmopSLk@#8Lq3p|2NX%3tjH&eSAHR*`s5s5uFX9> GW?TRxgcDo< delta 12 Tcmdm^cSv_b6VK*9JPup{C2|EF From 438b344909fa87f4afb895cff0ef933803fcca82 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 00:31:19 +0000 Subject: [PATCH 416/465] Updated Resources and Cmdlet documentation pages --- .../resources/intune/IntuneAppCategory.md | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 docs/docs/resources/intune/IntuneAppCategory.md diff --git a/docs/docs/resources/intune/IntuneAppCategory.md b/docs/docs/resources/intune/IntuneAppCategory.md new file mode 100644 index 0000000000..062055e54c --- /dev/null +++ b/docs/docs/resources/intune/IntuneAppCategory.md @@ -0,0 +1,155 @@ +# IntuneAppCategory + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **DisplayName** | Key | String | The name of the app category. | | +| **Id** | Write | String | The unique identifier for an entity. Read-only. | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Configures a resource for navigation property for Intune mobile app categories. Default app categories cannot be renamed. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - DeviceManagementApps.Read.All + +- **Update** + + - DeviceManagementApps.ReadWrite.All + +#### Application permissions + +- **Read** + + - DeviceManagementApps.Read.All + +- **Update** + + - DeviceManagementApps.ReadWrite.All + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneAppCategory "IntuneAppCategory-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management"; + Ensure = "Present"; + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneAppCategory "IntuneAppCategory-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management updated"; + Ensure = "Present"; + } + } +} +``` + +### Example 3 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + IntuneAppCategory "IntuneAppCategory-Data Management" + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management"; + Ensure = "Absent"; + } + } +} +``` + From 7cfc91573caebf27256b1e3bd08f7eb088593891 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 1 Oct 2024 20:33:15 -0400 Subject: [PATCH 417/465] SentinelWatchList - Initial Release --- CHANGELOG.md | 2 + .../MSFT_SentinelWatchlist.psm1 | 161 +++++++++-- .../MSFT_SentinelWatchlist.schema.mof | 2 +- .../Resources/SentinelWatchlist/1-Create.ps1 | 20 +- .../Resources/SentinelWatchlist/2-Update.ps1 | 20 +- .../Resources/SentinelWatchlist/3-Remove.ps1 | 20 +- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 53 ++++ ...icrosoft365DSC.SentinelWatchlist.Tests.ps1 | 266 +++++++++++++++--- Tests/Unit/Stubs/Microsoft365.psm1 | 19 ++ 9 files changed, 492 insertions(+), 71 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a79cd4fe31..d41ca862e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -94,6 +94,8 @@ FIXES [#3784](https://github.com/microsoft/Microsoft365DSC/issues/3784) * SentinelSetting * Initial release. +* SentinelWatchlist + * Initial release. * SPOAccessControlSettings * Added support for property EnableRestrictedAccessControl. * M365DSCUtil diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.psm1 index fd67a21020..38cce01c28 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.psm1 @@ -105,6 +105,12 @@ function Get-TargetResource $nullResult.Ensure = 'Absent' try { + if ([System.String]::IsNullOrEmpty($TenantId) -and $null -ne $Credential) + { + $TenantId = $Credential.UserName.Split('@')[1] + } + + Write-Verbose -Message "Retrieving watchlist {$Name}" if ($null -ne $Script:exportedInstances -and $Script:ExportMode) { if (-not [System.String]::IsNullOrEmpty($Id)) @@ -121,7 +127,8 @@ function Get-TargetResource { $watchLists = Get-M365DSCSentinelWatchlist -SubscriptionId $SubscriptionId ` -ResourceGroupName $ResourceName ` - -WorkspaceName $workspaceName + -WorkspaceName $workspaceName ` + -TenantId $TenantId if (-not [System.String]::IsNullOrEmpty($Id)) { @@ -135,9 +142,11 @@ function Get-TargetResource } if ($null -eq $instance) { + Write-Verbose -Message "Watchlist {$Name} was not found" return $nullResult } + Write-Verbose -Message "Found watchlist {$Name}" $results = @{ SubscriptionId = $SubscriptionId ResourceGroupName = $ResourceGroupName @@ -274,27 +283,51 @@ function Set-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - $currentInstance = Get-TargetResource @PSBoundParameters + if ([System.String]::IsNullOrEmpty($TenantId) -and $null -ne $Credential) + { + $TenantId = $Credential.UserName.Split('@')[1] + } - $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $body = @{ + properties = @{ + displayName = $DisplayName + provider = "Microsoft" + itemsSearchKey = $ItemsSearchKey + sourceType = $SourceType + description = $Description + defaultDuration = $defaultDuration + numberOfLinesToSkip = $NumberOfLinesToSkip + watchListAlias = $Alias + } + } - # CREATE - if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + if ($null -ne $RawContent) { - ##TODO - Replace by the New cmdlet for the resource - New-Cmdlet @SetParameters + Write-Verbose -Message "Adding rawContent and contentType to the payload" + $body.properties.Add('rawContent', $RawContent) + $body.properties.Add('contentType', 'text/csv') } - # UPDATE - elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + + # CREATE & UPDATE + if ($Ensure -eq 'Present') { - ##TODO - Replace by the Update/Set cmdlet for the resource - Set-cmdlet @SetParameters + Write-Verbose -Message "Configuring watchlist {$Name}" + Set-M365DSCSentinelWatchlist -SubscriptionId $SubscriptionId ` + -ResourceGroupName $ResourceGroupName ` + -WorkspaceName $WorkspaceName ` + -WatchListAlias $Alias ` + -Body $body ` + -TenantId $TenantId } # REMOVE - elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + elseif ($Ensure -eq 'Absent') { - ##TODO - Replace by the Remove cmdlet for the resource - Remove-cmdlet @SetParameters + Write-Verbose -Message "Removing watchlist {$Name}" + Remove-M365DSCSentinelWatchlist -SubscriptionId $SubscriptionId ` + -ResourceGroupName $ResourceGroupName ` + -WorkspaceName $WorkspaceName ` + -WatchListAlias $Alias ` + -TenantId $TenantId } } @@ -479,6 +512,11 @@ function Export-TargetResource { Write-Host "`r`n" -NoNewline } + + if ([System.String]::IsNullOrEmpty($TenantId) -and $null -ne $Credential) + { + $TenantId = $Credential.UserName.Split('@')[1] + } foreach ($workspace in $workspaces) { Write-Host " |---[$i/$($workspaces.Length)] $($workspace.Name)" -NoNewline @@ -488,7 +526,8 @@ function Export-TargetResource $currentWatchLists = Get-M365DSCSentinelWatchlist -SubscriptionId $subscriptionId ` -ResourceGroupName $resourceGroupName ` - -WorkspaceName $workspaceName + -WorkspaceName $workspaceName ` + -TenantId $TenantId $j = 1 if ($currentWatchLists.Length -eq 0 ) @@ -572,14 +611,19 @@ function Get-M365DSCSentinelWatchlist [Parameter()] [System.String] - $WorkspaceName + $WorkspaceName, + + [Parameter(Mandatory = $true)] + [System.String] + $TenantId ) try { - $uri = $Global:MSCloudLoginConnectionProfile.Azure.HostUrl + "/subscriptions/$($SubscriptionId)/resourceGroups/$($ResourceGroupName)/" + $hostUrl = Get-M365DSCAPIEndpoint -TenantId $TenantId + $uri = $hostUrl.AzureManagement + "/subscriptions/$($SubscriptionId)/resourceGroups/$($ResourceGroupName)/" $uri += "providers/Microsoft.OperationalInsights/workspaces/$($WorkspaceName)/providers/Microsoft.SecurityInsights/watchlists?api-version=2022-06-01-preview" - $response = Invoke-AzRest -Uri $uri -Method Get + $response = Invoke-AzRest -Uri $uri -Method 'GET' $result = ConvertFrom-Json $response.Content return $result.value } @@ -589,16 +633,14 @@ function Get-M365DSCSentinelWatchlist New-M365DSCLogEntry -Message 'Error retrieving data:' ` -Exception $_ ` -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential + -TenantId $TenantId throw $_ } } -function New-M365DSCSentinelWatchlist +function Set-M365DSCSentinelWatchlist { [CmdletBinding()] - [OutputType([Array])] param( [Parameter()] [System.String] @@ -612,18 +654,35 @@ function New-M365DSCSentinelWatchlist [System.String] $WorkspaceName, + [Parameter()] + [System.String] + $WatchListAlias, + [Parameter()] [System.Collections.Hashtable] - $Body + $Body, + + [Parameter(Mandatory = $true)] + [System.String] + $TenantId ) try { - $uri = $Global:MSCloudLoginConnectionProfile.Azure.HostUrl + "/subscriptions/$($SubscriptionId)/resourceGroups/$($ResourceGroupName)/" - $uri += "providers/Microsoft.OperationalInsights/workspaces/$($WorkspaceName)/providers/Microsoft.SecurityInsights/watchlists?api-version=2022-06-01-preview" - $response = Invoke-AzRest -Uri $uri -Method PUT - $result = ConvertFrom-Json $response.Content - return $result.value + $hostUrl = Get-M365DSCAPIEndpoint -TenantId $TenantId + $uri = $hostUrl.AzureManagement + "/subscriptions/$($SubscriptionId)/resourceGroups/$($ResourceGroupName)/" + $uri += "providers/Microsoft.OperationalInsights/workspaces/$($WorkspaceName)/providers/Microsoft.SecurityInsights/watchlists/$($WatchListAlias)?api-version=2022-06-01-preview" + $payload = ConvertTo-Json $Body -Depth 10 -Compress + + Write-Verbose -Message "Calling Url: {$($uri)}" + Write-Verbose -Message "Payload: {$payload}" + $response = Invoke-AzRest -Uri $uri -Method 'PUT' -Payload $payload + if ($response.StatusCode -ne 200 -and $response.StatusCode -ne 201) + { + Write-Verbose -Message $($response | Out-String) + $content = ConvertFrom-Json $response.Content + throw $content.error.message + } } catch { @@ -631,8 +690,50 @@ function New-M365DSCSentinelWatchlist New-M365DSCLogEntry -Message 'Error retrieving data:' ` -Exception $_ ` -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential + -TenantId $TenantId + throw $_ + } +} + +function Remove-M365DSCSentinelWatchlist +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $SubscriptionId, + + [Parameter()] + [System.String] + $ResourceGroupName, + + [Parameter()] + [System.String] + $WorkspaceName, + + [Parameter()] + [System.String] + $WatchListAlias, + + [Parameter(Mandatory = $true)] + [System.String] + $TenantId + ) + + try + { + $hostUrl = Get-M365DSCAPIEndpoint -TenantId $TenantId + $uri = $hostUrl.AzureManagement + "/subscriptions/$($SubscriptionId)/resourceGroups/$($ResourceGroupName)/" + $uri += "providers/Microsoft.OperationalInsights/workspaces/$($WorkspaceName)/providers/Microsoft.SecurityInsights/watchlists/$($WatchListAlias)?api-version=2022-06-01-preview" + Invoke-AzRest -Uri $uri -Method 'DELETE' + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId throw $_ } } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.schema.mof index d228bab204..11f39102ac 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.schema.mof @@ -1,7 +1,7 @@ [ClassVersion("1.0.0.0"), FriendlyName("SentinelWatchlist")] class MSFT_SentinelWatchlist : OMI_BaseResource { - [Key, Description("")] Name; + [Key, Description("")] String Name; [Write, Description("")] String SubscriptionId; [Write, Description("")] String ResourceGroupName; [Write, Description("")] String WorkspaceName; diff --git a/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/1-Create.ps1 index b516274848..1fe6876e36 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/1-Create.ps1 @@ -21,6 +21,24 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + SentinelWatchlist "SentinelWatchlist-TestWatch" + { + Alias = "MyAlias"; + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + DefaultDuration = "P1DT3H"; + Description = "My description"; + DisplayName = "My Display Name"; + Ensure = "Present"; + ItemsSearchKey = "Test"; + Name = "MyWatchList"; + NumberOfLinesToSkip = 1; + RawContent = (Get-Content 'C:\book2.csv' -Raw) + ResourceGroupName = "MyResourceGroup"; + SourceType = "Local"; + SubscriptionId = "20f41296-9edc-4374-b5e0-b1c1aa07e7d3"; + TenantId = $TenantId; + WorkspaceName = "MyWorkspace"; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/2-Update.ps1 index b516274848..eff2ea1d35 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/2-Update.ps1 @@ -21,6 +21,24 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + SentinelWatchlist "SentinelWatchlist-TestWatch" + { + Alias = "MyAlias"; + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + DefaultDuration = "P1DT3H"; + Description = "My description"; + DisplayName = "My Display Name"; + Ensure = "Present"; + ItemsSearchKey = "Test"; + Name = "MyWatchList"; + NumberOfLinesToSkip = 0; # Drift + RawContent = (Get-Content 'C:\book2.csv' -Raw) + ResourceGroupName = "MyResourceGroup"; + SourceType = "Local"; + SubscriptionId = "20f41296-9edc-4374-b5e0-b1c1aa07e7d3"; + TenantId = $TenantId; + WorkspaceName = "MyWorkspace"; + } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/3-Remove.ps1 index b516274848..fb0be88b8f 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/3-Remove.ps1 @@ -21,6 +21,24 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC node localhost { - + SentinelWatchlist "SentinelWatchlist-TestWatch" + { + Alias = "MyAlias"; + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + DefaultDuration = "P1DT3H"; + Description = "My description"; + DisplayName = "My Display Name"; + Ensure = "Absent"; + ItemsSearchKey = "Test"; + Name = "MyWatchList"; + NumberOfLinesToSkip = 1; + RawContent = (Get-Content 'C:\book2.csv' -Raw) + ResourceGroupName = "MyResourceGroup"; + SourceType = "Local"; + SubscriptionId = "20f41296-9edc-4374-b5e0-b1c1aa07e7d3"; + TenantId = $TenantId; + WorkspaceName = "MyWorkspace"; + } } } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 55612426e0..576bd52015 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1648,6 +1648,58 @@ function Remove-M365DSCInvalidDependenciesFromSession } } +<# +.Description +This function retrieves the various endpoint urls based on the cloud environment. + +.Example +Get-M365DSCAPIEndpoint -TenantId 'contoso.onmicrosoft.com' + +.Functionality +Private +#> +function Get-M365DSCAPIEndpoint +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param( + [Parameter(Mandatory = $true)] + [System.String] + $TenantId + ) + + try + { + $webrequest = Invoke-WebRequest -Uri "https://login.windows.net/$($TenantId)/.well-known/openid-configuration" -UseBasicParsing + $response = ConvertFrom-Json $webrequest.Content + $tenantRegionScope = $response."tenant_region_scope" + + $endpoints = @{ + AzureManagement = $null + } + + switch ($tenantRegionScope) + { + 'USGov' + { + if ($null -ne $response.'tenant_region_sub_scope' -and $response.'tenant_region_sub_scope' -eq 'DODCON') + { + $endpoints.AzureManagement = "https://management.usgovcloudapi.net" + } + } + default + { + $endpoints.AzureManagement = "https://management.azure.com" + } + } + return $endpoints + } + catch + { + throw $_ + } +} + <# .Description This function gets the onmicrosoft.com name of the tenant @@ -5103,6 +5155,7 @@ Export-ModuleMember -Function @( 'Export-M365DSCConfiguration', 'Get-AllSPOPackages', 'Get-M365DSCAllResources', + 'Get-M365DSCAPIEndpoint' 'Get-M365DSCAuthenticationMode', 'Get-M365DSCComponentsForAuthenticationType', 'Get-M365DSCComponentsWithMostSecureAuthenticationType', diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelWatchlist.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelWatchlist.Tests.ps1 index 780e0f343d..9e1b039434 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelWatchlist.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelWatchlist.Tests.ps1 @@ -26,7 +26,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { BeforeAll { $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force - $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@o365DSC.onmicrosoft.com', $secpasswd) Mock -CommandName Confirm-M365DSCDependencies -MockWith { } @@ -35,7 +35,13 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return "Credentials" } - ##TODO - Mock any Remove/Set/New cmdlets + Mock -CommandName Get-AzResource -MockWith { + return @{ + ResourceGroupName = "MyResourceGroup" + Name = 'MySentinelWorkspace' + ResourceId = "name/part/resourceId/" + } + } # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { @@ -47,14 +53,27 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance should exist but it DOES NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + Alias = "MyAlias"; + DefaultDuration = "P1DT3H"; + Description = "My description"; + DisplayName = "My Display Name"; + Ensure = "Present"; + ItemsSearchKey = "Test"; + Name = "MyWatchList"; + NumberOfLinesToSkip = 1; + RawContent = 'MyContent' + ResourceGroupName = "MyResourceGroup"; + SourceType = "Local"; + SubscriptionId = "20f41296-9edc-4374-b5e0-b1c1aa07e7d3"; + TenantId = $TenantId; + WorkspaceName = "MyWorkspace"; + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return $null - Mock -CommandName Get-Cmdlet -MockWith { - return $null + Mock -CommandName Invoke-AzRest -MockWith { + return @{ + statuscode = 200 + } } } It 'Should return Values from the Get method' { @@ -65,24 +84,70 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should create a new instance from the Set method' { - ##TODO - Replace the New-Cmdlet by the appropriate one Set-TargetResource @testParams - Should -Invoke -CommandName New-Cmdlet -Exactly 1 + Should -Invoke -CommandName Invoke-AzRest -Exactly 1 } } Context -Name "The instance exists but it SHOULD NOT" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Absent' - Credential = $Credential; + Alias = "MyAlias"; + DefaultDuration = "P1DT3H"; + Description = "My description"; + DisplayName = "My Display Name"; + Ensure = "Absent"; + ItemsSearchKey = "Test"; + Name = "MyWatchList"; + NumberOfLinesToSkip = 1; + RawContent = 'MyContent' + ResourceGroupName = "MyResourceGroup"; + SourceType = "Local"; + SubscriptionId = "20f41296-9edc-4374-b5e0-b1c1aa07e7d3"; + TenantId = $TenantId; + WorkspaceName = "MyWorkspace"; + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Invoke-AzRest -MockWith { return @{ - + StatusCode = '200' + Content = @" +{"value":[ +{ + "id": "/subscriptions/xxxx/resourceGroups/xxxx/providers/Microsoft.OperationalInsights/workspaces/xxxx/providers/Microsoft.SecurityInsights/Watchlists/xxxx", + "name": "MyWatchList", + "type": "Microsoft.SecurityInsights/Watchlists", + "properties": { + "watchlistId": "xxxx", + "displayName": "My Display Name", + "provider": "Microsoft", + "sourceType": "Local", + "itemsSearchKey": "Test", + "created": "2024-10-01T16:40:07.5468197-04:00", + "updated": "2024-10-01T16:58:54.4225042-04:00", + "createdBy": { + "objectId": "xxxx", + "name": "xxxx" + }, + "updatedBy": { + "objectId": "xxxx", + "name": "xxxx" + }, + "description": "My description", + "watchlistType": "watchlist", + "watchlistAlias": "MyAlias", + "isDeleted": false, + "labels": [], + "defaultDuration": "P1DT3H", + "tenantId": "xxx", + "numberOfLinesToSkip": 1, + "provisioningState": "Succeeded", + "sasUri": "", + "watchlistCategory": "General" + } + }]} +"@ } } } @@ -95,23 +160,69 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should remove the instance from the Set method' { Set-TargetResource @testParams - ##TODO - Replace the Remove-Cmdlet by the appropriate one - Should -Invoke -CommandName Remove-Cmdlet -Exactly 1 + Should -Invoke -CommandName Invoke-AzRest -Exactly 1 } } Context -Name "The instance exists and values are already in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + Alias = "MyAlias"; + DefaultDuration = "P1DT3H"; + Description = "My description"; + DisplayName = "My Display Name"; + Ensure = "Present"; + ItemsSearchKey = "Test"; + Name = "MyWatchList"; + NumberOfLinesToSkip = 1; + RawContent = 'MyContent' + ResourceGroupName = "MyResourceGroup"; + SourceType = "Local"; + SubscriptionId = "20f41296-9edc-4374-b5e0-b1c1aa07e7d3"; + TenantId = $TenantId; + WorkspaceName = "MyWorkspace"; + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return the desired values - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Invoke-AzRest -MockWith { return @{ - + StatusCode = '200' + Content = @" +{"value":[ +{ + "id": "/subscriptions/xxxx/resourceGroups/xxxx/providers/Microsoft.OperationalInsights/workspaces/xxxx/providers/Microsoft.SecurityInsights/Watchlists/xxxx", + "name": "MyWatchList", + "type": "Microsoft.SecurityInsights/Watchlists", + "properties": { + "watchlistId": "xxxx", + "displayName": "My Display Name", + "provider": "Microsoft", + "sourceType": "Local", + "itemsSearchKey": "Test", + "created": "2024-10-01T16:40:07.5468197-04:00", + "updated": "2024-10-01T16:58:54.4225042-04:00", + "createdBy": { + "objectId": "xxxx", + "name": "xxxx" + }, + "updatedBy": { + "objectId": "xxxx", + "name": "xxxx" + }, + "description": "My description", + "watchlistType": "watchlist", + "watchlistAlias": "MyAlias", + "isDeleted": false, + "labels": [], + "defaultDuration": "P1DT3H", + "tenantId": "xxx", + "numberOfLinesToSkip": 1, + "provisioningState": "Succeeded", + "sasUri": "", + "watchlistCategory": "General" + } + }]} +"@ } } } @@ -124,15 +235,62 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name "The instance exists and values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ - ##TODO - Add Parameters - Ensure = 'Present' - Credential = $Credential; + Alias = "MyAlias"; + DefaultDuration = "P1DT3H"; + Description = "My description"; + DisplayName = "My Display Name"; + Ensure = "Present"; + ItemsSearchKey = "Test"; + Name = "MyWatchList"; + NumberOfLinesToSkip = 0; # Drift + RawContent = 'MyContent' + ResourceGroupName = "MyResourceGroup"; + SourceType = "Local"; + SubscriptionId = "20f41296-9edc-4374-b5e0-b1c1aa07e7d3"; + TenantId = $TenantId; + WorkspaceName = "MyWorkspace"; + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return a drift - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Invoke-AzRest -MockWith { return @{ - + StatusCode = '200' + Content = @" +{"value":[ +{ + "id": "/subscriptions/xxxx/resourceGroups/xxxx/providers/Microsoft.OperationalInsights/workspaces/xxxx/providers/Microsoft.SecurityInsights/Watchlists/xxxx", + "name": "MyWatchList", + "type": "Microsoft.SecurityInsights/Watchlists", + "properties": { + "watchlistId": "xxxx", + "displayName": "My Display Name", + "provider": "Microsoft", + "sourceType": "Local", + "itemsSearchKey": "Test", + "created": "2024-10-01T16:40:07.5468197-04:00", + "updated": "2024-10-01T16:58:54.4225042-04:00", + "createdBy": { + "objectId": "xxxx", + "name": "xxxx" + }, + "updatedBy": { + "objectId": "xxxx", + "name": "xxxx" + }, + "description": "My description", + "watchlistType": "watchlist", + "watchlistAlias": "MyAlias", + "isDeleted": false, + "labels": [], + "defaultDuration": "P1DT3H", + "tenantId": "xxx", + "numberOfLinesToSkip": 1, + "provisioningState": "Succeeded", + "sasUri": "", + "watchlistCategory": "General" + } + }]} +"@ } } } @@ -147,8 +305,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the Set method' { Set-TargetResource @testParams - ##TODO - Replace the Update-Cmdlet by the appropriate one - Should -Invoke -CommandName Update-Cmdlet -Exactly 1 + Should -Invoke -CommandName Invoke-AzRest -Exactly 1 } } @@ -156,14 +313,49 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { BeforeAll { $Global:CurrentModeIsExport = $true $Global:PartialExportFileName = "$(New-Guid).partial.ps1" - $testParams = @{ - Credential = $Credential; + $testParams = @{ + Credential = $Credential; } - ##TODO - Mock the Get-Cmdlet to return an instance - Mock -CommandName Get-Cmdlet -MockWith { + Mock -CommandName Invoke-AzRest -MockWith { return @{ - + StatusCode = '200' + Content = @" +{"value":[ +{ + "id": "/subscriptions/xxxx/resourceGroups/xxxx/providers/Microsoft.OperationalInsights/workspaces/xxxx/providers/Microsoft.SecurityInsights/Watchlists/xxxx", + "name": "MyWatchList", + "type": "Microsoft.SecurityInsights/Watchlists", + "properties": { + "watchlistId": "xxxx", + "displayName": "My Display Name", + "provider": "Microsoft", + "sourceType": "Local", + "itemsSearchKey": "Test", + "created": "2024-10-01T16:40:07.5468197-04:00", + "updated": "2024-10-01T16:58:54.4225042-04:00", + "createdBy": { + "objectId": "xxxx", + "name": "xxxx" + }, + "updatedBy": { + "objectId": "xxxx", + "name": "xxxx" + }, + "description": "My description", + "watchlistType": "watchlist", + "watchlistAlias": "MyAlias", + "isDeleted": false, + "labels": [], + "defaultDuration": "P1DT3H", + "tenantId": "xxx", + "numberOfLinesToSkip": 1, + "provisioningState": "Succeeded", + "sasUri": "", + "watchlistCategory": "General" + } + }]} +"@ } } } diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index e79c895ab1..7ab66adf08 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -1,3 +1,22 @@ +#region Azure +function Invoke-AzRest +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $Uri, + + [Parameter()] + [System.String] + $Payload, + + [Parameter()] + [System.String] + $Method + ) +} +#endregion #region Microsoft.Graph.Beta.Applications function Get-MgBetaApplication From 650b62fbdf4b738fd9f1d42b0ad25419fa459e72 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 00:33:34 +0000 Subject: [PATCH 418/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 58be3d4bb1..442ef57a03 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -19059,6 +19059,61 @@ } ] }, + { + "ClassName": "MSFT_IntuneAppCategory", + "Parameters": [ + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_MicrosoftGraphAndroidPermissionAction", "Parameters": [ From 198983a48d9b222e44f5ba26892d580a616617b9 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 1 Oct 2024 20:46:00 -0400 Subject: [PATCH 419/465] Update Graph.PermissionList.txt --- Tests/QA/Graph.PermissionList.txt | Bin 5950 -> 6072 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index 7f3779a43e9e867bf837fb382d040ce492c277ce..5742ce0e3e04794f5af0a56aec295df1adf710e5 100644 GIT binary patch delta 11 Scmdm|w?lt}mH6ZXVs!u=#ss_o delta 12 Tcmdm?zfW(2l{gD80~Z4T8@B@R From 43a02c1861a6be4b99598fd13d56a4ab69a1dc56 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 1 Oct 2024 21:01:16 -0400 Subject: [PATCH 420/465] Update MSFT_SentinelWatchlist.schema.mof --- .../MSFT_SentinelWatchlist.schema.mof | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.schema.mof index 11f39102ac..d46d74df89 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SentinelWatchlist/MSFT_SentinelWatchlist.schema.mof @@ -1,19 +1,19 @@ [ClassVersion("1.0.0.0"), FriendlyName("SentinelWatchlist")] class MSFT_SentinelWatchlist : OMI_BaseResource { - [Key, Description("")] String Name; - [Write, Description("")] String SubscriptionId; - [Write, Description("")] String ResourceGroupName; - [Write, Description("")] String WorkspaceName; - [Write, Description("")] String Id; - [Write, Description("")] String DisplayName; - [Write, Description("")] String SourceType; - [Write, Description("")] String ItemsSearchKey; - [Write, Description("")] String Description; - [Write, Description("")] String DefaultDuration; - [Write, Description("")] String Alias; - [Write, Description("")] UInt32 NumberOfLinesToSkip; - [Write, Description("")] String RawContent; + [Key, Description("Tha name of the watchlist.")] String Name; + [Write, Description("The name of the resource group. The name is case insensitive.")] String SubscriptionId; + [Write, Description("The name of the resource group. The name is case insensitive.")] String ResourceGroupName; + [Write, Description("The name of the workspace.")] String WorkspaceName; + [Write, Description("The id (a Guid) of the watchlist")] String Id; + [Write, Description("The display name of the watchlist.")] String DisplayName; + [Write, Description("The source of the watchlist. Only accepts 'Local file' and 'Remote storage'. And it must included in the request.")] String SourceType; + [Write, Description("The search key is used to optimize query performance when using watchlists for joins with other data. For example, enable a column with IP addresses to be the designated SearchKey field, then use this field as the key field when joining to other event data by IP address.")] String ItemsSearchKey; + [Write, Description("A description of the watchlist")] String Description; + [Write, Description("The default duration of a watchlist (in ISO 8601 duration format)")] String DefaultDuration; + [Write, Description("The watchlist alias")] String Alias; + [Write, Description("The number of lines in a csv content to skip before the header")] UInt32 NumberOfLinesToSkip; + [Write, Description("The raw content that represents to watchlist items to create. Example : This line will be skipped header1,header2 value1,value2")] String RawContent; [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] 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 e267bcaf741338b068719e5cb401ef06d2478a46 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 1 Oct 2024 21:46:08 -0400 Subject: [PATCH 421/465] Fixes UT --- .../Examples/Resources/SentinelWatchlist/1-Create.ps1 | 2 +- .../Examples/Resources/SentinelWatchlist/2-Update.ps1 | 2 +- .../Examples/Resources/SentinelWatchlist/3-Remove.ps1 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/1-Create.ps1 index 1fe6876e36..22d433f47b 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/1-Create.ps1 @@ -33,7 +33,7 @@ Configuration Example ItemsSearchKey = "Test"; Name = "MyWatchList"; NumberOfLinesToSkip = 1; - RawContent = (Get-Content 'C:\book2.csv' -Raw) + RawContent = 'MyContent' ResourceGroupName = "MyResourceGroup"; SourceType = "Local"; SubscriptionId = "20f41296-9edc-4374-b5e0-b1c1aa07e7d3"; diff --git a/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/2-Update.ps1 index eff2ea1d35..56e24197f5 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/2-Update.ps1 @@ -33,7 +33,7 @@ Configuration Example ItemsSearchKey = "Test"; Name = "MyWatchList"; NumberOfLinesToSkip = 0; # Drift - RawContent = (Get-Content 'C:\book2.csv' -Raw) + RawContent = 'MyContent' ResourceGroupName = "MyResourceGroup"; SourceType = "Local"; SubscriptionId = "20f41296-9edc-4374-b5e0-b1c1aa07e7d3"; diff --git a/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/3-Remove.ps1 index fb0be88b8f..8fc5a78c3b 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SentinelWatchlist/3-Remove.ps1 @@ -33,7 +33,7 @@ Configuration Example ItemsSearchKey = "Test"; Name = "MyWatchList"; NumberOfLinesToSkip = 1; - RawContent = (Get-Content 'C:\book2.csv' -Raw) + RawContent = 'MyContent' ResourceGroupName = "MyResourceGroup"; SourceType = "Local"; SubscriptionId = "20f41296-9edc-4374-b5e0-b1c1aa07e7d3"; From 6260920d8a17ceb3d37e3887bb68bed455a0fcc2 Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Wed, 2 Oct 2024 10:04:53 +0200 Subject: [PATCH 422/465] expanded and updated tests to refer to beta-cmdlets where appropriate --- .../Microsoft365DSC.AADGroup.Tests.ps1 | 103 ++++++++++++++++-- 1 file changed, 93 insertions(+), 10 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADGroup.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADGroup.Tests.ps1 index ea04994692..7aa3b6429f 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADGroup.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADGroup.Tests.ps1 @@ -37,6 +37,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgGroupMember -MockWith { } + Mock -CommandName Get-MgBetaGroupMember -MockWith { + } + Mock -CommandName Get-MgGroup -MockWith { } @@ -51,6 +54,12 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MgGroupOwner -MockWith { } + Mock -CommandName Get-MgBetaGroupMemberOf -MockWith { + } + + Mock -CommandName Get-MgBetaGroupOwner -MockWith { + } + Mock -CommandName Invoke-MgGraphRequest -MockWith { } @@ -69,6 +78,15 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName New-MgGroupMember -MockWith { } + Mock -CommandName New-MgBetaGroupOwnerByRef -MockWith { + } + + Mock -CommandName New-MgBetaGroupMemberByRef -MockWith { + } + + Mock -CommandName New-MgBetaGroupMember -MockWith { + } + Mock -CommandName New-MgBetaDirectoryRoleMemberByRef -MockWith { } @@ -246,7 +264,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { GroupTypes = @() } } - Mock -CommandName Get-MgGroupMemberOf -MockWith { + Mock -CommandName Get-MgBetaGroupMemberOf -MockWith { return @{ AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.group' @@ -273,7 +291,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return Values from the Get method' { Get-TargetResource @testParams Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 - Should -Invoke -CommandName 'Get-MgGroupMemberOf' -Exactly 1 + Should -Invoke -CommandName 'Get-MgBetaGroupMemberOf' -Exactly 1 } It 'Should return true from the Test method' { @@ -314,7 +332,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { IsAssignableToRole = $true } } - Mock -CommandName Get-MgGroupMemberOf -MockWith { + Mock -CommandName Get-MgBetaGroupMemberOf -MockWith { return @{ AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.directoryRole' @@ -327,7 +345,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return Values from the Get method' { Get-TargetResource @testParams Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 - Should -Invoke -CommandName 'Get-MgGroupMemberOf' -Exactly 1 + Should -Invoke -CommandName 'Get-MgBetaGroupMemberOf' -Exactly 1 } It 'Should return true from the Test method' { @@ -435,7 +453,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return Values from the Get method' { Get-TargetResource @testParams Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 - Should -Invoke -CommandName 'Get-MgGroupMemberOf' -Exactly 1 + Should -Invoke -CommandName 'Get-MgBetaGroupMemberOf' -Exactly 1 } It 'Should return false from the Test method' { @@ -545,7 +563,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } - Mock -CommandName New-MgGroupMemberByRef -MockWith { + Mock -CommandName New-MgBetaGroupMemberByRef -MockWith { } } @@ -561,7 +579,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the Set method' { Set-TargetResource @testParams Should -Invoke -CommandName 'Get-MgGroup' -Exactly 2 - Should -Invoke -CommandName 'New-MgGroupMemberByRef' -Exactly 1 + Should -Invoke -CommandName 'New-MgBetaGroupMemberByRef' -Exactly 1 #Should -Invoke -CommandName 'Remove-MgGroupMemberDirectoryObjectByRef' -Exactly 1 } } @@ -599,7 +617,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { IsAssignableToRole = $true } } - Mock -CommandName Get-MgGroupMemberOf -MockWith { + Mock -CommandName Get-MgBetaGroupMemberOf -MockWith { return @{ AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.directoryRole' @@ -618,7 +636,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should return Values from the Get method' { Get-TargetResource @testParams Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 - Should -Invoke -CommandName 'Get-MgGroupMemberOf' -Exactly 1 + Should -Invoke -CommandName 'Get-MgBetaGroupMemberOf' -Exactly 1 } It 'Should return false from the Test method' { @@ -907,7 +925,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Should -Invoke -CommandName 'Set-MgGroupLicense' -Exactly 1 } } - Context -Name "The Group Exists and is assigned a license but it shouldn't be. Values are NOT in the desired state" -Fixture { + Context -Name "The Group exists and is assigned a license but it shouldn't be. Values are NOT in the desired state" -Fixture { BeforeAll { $testParams = @{ DisplayName = 'DSCGroup' @@ -979,6 +997,71 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } + Context -Name "The Group exists and is assigned a license. Tested values are in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + DisplayName = 'DSCGroup' + ID = '12345-12345-12345-12345' + Description = 'Microsoft DSC Group' + SecurityEnabled = $True + MailEnabled = $false + GroupTypes = @() + MailNickname = 'M365DSC' + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return 'Credentials' + } + + Mock -CommandName Get-MgGroup -MockWith { + return @{ + DisplayName = 'DSCGroup' + ID = '12345-12345-12345-12345' + Description = 'Microsoft DSC Group' + SecurityEnabled = $True + MailEnabled = $false + GroupTypes = @() + MailNickname = 'M365DSC' + IsAssignableToRole = $false + } + } + + Mock -CommandName Invoke-MgGraphRequest -MockWith { + return @{ + value = @{ + DisabledPlans = @() + SkuId = '12345-12345-12345' + } + } + } + + Mock -CommandName Get-MgBetaSubscribedSku -MockWith { + return [pscustomobject]@{ + ServicePlans = @( + @{ + ServicePlanId = '67890-67890-67890' + ServicePlanName = 'Something_P2' + } + ) + SkuId = '12345-12345-12345' + SkuPartNumber = 'AAD_PREMIUM_P2' + } + } + } + + It 'Should return Values from the Get method' { + Get-TargetResource @testParams + Should -Invoke -CommandName 'Get-MgGroup' -Exactly 1 + Should -Invoke -CommandName 'Invoke-MgGraphRequest' -Exactly 1 + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + Context -Name 'ReverseDSC Tests' -Fixture { BeforeAll { $Global:CurrentModeIsExport = $true From fcbfcc0c50692216a84120f354a99b401796fae6 Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Wed, 2 Oct 2024 10:12:32 +0200 Subject: [PATCH 423/465] updated resource to handle all scenarios for AssignedLicenses correctly --- .../MSFT_AADGroup/MSFT_AADGroup.psm1 | 73 +++++++++++++------ 1 file changed, 52 insertions(+), 21 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 index a342d7d613..e8e2fafeec 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 @@ -616,7 +616,7 @@ function Set-TargetResource Update-MgGroup @currentParameters | Out-Null } - if (($licensesToAdd.Length -gt 0 -or $licensesToRemove.Length -gt 0) -and $AssignedLicenses -ne $null) + if (($licensesToAdd.Length -gt 0 -or $licensesToRemove.Length -gt 0) -and $PSBoundParameters.ContainsKey('AssignedLicenses')) { try { @@ -1084,9 +1084,9 @@ function Test-TargetResource try { if ($null -ne $CurrentValues.AssignedLicenses -and $CurrentValues.AssignedLicenses.Length -gt 0 -and ` - $null -eq $AssignedLicenses) + ($PSBoundParameters.ContainsKey('AssignedLicenses') -and $null -eq $AssignedLicenses)) { - Write-Verbose -Message "The group currently has licenses assigned but it shouldn't" + Write-verbose -Message "The group {$DisplayName} currently has licenses assigned but it shouldn't" Write-Verbose -Message "Test-TargetResource returned $false" $EventMessage = "Assigned Licenses for Azure AD Group {$DisplayName} were not in the desired state.`r`nThe group should not have any licenses assigned but instead contained {$($CurrentValues.AssignedLicenses.SkuId)}" Add-M365DSCEvent -Message $EventMessage -EntryType 'Warning' ` @@ -1097,7 +1097,7 @@ function Test-TargetResource elseif ($null -eq $CurrentValues.AssignedLicenses -and $null -ne $AssignedLicenses -and ` $AssignedLicenses.Length -gt 0) { - Write-Verbose -Message "The group currently doesn't have licenses assigned but it should" + Write-verbose -Message "The group {$DisplayName} currently doesn't have licenses assigned but it should" Write-Verbose -Message "Test-TargetResource returned $false" $EventMessage = "Assigned Licenses for Azure AD Group {$DisplayName} were not in the desired state.`r`nThe group doesn't not have any licenses assigned but should have {$($CurrentValues.AssignedLicenses.SkuId)}" Add-M365DSCEvent -Message $EventMessage -EntryType 'Warning' ` @@ -1107,11 +1107,11 @@ function Test-TargetResource } elseif ($CurrentValues.AssignedLicenses.Length -gt 0 -and $AssignedLicenses.Length -gt 0) { - Write-Verbose -Message "Current assigned licenses and desired assigned licenses are not null" + Write-verbose -Message "Current assigned licenses and desired assigned licenses for group {$DisplayName} are not null" $licensesDiff = Compare-Object -ReferenceObject ($CurrentValues.AssignedLicenses.SkuId) -DifferenceObject ($AssignedLicenses.SkuId) if ($null -ne $licensesDiff) { - Write-Verbose -Message "AssignedLicenses differ: $($licensesDiff | Out-String)" + Write-verbose -Message "AssignedLicenses differ for group {$DisplayName}: $($licensesDiff | Out-String)" Write-Verbose -Message "Test-TargetResource returned $false" $EventMessage = "Assigned Licenses for Azure AD Group {$DisplayName} were not in the desired state.`r`nThey should contain {$($AssignedLicenses.SkuId)} but instead contained {$($CurrentValues.AssignedLicenses.SkuId)}" Add-M365DSCEvent -Message $EventMessage -EntryType 'Warning' ` @@ -1121,35 +1121,66 @@ function Test-TargetResource } else { - Write-Verbose -Message 'AssignedLicenses for Azure AD Group are the same' + Write-verbose -Message "AssignedLicenses for Azure AD Group {$DisplayName} are the same" } # Disabled Plans - $licensesDiff = Compare-Object -ReferenceObject ($CurrentValues.AssignedLicenses.DisabledPlans) -DifferenceObject ($AssignedLicenses.DisabledPlans) - if ($null -ne $licensesDiff) + #Compare DisabledPlans for each SkuId - all SkuId's are processed regardless of result + $result = $true + foreach ($assignedLicense in $AssignedLicenses) { - Write-Verbose -Message "DisabledPlans differ: $($licensesDiff | Out-String)" - Write-Verbose -Message "Test-TargetResource returned $false" - $EventMessage = "Disabled Plans for Azure AD Group Licenses {$DisplayName} were not in the desired state.`r`n" + ` - "They should contain {$($AssignedLicenses.DisabledPlans)} but instead contained {$($CurrentValues.AssignedLicenses.DisabledPlans)}" - Add-M365DSCEvent -Message $EventMessage -EntryType 'Warning' ` - -EventID 1 -Source $($MyInvocation.MyCommand.Source) - - return $false + write-verbose "Compare DisabledPlans for SkuId $($assignedLicense.SkuId) in group {$DisplayName}" + $currentLicense = $CurrentValues.AssignedLicenses | Where-Object -FilterScript {$_.SkuId -eq $assignedLicense.SkuId} + if ($assignedLicense.DisabledPlans.Count -ne 0 -or $currentLicense.DisabledPlans.Count -ne 0) + { + try { + $licensesDiff = Compare-Object -ReferenceObject $assignedLicense.DisabledPlans -DifferenceObject $currentLicense.DisabledPlans + if ($null -ne $licensesDiff) + { + Write-verbose -Message "DisabledPlans for SkuId $($assignedLicense.SkuId) differ: $($licensesDiff | Out-String)" + Write-Verbose -Message "Test-TargetResource returned $false" + $EventMessage = "Disabled Plans for Azure AD Group Licenses {$DisplayName} SkuId $($assignedLicense.SkuId) were not in the desired state.`r`n" + ` + "They should contain {$($assignedLicense.DisabledPlans -join ',')} but instead contained {$($currentLicense.DisabledPlans -join ',')}" + Add-M365DSCEvent -Message $EventMessage -EntryType 'Warning' ` + -EventID 1 -Source $($MyInvocation.MyCommand.Source) + + $result = $false + } + else + { + Write-verbose -Message "DisabledPlans for SkuId $($assignedLicense.SkuId) are the same" + } + } + catch + { + Write-verbose -Message "Test-TargetResource returned `$false (DisabledPlans: $($_.Exception.Message))" + $result = $false + } + } } - else + if ($true -ne $result) { - Write-Verbose -Message 'DisabledPlans for Azure AD Group Licensing are the same' + return $result } } + elseif ($PSBoundParameters.ContainsKey('AssignedLicenses')) + { + Write-verbose -Message "The group {$DisplayName} currently has licenses assigned but it shouldn't have" + Write-Verbose -Message "Test-TargetResource returned $false" + $EventMessage = "Assigned Licenses for Azure AD Group {$DisplayName} were not in the desired state.`r`nThe group has licenses assigned but shouldn't have {$($CurrentValues.AssignedLicenses.SkuId)}" + Add-M365DSCEvent -Message $EventMessage -EntryType 'Warning' ` + -EventID 1 -Source $($MyInvocation.MyCommand.Source) + + return $false + } else { - Write-Verbose -Message "Both the current and desired assigned licenses lists are empty." + Write-verbose -Message "Both the current and desired assigned licenses lists for group {$DisplayName} are empty or not specified." } } catch { - Write-Verbose -Message "Error evaluating the AssignedLicenses: $_" + Write-Verbose -Message "Error evaluating the AssignedLicenses for group {$DisplayName}: $_" Write-Verbose -Message "Test-TargetResource returned $false" return $false } From 151c3239420ffe9946dcfb0190ab4c1bd4987eff Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Wed, 2 Oct 2024 10:53:04 +0200 Subject: [PATCH 424/465] added example for using AssignedLicenses --- .../Examples/Resources/AADGroup/4-License.ps1 | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADGroup/4-License.ps1 diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADGroup/4-License.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADGroup/4-License.ps1 new file mode 100644 index 0000000000..bd9e330f0e --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/AADGroup/4-License.ps1 @@ -0,0 +1,43 @@ +<# +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()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + AADGroup 'MyGroups' + { + DisplayName = "DSCGroup" + Description = "Microsoft DSC Group with assigned license" # Updated Property + SecurityEnabled = $True + MailEnabled = $False + MailNickname = "M365DSC" + AssignedLicenses = @( + MSFT_AADGroupLicense -Property @{ + SkuId = 'AAD_PREMIUM_P2' + } + ) + + Ensure = "Present" + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} From 3eb2c8857524ce62af7f77dab193d38efb43bf26 Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Wed, 2 Oct 2024 11:21:56 +0200 Subject: [PATCH 425/465] updated changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22b720e3a1..214b1eef46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Change log for Microsoft365DSC # UNRELEASED +* AADGroup + * Fixes issue with code that is never executed + FIXES [#5001](https://github.com/microsoft/Microsoft365DSC/issues/5001) + * Fixes issue with incorrect removal of assigned license(s) + FIXES [#5128](https://github.com/microsoft/Microsoft365DSC/issues/5128) + * IntuneAppCategory * Initial release. From 1a2266a33eecb7da198d88db353f26596404f247 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Wed, 2 Oct 2024 11:37:47 +0200 Subject: [PATCH 426/465] Fix AccessTokens parameter not available in Intune Antivirus policy --- CHANGELOG.md | 2 ++ ...MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.schema.mof | 1 + 2 files changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22b720e3a1..1eac371aa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,8 @@ * IntuneAntivirusPolicyWindows10SettingCatalog * Fixes an issue with invalid parameter definition. FIXES [#5015](https://github.com/microsoft/Microsoft365DSC/issues/5015) + * Fixes an issue where the `AccessTokens` parameter was not available. + FIXES [#5121](https://github.com/microsoft/Microsoft365DSC/issues/5121) * IntuneDeviceCompliancePolicyWindows10 * Fixes an issue where the property `ValidOperatingSystemBuildRanges` was not exported properly. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.schema.mof index f95e692cab..da964ec534 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.schema.mof @@ -97,4 +97,5 @@ class MSFT_IntuneAntivirusPolicyWindows10SettingCatalog : OMI_BaseResource [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; }; From 3f343f673bd5b24522b6eee97b9609a5a977dd16 Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Wed, 2 Oct 2024 11:58:55 +0200 Subject: [PATCH 427/465] fixed example --- .../Microsoft365DSC/Examples/Resources/AADGroup/4-License.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADGroup/4-License.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADGroup/4-License.ps1 index bd9e330f0e..0704ae08bd 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADGroup/4-License.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADGroup/4-License.ps1 @@ -29,7 +29,7 @@ Configuration Example MailEnabled = $False MailNickname = "M365DSC" AssignedLicenses = @( - MSFT_AADGroupLicense -Property @{ + MSFT_AADGroupLicense { SkuId = 'AAD_PREMIUM_P2' } ) From 0b9897c414c6e099ef6873a55e4c529f6bfcfbed Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Wed, 2 Oct 2024 12:24:15 +0200 Subject: [PATCH 428/465] fixed typos --- .../MSFT_AADGroup/MSFT_AADGroup.psm1 | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 index e8e2fafeec..92e1614b52 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 @@ -1086,9 +1086,9 @@ function Test-TargetResource if ($null -ne $CurrentValues.AssignedLicenses -and $CurrentValues.AssignedLicenses.Length -gt 0 -and ` ($PSBoundParameters.ContainsKey('AssignedLicenses') -and $null -eq $AssignedLicenses)) { - Write-verbose -Message "The group {$DisplayName} currently has licenses assigned but it shouldn't" + Write-Verbose -Message "The group {$DisplayName} currently has licenses assigned but it shouldn't" Write-Verbose -Message "Test-TargetResource returned $false" - $EventMessage = "Assigned Licenses for Azure AD Group {$DisplayName} were not in the desired state.`r`nThe group should not have any licenses assigned but instead contained {$($CurrentValues.AssignedLicenses.SkuId)}" + $EventMessage = "Assigned Licenses for Azure AD Group {$DisplayName} were not in the desired state.`r`nThe group should not have any licenses assigned but instead contained {$($CurrentValues.AssignedLicenses.SkuId -join ',')}" Add-M365DSCEvent -Message $EventMessage -EntryType 'Warning' ` -EventID 1 -Source $($MyInvocation.MyCommand.Source) @@ -1097,9 +1097,9 @@ function Test-TargetResource elseif ($null -eq $CurrentValues.AssignedLicenses -and $null -ne $AssignedLicenses -and ` $AssignedLicenses.Length -gt 0) { - Write-verbose -Message "The group {$DisplayName} currently doesn't have licenses assigned but it should" + Write-Verbose -Message "The group {$DisplayName} currently doesn't have licenses assigned but it should" Write-Verbose -Message "Test-TargetResource returned $false" - $EventMessage = "Assigned Licenses for Azure AD Group {$DisplayName} were not in the desired state.`r`nThe group doesn't not have any licenses assigned but should have {$($CurrentValues.AssignedLicenses.SkuId)}" + $EventMessage = "Assigned Licenses for Azure AD Group {$DisplayName} were not in the desired state.`r`nThe group doesn't not have any licenses assigned but should have {$($CurrentValues.AssignedLicenses.SkuId -join ',')}" Add-M365DSCEvent -Message $EventMessage -EntryType 'Warning' ` -EventID 1 -Source $($MyInvocation.MyCommand.Source) @@ -1107,13 +1107,13 @@ function Test-TargetResource } elseif ($CurrentValues.AssignedLicenses.Length -gt 0 -and $AssignedLicenses.Length -gt 0) { - Write-verbose -Message "Current assigned licenses and desired assigned licenses for group {$DisplayName} are not null" + Write-Verbose -Message "Current assigned licenses and desired assigned licenses for group {$DisplayName} are not null and will be compared" $licensesDiff = Compare-Object -ReferenceObject ($CurrentValues.AssignedLicenses.SkuId) -DifferenceObject ($AssignedLicenses.SkuId) if ($null -ne $licensesDiff) { - Write-verbose -Message "AssignedLicenses differ for group {$DisplayName}: $($licensesDiff | Out-String)" + Write-Verbose -Message "AssignedLicenses differ for group {$DisplayName}: $($licensesDiff | Out-String)" Write-Verbose -Message "Test-TargetResource returned $false" - $EventMessage = "Assigned Licenses for Azure AD Group {$DisplayName} were not in the desired state.`r`nThey should contain {$($AssignedLicenses.SkuId)} but instead contained {$($CurrentValues.AssignedLicenses.SkuId)}" + $EventMessage = "Assigned Licenses for Azure AD Group {$DisplayName} were not in the desired state.`r`nThey should contain {$($AssignedLicenses.SkuId -join ',')} but instead contained {$($CurrentValues.AssignedLicenses.SkuId -join ',')}" Add-M365DSCEvent -Message $EventMessage -EntryType 'Warning' ` -EventID 1 -Source $($MyInvocation.MyCommand.Source) @@ -1121,7 +1121,7 @@ function Test-TargetResource } else { - Write-verbose -Message "AssignedLicenses for Azure AD Group {$DisplayName} are the same" + Write-Verbose -Message "AssignedLicenses for Azure AD Group {$DisplayName} are the same, checking DisabledPlans" } # Disabled Plans @@ -1129,7 +1129,7 @@ function Test-TargetResource $result = $true foreach ($assignedLicense in $AssignedLicenses) { - write-verbose "Compare DisabledPlans for SkuId $($assignedLicense.SkuId) in group {$DisplayName}" + Write-Verbose "Compare DisabledPlans for SkuId $($assignedLicense.SkuId) in group {$DisplayName}" $currentLicense = $CurrentValues.AssignedLicenses | Where-Object -FilterScript {$_.SkuId -eq $assignedLicense.SkuId} if ($assignedLicense.DisabledPlans.Count -ne 0 -or $currentLicense.DisabledPlans.Count -ne 0) { @@ -1137,7 +1137,7 @@ function Test-TargetResource $licensesDiff = Compare-Object -ReferenceObject $assignedLicense.DisabledPlans -DifferenceObject $currentLicense.DisabledPlans if ($null -ne $licensesDiff) { - Write-verbose -Message "DisabledPlans for SkuId $($assignedLicense.SkuId) differ: $($licensesDiff | Out-String)" + Write-Verbose -Message "DisabledPlans for SkuId $($assignedLicense.SkuId) differ: $($licensesDiff | Out-String)" Write-Verbose -Message "Test-TargetResource returned $false" $EventMessage = "Disabled Plans for Azure AD Group Licenses {$DisplayName} SkuId $($assignedLicense.SkuId) were not in the desired state.`r`n" + ` "They should contain {$($assignedLicense.DisabledPlans -join ',')} but instead contained {$($currentLicense.DisabledPlans -join ',')}" @@ -1148,12 +1148,12 @@ function Test-TargetResource } else { - Write-verbose -Message "DisabledPlans for SkuId $($assignedLicense.SkuId) are the same" + Write-Verbose -Message "DisabledPlans for SkuId $($assignedLicense.SkuId) are the same" } } catch { - Write-verbose -Message "Test-TargetResource returned `$false (DisabledPlans: $($_.Exception.Message))" + Write-Verbose -Message "Test-TargetResource returned `$false (DisabledPlans: $($_.Exception.Message))" $result = $false } } @@ -1165,7 +1165,7 @@ function Test-TargetResource } elseif ($PSBoundParameters.ContainsKey('AssignedLicenses')) { - Write-verbose -Message "The group {$DisplayName} currently has licenses assigned but it shouldn't have" + Write-Verbose -Message "The group {$DisplayName} currently has licenses assigned but it shouldn't have" Write-Verbose -Message "Test-TargetResource returned $false" $EventMessage = "Assigned Licenses for Azure AD Group {$DisplayName} were not in the desired state.`r`nThe group has licenses assigned but shouldn't have {$($CurrentValues.AssignedLicenses.SkuId)}" Add-M365DSCEvent -Message $EventMessage -EntryType 'Warning' ` @@ -1175,7 +1175,7 @@ function Test-TargetResource } else { - Write-verbose -Message "Both the current and desired assigned licenses lists for group {$DisplayName} are empty or not specified." + Write-Verbose -Message "Both the current and desired assigned licenses lists for group {$DisplayName} are empty or not specified." } } catch From 4dc3923d788663a1d8da6f34e67ba3610de3ca58 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 2 Oct 2024 06:30:45 -0400 Subject: [PATCH 429/465] Update Microsoft365DSC.SentinelSetting.Tests.ps1 --- .../Microsoft365DSC/Microsoft365DSC.SentinelSetting.Tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelSetting.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelSetting.Tests.ps1 index 54e5f57ef4..fe6c03151d 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelSetting.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SentinelSetting.Tests.ps1 @@ -42,6 +42,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return @{ ResourceGroupName = "MyResourceGroup" Name = 'MySentinelWorkspace' + ResourceId = "name/part/resourceId/" } } From ddd34de3c5651c5aa83643e9f285269117618cdf Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 10:44:07 +0000 Subject: [PATCH 430/465] Updated Resources and Cmdlet documentation pages --- .../security-compliance/SentinelWatchlist.md | 201 ++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 docs/docs/resources/security-compliance/SentinelWatchlist.md diff --git a/docs/docs/resources/security-compliance/SentinelWatchlist.md b/docs/docs/resources/security-compliance/SentinelWatchlist.md new file mode 100644 index 0000000000..42ef092a7e --- /dev/null +++ b/docs/docs/resources/security-compliance/SentinelWatchlist.md @@ -0,0 +1,201 @@ +# SentinelWatchlist + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Name** | Key | String | Tha name of the watchlist. | | +| **SubscriptionId** | Write | String | The name of the resource group. The name is case insensitive. | | +| **ResourceGroupName** | Write | String | The name of the resource group. The name is case insensitive. | | +| **WorkspaceName** | Write | String | The name of the workspace. | | +| **Id** | Write | String | The id (a Guid) of the watchlist | | +| **DisplayName** | Write | String | The display name of the watchlist. | | +| **SourceType** | Write | String | The source of the watchlist. Only accepts 'Local file' and 'Remote storage'. And it must included in the request. | | +| **ItemsSearchKey** | Write | String | The search key is used to optimize query performance when using watchlists for joins with other data. For example, enable a column with IP addresses to be the designated SearchKey field, then use this field as the key field when joining to other event data by IP address. | | +| **Description** | Write | String | A description of the watchlist | | +| **DefaultDuration** | Write | String | The default duration of a watchlist (in ISO 8601 duration format) | | +| **Alias** | Write | String | The watchlist alias | | +| **NumberOfLinesToSkip** | Write | UInt32 | The number of lines in a csv content to skip before the header | | +| **RawContent** | Write | String | The raw content that represents to watchlist items to create. Example : This line will be skipped header1,header2 value1,value2 | | +| **Ensure** | Write | String | Present ensures the instance exists, absent ensures it is removed. | `Absent`, `Present` | +| **Credential** | Write | PSCredential | Credentials of the workload's Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + + +## Description + +Configures watchlists in Azure Sentinel. + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - None + +- **Update** + + - None + +#### Application permissions + +- **Read** + + - None + +- **Update** + + - None + +## Examples + +### Example 1 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SentinelWatchlist "SentinelWatchlist-TestWatch" + { + Alias = "MyAlias"; + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + DefaultDuration = "P1DT3H"; + Description = "My description"; + DisplayName = "My Display Name"; + Ensure = "Present"; + ItemsSearchKey = "Test"; + Name = "MyWatchList"; + NumberOfLinesToSkip = 1; + RawContent = 'MyContent' + ResourceGroupName = "MyResourceGroup"; + SourceType = "Local"; + SubscriptionId = "20f41296-9edc-4374-b5e0-b1c1aa07e7d3"; + TenantId = $TenantId; + WorkspaceName = "MyWorkspace"; + } + } +} +``` + +### Example 2 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SentinelWatchlist "SentinelWatchlist-TestWatch" + { + Alias = "MyAlias"; + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + DefaultDuration = "P1DT3H"; + Description = "My description"; + DisplayName = "My Display Name"; + Ensure = "Present"; + ItemsSearchKey = "Test"; + Name = "MyWatchList"; + NumberOfLinesToSkip = 0; # Drift + RawContent = 'MyContent' + ResourceGroupName = "MyResourceGroup"; + SourceType = "Local"; + SubscriptionId = "20f41296-9edc-4374-b5e0-b1c1aa07e7d3"; + TenantId = $TenantId; + WorkspaceName = "MyWorkspace"; + } + } +} +``` + +### Example 3 + +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. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + SentinelWatchlist "SentinelWatchlist-TestWatch" + { + Alias = "MyAlias"; + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + DefaultDuration = "P1DT3H"; + Description = "My description"; + DisplayName = "My Display Name"; + Ensure = "Absent"; + ItemsSearchKey = "Test"; + Name = "MyWatchList"; + NumberOfLinesToSkip = 1; + RawContent = 'MyContent' + ResourceGroupName = "MyResourceGroup"; + SourceType = "Local"; + SubscriptionId = "20f41296-9edc-4374-b5e0-b1c1aa07e7d3"; + TenantId = $TenantId; + WorkspaceName = "MyWorkspace"; + } + } +} +``` + From a17c10f729a20be5dc189452e9d5c3e17e3e0822 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 10:46:05 +0000 Subject: [PATCH 431/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 442ef57a03..610bdf1c69 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -43019,6 +43019,111 @@ } ] }, + { + "ClassName": "MSFT_SentinelWatchlist", + "Parameters": [ + { + "CIMType": "String", + "Name": "Name", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "SubscriptionId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ResourceGroupName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "WorkspaceName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "SourceType", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ItemsSearchKey", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DefaultDuration", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Alias", + "Option": "Write" + }, + { + "CIMType": "UInt32", + "Name": "NumberOfLinesToSkip", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "RawContent", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_SPOAccessControlSettings", "Parameters": [ From cc3bc78052ee0bad53711c9fde8c9ee18e613d58 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 10:46:22 +0000 Subject: [PATCH 432/465] Updated {Create} Intune Integration Tests --- .../M365DSCIntegration.INTUNE.Create.Tests.ps1 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 index 09a05d0878..05e2c09569 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 @@ -106,6 +106,12 @@ TenantId = $TenantId; CertificateThumbprint = $CertificateThumbprint; } + IntuneAppCategory 'IntuneAppCategory-Data Management' + { + Id = "a1fc9fe2-728d-4867-9a72-a61e18f8c606"; + DisplayName = "Custom Data Management"; + Ensure = "Present"; + } IntuneAppConfigurationDevicePolicy 'IntuneAppConfigurationDevicePolicy-Example' { Assignments = @(); From 0bb5154638ef94b8ce8a2d980d13cd793b03c7d2 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 11:20:18 +0000 Subject: [PATCH 433/465] Updated Graph Permissions List --- Tests/QA/Graph.PermissionList.txt | Bin 3035 -> 5826 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/QA/Graph.PermissionList.txt b/Tests/QA/Graph.PermissionList.txt index 451430ea55541130cde49fd1d246a0d2b11f585c..826113f235a6a0d9238e46bc09b5d42a131a610f 100644 GIT binary patch literal 5826 zcmb_gU2hsO5ZvcV{U;y zTCKo7eX{Uz=Jd=G^jPLrzGKaE`0qk~swZi$=X_`C^EGTnuU+EV%QyVJQEvoG2HV9P zAxelngwzTM6)^T{|Jv}mC4T`wZJ_TS(mNSF#n4CmGFJDd=kjGNMn)QStzn-DIAe~U z#$jso0`s}LDQtQSC9rbdJ)~;&#|o>Vor&MxDeYM|7+=dBzIW0318Uf#ZMl)+a&Onz z0r9#{m$2EmJ0D=T0oE1bB1X4o*l6@T<7EuJYqe5?jN~F=pmD*yOlytQip(%vna%ui zG+RrTTQ=|r?K?$`H~3JOJJ`bS9cs!9OY5iheg7#>m1C7^=&bn&-59^r@0caKSKN(f zY3gHt0bkQ@j3dT4tCPzc)a(P^aL2^eB8A2kO@U!W1lbP9yO3^_dx9v7tJVlC^!OH9 z+50MHI}M{mqY9dA3pF{EEz#h#TH9rv9JCTGV^7R9_xgw^^I{%eiKau;>MD^{yR3I8 zTcQE8+wR|vi9OP_yJD;OPA><|)^Z6gm}l9E?9jj1?CDu~sO)#AU|8ehdjX%jQ?c=! zGZ(|wh};v+!}bcTaSQ26b0sSeE2X!;z|WC8&TRK(q5BD3_Dl=?8dZ?-$JlES?V+;recb;A zo_raL@fN78!0Z8jby%-^?kNoHyV<*wd!~_Z_i`!LFP+AHqfD+p-r#)P$QyYl zZ{->q@svfo@@(SwUx>7n9%JY+!(+*?r{fvY_3dqome04mI{=S6)!J1eJ#L+c`K|wrexde`9J!!F?lw*hZZik#CH%Sc@U31%ZaJN~E?JW>_WAuEVTP#D&WdvVoge|b{J3NdwW@(-W zXxkYo9%sb}mzcA|yU@Y({@st{R%OrLHNOw`a3as=d5Ml!@E^F+SGQDGj z@)g7=r>!NG1uR|sjm2DZ2P+D1D!ChJx4ak}Y0Y4yG2(OTb*@Bgg9LwRgu!tCbpU6ldEr3lj$|1`9}b(_i1Qal+Wf*&cdi=Di0D z^Fc0ZsipIld3lCsE&XB#Oe}JxvOMkkZKa0*s4PGYnsS<^V4f*cbvgu#4zPZ2PtF%c zA7piE_cWU9cNa2{Qj$-}1LHhAc%I%gh~*{Ao94=U*g0&59$_8q{J13i?OsO&h3R zz>bdJ`%3U$>WZ8$2>C-8k;H5< zbqPH8-pZF#`#J|q*kR%nAEE9E;xW(CVImF>Igy;;qG%iaig^%Qu(ib8F#3nZD2$@N zg0tih13}hQs|9VCW>qMyl3Ur(ObWCa#JmtDI(hK1$jv)1FjKW-r73J)GF(Cgi94rD z;O0el%bcX@_;@$(yg&)IeFM?}x^6dCn!<>rw7|Ww7xLNzQv$jJZffi)qU&rl8dqit zL4-`rBx$FsxQ?K;_R^~^vq%QrTK>E{O8l_q)GP`MnDJRy-1u=h!ara%&tToCYj^mm zZ$u`&tb2)$MT`;tC~z7{f9Z-<^!=~nBt4P%WGklSpV9Fq)--{sC6>DwG!RN1`3E8x z7tc7Eph&#-=ZCf`b1nKzBPl^atBYo}fZ0lR=WO$Lnqlj#^R@gLRz4gAS5W5PC${`>?y^?C#1H&H(`7uRg`^||paa%>e`rU)oOktX690-H&?u_q0 Ikw1U>3$l}G7ytkO From 0b5f3a10fb34307dcaa6ae800c4f6cd1152507f2 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Wed, 2 Oct 2024 13:55:30 +0200 Subject: [PATCH 434/465] Enable multiple values for app mgmt levels --- CHANGELOG.md | 3 +++ .../MSFT_IntuneAppProtectionPolicyiOS.psm1 | 22 ++++++++++--------- ...FT_IntuneAppProtectionPolicyiOS.schema.mof | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22b720e3a1..fd7b33d15c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,9 @@ * IntuneAntivirusPolicyWindows10SettingCatalog * Fixes an issue with invalid parameter definition. FIXES [#5015](https://github.com/microsoft/Microsoft365DSC/issues/5015) +* IntuneAppProtectionPolicyiOS + * Improve `TargetedAppManagementLevels` property to specify multiple values. + FIXES [#5032](https://github.com/microsoft/Microsoft365DSC/issues/5032) * IntuneDeviceCompliancePolicyWindows10 * Fixes an issue where the property `ValidOperatingSystemBuildRanges` was not exported properly. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppProtectionPolicyiOS/MSFT_IntuneAppProtectionPolicyiOS.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppProtectionPolicyiOS/MSFT_IntuneAppProtectionPolicyiOS.psm1 index 94f6a51ff1..73f67afefb 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppProtectionPolicyiOS/MSFT_IntuneAppProtectionPolicyiOS.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppProtectionPolicyiOS/MSFT_IntuneAppProtectionPolicyiOS.psm1 @@ -170,7 +170,7 @@ function Get-TargetResource [Parameter()] [ValidateSet('unspecified', 'unmanaged', 'mdm', 'androidEnterprise')] - [System.String] + [System.String[]] $TargetedAppManagementLevels, [Parameter()] @@ -393,7 +393,7 @@ function Get-TargetResource PinRequiredInsteadOfBiometricTimeout = $myPinRequiredInsteadOfBiometricTimeout AllowedOutboundClipboardSharingExceptionLength = $policy.AllowedOutboundClipboardSharingExceptionLength NotificationRestriction = [String]$policy.NotificationRestriction - TargetedAppManagementLevels = [String]$policy.TargetedAppManagementLevels + TargetedAppManagementLevels = [String[]]$policy.TargetedAppManagementLevels.ToString().Split(',') ExemptedAppProtocols = $exemptedAppProtocolsArray MinimumWipeSdkVersion = $policy.MinimumWipeSdkVersion AllowedIosDeviceModels = $policy.AllowedIosDeviceModels @@ -594,7 +594,7 @@ function Set-TargetResource [Parameter()] [ValidateSet('unspecified', 'unmanaged', 'mdm', 'androidEnterprise')] - [System.String] + [System.String[]] $TargetedAppManagementLevels, [Parameter()] @@ -707,9 +707,10 @@ function Set-TargetResource { Write-Verbose -Message "Creating new iOS App Protection Policy {$DisplayName}" $createParameters = ([Hashtable]$PSBoundParameters).clone() - $createParameters.remove('Identity') - $createParameters.remove('Assignments') - $createParameters.remove('Apps') + $createParameters.Remove('Identity') + $createParameters.Remove('Assignments') + $createParameters.Remove('Apps') + $createParameter.TargetedAppManagementLevels = $createParameters.TargetedAppManagementLevels -join ',' $myApps = Get-IntuneAppProtectionPolicyiOSAppsToHashtable -Parameters $PSBoundParameters $myAssignments = Get-IntuneAppProtectionPolicyiOSAssignmentToHashtable -Parameters $PSBoundParameters @@ -758,9 +759,10 @@ function Set-TargetResource { Write-Verbose -Message "Updating existing iOS App Protection Policy {$DisplayName}" $updateParameters = ([Hashtable]$PSBoundParameters).clone() - $updateParameters.remove('Identity') - $updateParameters.remove('Assignments') - $updateParameters.remove('Apps') + $updateParameters.Remove('Identity') + $updateParameters.Remove('Assignments') + $updateParameters.Remove('Apps') + $updateParameters.TargetedAppManagementLevels = $updateParameters.TargetedAppManagementLevels -join ',' $myApps = Get-IntuneAppProtectionPolicyiOSAppsToHashtable -Parameters $PSBoundParameters $myAssignments = Get-IntuneAppProtectionPolicyiOSAssignmentToHashtable -Parameters $PSBoundParameters @@ -982,7 +984,7 @@ function Test-TargetResource [Parameter()] [ValidateSet('unspecified', 'unmanaged', 'mdm', 'androidEnterprise')] - [System.String] + [System.String[]] $TargetedAppManagementLevels, [Parameter()] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppProtectionPolicyiOS/MSFT_IntuneAppProtectionPolicyiOS.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppProtectionPolicyiOS/MSFT_IntuneAppProtectionPolicyiOS.schema.mof index 58efec471d..1801c4dd5f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppProtectionPolicyiOS/MSFT_IntuneAppProtectionPolicyiOS.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppProtectionPolicyiOS/MSFT_IntuneAppProtectionPolicyiOS.schema.mof @@ -40,7 +40,7 @@ class MSFT_IntuneAppProtectionPolicyiOS : OMI_BaseResource [Write, Description("Timeout in minutes for an app pin instead of non biometrics passcode .")] String PinRequiredInsteadOfBiometricTimeout; [Write, Description("Specify the number of characters that may be cut or copied from Org data and accounts to any application. This setting overrides the AllowedOutboundClipboardSharingLevel restriction. Default value of '0' means no exception is allowed.")] Uint32 AllowedOutboundClipboardSharingExceptionLength; [Write, Description("Specify app notification restriction."), ValueMap{"allow","blockOrganizationalData","block"}, Values{"allow","blockOrganizationalData","block"}] String NotificationRestriction; - [Write, Description("The intended app management levels for this policy."), ValueMap{"unspecified","unmanaged","mdm","androidEnterprise"}, Values{"unspecified","unmanaged","mdm","androidEnterprise"}] String TargetedAppManagementLevels; + [Write, Description("The intended app management levels for this policy."), ValueMap{"unspecified","unmanaged","mdm","androidEnterprise"}, Values{"unspecified","unmanaged","mdm","androidEnterprise"}] String TargetedAppManagementLevels[]; [Write, Description("Require app data to be encrypted."), Values{"useDeviceSettings","afterDeviceRestart","whenDeviceLockedExceptOpenFiles","whenDeviceLocked"}, ValueMap{"useDeviceSettings","afterDeviceRestart","whenDeviceLockedExceptOpenFiles","whenDeviceLocked"}] String AppDataEncryptionType; [Write, Description("Apps in this list will be exempt from the policy and will be able to receive data from managed apps.")] String ExemptedAppProtocols[]; [Write, Description("Versions less than the specified version will block the managed app from accessing company data.")] String MinimumWipeSdkVersion; From 83b99c2309ef0612a2897498e0779b9e10fdd4cb Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 12:08:36 +0000 Subject: [PATCH 435/465] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/exchange/EXOMailTips.md | 81 --------------------- 1 file changed, 81 deletions(-) diff --git a/docs/docs/resources/exchange/EXOMailTips.md b/docs/docs/resources/exchange/EXOMailTips.md index 166ea4f104..6c5cb88be6 100644 --- a/docs/docs/resources/exchange/EXOMailTips.md +++ b/docs/docs/resources/exchange/EXOMailTips.md @@ -10,7 +10,6 @@ | **MailTipsLargeAudienceThreshold** | Write | UInt32 | Specifies what a large audience is. | | | **MailTipsMailboxSourcedTipsEnabled** | Write | Boolean | Specifies whether MailTips that rely on mailbox data (out-of-office or full mailbox) are enabled. | | | **MailTipsExternalRecipientsTipsEnabled** | Write | Boolean | Specifies whether MailTips for external recipients are enabled. | | -| **Ensure** | Write | String | Specifies if this MailTip should exist. | `Present`, `Absent` | | **Credential** | Write | PSCredential | Credentials of the Exchange Global Admin | | | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | @@ -45,48 +44,6 @@ To authenticate with Microsoft Exchange, this resource required the following pe 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. -```powershell -Configuration Example -{ - param( - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - Import-DscResource -ModuleName Microsoft365DSC - - node localhost - { - EXOMailTips 'OrgWideMailTips' - { - IsSingleInstance = 'Yes' - MailTipsAllTipsEnabled = $True - MailTipsGroupMetricsEnabled = $True - #MailTipsLargeAudienceThreshold = 100 - MailTipsMailboxSourcedTipsEnabled = $True - MailTipsExternalRecipientsTipsEnabled = $True - Ensure = "Present" - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - } - } -} -``` - -### Example 2 - -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. - ```powershell Configuration Example { @@ -115,44 +72,6 @@ Configuration Example #MailTipsLargeAudienceThreshold = 100 MailTipsMailboxSourcedTipsEnabled = $True MailTipsExternalRecipientsTipsEnabled = $True - Ensure = "Present" - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - } - } -} -``` - -### Example 3 - -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. - -```powershell -Configuration Example -{ - param( - [Parameter()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - Import-DscResource -ModuleName Microsoft365DSC - - node localhost - { - EXOMailTips 'OrgWideMailTips' - { - IsSingleInstance = 'Yes' - Ensure = "Absent" ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint From d20dfc2de901f1135a5ed42684eb1ccbd60f746a Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 12:11:06 +0000 Subject: [PATCH 436/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 610bdf1c69..6a072f3b51 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -11557,11 +11557,6 @@ "Name": "MailTipsExternalRecipientsTipsEnabled", "Option": "Write" }, - { - "CIMType": "String", - "Name": "Ensure", - "Option": "Write" - }, { "CIMType": "MSFT_Credential", "Name": "Credential", From a55cec971424b11de28e9aa1408dcfdcc2d17d13 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 12:11:19 +0000 Subject: [PATCH 437/465] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index b77b1a29db..f69b8d3f89 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -458,19 +458,6 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } - EXOMailTips 'OrgWideMailTips' - { - IsSingleInstance = 'Yes' - MailTipsAllTipsEnabled = $True - MailTipsGroupMetricsEnabled = $True - #MailTipsLargeAudienceThreshold = 100 - MailTipsMailboxSourcedTipsEnabled = $True - MailTipsExternalRecipientsTipsEnabled = $True - Ensure = "Present" - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - } EXOMalwareFilterPolicy 'ConfigureMalwareFilterPolicy' { Identity = "IntegrationMFP" From a6fd1ef1eb14fee9e614450bb38e8731ca1bb0b4 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 2 Oct 2024 08:11:31 -0400 Subject: [PATCH 438/465] Update Scheduled - Generate Permission List.yml --- .../Scheduled - Generate Permission List.yml | 286 +++++++++++++++--- 1 file changed, 237 insertions(+), 49 deletions(-) diff --git a/.github/workflows/Scheduled - Generate Permission List.yml b/.github/workflows/Scheduled - Generate Permission List.yml index 6d02dc3383..9a918fa9fa 100644 --- a/.github/workflows/Scheduled - Generate Permission List.yml +++ b/.github/workflows/Scheduled - Generate Permission List.yml @@ -1,49 +1,237 @@ -name: Generate Permissions List -on: - push: - branches: - - Master - - Dev - schedule: - - cron: "0 0 * * *" - -jobs: - # This workflow contains a single job called "build" - GeneratePermissionsList: - # The type of runner that the job will run on - runs-on: windows-latest - - permissions: write-all - - # Only when run from the main repo - if: github.repository == 'microsoft/Microsoft365DSC' - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - name: Checkout Repository - uses: actions/checkout@v3 - - - name: Install Dependencies - shell: powershell - run: | - Import-Module './Modules/Microsoft365DSC/Microsoft365DSC.psd1' -Force; - Import-Module './Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1' -Force; - Update-M365DSCModule - - name: Get Permissions List - shell: powershell - run: | - Import-Module './Tests/TestHarness.psm1' -Force; - $permissions = Get-M365DSCAllGraphPermissionsList - $permissions -join ',' | Out-File '.\Tests\QA\Graph.PermissionList.txt' - - name: Commit Permissions List - shell: powershell - run: | - git config --local user.email "nicharl@microsoft.com" - git config --local user.name "NikCharlebois" - git add D:/a/Microsoft365DSC/Microsoft365DSC/Tests/QA/* - git pull - git commit -m "Updated Graph Permissions List" - git push - $SHA = git rev-parse HEAD - echo "commitid=$SHA" >> $env:GITHUB_OUTPUT +function Invoke-TestHarness +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $TestResultsFile, + + [Parameter()] + [System.String] + $DscTestsPath, + + [Parameter()] + [Switch] + $IgnoreCodeCoverage + ) + + $sw = [System.Diagnostics.StopWatch]::startnew() + + $MaximumFunctionCount = 32767 + Write-Host -Object 'Running all Microsoft365DSC Unit Tests' + + $repoDir = Join-Path -Path $PSScriptRoot -ChildPath '..\' -Resolve + + $oldModPath = $env:PSModulePath + $env:PSModulePath = $env:PSModulePath + [System.IO.Path]::PathSeparator + (Join-Path -Path $repoDir -ChildPath 'Modules\Microsoft365DSC') + + $testCoverageFiles = @() + if ($IgnoreCodeCoverage.IsPresent -eq $false) + { + Get-ChildItem -Path "$repoDir\Modules\Microsoft365DSC\DSCResources\**\*.psm1" -Recurse | ForEach-Object { + if ($_.FullName -notlike '*\DSCResource.Tests\*') + { + $testCoverageFiles += $_.FullName + } + } + } + + Import-Module -Name "$repoDir/Modules/Microsoft365DSC/Microsoft365DSC.psd1" + Import-Module -Name PSDesiredStateConfiguration -Global -Prefix 'Pwsh' -Force + $testsToRun = @() + + # Run Unit Tests + $versionsPath = Join-Path -Path $repoDir -ChildPath '\Tests\Unit\Stubs\' + # Import the first stub found so that there is a base module loaded before the tests start + $firstStub = Join-Path -Path $repoDir ` + -ChildPath '\Tests\Unit\Stubs\Microsoft365.psm1' + Import-Module $firstStub -WarningAction SilentlyContinue + + $stubPath = Join-Path -Path $repoDir ` + -ChildPath '\Tests\Unit\Stubs\Microsoft365.psm1' + + # DSC Common Tests + $getChildItemParameters = @{ + Path = (Join-Path -Path $repoDir -ChildPath '\Tests\Unit') + Recurse = $true + Filter = '*.Tests.ps1' + } + + # Get all tests '*.Tests.ps1'. + $commonTestFiles = Get-ChildItem @getChildItemParameters + + # Remove DscResource.Tests unit tests. + $commonTestFiles = $commonTestFiles | Where-Object -FilterScript { + $_.FullName -notmatch 'DSCResource.Tests\\Tests' + } + + $testsToRun += @( $commonTestFiles.FullName ) + + $filesToExecute = @() + if ($DscTestsPath -ne '') + { + $filesToExecute += $DscTestsPath + } + else + { + foreach ($testToRun in $testsToRun) + { + $filesToExecute += $testToRun + } + } + + $Params = [ordered]@{ + Path = $filesToExecute + } + + $Container = New-PesterContainer @Params + + $Configuration = [PesterConfiguration]@{ + Run = @{ + Container = $Container + PassThru = $true + } + Output = @{ + Verbosity = 'Normal' + } + Should = @{ + ErrorAction = 'Continue' + } + } + + if ([String]::IsNullOrEmpty($TestResultsFile) -eq $false) + { + $Configuration.Output.Enabled = $true + $Configuration.Output.OutputFormat = 'NUnitXml' + $Configuration.Output.OutputFile = $TestResultsFile + } + + if ($IgnoreCodeCoverage.IsPresent -eq $false) + { + $Configuration.CodeCoverage.Enabled = $true + $Configuration.CodeCoverage.Path = $testCoverageFiles + $Configuration.CodeCoverage.OutputPath = 'CodeCov.xml' + $Configuration.CodeCoverage.OutputFormat = 'JaCoCo' + $Configuration.CodeCoverage.UseBreakpoints = $false + } + + $results = Invoke-Pester -Configuration $Configuration + + $message = 'Running the tests took {0} hours, {1} minutes, {2} seconds' -f $sw.Elapsed.Hours, $sw.Elapsed.Minutes, $sw.Elapsed.Seconds + Write-Host -Object $message + + $env:PSModulePath = $oldModPath + Write-Host -Object 'Completed running all Microsoft365DSC Unit Tests' + + return $results +} + +function Get-M365DSCAllGraphPermissionsList +{ + [CmdletBinding()] + [OutputType([System.String[]])] + param() + + $allModules = Get-module Microsoft.graph.* -ListAvailable + $allPermissions = @() + foreach ($module in $allModules) + { + $cmds = Get-Command -Module $module.Name + foreach ($cmd in $cmds) + { + $graphInfo = Find-MgGraphCommand -Command $cmd.Name -ErrorAction SilentlyContinue + if ($null -ne $graphInfo) + { + $permissions = $graphInfo.Permissions | Where-Object -FilterScript {$_.PermissionType -eq 'Application'} + $allPermissions += $permissions.Name + } + } + } + + $allPermissions+= @('OrgSettings-Microsoft365Install.Read.All', ` + 'OrgSettings-Forms.Read.All', ` + 'OrgSettings-Todo.Read.All', ` + 'OrgSettings-AppsAndServices.Read.All', ` + 'OrgSettings-DynamicsVoice.Read.All', ` + 'ReportSettings.Read.All', ` + 'RoleManagementPolicy.Read.Directory', ` + 'RoleEligibilitySchedule.Read.Directory', ` + 'Agreement.Read.All', ` + 'Policy.ReadWrite.ConditionalAccess', ` + 'Policy.Read.ConditionalAccess', ` + 'Policy.ReadWrite.AuthenticationMethod', ` + 'SharePointTenantSettings.Read.All', ` + 'AppCatalog.ReadWrite.All', ` + 'TeamSettings.ReadWrite.All', ` + 'Channel.Delete.All', ` + 'ChannelSettings.ReadWrite.All', ` + 'ChannelMember.ReadWrite.All', ` + 'ChannelSettings.Read.All', + 'EntitlementManagement.Read.All', + 'ExternalConnection.Read.All') + $roles = $allPermissions | Select-Object -Unique | Sort-Object -Descending:$false + return $roles +} + +function Invoke-QualityChecksHarness +{ + [CmdletBinding()] + param () + + $sw = [System.Diagnostics.StopWatch]::startnew() + + Write-Host -Object 'Running all Quality Check Tests' + + $repoDir = Join-Path -Path $PSScriptRoot -ChildPath '..\' -Resolve + + $oldModPath = $env:PSModulePath + $env:PSModulePath = $env:PSModulePath + [System.IO.Path]::PathSeparator + (Join-Path -Path $repoDir -ChildPath 'modules\Microsoft365DSC') + + # DSC Common Tests + $getChildItemParameters = @{ + Path = (Join-Path -Path $repoDir -ChildPath '\Tests\QA') + Filter = '*.Tests.ps1' + } + + # Get all tests '*.Tests.ps1'. + $commonTestFiles = Get-ChildItem @getChildItemParameters + + $testsToRun = @() + $testsToRun += @( $commonTestFiles.FullName ) + + $filesToExecute = @() + foreach ($testToRun in $testsToRun) + { + $filesToExecute += $testToRun + } + + $Params = [ordered]@{ + Path = $filesToExecute + } + + $Container = New-PesterContainer @Params + + $Configuration = [PesterConfiguration]@{ + Run = @{ + Container = $Container + PassThru = $true + } + Output = @{ + Verbosity = 'Detailed' + } + Should = @{ + ErrorAction = 'Continue' + } + } + + $results = Invoke-Pester -Configuration $Configuration + + $message = 'Running the tests took {0} hours, {1} minutes, {2} seconds' -f $sw.Hours, $sw.Minutes, $sw.Seconds + Write-Host -Object $message + + $env:PSModulePath = $oldModPath + Write-Host -Object 'Completed running all Quality Check Tests' + + return $results +} From b63f0975e4ca94b281e189bb813eee68bfcb670e Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 12:11:51 +0000 Subject: [PATCH 439/465] Updated {Update} EXO Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index f62b9934f7..bae977e5b8 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -763,7 +763,6 @@ #MailTipsLargeAudienceThreshold = 100 MailTipsMailboxSourcedTipsEnabled = $True MailTipsExternalRecipientsTipsEnabled = $True - Ensure = "Present" ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint From a45176465cf461a1b68c020dea92561a9548ccbc Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 12:12:14 +0000 Subject: [PATCH 440/465] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Remove.Tests.ps1 | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 index d309331b25..331165c9c1 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Remove.Tests.ps1 @@ -301,14 +301,6 @@ TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } - EXOMailTips 'OrgWideMailTips' - { - IsSingleInstance = 'Yes' - Ensure = "Absent" - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - } EXOMalwareFilterPolicy 'ConfigureMalwareFilterPolicy' { Identity = "IntegrationMFP" From ec6970fad9770892ba45cdc6a86c25a06496f959 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 12:16:38 +0000 Subject: [PATCH 441/465] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/exchange/EXOAntiPhishPolicy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/resources/exchange/EXOAntiPhishPolicy.md b/docs/docs/resources/exchange/EXOAntiPhishPolicy.md index 5c09c05326..0d7db2cedd 100644 --- a/docs/docs/resources/exchange/EXOAntiPhishPolicy.md +++ b/docs/docs/resources/exchange/EXOAntiPhishPolicy.md @@ -7,7 +7,7 @@ | **Identity** | Key | String | The Identity parameter specifies the name of the antiphishing policy that you want to modify. | | | **Ensure** | Write | String | Specify if this policy should exist or not. | `Present`, `Absent` | | **AdminDisplayName** | Write | String | The AdminDisplayName parameter specifies a description for the policy. | | -| **PhishThresholdLevel** | Write | String | The PhishThresholdLevel parameter specifies the tolerance level that's used by machine learning in the handling of phishing messages. | `1`, `2`, `3`, `4` | +| **PhishThresholdLevel** | Write | UInt32 | The PhishThresholdLevel parameter specifies the tolerance level that's used by machine learning in the handling of phishing messages. | `1`, `2`, `3`, `4` | | **AuthenticationFailAction** | Write | String | The AuthenticationFailAction parameter specifies the action to take when the message fails composite authentication. | `MoveToJmf`, `Quarantine` | | **TargetedUserProtectionAction** | Write | String | The TargetedUserProtectionAction parameter specifies the action to take on detected user impersonation messages for the users specified by the TargetedUsersToProtect parameter. | `BccMessage`, `Delete`, `MoveToJmf`, `NoAction`, `Quarantine`, `Redirect` | | **Enabled** | Write | Boolean | Specify if this policy should be enabled. Default is $true. | | From 176cd1f987dd3733993583bb68c6a50dca2dd6a0 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 12:18:28 +0000 Subject: [PATCH 442/465] Updated Resources and Cmdlet documentation pages --- .../teams/TeamsComplianceRecordingPolicy.md | 46 ++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/docs/docs/resources/teams/TeamsComplianceRecordingPolicy.md b/docs/docs/resources/teams/TeamsComplianceRecordingPolicy.md index f1f8ce6b78..a289995bec 100644 --- a/docs/docs/resources/teams/TeamsComplianceRecordingPolicy.md +++ b/docs/docs/resources/teams/TeamsComplianceRecordingPolicy.md @@ -5,7 +5,7 @@ | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **Identity** | Key | String | Unique identifier of the application instance of a policy-based recording application to be retrieved. | | -| **ComplianceRecordingApplications** | Write | StringArray[] | A list of application instances of policy-based recording applications to assign to this policy. The Id of each of these application instances must be the ObjectId of the application instance as obtained by the Get-CsOnlineApplicationInstance cmdlet. | | +| **ComplianceRecordingApplications** | Write | MSFT_TeamsComplianceRecordingApplication[] | A list of application instances of policy-based recording applications to assign to this policy. The Id of each of these application instances must be the ObjectId of the application instance as obtained by the Get-CsOnlineApplicationInstance cmdlet. | | | **Description** | Write | String | Enables administrators to provide explanatory text to accompany a Teams recording policy. For example, the Description might include information about the users the policy should be assigned to. | | | **DisableComplianceRecordingAudioNotificationForCalls** | Write | Boolean | Setting this attribute to true disables recording audio notifications for 1:1 calls that are under compliance recording. | | | **Enabled** | Write | Boolean | Controls whether this Teams recording policy is active or not. | | @@ -18,6 +18,20 @@ | **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | | **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | +### MSFT_TeamsComplianceRecordingApplication + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Id** | Write | String | A name that uniquely identifies the application instance of the policy-based recording application. | | +| **ComplianceRecordingPairedApplications** | Write | StringArray[] | Determines the other policy-based recording applications to pair with this application to achieve application resiliency. Can only have one paired application. | | +| **RequiredBeforeMeetingJoin** | Write | Boolean | Indicates whether the policy-based recording application must be in the meeting before the user is allowed to join the meeting. | | +| **RequiredBeforeCallEstablishment** | Write | Boolean | Indicates whether the policy-based recording application must be in the call before the call is allowed to establish. | | +| **RequiredDuringMeeting** | Write | Boolean | Indicates whether the policy-based recording application must be in the meeting while the user is in the meeting. | | +| **RequiredDuringCall** | Write | Boolean | Indicates whether the policy-based recording application must be in the call while the call is active. | | +| **ConcurrentInvitationCount** | Write | String | Determines the number of invites to send out to the application instance of the policy-based recording application. Can be set to 1 or 2 only. | | + ## Description @@ -68,14 +82,34 @@ Configuration Example node localhost { - TeamsComplianceRecordingPolicy 'Example' + TeamsComplianceRecordingPolicy "TeamsComplianceRecordingPolicy-Tag:MyTeamsComplianceRecordingPolicy" { - ComplianceRecordingApplications = @('qwertzuio-abcd-abcd-abcd-qwertzuio'); - Credential = $Credscredential; + Credential = $credsCredential; + ComplianceRecordingApplications = @( + MSFT_TeamsComplianceRecordingApplication{ + Id = '00000000-0000-0000-0000-000000000000' + ComplianceRecordingPairedApplications = @('00000000-0000-0000-0000-000000000000') + ConcurrentInvitationCount = 1 + RequiredDuringCall = $True + RequiredBeforeMeetingJoin = $True + RequiredBeforeCallEstablishment = $True + RequiredDuringMeeting = $True + } + MSFT_TeamsComplianceRecordingApplication{ + Id = '12345678-0000-0000-0000-000000000000' + ComplianceRecordingPairedApplications = @('87654321-0000-0000-0000-000000000000') + ConcurrentInvitationCount = 1 + RequiredDuringCall = $True + RequiredBeforeMeetingJoin = $True + RequiredBeforeCallEstablishment = $True + RequiredDuringMeeting = $True + } + ); + Description = "MyTeamsComplianceRecordingPolicy"; DisableComplianceRecordingAudioNotificationForCalls = $False; - Enabled = $False; + Enabled = $True; Ensure = "Present"; - Identity = "Global"; + Identity = "Tag:MyTeamsComplianceRecordingPolicy"; WarnUserOnRemoval = $True; } } From 9dfa03c39b41039299f5061891d4aa0d95c07c4b Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 12:18:45 +0000 Subject: [PATCH 443/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 6a072f3b51..cd38f93d64 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -6363,7 +6363,7 @@ "Option": "Write" }, { - "CIMType": "String", + "CIMType": "UInt32", "Name": "PhishThresholdLevel", "Option": "Write" }, From 3be71a0eea732873491e77625c16254e184b41b5 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 12:28:54 +0000 Subject: [PATCH 444/465] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/office365/O365ExternalConnection.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/resources/office365/O365ExternalConnection.md b/docs/docs/resources/office365/O365ExternalConnection.md index 2f2c8b3ddd..051d8412e1 100644 --- a/docs/docs/resources/office365/O365ExternalConnection.md +++ b/docs/docs/resources/office365/O365ExternalConnection.md @@ -41,11 +41,11 @@ To authenticate with the Microsoft Graph API, this resource required the followi - **Read** - - ExternalConnection.Read.All + - Application.Read.All, ExternalConnection.Read.All - **Update** - - ExternalConnection.ReadWrite.All + - Application.Read.All, ExternalConnection.ReadWrite.All ## Examples From 046b5846a8c1d4d52af5af31cb1d161aa0b8c0ad Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 12:31:19 +0000 Subject: [PATCH 445/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index cd38f93d64..7c850ee8b5 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -46309,6 +46309,46 @@ } ] }, + { + "ClassName": "MSFT_TeamsComplianceRecordingApplication", + "Parameters": [ + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "ComplianceRecordingPairedApplications", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "RequiredBeforeMeetingJoin", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "RequiredBeforeCallEstablishment", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "RequiredDuringMeeting", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "RequiredDuringCall", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ConcurrentInvitationCount", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_TeamsComplianceRecordingPolicy", "Parameters": [ @@ -46318,7 +46358,7 @@ "Option": "Key" }, { - "CIMType": "String[]", + "CIMType": "MSFT_TeamsComplianceRecordingApplication[]", "Name": "ComplianceRecordingApplications", "Option": "Write" }, From d42fe4fbf5d4f350272ab9299546eb18d73ab4cb Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 12:38:42 +0000 Subject: [PATCH 446/465] Updated Resources and Cmdlet documentation pages --- .../intune/IntuneFirewallPolicyWindows10.md | 292 ++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 docs/docs/resources/intune/IntuneFirewallPolicyWindows10.md diff --git a/docs/docs/resources/intune/IntuneFirewallPolicyWindows10.md b/docs/docs/resources/intune/IntuneFirewallPolicyWindows10.md new file mode 100644 index 0000000000..f9ad6cee2b --- /dev/null +++ b/docs/docs/resources/intune/IntuneFirewallPolicyWindows10.md @@ -0,0 +1,292 @@ +# IntuneFirewallPolicyWindows10 + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Description** | Write | String | Policy description | | +| **DisplayName** | Key | String | Policy name | | +| **RoleScopeTagIds** | Write | StringArray[] | List of Scope Tags for this Entity instance. | | +| **Id** | Write | String | The unique identifier for an entity. Read-only. | | +| **CRLcheck** | Write | String | Certificate revocation list verification (0: Disables CRL checking, 1: Specifies that CRL checking is attempted and that certificate validation fails only if the certificate is revoked. Other failures that are encountered during CRL checking (such as the revocation URL being unreachable) do not cause certificate validation to fail., 2: Means that checking is required and that certificate validation fails if any error is encountered during CRL processing) | `0`, `1`, `2` | +| **DisableStatefulFtp** | Write | String | Disable Stateful Ftp (false: Stateful FTP enabled, true: Stateful FTP disabled) | `false`, `true` | +| **EnablePacketQueue** | Write | SInt32Array[] | Enable Packet Queue (0: Indicates that all queuing is to be disabled, 1: Specifies that inbound encrypted packets are to be queued, 2: Specifies that packets are to be queued after decryption is performed for forwarding) | `0`, `1`, `2` | +| **IPsecExempt** | Write | SInt32Array[] | IPsec Exceptions (0: FW_GLOBAL_CONFIG_IPSEC_EXEMPT_NONE: No IPsec exemptions., 1: FW_GLOBAL_CONFIG_IPSEC_EXEMPT_NEIGHBOR_DISC: Exempt neighbor discover IPv6 ICMP type-codes from IPsec., 2: FW_GLOBAL_CONFIG_IPSEC_EXEMPT_ICMP: Exempt ICMP from IPsec., 4: FW_GLOBAL_CONFIG_IPSEC_EXEMPT_ROUTER_DISC: Exempt router discover IPv6 ICMP type-codes from IPsec., 8: FW_GLOBAL_CONFIG_IPSEC_EXEMPT_DHCP: Exempt both IPv4 and IPv6 DHCP traffic from IPsec.) | `0`, `1`, `2`, `4`, `8` | +| **OpportunisticallyMatchAuthSetPerKM** | Write | String | Opportunistically Match Auth Set Per KM (false: FALSE, true: TRUE) | `false`, `true` | +| **PresharedKeyEncoding** | Write | String | Preshared Key Encoding (0: FW_GLOBAL_CONFIG_PRESHARED_KEY_ENCODING_NONE: Preshared key is not encoded. Instead, it is kept in its wide-character format. This symbolic constant has a value of 0., 1: FW_GLOBAL_CONFIG_PRESHARED_KEY_ENCODING_UTF_8: Encode the preshared key using UTF-8. This symbolic constant has a value of 1.) | `0`, `1` | +| **SaIdleTime** | Write | SInt32 | Security association idle time | | +| **DomainProfile_EnableFirewall** | Write | String | Enable Domain Network Firewall (false: Disable Firewall, true: Enable Firewall) | `false`, `true` | +| **DomainProfile_DisableUnicastResponsesToMulticastBroadcast** | Write | String | Disable Unicast Responses To Multicast Broadcast (false: Unicast Responses Not Blocked, true: Unicast Responses Blocked) | `false`, `true` | +| **DomainProfile_EnableLogIgnoredRules** | Write | String | Enable Log Ignored Rules (false: Disable Logging Of Ignored Rules, true: Enable Logging Of Ignored Rules) | `false`, `true` | +| **DomainProfile_GlobalPortsAllowUserPrefMerge** | Write | String | Global Ports Allow User Pref Merge (false: GlobalPortsAllowUserPrefMerge Off, true: GlobalPortsAllowUserPrefMerge On) | `false`, `true` | +| **DomainProfile_DefaultInboundAction** | Write | String | Default Inbound Action for Domain Profile (0: Allow Inbound By Default, 1: Block Inbound By Default) | `0`, `1` | +| **DomainProfile_DisableStealthModeIpsecSecuredPacketExemption** | Write | String | Disable Stealth Mode Ipsec Secured Packet Exemption (false: FALSE, true: TRUE) | `false`, `true` | +| **DomainProfile_AllowLocalPolicyMerge** | Write | String | Allow Local Policy Merge (false: AllowLocalPolicyMerge Off, true: AllowLocalPolicyMerge On) | `false`, `true` | +| **DomainProfile_EnableLogSuccessConnections** | Write | String | Enable Log Success Connections (false: Disable Logging Of Successful Connections, true: Enable Logging Of Successful Connections) | `false`, `true` | +| **DomainProfile_AllowLocalIpsecPolicyMerge** | Write | String | Allow Local Ipsec Policy Merge (false: AllowLocalIpsecPolicyMerge Off, true: AllowLocalIpsecPolicyMerge On) | `false`, `true` | +| **DomainProfile_LogFilePath** | Write | String | Log File Path | | +| **DomainProfile_DisableStealthMode** | Write | String | Disable Stealth Mode (false: Use Stealth Mode, true: Disable Stealth Mode) | `false`, `true` | +| **DomainProfile_AuthAppsAllowUserPrefMerge** | Write | String | Auth Apps Allow User Pref Merge (false: AuthAppsAllowUserPrefMerge Off, true: AuthAppsAllowUserPrefMerge On) | `false`, `true` | +| **DomainProfile_EnableLogDroppedPackets** | Write | String | Enable Log Dropped Packets (false: Disable Logging Of Dropped Packets, true: Enable Logging Of Dropped Packets) | `false`, `true` | +| **DomainProfile_Shielded** | Write | String | Shielded (false: Shielding Off, true: Shielding On) | `false`, `true` | +| **DomainProfile_DefaultOutboundAction** | Write | String | Default Outbound Action (0: Allow Outbound By Default, 1: Block Outbound By Default) | `0`, `1` | +| **DomainProfile_DisableInboundNotifications** | Write | String | Disable Inbound Notifications (false: Firewall May Display Notification, true: Firewall Must Not Display Notification) | `false`, `true` | +| **DomainProfile_LogMaxFileSize** | Write | SInt32 | Log Max File Size | | +| **PrivateProfile_EnableFirewall** | Write | String | Enable Private Network Firewall (false: Disable Firewall, true: Enable Firewall) | `false`, `true` | +| **PrivateProfile_AllowLocalIpsecPolicyMerge** | Write | String | Allow Local Ipsec Policy Merge (false: AllowLocalIpsecPolicyMerge Off, true: AllowLocalIpsecPolicyMerge On) | `false`, `true` | +| **PrivateProfile_DisableStealthModeIpsecSecuredPacketExemption** | Write | String | Disable Stealth Mode Ipsec Secured Packet Exemption (false: FALSE, true: TRUE) | `false`, `true` | +| **PrivateProfile_DisableInboundNotifications** | Write | String | Disable Inbound Notifications (false: Firewall May Display Notification, true: Firewall Must Not Display Notification) | `false`, `true` | +| **PrivateProfile_Shielded** | Write | String | Shielded (false: Shielding Off, true: Shielding On) | `false`, `true` | +| **PrivateProfile_AllowLocalPolicyMerge** | Write | String | Allow Local Policy Merge (false: AllowLocalPolicyMerge Off, true: AllowLocalPolicyMerge On) | `false`, `true` | +| **PrivateProfile_DefaultOutboundAction** | Write | String | Default Outbound Action (0: Allow Outbound By Default, 1: Block Outbound By Default) | `0`, `1` | +| **PrivateProfile_AuthAppsAllowUserPrefMerge** | Write | String | Auth Apps Allow User Pref Merge (false: AuthAppsAllowUserPrefMerge Off, true: AuthAppsAllowUserPrefMerge On) | `false`, `true` | +| **PrivateProfile_EnableLogIgnoredRules** | Write | String | Enable Log Ignored Rules (false: Disable Logging Of Ignored Rules, true: Enable Logging Of Ignored Rules) | `false`, `true` | +| **PrivateProfile_LogMaxFileSize** | Write | SInt32 | Log Max File Size | | +| **PrivateProfile_DefaultInboundAction** | Write | String | Default Inbound Action for Private Profile (0: Allow Inbound By Default, 1: Block Inbound By Default) | `0`, `1` | +| **PrivateProfile_DisableUnicastResponsesToMulticastBroadcast** | Write | String | Disable Unicast Responses To Multicast Broadcast (false: Unicast Responses Not Blocked, true: Unicast Responses Blocked) | `false`, `true` | +| **PrivateProfile_LogFilePath** | Write | String | Log File Path | | +| **PrivateProfile_DisableStealthMode** | Write | String | Disable Stealth Mode (false: Use Stealth Mode, true: Disable Stealth Mode) | `false`, `true` | +| **PrivateProfile_EnableLogSuccessConnections** | Write | String | Enable Log Success Connections (false: Disable Logging Of Successful Connections, true: Enable Logging Of Successful Connections) | `false`, `true` | +| **PrivateProfile_GlobalPortsAllowUserPrefMerge** | Write | String | Global Ports Allow User Pref Merge (false: GlobalPortsAllowUserPrefMerge Off, true: GlobalPortsAllowUserPrefMerge On) | `false`, `true` | +| **PrivateProfile_EnableLogDroppedPackets** | Write | String | Enable Log Dropped Packets (false: Disable Logging Of Dropped Packets, true: Enable Logging Of Dropped Packets) | `false`, `true` | +| **PublicProfile_EnableFirewall** | Write | String | Enable Public Network Firewall (false: Disable Firewall, true: Enable Firewall) | `false`, `true` | +| **PublicProfile_DefaultOutboundAction** | Write | String | Default Outbound Action (0: Allow Outbound By Default, 1: Block Outbound By Default) | `0`, `1` | +| **PublicProfile_DisableInboundNotifications** | Write | String | Disable Inbound Notifications (false: Firewall May Display Notification, true: Firewall Must Not Display Notification) | `false`, `true` | +| **PublicProfile_DisableStealthModeIpsecSecuredPacketExemption** | Write | String | Disable Stealth Mode Ipsec Secured Packet Exemption (false: FALSE, true: TRUE) | `false`, `true` | +| **PublicProfile_Shielded** | Write | String | Shielded (false: Shielding Off, true: Shielding On) | `false`, `true` | +| **PublicProfile_AllowLocalPolicyMerge** | Write | String | Allow Local Policy Merge (false: AllowLocalPolicyMerge Off, true: AllowLocalPolicyMerge On) | `false`, `true` | +| **PublicProfile_AuthAppsAllowUserPrefMerge** | Write | String | Auth Apps Allow User Pref Merge (false: AuthAppsAllowUserPrefMerge Off, true: AuthAppsAllowUserPrefMerge On) | `false`, `true` | +| **PublicProfile_LogFilePath** | Write | String | Log File Path | | +| **PublicProfile_DefaultInboundAction** | Write | String | Default Inbound Action for Public Profile (0: Allow Inbound By Default, 1: Block Inbound By Default) | `0`, `1` | +| **PublicProfile_DisableUnicastResponsesToMulticastBroadcast** | Write | String | Disable Unicast Responses To Multicast Broadcast (false: Unicast Responses Not Blocked, true: Unicast Responses Blocked) | `false`, `true` | +| **PublicProfile_GlobalPortsAllowUserPrefMerge** | Write | String | Global Ports Allow User Pref Merge (false: GlobalPortsAllowUserPrefMerge Off, true: GlobalPortsAllowUserPrefMerge On) | `false`, `true` | +| **PublicProfile_EnableLogSuccessConnections** | Write | String | Enable Log Success Connections (false: Disable Logging Of Successful Connections, true: Enable Logging Of Successful Connections) | `false`, `true` | +| **PublicProfile_AllowLocalIpsecPolicyMerge** | Write | String | Allow Local Ipsec Policy Merge (false: AllowLocalIpsecPolicyMerge Off, true: AllowLocalIpsecPolicyMerge On) | `false`, `true` | +| **PublicProfile_EnableLogDroppedPackets** | Write | String | Enable Log Dropped Packets (false: Disable Logging Of Dropped Packets, true: Enable Logging Of Dropped Packets) | `false`, `true` | +| **PublicProfile_EnableLogIgnoredRules** | Write | String | Enable Log Ignored Rules (false: Disable Logging Of Ignored Rules, true: Enable Logging Of Ignored Rules) | `false`, `true` | +| **PublicProfile_LogMaxFileSize** | Write | SInt32 | Log Max File Size | | +| **PublicProfile_DisableStealthMode** | Write | String | Disable Stealth Mode (false: Use Stealth Mode, true: Disable Stealth Mode) | `false`, `true` | +| **ObjectAccess_AuditFilteringPlatformConnection** | Write | String | Object Access Audit Filtering Platform Connection (0: Off/None, 1: Success, 2: Failure, 3: Success+Failure) | `0`, `1`, `2`, `3` | +| **ObjectAccess_AuditFilteringPlatformPacketDrop** | Write | String | Object Access Audit Filtering Platform Packet Drop (0: Off/None, 1: Success, 2: Failure, 3: Success+Failure) | `0`, `1`, `2`, `3` | +| **AllowedTlsAuthenticationEndpoints** | Write | StringArray[] | Allowed Tls Authentication Endpoints | | +| **ConfiguredTlsAuthenticationNetworkName** | Write | String | Configured Tls Authentication Network Name | | +| **Target** | Write | String | Hyper-V: Target (wsl: WSL) | `wsl` | +| **HyperVVMSettings_DomainProfile_EnableFirewall** | Write | String | Hyper-V: Enable Domain Network Firewall (false: Disable Firewall, true: Enable Firewall) | `false`, `true` | +| **HyperVVMSettings_DomainProfile_AllowLocalPolicyMerge** | Write | String | Hyper-V: Allow Local Policy Merge (false: AllowLocalPolicyMerge Off, true: AllowLocalPolicyMerge On) | `false`, `true` | +| **HyperVVMSettings_DomainProfile_DefaultInboundAction** | Write | String | Hyper-V: Default Inbound Action (0: Allow Inbound By Default, 1: Block Inbound By Default) | `0`, `1` | +| **HyperVVMSettings_DomainProfile_DefaultOutboundAction** | Write | String | Hyper-V: Default Outbound Action (0: Allow Outbound By Default, 1: Block Outbound By Default) | `0`, `1` | +| **EnableLoopback** | Write | String | Hyper-V: Enable Loopback (false: Disable loopback, true: Enable loopback) | `false`, `true` | +| **HyperVVMSettings_PublicProfile_EnableFirewall** | Write | String | Hyper-V: Enable Public Network Firewall (false: Disable Hyper-V Firewall, true: Enable Hyper-V Firewall) | `false`, `true` | +| **HyperVVMSettings_PublicProfile_DefaultInboundAction** | Write | String | Hyper-V: Default Inbound Action (0: Allow Inbound By Default, 1: Block Inbound By Default) | `0`, `1` | +| **HyperVVMSettings_PublicProfile_DefaultOutboundAction** | Write | String | Hyper-V: Default Outbound Action (0: Allow Outbound By Default, 1: Block Outbound By Default) | `0`, `1` | +| **HyperVVMSettings_PublicProfile_AllowLocalPolicyMerge** | Write | String | Hyper-V: Allow Local Policy Merge (false: AllowLocalPolicyMerge Off, true: AllowLocalPolicyMerge On) | `false`, `true` | +| **HyperVVMSettings_PrivateProfile_EnableFirewall** | Write | String | Hyper-V: Enable Private Network Firewall (false: Disable Firewall, true: Enable Firewall) | `false`, `true` | +| **HyperVVMSettings_PrivateProfile_DefaultOutboundAction** | Write | String | Hyper-V: Default Outbound Action (0: Allow Outbound By Default, 1: Block Outbound By Default) | `0`, `1` | +| **HyperVVMSettings_PrivateProfile_DefaultInboundAction** | Write | String | Hyper-V: Default Inbound Action (0: Allow Inbound By Default, 1: Block Inbound By Default) | `0`, `1` | +| **HyperVVMSettings_PrivateProfile_AllowLocalPolicyMerge** | Write | String | Hyper-V: Allow Local Policy Merge (false: AllowLocalPolicyMerge Off, true: AllowLocalPolicyMerge On) | `false`, `true` | +| **AllowHostPolicyMerge** | Write | String | Hyper-V: Allow Host Policy Merge (false: AllowHostPolicyMerge Off, true: AllowHostPolicyMerge On) | `false`, `true` | +| **Assignments** | Write | MSFT_DeviceManagementConfigurationPolicyAssignments[] | Represents the assignment to the Intune policy. | | +| **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_DeviceManagementConfigurationPolicyAssignments + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **dataType** | Write | String | The type of the target assignment. | `#microsoft.graph.groupAssignmentTarget`, `#microsoft.graph.allLicensedUsersAssignmentTarget`, `#microsoft.graph.allDevicesAssignmentTarget`, `#microsoft.graph.exclusionGroupAssignmentTarget`, `#microsoft.graph.configurationManagerCollectionAssignmentTarget` | +| **deviceAndAppManagementAssignmentFilterType** | Write | String | The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude. | `none`, `include`, `exclude` | +| **deviceAndAppManagementAssignmentFilterId** | Write | String | The Id of the filter for the target assignment. | | +| **groupId** | Write | String | The group Id that is the target of the assignment. | | +| **groupDisplayName** | Write | String | The group Display Name that is the target of the assignment. | | +| **collectionId** | Write | String | The collection Id that is the target of the assignment.(ConfigMgr) | | + + +## Description + +Intune Firewall Policy for Windows10 + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - DeviceManagementConfiguration.Read.All + +- **Update** + + - DeviceManagementConfiguration.ReadWrite.All + +#### Application permissions + +- **Read** + + - DeviceManagementConfiguration.Read.All + +- **Update** + + - DeviceManagementConfiguration.ReadWrite.All + +## Examples + +### Example 1 + +This example creates a new Intune Firewall Policy for Windows10. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneFirewallPolicyWindows10 'ConfigureIntuneFirewallPolicyWindows10' + { + Assignments = @( + MSFT_DeviceManagementConfigurationPolicyAssignments{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '11111111-1111-1111-1111-111111111111' + } + ); + Description = 'Description' + DisplayName = "Intune Firewall Policy Windows10"; + DisableStatefulFtp = "false"; + DomainProfile_AllowLocalIpsecPolicyMerge = "false"; + DomainProfile_EnableFirewall = "true"; + DomainProfile_LogFilePath = "%systemroot%\system32\LogFiles\Firewall\pfirewall.log"; + DomainProfile_LogMaxFileSize = 1024; + ObjectAccess_AuditFilteringPlatformPacketDrop = "1"; + PrivateProfile_EnableFirewall = "true"; + PublicProfile_EnableFirewall = "true"; + Target = "wsl"; + AllowHostPolicyMerge = "false"; + Ensure = "Present"; + Id = '00000000-0000-0000-0000-000000000000' + RoleScopeTagIds = @("0"); + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + +### Example 2 + +This example updates a Intune Firewall Policy for Windows10. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneFirewallPolicyWindows10 'ConfigureIntuneFirewallPolicyWindows10' + { + Assignments = @( + MSFT_DeviceManagementConfigurationPolicyAssignments{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '11111111-1111-1111-1111-111111111111' + } + ); + Description = 'Description' + DisplayName = "Intune Firewall Policy Windows10"; + DisableStatefulFtp = "false"; + DomainProfile_AllowLocalIpsecPolicyMerge = "true"; # Updated property + DomainProfile_EnableFirewall = "true"; + DomainProfile_LogFilePath = "%systemroot%\system32\LogFiles\Firewall\pfirewall.log"; + DomainProfile_LogMaxFileSize = 1024; + ObjectAccess_AuditFilteringPlatformPacketDrop = "1"; + PrivateProfile_EnableFirewall = "true"; + PublicProfile_EnableFirewall = "true"; + Target = "wsl"; + AllowHostPolicyMerge = "false"; + Ensure = "Present"; + Id = '00000000-0000-0000-0000-000000000000' + RoleScopeTagIds = @("0"); + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + +### Example 3 + +This example removes a Device Control Policy. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneFirewallPolicyWindows10 'ConfigureIntuneFirewallPolicyWindows10' + { + Id = '00000000-0000-0000-0000-000000000000' + DisplayName = 'Intune Firewall Policy Windows10' + Ensure = 'Absent' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + From 5b4beb0ecd45bf48836fa24d46c8a208f5e9f1fd Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 12:40:22 +0000 Subject: [PATCH 447/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 455 ++++++++++++++++++ 1 file changed, 455 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 7c850ee8b5..e0fd0b88ab 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -33674,6 +33674,461 @@ } ] }, + { + "ClassName": "MSFT_IntuneFirewallPolicyWindows10", + "Parameters": [ + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" + }, + { + "CIMType": "String[]", + "Name": "RoleScopeTagIds", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CRLcheck", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DisableStatefulFtp", + "Option": "Write" + }, + { + "CIMType": "SInt32[]", + "Name": "EnablePacketQueue", + "Option": "Write" + }, + { + "CIMType": "SInt32[]", + "Name": "IPsecExempt", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "OpportunisticallyMatchAuthSetPerKM", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PresharedKeyEncoding", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "SaIdleTime", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_EnableFirewall", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_DisableUnicastResponsesToMulticastBroadcast", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_EnableLogIgnoredRules", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_GlobalPortsAllowUserPrefMerge", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_DefaultInboundAction", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_DisableStealthModeIpsecSecuredPacketExemption", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_AllowLocalPolicyMerge", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_EnableLogSuccessConnections", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_AllowLocalIpsecPolicyMerge", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_LogFilePath", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_DisableStealthMode", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_AuthAppsAllowUserPrefMerge", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_EnableLogDroppedPackets", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_Shielded", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_DefaultOutboundAction", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "DomainProfile_DisableInboundNotifications", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "DomainProfile_LogMaxFileSize", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_EnableFirewall", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_AllowLocalIpsecPolicyMerge", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_DisableStealthModeIpsecSecuredPacketExemption", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_DisableInboundNotifications", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_Shielded", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_AllowLocalPolicyMerge", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_DefaultOutboundAction", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_AuthAppsAllowUserPrefMerge", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_EnableLogIgnoredRules", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "PrivateProfile_LogMaxFileSize", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_DefaultInboundAction", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_DisableUnicastResponsesToMulticastBroadcast", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_LogFilePath", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_DisableStealthMode", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_EnableLogSuccessConnections", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_GlobalPortsAllowUserPrefMerge", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PrivateProfile_EnableLogDroppedPackets", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_EnableFirewall", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_DefaultOutboundAction", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_DisableInboundNotifications", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_DisableStealthModeIpsecSecuredPacketExemption", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_Shielded", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_AllowLocalPolicyMerge", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_AuthAppsAllowUserPrefMerge", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_LogFilePath", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_DefaultInboundAction", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_DisableUnicastResponsesToMulticastBroadcast", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_GlobalPortsAllowUserPrefMerge", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_EnableLogSuccessConnections", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_AllowLocalIpsecPolicyMerge", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_EnableLogDroppedPackets", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_EnableLogIgnoredRules", + "Option": "Write" + }, + { + "CIMType": "SInt32", + "Name": "PublicProfile_LogMaxFileSize", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "PublicProfile_DisableStealthMode", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ObjectAccess_AuditFilteringPlatformConnection", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ObjectAccess_AuditFilteringPlatformPacketDrop", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AllowedTlsAuthenticationEndpoints", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ConfiguredTlsAuthenticationNetworkName", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Target", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "HyperVVMSettings_DomainProfile_EnableFirewall", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "HyperVVMSettings_DomainProfile_AllowLocalPolicyMerge", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "HyperVVMSettings_DomainProfile_DefaultInboundAction", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "HyperVVMSettings_DomainProfile_DefaultOutboundAction", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "EnableLoopback", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "HyperVVMSettings_PublicProfile_EnableFirewall", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "HyperVVMSettings_PublicProfile_DefaultInboundAction", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "HyperVVMSettings_PublicProfile_DefaultOutboundAction", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "HyperVVMSettings_PublicProfile_AllowLocalPolicyMerge", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "HyperVVMSettings_PrivateProfile_EnableFirewall", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "HyperVVMSettings_PrivateProfile_DefaultOutboundAction", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "HyperVVMSettings_PrivateProfile_DefaultInboundAction", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "HyperVVMSettings_PrivateProfile_AllowLocalPolicyMerge", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "AllowHostPolicyMerge", + "Option": "Write" + }, + { + "CIMType": "MSFT_DeviceManagementConfigurationPolicyAssignments[]", + "Name": "Assignments", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_DeviceManagementConfigurationPolicyItems", "Parameters": [ From 27d4f17a0b361da11a31b686d65c7328c93a5039 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Wed, 2 Oct 2024 14:40:35 +0200 Subject: [PATCH 448/465] Fix typo and tests --- .../MSFT_IntuneAppProtectionPolicyiOS.psm1 | 2 +- ...Microsoft365DSC.IntuneAppProtectionPolicyiOS.Tests.ps1 | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppProtectionPolicyiOS/MSFT_IntuneAppProtectionPolicyiOS.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppProtectionPolicyiOS/MSFT_IntuneAppProtectionPolicyiOS.psm1 index 73f67afefb..3148f18042 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppProtectionPolicyiOS/MSFT_IntuneAppProtectionPolicyiOS.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppProtectionPolicyiOS/MSFT_IntuneAppProtectionPolicyiOS.psm1 @@ -710,7 +710,7 @@ function Set-TargetResource $createParameters.Remove('Identity') $createParameters.Remove('Assignments') $createParameters.Remove('Apps') - $createParameter.TargetedAppManagementLevels = $createParameters.TargetedAppManagementLevels -join ',' + $createParameters.TargetedAppManagementLevels = $createParameters.TargetedAppManagementLevels -join ',' $myApps = Get-IntuneAppProtectionPolicyiOSAppsToHashtable -Parameters $PSBoundParameters $myAssignments = Get-IntuneAppProtectionPolicyiOSAssignmentToHashtable -Parameters $PSBoundParameters diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppProtectionPolicyiOS.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppProtectionPolicyiOS.Tests.ps1 index 79eaf337e1..58a7cc4997 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppProtectionPolicyiOS.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAppProtectionPolicyiOS.Tests.ps1 @@ -99,6 +99,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { SaveAsBlocked = $True SimplePinBlocked = $False Identity = '12345-12345-12345-12345-12345' + TargetedAppManagementLevels = @('unmanaged') } Mock -CommandName Get-MgBetaDeviceAppManagementiosManagedAppProtection -MockWith { return $null @@ -160,6 +161,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { SaveAsBlocked = $True SimplePinBlocked = $False Identity = '12345-12345-12345-12345-12345' + TargetedAppManagementLevels = @('unmanaged') } Mock -CommandName Get-MgBetaDeviceAppManagementiosManagedAppProtection -MockWith { @@ -198,6 +200,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { SaveAsBlocked = $True SimplePinBlocked = $False id = '12345-12345-12345-12345-12345' + TargetedAppManagementLevels = 'unmanaged' } } Mock -CommandName Get-MgBetaDeviceAppManagementiosManagedAppProtectionApp -MockWith { @@ -305,6 +308,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { SaveAsBlocked = $True SimplePinBlocked = $False Identity = '12345-12345-12345-12345-12345' + TargetedAppManagementLevels = @('unmanaged') } Mock -CommandName Get-MgBetaDeviceAppManagementiosManagedAppProtection -MockWith { @@ -343,6 +347,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { SaveAsBlocked = $True SimplePinBlocked = $False id = '12345-12345-12345-12345-12345' + TargetedAppManagementLevels = 'unmanaged' } } Mock -CommandName Get-MgBetaDeviceAppManagementiosManagedAppProtectionApp -MockWith { @@ -441,6 +446,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { SaveAsBlocked = $True SimplePinBlocked = $False Identity = '12345-12345-12345-12345-12345' + TargetedAppManagementLevels = @('unmanaged') } Mock -CommandName Get-MgBetaDeviceAppManagementiosManagedAppProtection -MockWith { @@ -479,6 +485,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { SaveAsBlocked = $True SimplePinBlocked = $False id = '12345-12345-12345-12345-12345' + TargetedAppManagementLevels = 'unmanaged' } } Mock -CommandName Get-MgBetaDeviceAppManagementiosManagedAppProtectionApp -MockWith { @@ -589,6 +596,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { SaveAsBlocked = $True SimplePinBlocked = $False id = '12345-12345-12345-12345-12345' + TargetedAppManagementLevels = 'unmanaged' } } Mock -CommandName Get-MgBetaDeviceAppManagementiosManagedAppProtectionApp -MockWith { From b85abb7c170cb229691c373e51e47091bfae8e17 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 12:40:55 +0000 Subject: [PATCH 449/465] Updated {Create} Intune Integration Tests --- ...M365DSCIntegration.INTUNE.Create.Tests.ps1 | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 index 05e2c09569..f60efd6f58 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 @@ -2450,6 +2450,34 @@ TenantId = $TenantId; CertificateThumbprint = $CertificateThumbprint; } + IntuneFirewallPolicyWindows10 'ConfigureIntuneFirewallPolicyWindows10' + { + Assignments = @( + MSFT_DeviceManagementConfigurationPolicyAssignments{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.groupAssignmentTarget' + groupId = '11111111-1111-1111-1111-111111111111' + } + ); + Description = 'Description' + DisplayName = "Intune Firewall Policy Windows10"; + DisableStatefulFtp = "false"; + DomainProfile_AllowLocalIpsecPolicyMerge = "false"; + DomainProfile_EnableFirewall = "true"; + DomainProfile_LogFilePath = "%systemroot%\system32\LogFiles\Firewall\pfirewall.log"; + DomainProfile_LogMaxFileSize = 1024; + ObjectAccess_AuditFilteringPlatformPacketDrop = "1"; + PrivateProfile_EnableFirewall = "true"; + PublicProfile_EnableFirewall = "true"; + Target = "wsl"; + AllowHostPolicyMerge = "false"; + Ensure = "Present"; + Id = '00000000-0000-0000-0000-000000000000' + RoleScopeTagIds = @("0"); + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } IntunePolicySets 'Example' { Assignments = @( From f5d3511aec849b77d4d58c8f533f34735eec6966 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 12:55:52 +0000 Subject: [PATCH 450/465] Updated Resources and Cmdlet documentation pages --- .../intune/IntuneAntivirusPolicyWindows10SettingCatalog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/resources/intune/IntuneAntivirusPolicyWindows10SettingCatalog.md b/docs/docs/resources/intune/IntuneAntivirusPolicyWindows10SettingCatalog.md index 2ad9520438..15667b067a 100644 --- a/docs/docs/resources/intune/IntuneAntivirusPolicyWindows10SettingCatalog.md +++ b/docs/docs/resources/intune/IntuneAntivirusPolicyWindows10SettingCatalog.md @@ -89,6 +89,7 @@ | **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | | **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | ### MSFT_DeviceManagementConfigurationPolicyAssignments From 99b1ac8ebbebdf3c1e52c6bb1b3b3535755841dd Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 12:57:50 +0000 Subject: [PATCH 451/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index e0fd0b88ab..9a5b65af10 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -19051,6 +19051,11 @@ "CIMType": "Boolean", "Name": "ManagedIdentity", "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" } ] }, From b837e7600324fbfc5227a58ade86d03272d678b9 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 13:19:25 +0000 Subject: [PATCH 452/465] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/intune/IntuneAppProtectionPolicyiOS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/resources/intune/IntuneAppProtectionPolicyiOS.md b/docs/docs/resources/intune/IntuneAppProtectionPolicyiOS.md index 742ce453d8..3f09651531 100644 --- a/docs/docs/resources/intune/IntuneAppProtectionPolicyiOS.md +++ b/docs/docs/resources/intune/IntuneAppProtectionPolicyiOS.md @@ -43,7 +43,7 @@ | **PinRequiredInsteadOfBiometricTimeout** | Write | String | Timeout in minutes for an app pin instead of non biometrics passcode . | | | **AllowedOutboundClipboardSharingExceptionLength** | Write | UInt32 | Specify the number of characters that may be cut or copied from Org data and accounts to any application. This setting overrides the AllowedOutboundClipboardSharingLevel restriction. Default value of '0' means no exception is allowed. | | | **NotificationRestriction** | Write | String | Specify app notification restriction. | `allow`, `blockOrganizationalData`, `block` | -| **TargetedAppManagementLevels** | Write | String | The intended app management levels for this policy. | `unspecified`, `unmanaged`, `mdm`, `androidEnterprise` | +| **TargetedAppManagementLevels** | Write | StringArray[] | The intended app management levels for this policy. | `unspecified`, `unmanaged`, `mdm`, `androidEnterprise` | | **AppDataEncryptionType** | Write | String | Require app data to be encrypted. | `useDeviceSettings`, `afterDeviceRestart`, `whenDeviceLockedExceptOpenFiles`, `whenDeviceLocked` | | **ExemptedAppProtocols** | Write | StringArray[] | Apps in this list will be exempt from the policy and will be able to receive data from managed apps. | | | **MinimumWipeSdkVersion** | Write | String | Versions less than the specified version will block the managed app from accessing company data. | | From ddf9b225da84158c44a5be926ad4a95fe07d1c7c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 13:22:12 +0000 Subject: [PATCH 453/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 9a5b65af10..190ce0965d 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -19883,7 +19883,7 @@ "Option": "Write" }, { - "CIMType": "String", + "CIMType": "String[]", "Name": "TargetedAppManagementLevels", "Option": "Write" }, From b328025f17934ba81cdde18407ae32da722440a5 Mon Sep 17 00:00:00 2001 From: salbeck-sit Date: Wed, 2 Oct 2024 15:23:34 +0200 Subject: [PATCH 454/465] removed 4th example and updated changelog --- CHANGELOG.md | 10 ++--- .../Examples/Resources/AADGroup/2-Update.ps1 | 27 +++++++----- .../Examples/Resources/AADGroup/4-License.ps1 | 43 ------------------- 3 files changed, 20 insertions(+), 60 deletions(-) delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/AADGroup/4-License.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cc11846ec..7b91448c0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,6 @@ # Change log for Microsoft365DSC # UNRELEASED -* AADGroup - * Fixes issue with code that is never executed - FIXES [#5001](https://github.com/microsoft/Microsoft365DSC/issues/5001) - * Fixes issue with incorrect removal of assigned license(s) - FIXES [#5128](https://github.com/microsoft/Microsoft365DSC/issues/5128) - * AADApplication * Added AppRoles @@ -24,8 +18,12 @@ * AADFeatureRolloutPolicy * Initial release * AADGroup + * Fixes issue with incorrect removal of assigned license(s) + FIXES [#5128](https://github.com/microsoft/Microsoft365DSC/issues/5128) * Fixes logic to evaluate license assignments and disabled plans. FIXES [#5101](https://github.com/microsoft/Microsoft365DSC/issues/5101) + * Fixes issue with code that is never executed + FIXES [#5001](https://github.com/microsoft/Microsoft365DSC/issues/5001) * Adds support to assign Service Principal as members or owners. FIXES [#4972](https://github.com/microsoft/Microsoft365DSC/issues/4972) * AADPasswordRuleSettings diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADGroup/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADGroup/2-Update.ps1 index 07b9ba1c62..0a91bf600f 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADGroup/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADGroup/2-Update.ps1 @@ -23,17 +23,22 @@ Configuration Example { AADGroup 'MyGroups' { - DisplayName = "DSCGroup" - Description = "Microsoft DSC Group Updated" # Updated Property - SecurityEnabled = $True - MailEnabled = $True - GroupTypes = @("Unified") - MailNickname = "M365DSC" - Members = @("AdeleV@$TenantId") - GroupAsMembers = @("Group1") - Visibility = "Private" - Owners = @("admin@$TenantId", "AdeleV@$TenantId") - Ensure = "Present" + DisplayName = "DSCGroup" + Description = "Microsoft DSC Group Updated" # Updated Property + SecurityEnabled = $True + MailEnabled = $True + GroupTypes = @("Unified") + MailNickname = "M365DSC" + Members = @("AdeleV@$TenantId") + GroupAsMembers = @("Group1") + Visibility = "Private" + Owners = @("admin@$TenantId", "AdeleV@$TenantId") + AssignedLicenses = @( + MSFT_AADGroupLicense { + SkuId = 'AAD_PREMIUM_P2' + } + ) + Ensure = "Present" ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADGroup/4-License.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADGroup/4-License.ps1 deleted file mode 100644 index 0704ae08bd..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/AADGroup/4-License.ps1 +++ /dev/null @@ -1,43 +0,0 @@ -<# -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()] - [System.String] - $ApplicationId, - - [Parameter()] - [System.String] - $TenantId, - - [Parameter()] - [System.String] - $CertificateThumbprint - ) - Import-DscResource -ModuleName Microsoft365DSC - node localhost - { - AADGroup 'MyGroups' - { - DisplayName = "DSCGroup" - Description = "Microsoft DSC Group with assigned license" # Updated Property - SecurityEnabled = $True - MailEnabled = $False - MailNickname = "M365DSC" - AssignedLicenses = @( - MSFT_AADGroupLicense { - SkuId = 'AAD_PREMIUM_P2' - } - ) - - Ensure = "Present" - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - } - } -} From c21a25ebe92d862f947b19d1ce188c46530160d7 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 13:39:21 +0000 Subject: [PATCH 455/465] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/azure-ad/AADGroup.md | 27 ++++++++++++++---------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/docs/docs/resources/azure-ad/AADGroup.md b/docs/docs/resources/azure-ad/AADGroup.md index 7eb2ef6775..8e8fb1e3c4 100644 --- a/docs/docs/resources/azure-ad/AADGroup.md +++ b/docs/docs/resources/azure-ad/AADGroup.md @@ -145,17 +145,22 @@ Configuration Example { AADGroup 'MyGroups' { - DisplayName = "DSCGroup" - Description = "Microsoft DSC Group Updated" # Updated Property - SecurityEnabled = $True - MailEnabled = $True - GroupTypes = @("Unified") - MailNickname = "M365DSC" - Members = @("AdeleV@$TenantId") - GroupAsMembers = @("Group1") - Visibility = "Private" - Owners = @("admin@$TenantId", "AdeleV@$TenantId") - Ensure = "Present" + DisplayName = "DSCGroup" + Description = "Microsoft DSC Group Updated" # Updated Property + SecurityEnabled = $True + MailEnabled = $True + GroupTypes = @("Unified") + MailNickname = "M365DSC" + Members = @("AdeleV@$TenantId") + GroupAsMembers = @("Group1") + Visibility = "Private" + Owners = @("admin@$TenantId", "AdeleV@$TenantId") + AssignedLicenses = @( + MSFT_AADGroupLicense { + SkuId = 'AAD_PREMIUM_P2' + } + ) + Ensure = "Present" ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint From fe68fa29924e446cd43b83c9e70aa21bc5666259 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 13:39:39 +0000 Subject: [PATCH 456/465] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Update.Tests.ps1 | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index 5e7b294392..0c37abdb2c 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -710,17 +710,22 @@ } AADGroup 'MyGroups' { - DisplayName = "DSCGroup" - Description = "Microsoft DSC Group Updated" # Updated Property - SecurityEnabled = $True - MailEnabled = $True - GroupTypes = @("Unified") - MailNickname = "M365DSC" - Members = @("AdeleV@$TenantId") - GroupAsMembers = @("Group1") - Visibility = "Private" - Owners = @("admin@$TenantId", "AdeleV@$TenantId") - Ensure = "Present" + DisplayName = "DSCGroup" + Description = "Microsoft DSC Group Updated" # Updated Property + SecurityEnabled = $True + MailEnabled = $True + GroupTypes = @("Unified") + MailNickname = "M365DSC" + Members = @("AdeleV@$TenantId") + GroupAsMembers = @("Group1") + Visibility = "Private" + Owners = @("admin@$TenantId", "AdeleV@$TenantId") + AssignedLicenses = @( + MSFT_AADGroupLicense { + SkuId = 'AAD_PREMIUM_P2' + } + ) + Ensure = "Present" ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint From 62fc9882aee07c1ca410a28c43e8ac4b44c6cc6d Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 2 Oct 2024 09:40:37 -0400 Subject: [PATCH 457/465] Release 1.24.1002.1 --- CHANGELOG.md | 2 +- Modules/Microsoft365DSC/Microsoft365DSC.psd1 | 137 +++++++++++++++++-- docs/docs/blog/index.md | 1 + docs/docs/blog/october-2024-major-release.md | 39 ++++++ 4 files changed, 164 insertions(+), 15 deletions(-) create mode 100644 docs/docs/blog/october-2024-major-release.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a312616ab..8e1581cf47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Change log for Microsoft365DSC -# UNRELEASED +# 1.24.1002.1 * AADApplication * Added AppRoles diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index 0d8b221bdd..68bd75c4a8 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -3,7 +3,7 @@ # # Generated by: Microsoft Corporation # -# Generated on: 2024-09-05 +# Generated on: 2024-10-02 @{ @@ -11,7 +11,7 @@ # RootModule = '' # Version number of this module. - ModuleVersion = '1.24.904.1' + ModuleVersion = '1.24.1002.1' # Supported PSEditions # CompatiblePSEditions = @() @@ -144,22 +144,131 @@ IconUri = 'https://github.com/microsoft/Microsoft365DSC/blob/Dev/Modules/Microsoft365DSC/Dependencies/Images/Logo.png?raw=true' # ReleaseNotes of this module - ReleaseNotes = '* EXOOwaMailboxPolicy - * Add support for AccountTransferEnabled parameter -* EXOSweepRule + ReleaseNotes = '* AADApplication + * Added AppRoles + * Added AuthenticationBehavior + * Added KeyCredentials + * Added OptionalClaims + * Added PasswordCredentials + * Added PreAuthorizationApplications +* AADAuthenticationMethodPolicy + * Added ReportSuspiciousActivitySettings +* AADAuthenticationMethodPolicyHardware + * Initial release. +* AADEntitlementManagementSettings + * Initial release. +* AADFeatureRolloutPolicy + * Initial release +* AADGroup + * Fixes logic to evaluate license assignments and disabled plans. + FIXES [#5101](https://github.com/microsoft/Microsoft365DSC/issues/5101) + * Adds support to assign Service Principal as members or owners. + FIXES [#4972](https://github.com/microsoft/Microsoft365DSC/issues/4972) +* AADPasswordRuleSettings + * Initial release +* ADOOrganizationOwner + * Initial release. +* ADOPermissionGroup + * Initial release. +* ADOSecurityPolicy + * Initial release. +* AzureSubscription * Initial Release. -* FabricAdminTenantSettings +* DefenderSubscriptionDefenderPlan + * Initial release. +* EXOAntiPhishPolicy + * Use correct type integer for variable `PhishThresholdLevel` +* EXOArcConfig * Initial Release. -* IntuneDeviceControlPolicyWindows10 - * Initial Release +* EXODnssecForVerifiedDomain + * Initial Release. +* EXOEmailTenantSettings + * Initial Release. +* EXOFocusedInbox + * Initial Release. +* EXOMailboxCalendarConfiguration + * Initial Release. +* EXOMailboxIRMAccess + * Initial Release. +* EXOMailboxFolderPermission + * Initial Release. +* EXOMailboxIRMAccess + * Initial Release. +* EXOMailTips + * Remove property `Ensure` since this resource is of type `IsSingleInstance` +* EXOManagementScope + * Initial Release. +* EXORetentionPolicy + * Initial Release. +* EXOPhishSimOverrideRule + * Initial Release. +* IntuneAntivirusPolicyWindows10SettingCatalog + * Fixes an issue with invalid parameter definition. + FIXES [#5015](https://github.com/microsoft/Microsoft365DSC/issues/5015) + * Fixes an issue where the `AccessTokens` parameter was not available. + FIXES [#5121](https://github.com/microsoft/Microsoft365DSC/issues/5121) +* IntuneAppCategory + * Initial release. +* IntuneDeviceCompliancePolicyWindows10 + * Fixes an issue where the property `ValidOperatingSystemBuildRanges` was + not exported properly. + FIXES [#5030](https://github.com/microsoft/Microsoft365DSC/issues/5030) +* IntuneDeviceConfigurationSharedMultiDevicePolicyWindows10 + * Add missing `AccessTokens` parameter to `Export-TargetResource` + FIXES [#5034](https://github.com/microsoft/Microsoft365DSC/issues/5034) +* IntuneFirewallPolicyWindows10 + * Initial release + FIXES [#3033](https://github.com/microsoft/Microsoft365DSC/issues/3033) +* IntuneSettingCatalogCustomPolicyWindows10 + * Update export logic to target more specific policy types. + * Prevent thrown exception to be caught by exception handler. + FIXES [#5088](https://github.com/microsoft/Microsoft365DSC/issues/5088) * M365DSCDRGUtil - * Fixes an issue where a Intune settings catalog DSC param was not handled - correctly when it was not specified. - FIXES [#5000](https://github.com/microsoft/Microsoft365DSC/issues/5000) - * Fixes an issue where the exported nested CIM instances had too many line breaks. - * Fixes an issue where Settings Catalog properties were not correctly handled. + * Add support for more complex Intune Settings Catalog properties + * Update handling of `Update-IntuneDeviceConfigurationPolicy` to throw on error + FIXES [#5055](https://github.com/microsoft/Microsoft365DSC/issues/5055) +* M365DSCResourceGenerator + * Update Intune resource generation for the Settings Catalog. +* O365ExternalConnection + * Initial release. +* SCDeviceConditionalAccessRule + * Initial release. +* SCDeviceConfigurationRule + * Initial release. +* SCInsiderRiskEntityList + * Initial release. +* SCInsiderRiskPolicy + * Initial release. +* SCRecordReviewNotificationTemplateConfig + * Initial release. +* SCRoleGroup + * Fixes an issue with creation without specifying Displayname + * Fixes an issue with Drifts because of returned Role format + FIXES [#5036](https://github.com/microsoft/Microsoft365DSC/issues/5036) +* SCAutoSensitivityLabelRule + * Fixed issue with incorrectly applying HeaderMatchesPatterns, even when + parameter wasn`t specified. + FIXES [#4641](https://github.com/microsoft/Microsoft365DSC/issues/4641) +* SCSensitivityLabel + * Added support for Auto Labeling settings + FIXES [#3784](https://github.com/microsoft/Microsoft365DSC/issues/3784) +* SentinelSetting + * Initial release. +* SentinelWatchlist + * Initial release. +* SPOAccessControlSettings + * Added support for property EnableRestrictedAccessControl. +* M365DSCUtil + * Fixes an issue where the O365Group workload was not properly detected. + FIXES [#5095](https://github.com/microsoft/Microsoft365DSC/issues/5095) * DEPENDENCIES - * Updated MSCloudLoginAssistant to version 1.1.20.' + * Updated DSCParser to version 2.0.0.10. + * Updated Microsoft.Graph to version 2.23.0. + * Added dependencies on Az.Accounts, Az.Resources and Az.SecurityInsights + * Updated DSCParser to version 2.0.0.9. + * Updated MSCloudLoginAssistant to version 1.1.25. + * Added dependency on Microsoft.Graph.Beta.Search. + * Removed unnecessary dependency PSDesiredStateConfiguration v1.1' # Flag to indicate whether the module requires explicit user acceptance for install/update # RequireLicenseAcceptance = $false diff --git a/docs/docs/blog/index.md b/docs/docs/blog/index.md index 719a60c7a6..75a3bf47b6 100644 --- a/docs/docs/blog/index.md +++ b/docs/docs/blog/index.md @@ -2,6 +2,7 @@ ## Major Updates +* [October 2024 Major Release](https://microsoft365dsc.com/blog/october-2024-major-release/index.html) * [April 2024 Major Release](https://microsoft365dsc.com/blog/april-2024-major-release/index.html) * [October 2023 Major Release](https://microsoft365dsc.com/blog/october-2023-major-release/index.html) * [April 2023 Major Release](https://microsoft365dsc.com/blog/april-2023-major-release/index.html) diff --git a/docs/docs/blog/october-2024-major-release.md b/docs/docs/blog/october-2024-major-release.md new file mode 100644 index 0000000000..624c6cb48f --- /dev/null +++ b/docs/docs/blog/october-2024-major-release.md @@ -0,0 +1,39 @@ +# Microsoft365DSC – OCtober 2024 Major Release (version 1.24.1002.1) + +As defined by our [Breaking Changes Policy](https://microsoft365dsc.com/concepts/breaking-changes/), twice a year we allow for breaking changes to be deployed as part of a release. Our next major release, scheduled to go out on October 2nd 2024, will include several breaking changes and will be labeled version 1.24.1002.1. This article provides details on the breaking changes and other important updates that will be included as part of our October 2024 Major release. + +## EXOMailTips - Removal of the Ensure Parameter ([#4823](https://github.com/microsoft/Microsoft365DSC/pull/4823)) + +The EXOMailTips resource manages a tenant wide setting where only one instance can ever exist. Therefore, the Ensure parameter has been removed from the resource. In order to fix your baseline, search for any EXOMailTips entry and remove the Ensure parameter from the configuration file. + +## EXOAntiPhishPolicy - Changed PhishThresholdLevel to Integer ([#4687](https://github.com/microsoft/Microsoft365DSC/pull/4687/)) + +The PhishThresholdLevel property of the EXOAntiPhishPolicy resource was incorrectly defined as a string. In this major release, the parameter type will change from String to Int32. In order to fix your baseline, search for the PhishThresholdLevel property and make sure you update the type to be an integer (e.g., remove quotes around the level value). + +## TeamsComplianceRecordingPolicy - Added Complex type for ComplianceRecordingApplications ([3754](https://github.com/microsoft/Microsoft365DSC/pull/3754)) + +The ComplianceRecordingApplications parameter of the TeamsComplianceRecordingPolicy resource was changed from being a string array to being an array of CIMInstances (complex types). There are unfortunately no direct ways to update existing configurations. Instead, make sure you search for the ComplianceRecordingApplications property in your config and update the entries to match the CimInstances definition. + +e.g., +```Powershell +ComplianceRecordingApplications = @( + MSFT_TeamsComplianceRecordingApplication{ + Id = '00000000-0000-0000-0000-000000000000' + ComplianceRecordingPairedApplications = @('00000000-0000-0000-0000-000000000000') + ConcurrentInvitationCount = 1 + RequiredDuringCall = $True + RequiredBeforeMeetingJoin = $True + RequiredBeforeCallEstablishment = $True + RequiredDuringMeeting = $True + } + MSFT_TeamsComplianceRecordingApplication{ + Id = '12345678-0000-0000-0000-000000000000' + ComplianceRecordingPairedApplications = @('87654321-0000-0000-0000-000000000000') + ConcurrentInvitationCount = 1 + RequiredDuringCall = $True + RequiredBeforeMeetingJoin = $True + RequiredBeforeCallEstablishment = $True + RequiredDuringMeeting = $True + } +); +``` From 0752121b9af18c547bdc41ab64609de2232508ab Mon Sep 17 00:00:00 2001 From: Dan Lag Date: Wed, 2 Oct 2024 09:42:38 -0400 Subject: [PATCH 458/465] Modified AADAdministrativeUnit.Tests with new MgBeta cmdlet --- .../Microsoft365DSC.AADAdministrativeUnit.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAdministrativeUnit.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAdministrativeUnit.Tests.ps1 index 2f72570e31..f9b56e9ab3 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAdministrativeUnit.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADAdministrativeUnit.Tests.ps1 @@ -115,7 +115,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } It 'Should Create the AU from the Set method' { Set-TargetResource @testParams - Should -Invoke -CommandName Invoke-MgGraphRequest -Exactly 1 + Should -Invoke -CommandName New-MgBetaDirectoryAdministrativeUnit -Exactly 1 } } From 5ce9c7fbf1a2ec895550893943e03f37b0b82941 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 14:25:49 +0000 Subject: [PATCH 459/465] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/azure-ad/AADAdministrativeUnit.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/docs/resources/azure-ad/AADAdministrativeUnit.md b/docs/docs/resources/azure-ad/AADAdministrativeUnit.md index 89dd351064..eafad9c5e6 100644 --- a/docs/docs/resources/azure-ad/AADAdministrativeUnit.md +++ b/docs/docs/resources/azure-ad/AADAdministrativeUnit.md @@ -8,6 +8,7 @@ | **Id** | Write | String | Object-Id of the Administrative Unit | | | **Description** | Write | String | Description of the Administrative Unit | | | **Visibility** | Write | String | Visibility of the Administrative Unit. Specify HiddenMembership if members of the AU are hidden | | +| **IsMemberManagementRestricted** | Write | Boolean | Indicates whether the management rights on resources in the administrative units should be restricted to ONLY the administrators scoped on the administrative unit object. | | | **MembershipType** | Write | String | Specify membership type. Possible values are Assigned and Dynamic. Note that the functionality is currently in preview. | | | **MembershipRule** | Write | String | Specify membership rule. Requires that MembershipType is set to Dynamic. Note that the functionality is currently in preview. | | | **MembershipRuleProcessingState** | Write | String | Specify dynamic membership-rule processing-state. Valid values are 'On' and 'Paused'. Requires that MembershipType is set to Dynamic. Note that the functionality is currently in preview. | | @@ -105,6 +106,7 @@ Configuration Example MembershipRule = "(user.country -eq `"Canada`")" MembershipRuleProcessingState = 'On' MembershipType = 'Dynamic' + IsMemberManagementRestricted = $False; ScopedRoleMembers = @( MSFT_MicrosoftGraphScopedRoleMembership { @@ -157,6 +159,7 @@ Configuration Example MembershipRule = "(user.country -eq `"US`")" # Updated Property MembershipRuleProcessingState = 'On' MembershipType = 'Dynamic' + IsMemberManagementRestricted = $False ScopedRoleMembers = @( MSFT_MicrosoftGraphScopedRoleMembership { From 6738f9bf488971cdaa8c81e4610789531d94b38e Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 14:25:52 +0000 Subject: [PATCH 460/465] Updated {Create} AAD Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 index acc46c6e4b..d45e6582da 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 @@ -41,6 +41,7 @@ MembershipRule = "(user.country -eq `"Canada`")" MembershipRuleProcessingState = 'On' MembershipType = 'Dynamic' + IsMemberManagementRestricted = $False; ScopedRoleMembers = @( MSFT_MicrosoftGraphScopedRoleMembership { From 38f7712b9d050c8f27fb1bf419b4d70d8e5fa92b Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 14:26:10 +0000 Subject: [PATCH 461/465] Updated {Update} AAD Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index 0c37abdb2c..c9363e1d89 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -42,6 +42,7 @@ MembershipRule = "(user.country -eq `"US`")" # Updated Property MembershipRuleProcessingState = 'On' MembershipType = 'Dynamic' + IsMemberManagementRestricted = $False ScopedRoleMembers = @( MSFT_MicrosoftGraphScopedRoleMembership { From fbd3837d00c4186a1a66bb244dc579adcc069763 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 2 Oct 2024 14:27:42 +0000 Subject: [PATCH 462/465] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 190ce0965d..08ad6e8253 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -112,6 +112,11 @@ "Name": "Visibility", "Option": "Write" }, + { + "CIMType": "Boolean", + "Name": "IsMemberManagementRestricted", + "Option": "Write" + }, { "CIMType": "String", "Name": "MembershipType", From 72c2d2878efb15f6b7e38523bb36cd3b37c79d4a Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 2 Oct 2024 10:46:14 -0400 Subject: [PATCH 463/465] Fixes --- CHANGELOG.md | 3 ++- .../MSFT_ADOOrganizationOwner.psm1 | 3 ++- .../MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.psm1 | 3 ++- Modules/Microsoft365DSC/Dependencies/Manifest.psd1 | 8 ++++++++ Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 2 +- 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da5dffec9c..2196377267 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -135,7 +135,8 @@ * DEPENDENCIES * Updated DSCParser to version 2.0.0.10. * Updated Microsoft.Graph to version 2.23.0. - * Added dependencies on Az.Accounts, Az.Resources and Az.SecurityInsights + * Added dependencies on Az.Accounts, Az.Resources, Az.ResourceGraph + and Az.SecurityInsights. * Updated DSCParser to version 2.0.0.9. * Updated MSCloudLoginAssistant to version 1.1.25. * Added dependency on Microsoft.Graph.Beta.Search. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 index a6bae9c949..db746c4549 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOOrganizationOwner/MSFT_ADOOrganizationOwner.psm1 @@ -281,9 +281,10 @@ function Export-TargetResource $i = 1 $dscContent = '' - if ($accounts.Length -eq 0) + if ($accounts.count -eq 0) { Write-Host $Global:M365DSCEmojiGreenCheckMark + return '' } else { diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.psm1 index ede45030e4..1f9df20d61 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_ADOPermissionGroup/MSFT_ADOPermissionGroup.psm1 @@ -482,9 +482,10 @@ function Export-TargetResource $i = 1 $dscContent = '' - if ($accounts.Length -eq 0) + if ($accounts.count -eq 0) { Write-Host $Global:M365DSCEmojiGreenCheckMark + return '' } else { diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 92f8fb55a5..d2d088cc8d 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -4,10 +4,18 @@ ModuleName = 'Az.Accounts' RequiredVersion = '3.0.2' }, + @{ + ModuleName = 'Az.ResourceGraph' + RequiredVersion = '1.0.0' + }, @{ ModuleName = 'Az.Resources' RequiredVersion = '7.2.0' }, + @{ + ModuleName = 'Az.ResourceGraph' + RequiredVersion = '1.0.0' + }, @{ ModuleName = 'Az.SecurityInsights' RequiredVersion = '3.1.2' diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 576bd52015..4c8a60fca0 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -9,7 +9,7 @@ $Global:DefaultComponents = @('SPOApp', 'SPOSiteDesign') $Global:FullComponents = @('AADGroup', 'AADServicePrincipal', 'ADOSecurityPolicy', 'AzureSubscription','FabricAdminTenantSettings', ` 'EXOCalendarProcessing', 'EXODistributionGroup', 'EXOMailboxAutoReplyConfiguration', ` 'EXOMailboxPermission','EXOMailboxCalendarFolder','EXOMailboxSettings', 'EXOManagementRole', 'O365Group', 'AADUser', ` - 'PlannerPlan', 'PlannerBucket', 'PlannerTask', 'PPPowerAppsEnvironment', 'PPTenantSettings', ` + 'PlannerPlan', 'PlannerBucket', 'PlannerTask', 'PPPowerAppsEnvironment', 'PPTenantSettings', 'SentinelSetting', 'SentinelWatchlist', ` 'SPOSiteAuditSettings', 'SPOSiteGroup', 'SPOSite', 'SPOUserProfileProperty', 'SPOPropertyBag', 'TeamsTeam', 'TeamsChannel', ` 'TeamsUser', 'TeamsChannelTab', 'TeamsOnlineVoicemailUserSettings', 'TeamsUserCallingSettings', 'TeamsUserPolicyAssignment') #endregion From b78f8e8d8563f783c607ba96bbeb8bdd11607893 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 2 Oct 2024 12:31:35 -0400 Subject: [PATCH 464/465] Various fixes --- .../MSFT_DefenderSubscriptionPlan.psm1 | 25 ++++++++++++------- .../MSFT_EXOMailboxFolderPermission.psm1 | 10 ++++++-- .../MSFT_SCDLPComplianceRule.psm1 | 2 +- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 2 +- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_DefenderSubscriptionPlan/MSFT_DefenderSubscriptionPlan.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_DefenderSubscriptionPlan/MSFT_DefenderSubscriptionPlan.psm1 index bcb06d6007..13a1b423f4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_DefenderSubscriptionPlan/MSFT_DefenderSubscriptionPlan.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_DefenderSubscriptionPlan/MSFT_DefenderSubscriptionPlan.psm1 @@ -454,21 +454,28 @@ function Export-TargetResource function Get-SubscriptionsDefenderPlansFromArg { - $results = @() - $argQuery=@' + try + { + $results = @() + $argQuery=@' securityresources | where type == "microsoft.security/pricings" | project Id=id, PlanName=name, SubscriptionId=subscriptionId, SubPlan=tostring(properties.subPlan), PricingTier=tostring(properties.pricingTier), Extensions=tostring(properties.extensions) | join kind=inner (resourcecontainers | where type == "microsoft.resources/subscriptions" | project SubscriptionName = name, SubscriptionId = subscriptionId) on SubscriptionId | project-away SubscriptionId1 '@ - $queryResult = Search-AzGraph -Query $argQuery -First 1000 -UseTenantScope -ErrorAction Stop - $results+=$queryResult.Data + $queryResult = Search-AzGraph -Query $argQuery -First 1000 -UseTenantScope -ErrorAction Stop + $results += $queryResult.Data + + while($queryResult.SkipToken -ne $null) + { + $queryResult = Search-AzGraph -Query $argQuery -First 1000 -UseTenantScope -SkipToken $queryResult.SkipToken -ErrorAction Stop + $results+=$queryResult.Data + } - while($queryResult.SkipToken -ne $null) + return $results + } + catch { - $queryResult = Search-AzGraph -Query $argQuery -First 1000 -UseTenantScope -SkipToken $queryResult.SkipToken -ErrorAction Stop - $results+=$queryResult.Data + throw $_ } - - return $results } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 index 419d5aea79..21fcb822c9 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxFolderPermission/MSFT_EXOMailboxFolderPermission.psm1 @@ -390,8 +390,14 @@ function Export-TargetResource try { - Write-Host "`r`n" -NoNewline - Write-Host " |---Getting only the mailbox folders for the current admin" -NoNewline + # Ensure the cmdlet is available + $cmdletInfo = Get-Command Get-MailboxFolder -ErrorAction SilentlyContinue + + if ($null -eq $cmdletInfo) + { + Write-Host " `r`n$($Global:M365DSCEmojiYellowCircle) The Get-MailboxFolder cmdlet is not avalaible. Service Principals do not have mailboxes." + return '' + } [Array]$mailboxFolders = Get-MailboxFolder -Recurse diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 index 58cd3a9831..053cd48070 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 @@ -407,7 +407,7 @@ function Get-TargetResource { $ruleobject.Condition.SubConditions[$index].Value = $ruleobject.Condition.SubConditions[$index].Value | Select-Object * -ExcludeProperty Id } - else + elseif ($null -ne $ruleObject.Condition.SubConditions[$index].Value.Groups.Sensitivetypes) { $ruleobject.Condition.SubConditions[$index].Value.Groups.Sensitivetypes = @($ruleobject.Condition.SubConditions[$index].Value.Groups.Sensitivetypes | Select-Object * -ExcludeProperty Id) } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 4c8a60fca0..d8e020b073 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -7,7 +7,7 @@ $Global:SessionSecurityCompliance = $null $Global:DefaultComponents = @('SPOApp', 'SPOSiteDesign') $Global:FullComponents = @('AADGroup', 'AADServicePrincipal', 'ADOSecurityPolicy', 'AzureSubscription','FabricAdminTenantSettings', ` - 'EXOCalendarProcessing', 'EXODistributionGroup', 'EXOMailboxAutoReplyConfiguration', ` + 'DefenderSubscriptionPlan', 'EXOCalendarProcessing', 'EXODistributionGroup', 'EXOMailboxAutoReplyConfiguration', ` 'EXOMailboxPermission','EXOMailboxCalendarFolder','EXOMailboxSettings', 'EXOManagementRole', 'O365Group', 'AADUser', ` 'PlannerPlan', 'PlannerBucket', 'PlannerTask', 'PPPowerAppsEnvironment', 'PPTenantSettings', 'SentinelSetting', 'SentinelWatchlist', ` 'SPOSiteAuditSettings', 'SPOSiteGroup', 'SPOSite', 'SPOUserProfileProperty', 'SPOPropertyBag', 'TeamsTeam', 'TeamsChannel', ` From 335a5c9fc280bcb118804306294e93f6e43c29c5 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 2 Oct 2024 12:47:43 -0400 Subject: [PATCH 465/465] Update MSFT_TeamsM365App.psm1 --- .../MSFT_TeamsM365App/MSFT_TeamsM365App.psm1 | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsM365App/MSFT_TeamsM365App.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsM365App/MSFT_TeamsM365App.psm1 index 232f63ddc3..ee499942df 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsM365App/MSFT_TeamsM365App.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsM365App/MSFT_TeamsM365App.psm1 @@ -435,7 +435,16 @@ function Export-TargetResource try { $Script:ExportMode = $true - [array] $Script:exportedInstances = Get-AllM365TeamsApps -ErrorAction Stop + + [array] $Script:exportedInstances = @() + try + { + [array] $Script:exportedInstances = Get-AllM365TeamsApps -ErrorAction Stop + } + catch + { + Write-Verbose $_ + } $i = 1 $dscContent = ''