是否有可用的 powershell 命令来处理安全角色?
以下是安全角色示例:
Security Role: Sample Standard User
Entity: Contact
Privilege: Read, Append, and Append To
Security Role: Sample Advance User
Entity: Contact
Privilege: Create, Read, Write, Append, and Append to
Security Role: Sample Admin User
Entity: Contact
Privilege: Create, Read, Write, Delete, Append, and Append to
Microsoft Dynamics 中的安全角色配置很繁琐吧? 使用此示例,目标是复制特定的安全角色,然后应用其他权限。
现在使用上面给出的示例,如果我们可以使用 powershell 复制“示例标准用户”来创建“示例高级用户”,然后添加“创建和读取”权限(再次使用 powershell),我们可以跳过配置的繁琐部分并以编程方式创建它们。
如果我理解正确,您可以利用我用于动态角色创建分配和到期的以下代码片段。
Install-Module -Name Microsoft.Xrm.Data.PowerShell -AllowClobber -Scope CurrentUser
Import-Module Microsoft.Xrm.Data.PowerShell
$connection = Get-CrmConnection -InteractiveMode
找回原来的安全角色:
$originalRole = Get-CrmSecurityRole -conn $connection -RoleName "Sample Standard User"
克隆安全角色:
$newRole = New-CrmSecurityRole -conn $connection -OriginalRole $originalRole -NewRoleName "Sample Advance User"
为新角色添加权限:
$entityName = "contact"
$privileges = @("Create", "Write")
foreach ($privilege in $privileges) {
Set-CrmSecurityRolePrivilege -conn $connection -RoleId $newRole.RoleId -EntityName $entityName -PrivilegeName $privilege -AccessLevel "Organization"
}
验证更改:
$updatedRole = Get-CrmSecurityRole -conn $connection -RoleName "Sample Advance User"
此答案基于@Laviza Falak Naz 发布的答案。
代码主要包含以下步骤:
创建连接
检索StandardRole的必要信息(如果还需要创建StandardRole,则调用方法Create-Role和Add-Privilege)
创建新角色。
将权限从 StandardRole 复制到新角色
为新角色添加更多权限
# Install the Microsoft.Xrm.Data.PowerShell module if not installed yet
if (-not (Get-Module -ListAvailable -Name Microsoft.Xrm.Data.PowerShell)) {
Install-Module -Name Microsoft.Xrm.Data.PowerShell -Scope CurrentUser
}
# Import the module
Import-Module Microsoft.Xrm.Data.PowerShell
# Define privilegeDepthMask enum
Add-Type -TypeDefinition @"
public enum PrivilegeDepthMask
{
Basic = 1,
Local = 2,
Deep = 4,
Global = 8
}
"@
# Define privilegeDepth enum
Add-Type -TypeDefinition @"
public enum PrivilegeDepth
{
Basic = 0,
Local = 1,
Deep = 2,
Global = 3
}
"@
# Define AccessRight enum
Add-Type -TypeDefinition @"
public enum AccessRight
{
None = 0,
ReadAccess = 1,
WriteAccess = 2,
AppendAccess = 4,
AppendToAccess = 16,
CreateAccess = 32,
DeleteAccess = 65536,
ShareAccess = 262144,
AssignAccess = 524288
}
"@
# Mapping dictionary for PrivilegeType to AccessRight
$privilegeTypeToAccessRightMap = @{
"Read" = [AccessRight]::ReadAccess
"Write" = [AccessRight]::WriteAccess
"Append" = [AccessRight]::AppendAccess
"AppendTo" = [AccessRight]::AppendToAccess
"Create" = [AccessRight]::CreateAccess
"Delete" = [AccessRight]::DeleteAccess
"Share" = [AccessRight]::ShareAccess
"Assign" = [AccessRight]::AssignAccess
}
# Function to get role by name
function Get-RoleByName {
param (
[string]$roleName,
[Microsoft.Xrm.Tooling.Connector.CrmServiceClient]$conn
)
$fetchXML = @"
<fetch mapping='logical'>
<entity name='role'>
<attribute name='roleid' />
<attribute name='name' />
<attribute name='businessunitid' />
<filter type='and'>
<condition attribute='name' operator='eq' value='$roleName' />
<condition attribute='parentroleid' operator='null' />
</filter>
</entity>
</fetch>
"@
return Get-CrmRecordsByFetch -conn $conn -Fetch $fetchXML
}
# Function to map PrivilegeDepthMask to PrivilegeDepth
function Get-PrivilegeDepth {
param (
[PrivilegeDepthMask]$privilegeDepthMask,
[string]$ownershipType
)
Write-Host "PrivilegeDepthMask value: $privilegeDepthMask"
if ($ownershipType -eq "OrganizationOwned") {
return [PrivilegeDepth]::Global
}
if ($privilegeDepthMask -eq [PrivilegeDepthMask]::Basic) {
return [PrivilegeDepth]::Basic
}
elseif ($privilegeDepthMask -eq [PrivilegeDepthMask]::Local) {
return [PrivilegeDepth]::Local
}
elseif ($privilegeDepthMask -eq [PrivilegeDepthMask]::Deep) {
return [PrivilegeDepth]::Deep
}
elseif ($privilegeDepthMask -eq [PrivilegeDepthMask]::Global) {
return [PrivilegeDepth]::Global
}
else {
throw "Invalid PrivilegeDepthMask value: $privilegeDepthMask"
}
}
# Function to create a role if it does not exist
function Create-Role {
param (
[string]$roleName,
[Guid]$businessUnitId,
[Microsoft.Xrm.Tooling.Connector.CrmServiceClient]$conn
)
$role = Get-RoleByName -roleName $roleName -conn $conn
if ($role.CrmRecords.Count -eq 0) {
# Create the new role
$newRole = New-CrmRecord -EntityLogicalName role -Fields @{
name = $roleName
businessunitid = New-Object Microsoft.Xrm.Sdk.EntityReference("businessunit", $businessUnitId)
} -conn $conn
Write-Host "New role '$roleName' created successfully."
return $newRole
}
else {
# Use the existing role
$roleId = $role.CrmRecords[0].roleid
Write-Host "Role '$roleName' already exists. Using the existing role."
return $roleId
}
}
# Function to add a single privilege to a role
function Add-Privilege {
param (
[Guid]$roleId,
[Guid]$privilegeId,
[int]$depth,
[Microsoft.Xrm.Tooling.Connector.CrmServiceClient]$conn
)
# Create the RolePrivilege object
$rolePriv = New-Object Microsoft.Crm.Sdk.Messages.RolePrivilege
$rolePriv.PrivilegeId = $privilegeId
$rolePriv.Depth = $depth
# Create the AddPrivilegesRoleRequest object
$addPrivRoleReq = New-Object Microsoft.Crm.Sdk.Messages.AddPrivilegesRoleRequest
$addPrivRoleReq.RoleId = $roleId
$addPrivRoleReq.Privileges = @($rolePriv)
# Execute the request
$response = $conn.ExecuteCrmOrganizationRequest($addPrivRoleReq)
Write-Host "Privilege with ID $privilegeId added to role successfully."
}
# Function to get privilege ID by entity metadata and access right
function Get-PrivilegeId {
param (
[Microsoft.Xrm.Sdk.Metadata.EntityMetadata]$entityMetadata,
[AccessRight]$accessRight
)
foreach ($privilege in $entityMetadata.Privileges) {
# Map PrivilegeType to AccessRight
if ($privilegeTypeToAccessRightMap.ContainsKey($privilege.PrivilegeType.ToString()) -and $privilegeTypeToAccessRightMap[$privilege.PrivilegeType.ToString()] -eq $accessRight) {
return $privilege.PrivilegeId
}
}
throw "Privilege with AccessRight $accessRight not found."
}
# Function to copy privileges from one role to another
function Copy-Privileges {
param (
[Guid]$sourceRoleId,
[Guid]$targetRoleId,
[Microsoft.Xrm.Tooling.Connector.CrmServiceClient]$conn,
[string]$ownershipType
)
# Retrieve all privileges associated with the source role
$rolePrivileges = Get-CrmRecords -conn $conn -EntityLogicalName roleprivileges -FilterAttribute roleid -FilterOperator eq -FilterValue $sourceRoleId -Fields privilegeid, privilegedepthmask
foreach ($privilege in $rolePrivileges.CrmRecords) {
# Log the privilege object to understand its structure
#Write-Host "Privilege object: $($privilege | Out-String)"
# Extract the integer value from the privilegedepthmask property
$privilegeDepthMaskValue = [int]$privilege.privilegedepthmask
Write-Host "Extracted PrivilegeDepthMask value: $privilegeDepthMaskValue"
# Cast the extracted integer value to the PrivilegeDepthMask enum type
$privilegeDepthMask = [PrivilegeDepthMask]$privilegeDepthMaskValue
Write-Host "Casted PrivilegeDepthMask enum: $privilegeDepthMask"
$depth = Get-PrivilegeDepth -privilegeDepthMask $privilegeDepthMask -ownershipType $ownershipType
# Add the privilege to the target role
Add-Privilege -roleId $targetRoleId -privilegeId ([Guid]::Parse($privilege.privilegeid)) -depth $depth -conn $conn
}
}
# Change below values to match your needs
$username = "[email protected]"
$password = ConvertTo-SecureString "yourpassword" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($username, $password)
$standardRoleName = "Sample Standard User"
$newRoleName = "Sample Advance User"
$entityName = "contact"
$addPrivilege = [AccessRight]::AppendAccess
$addPrivilegeDepth = [PrivilegeDepth]::Local
$serverUrl = "https://domain.crmX.dynamics.com/"
$organizationName = "Demo"
$conn = Get-CrmConnection -serverUrl $serverUrl -credential $credential -organizationName $organizationName
# Check if the connection was successful
if ($conn -eq $null) {
Write-Host "Failed to connect to CRM. Exiting script."
exit
}
# Retrieve the standard role
$standardRole = Get-RoleByName -roleName $standardRoleName -conn $conn
# Check if the role was found
if ($standardRole.CrmRecords.Count -eq 0) {
Write-Host "$standardRoleName role not found."
exit
}
# Retrieve the business unit ID from the standard role
$businessUnitId = $standardRole.CrmRecords[0].businessunitid_Property.Value.Id
# Create the new role if it does not exist
$newRoleId = Create-Role -roleName $newRoleName -businessUnitId $businessUnitId -conn $conn
# Retrieve the entity metadata to check the owningtype
$entityMetadata = Get-CrmEntityMetadata -conn $conn -EntityLogicalName $entityName -EntityFilters "all"
# Copy privileges from the standard role to the new role
Copy-Privileges -sourceRoleId $standardRole.CrmRecords[0].roleid -targetRoleId $newRoleId -conn $conn -ownershipType $entityMetadata.OwnershipType
# Add the specified privilege to the new role
$privilegeId = Get-PrivilegeId -entityMetadata $entityMetadata -accessRight $addPrivilege
Add-Privilege -roleId $newRoleId -privilegeId $privilegeId -depth $addPrivilegeDepth -conn $conn
代码中使用的业务单元是最佳实践的根业务单元(Get-RoleByName)。
对于组织拥有的实体,权限深度只有“基本”和“全局”