Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AADGroup: Implements #2301 #2316

Merged
merged 11 commits into from
Sep 29, 2022
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

# UNRELEASED

* AADGroup
* Added properties MemberOf and AssignedToRole
Implements [#2301](https://github.com/microsoft/Microsoft365DSC/issues/2301)
* EXOMailContact
* Initial Release.
* EXOMailTips
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ function Get-TargetResource
[System.String[]]
$Members,

[Parameter()]
[System.String[]]
$MemberOf,

[Parameter()]
[System.String]
$Description,
Expand Down Expand Up @@ -53,6 +57,10 @@ function Get-TargetResource
[System.Boolean]
$IsAssignableToRole,

[Parameter()]
[System.String[]]
$AssignedToRole,

[Parameter()]
[ValidateSet('Public', 'Private', 'HiddenMembership')]
[System.String]
Expand Down Expand Up @@ -175,7 +183,36 @@ function Get-TargetResource
}
}

# MemberOf
[Array]$memberOf = Get-MgGroupMemberOf -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"}))
{
if ($null -ne $member.AdditionalProperties.displayName)
{
$MemberOfValues += $member.AdditionalProperties.displayName
}
}

# AssignedToRole
$AssignedToRoleValues = $null
if ($Group.IsAssignableToRole -eq $true)
{
$AssignedToRoleValues = @()
# Note: only process directory roles and not group membership (if any)
foreach ($role in $($memberOf | Where-Object -FilterScript {$_.AdditionalProperties.'@odata.type' -eq "#microsoft.graph.directoryRole"}))
{
if ($null -ne $role.AdditionalProperties.displayName)
{
$AssignedToRoleValues += $role.AdditionalProperties.displayName
}
}
}


# Licenses
$assignedLicensesValues = $null
$assignedLicensesRequest = Invoke-MgGraphRequest -Method 'GET' `
-Uri "https://graph.microsoft.com/v1.0/groups/$($Group.Id)/assignedLicenses"

Expand All @@ -190,13 +227,15 @@ function Get-TargetResource
Id = $Group.Id
Owners = $OwnersValues
Members = $MembersValues
MemberOf = $MemberOfValues
Description = $Group.Description
GroupTypes = [System.String[]]$Group.GroupTypes
MembershipRule = $Group.MembershipRule
MembershipRuleProcessingState = $Group.MembershipRuleProcessingState
SecurityEnabled = $Group.SecurityEnabled
MailEnabled = $Group.MailEnabled
IsAssignableToRole = $Group.IsAssignableToRole
AssignedToRole = $AssignedToRoleValues
MailNickname = $Group.MailNickname
Visibility = $Group.Visibility
AssignedLicenses = $assignedLicensesValues
Expand Down Expand Up @@ -259,6 +298,10 @@ function Set-TargetResource
[System.String[]]
$Members,

[Parameter()]
[System.String[]]
$MemberOf,

[Parameter()]
[System.String]
$Description,
Expand Down Expand Up @@ -288,6 +331,10 @@ function Set-TargetResource
[System.Boolean]
$IsAssignableToRole,

[Parameter()]
[System.string[]]
$AssignedToRole,

[Parameter()]
[ValidateSet('Public', 'Private', 'HiddenMembership')]
[System.String]
Expand Down Expand Up @@ -352,8 +399,12 @@ function Set-TargetResource
$currentParameters.Remove('ManagedIdentity') | Out-Null
$backCurrentOwners = $currentGroup.Owners
$backCurrentMembers = $currentGroup.Members
$backCurrentMemberOf = $currentGroup.MemberOf
$backCurrentAssignedToRole = $currentGroup.AssignedToRole
$currentParameters.Remove('Owners') | Out-Null
$currentParameters.Remove('Members') | Out-Null
$currentParameters.Remove('MemberOf') | Out-Null
$currentParameters.Remove('AssignedToRole') | Out-Null

if ($Ensure -eq 'Present' -and `
($null -ne $GroupTypes -and $GroupTypes.Contains('Unified')) -and `
Expand Down Expand Up @@ -607,6 +658,122 @@ function Set-TargetResource
{
Write-Verbose -Message 'Ignoring membership since this is a dynamic group.'
}

#MemberOf
$currentMemberOfValue = @()
if ($currentParameters.MemberOf.Length -ne 0)
{
$currentMemberOfValue = $backCurrentMemberOf
}
$desiredMemberOfValue = @()
if ($MemberOf.Length -ne 0)
{
$desiredMemberOfValue = $MemberOf
}
if ($null -eq $backCurrentMemberOf)
{
$backCurrentMemberOf = @()
}
$memberOfDiff = Compare-Object -ReferenceObject $backCurrentMemberOf -DifferenceObject $desiredMemberOfValue
foreach ($diff in $memberOfDiff)
{
try
{
$memberOfGroup = Get-MgGroup -Filter "DisplayName -eq '$($diff.InputObject)'" -ErrorAction Stop
}
catch
{
$memberOfGroup = $null
}
if ($null -eq $memberOfGroup)
{
throw "Security-group or directory role '$($diff.InputObject)' does not exist"
}
else
{
if ($diff.SideIndicator -eq '=>')
{
# see if memberOfGroup contains property SecurityEnabled (it can be true or false)
if ($memberOfgroup.psobject.Typenames -match 'Group')
{
Write-Verbose -Message "Adding AAD group {$($currentGroup.DisplayName)} as member of AAD group {$($memberOfGroup.DisplayName)}"
#$memberOfObject = @{
# "@odata.id"= "https://graph.microsoft.com/v1.0/groups/{$($group.Id)}"
#}
New-MgGroupMember -GroupId ($memberOfGroup.Id) -DirectoryObject ($currentGroup.Id) | Out-Null
}
else
{
Throw "Cannot add AAD group {$($currentGroup.DisplayName)} to {$($memberOfGroup.DisplayName)} as it is not a security-group"
}

}
elseif ($diff.SideIndicator -eq '<=')
{
if ($memberOfgroup.psobject.Typenames -match 'Group')
{
Write-Verbose -Message "Removing AAD Group {$($currentGroup.DisplayName)} from AAD group {$($memberOfGroup.DisplayName)}"
Remove-MgGroupMemberByRef -GroupId ($memberOfGroup.Id) -DirectoryObjectId ($currentGroup.Id) |Out-Null
}
else
{
Throw "Cannot remove AAD group {$($currentGroup.DisplayName)} from {$($memberOfGroup.DisplayName)} as it is not a security-group"
}
}
}
}

if ($currentGroup.IsAssignableToRole -eq $true)
{
#AssignedToRole
$currentAssignedToRoleValue = @()
if ($currentParameters.AssignedToRole.Length -ne 0)
{
$currentAssignedToRoleValue = $backCurrentAssignedToRole
}
$desiredAssignedToRoleValue = @()
if ($AssignedToRole.Length -ne 0)
{
$desiredAssignedToRoleValue = $AssignedToRole
}
if ($null -eq $backCurrentAssignedToRole)
{
$backCurrentAssignedToRole = @()
}
$assignedToRoleDiff = Compare-Object -ReferenceObject $backCurrentAssignedToRole -DifferenceObject $desiredAssignedToRoleValue
foreach ($diff in $assignedToRoleDiff)
{
try
{
$role = Get-MgDirectoryRole -Filter "DisplayName -eq '$($diff.InputObject)'" -ErrorAction Stop
}
catch
{
$role = $null
}
if ($null -eq $role)
{
throw "Directory Role '$($diff.InputObject)' does not exist or is not enabled"
}
else
{
if ($diff.SideIndicator -eq '=>')
{
Write-Verbose -Message "Assigning AAD group {$($currentGroup.DisplayName)} to Directory Role {$($diff.InputObject)}"
$DirObject = @{
"@odata.id" = "https://graph.microsoft.com/v1.0/directoryObjects/$($currentGroup.Id)"
}
New-MgDirectoryRoleMemberByRef -DirectoryRoleId ($role.Id) -BodyParameter $DirObject | Out-null

}
elseif ($diff.SideIndicator -eq '<=')
{
Write-Verbose -Message "Removing AAD group {$($currentGroup.DisplayName)} from Directory Role {$($role.DisplayName)}"
Remove-MgDirectoryRoleMemberByRef -DirectoryRoleId ($role.Id) -DirectoryObjectId ($currentGroup.Id) | Out-null
}
}
}
}
}
}

Expand Down Expand Up @@ -636,6 +803,10 @@ function Test-TargetResource
[System.String[]]
$Members,

[Parameter()]
[System.String[]]
$MemberOf,

[Parameter()]
[System.String]
$Description,
Expand Down Expand Up @@ -665,6 +836,10 @@ function Test-TargetResource
[System.Boolean]
$IsAssignableToRole,

[Parameter()]
[System.String[]]
$AssignedToRole,

[Parameter()]
[ValidateSet('Public', 'Private', 'HiddenMembership')]
[System.String]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ class MSFT_AADGroup : OMI_BaseResource
[Write, Description("Specifies an ID for the group.")] String Id;
[Write, Description("User Service Principal values for the group's owners.")] String Owners[];
[Write, Description("User Service Principal values for the group's members.")] String Members[];
[Write, Description("DisplayName values for the groups that this group is a member of.")] String MemberOf[];
[Write, Description("Specifies that the group is a dynamic group. To create a dynamic group, specify a value of DynamicMembership.")] String GroupTypes[];
[Write, Description("Specifies the membership rule for a dynamic group.")] String MembershipRule;
[Write, Description("Specifies the rule processing state. The acceptable values for this parameter are: On. Process the group rule or Paused. Stop processing the group rule."), ValueMap{"On","Paused"}, Values{"On","Paused"}] String MembershipRuleProcessingState;
[Write, Description("Specifies whether the group is security enabled. For security groups, this value must be $True.")] Boolean SecurityEnabled;
[Write, Description("Specifies whether this group is mail enabled. Currently, you cannot create mail enabled groups in Azure AD.")] Boolean MailEnabled;
[Write, Description("Specifies whether this group can be assigned a role. Only available when creating a group and can't be modified after group is created.")] Boolean IsAssignableToRole;
[Write, Description("DisplayName values for the roles that the group is assigned to.")] String AssignedToRole[];
[Write, Description("This parameter determines the visibility of the group's content and members list."), ValueMap{"Public","Private","HiddenMembership"}, Values{"Public","Private","HiddenMembership"}] String Visibility;
[Write, Description("List of Licenses assigned to the group."),EmbeddedInstance("MSFT_AADGroupLicense")] String AssignedLicenses[];
[Write, Description("Specify if the Azure AD Group should exist or not."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<#
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]
$credsGlobalAdmin
)
Import-DscResource -ModuleName Microsoft365DSC

node localhost
{
AADGroup 'MyGroups'
{
DisplayName = "DSCGroup"
Description = "Microsoft DSC Group"
SecurityEnabled = $True
MailEnabled = $False
GroupTypes = @()
MailNickname = "DSCGroup"
Ensure = "Present"
IsAssignableToRole = $True
AssignedToRole = "Identity Governance Administrator"
Credential = $credsGlobalAdmin
}
}
}
Original file line number Diff line number Diff line change
@@ -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(Mandatory = $true)]
[PSCredential]
$credsGlobalAdmin
)
Import-DscResource -ModuleName Microsoft365DSC

node localhost
{
AADGroup 'MyGroups1'
{
DisplayName = "DSCGroup"
Description = "Microsoft DSC Group"
SecurityEnabled = $True
GroupTypes = @()
MailNickname = "M365DSCG"
Ensure = "Present"
Credential = $credsGlobalAdmin
}
AADGroup 'MyGroups2'
{
DisplayName = "DSCMemberGroup"
Description = "Microsoft DSC Editor"
SecurityEnabled = $True
GroupTypes = @()
MailNickname = "M365DSCMG"
Ensure = "Present"
MemberOf = @("DSCGroup")
Credential = $credsGlobalAdmin
}
}
}
Loading