functions/Set-FnOEnvironmentSecurityRoleMember.ps1
|
<# .SYNOPSIS Set security role members in a Finance and Operations environment. .DESCRIPTION Enables the user to assign security roles to users in a Finance and Operations environment based on members of an Entra ID (Azure AD) Security Group. .PARAMETER EnvironmentId The id of the environment that you want to work against. .PARAMETER ObjectId The ObjectId of the Entra ID (Azure AD) Security Group whose members you want to assign to the security role. .PARAMETER Role Name or RoleId of the security role to assign the members to. .PARAMETER ImportMissing Instruct the cmdlet to import missing users from the Entra ID (Azure AD) Security Group into the Finance and Operations environment as Claims Users. .EXAMPLE PS C:\> Set-FnOEnvironmentSecurityRoleMember -EnvironmentId *uat* -ObjectId "Developers" -Role "-SYSADMIN-" This will assign all members of the Entra ID (Azure AD) Security Group with display name starting with "Developers" to the Security Role with the RoleId "-SYSADMIN-" in the Finance and Operations environment. .EXAMPLE PS C:\> Set-FnOEnvironmentSecurityRoleMember -EnvironmentId *uat* -ObjectId "b1a2c3d4-e5f6-4789-9012-34567abcdef" -Role "System Administrator" This will assign all members of the Entra ID (Azure AD) Security Group with the ObjectId "b1a2c3d4-e5f6-4789-9012-34567abcdef" to the Security Role with the name "System Administrator" in the Finance and Operations environment. .EXAMPLE PS C:\> Set-FnOEnvironmentSecurityRoleMember -EnvironmentId *uat* -ObjectId "b1a2c3d4-e5f6-4789-9012-34567abcdef" -Role "System Administrator" -ImportMissing This will assign all members of the Entra ID (Azure AD) Security Group with the ObjectId "b1a2c3d4-e5f6-4789-9012-34567abcdef" to the Security Role with the name "System Administrator" in the Finance and Operations environment. Will import any missing users from the Entra ID (Azure AD) Security Group into the Finance and Operations environment as Claims Users prior to assigning the security role. .NOTES Author: Mötz Jensen (@Splaxi) #> function Set-FnOEnvironmentSecurityRoleMember { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] [CmdletBinding()] param ( [Parameter (Mandatory = $true)] [string] $EnvironmentId, [Parameter (Mandatory = $true)] [Alias('EntraGroup')] [string] $ObjectId, [Parameter (Mandatory = $true)] [Alias('RoleName')] [string] $Role, [switch] $ImportMissing ) begin { # Make sure all *BapEnvironment* cmdlets will validate that the environment exists prior running anything. $envObj = Get-BapEnvironment -EnvironmentId $EnvironmentId | Select-Object -First 1 if ($null -eq $envObj) { $messageString = "The supplied EnvironmentId: <c='em'>$EnvironmentId</c> didn't return any matching environment details. Please verify that the EnvironmentId is correct - try running the <c='em'>Get-BapEnvironment</c> cmdlet." Write-PSFMessage -Level Important -Message $messageString Stop-PSFFunction -Message "Stopping because environment was NOT found based on the id." -Exception $([System.Exception]::new($($messageString -replace '<[^>]+>', ''))) } if (Test-PSFFunctionInterrupt) { return } $baseUri = $envObj.FnOEnvUri -replace '.com/', '.com' $secureToken = (Get-AzAccessToken -ResourceUrl $baseUri -AsSecureString).Token $tokenFnoOdataValue = ConvertFrom-SecureString -AsPlainText -SecureString $secureToken $headersFnO = @{ "Authorization" = "Bearer $($tokenFnoOdataValue)" } $secureTokenGraph = (Get-AzAccessToken -ResourceUrl "https://graph.microsoft.com/" -AsSecureString).Token $tokenGraphValue = ConvertFrom-SecureString -AsPlainText -SecureString $secureTokenGraph $headersGraphApi = @{ "Authorization" = "Bearer $($tokenGraphValue)" "Content-Type" = "application/json" } $uriGraphBase = 'https://graph.microsoft.com/v1.0/groups?$select=id,displayName&' if (Test-Guid -InputObject $ObjectId) { # Validate that the Security Group exists in Azure AD / Entra ID $uriGraph = "$uriGraphBase`$filter=id eq '$ObjectId'" } else { $uriGraph = "$uriGraphBase`$filter=startswith(displayName, '$ObjectId')" } $colGroups = Invoke-RestMethod -Method Get ` -Uri $uriGraph ` -Headers $headersGraphApi | Select-Object -ExpandProperty Value if ($colGroups.Count -eq 0) { $messageString = "The supplied ObjectId / Entra Group: <c='em'>$ObjectId</c> didn't return any matching Security Group in Azure AD / Entra ID. Please verify that the ObjectId is correct - try running the <c='em'>Get-AzADGroup</c> cmdlet." Write-PSFMessage -Level Important -Message $messageString Stop-PSFFunction -Message "Stopping because Security Group was NOT found based on the ObjectId." -Exception $([System.Exception]::new($($messageString -replace '<[^>]+>', ''))) } if ($colGroups.Count -gt 1) { $messageString = "The supplied ObjectId / Entra Group: <c='em'>$ObjectId</c> returned multiple matching Security Groups in Azure AD / Entra ID. Please verify that the ObjectId is correct - try running the <c='em'>Get-AzADGroup</c> cmdlet." Write-PSFMessage -Level Important -Message $messageString Stop-PSFFunction -Message "Stopping because multiple Security Groups were found based on the ObjectId." -Exception $([System.Exception]::new($($messageString -replace '<[^>]+>', ''))) } $uriGraphMembers = "https://graph.microsoft.com/v1.0/groups/$($colGroups[0].id)/transitiveMembers`?`$select=id,displayName,mail,userPrincipalName" $colMembers = Invoke-RestMethod -Method Get ` -Uri $uriGraphMembers ` -Headers $headersGraphApi | Select-Object -ExpandProperty Value if ($colMembers.Count -eq 0) { $messageString = "The Security Group: <c='em'>$($colGroups[0].displayName)</c> doesn't contain any members. Please verify that the Security Group has members." Write-PSFMessage -Level Important -Message $messageString Stop-PSFFunction -Message "Stopping because the Security Group has no members." -Exception $([System.Exception]::new($($messageString -replace '<[^>]+>', ''))) } $colSecurityRoles = Get-FnOEnvironmentSecurityRole -EnvironmentId $envObj.PpacEnvId -Name $Role if ($colSecurityRoles.Count -eq 0) { $messageString = "The supplied Role Name / Id: <c='em'>$Role</c> didn't return any matching Security Role in the Dynamics 365 ERP environment. Please verify that the Role Name / Id is correct - try running the <c='em'>Get-FnOEnvironmentSecurityRole</c> cmdlet." Write-PSFMessage -Level Important -Message $messageString Stop-PSFFunction -Message "Stopping because Security Role was NOT found based on the Role Name / Id." -Exception $([System.Exception]::new($($messageString -replace '<[^>]+>', ''))) } if ($colSecurityRoles.Count -gt 1) { $messageString = "The supplied Role Name / Id: <c='em'>$Role</c> returned multiple matching Security Roles in the Dynamics 365 ERP environment. Please verify that the Role Name / Id is correct - try running the <c='em'>Get-FnOEnvironmentSecurityRole</c> cmdlet." Write-PSFMessage -Level Important -Message $messageString Stop-PSFFunction -Message "Stopping because multiple Security Roles were found based on the Role Name / Id." -Exception $([System.Exception]::new($($messageString -replace '<[^>]+>', ''))) } if (Test-PSFFunctionInterrupt) { return } } process { if (Test-PSFFunctionInterrupt) { return } $colUsers = Get-FnOEnvironmentUser -EnvironmentId $envObj.PpacEnvId $colAssignedUsers = Get-FnOEnvironmentSecurityRoleMember -EnvironmentId $envObj.PpacEnvId ` -Role $colSecurityRoles[0].FnORoleId foreach ($usrObj in $colMembers | Where-Object { $_.'@odata.type' -eq "#microsoft.graph.user" }) { $matchedUser = $colUsers | Where-Object { $_.Upn -eq $usrObj.userPrincipalName } | Select-Object -First 1 if ($null -eq $matchedUser) { if ($ImportMissing) { $payloadUser = [PsCustomObject][ordered]@{ "UserID" = $usrObj.userPrincipalName.Split('@')[0] + "_imp" "NetworkDomain" = "https://sts.windows.net/" "UserInfo_language" = "en-us" "Helplanguage" = "en-us" "UserName" = $usrObj.userPrincipalName.Split('@')[0] "Email" = $usrObj.userPrincipalName "Company" = "DAT" "Alias" = $usrObj.userPrincipalName "AccountType" = "ClaimsUser" "Theme" = "Theme1" "Enabled" = $true } | ConvertTo-Json Invoke-RestMethod -Method Post ` -Uri ($baseUri + '/data/SystemUsers') ` -Headers $headersFnO ` -Body $payloadUser ` -ContentType 'application/json; charset=utf-8' > $null continue } $messageString = "The member: <c='em'>$($usrObj.displayName) - $($usrObj.userPrincipalName)</c> from the Security Group: <c='em'>$($colGroups[0].displayName)</c> was not found as a user in the Dynamics 365 ERP environment. Please verify that the user exists in the environment." Write-PSFMessage -Level Warning -Message $messageString continue } if ($colAssignedUsers.FnOUserId ` -contains $matchedUser.FnOUserId) { continue } $payload = [PsCustomObject][ordered]@{ "SecurityRoleIdentifier" = $colSecurityRoles[0].FnORoleId "UserId" = $matchedUser.FnOUserId "AssignmentStatus" = "Enabled" "AssignmentMode" = "Manual" "SecurityRoleName" = $colSecurityRoles[0].Name "UserLicenseType" = $colSecurityRoles[0].License } | ConvertTo-Json Invoke-RestMethod -Method Post ` -Uri ($baseUri + '/data/SecurityUserRoles') ` -Headers $headersFnO ` -Body $payload ` -ContentType 'application/json; charset=utf-8' > $null } } end { } } |