Power Of Sitecore Module In XM Cloud
In this blog, we will explore how to automate the process of creating roles with appropriate permissions when working in a multilingual and multisite environment. As soon as we think about automation, PowerShell scripts are often the first tool that comes to mind.
And you’re absolutely right—we will be using PowerShell scripts, but with a twist. We'll leverage Sitecore Modules to approach this differently, integrating the module into the scaffolding definition. This way, whenever a new site is created in XM Cloud, roles and permissions will be automatically set up. So let's quickly start.
Before we move forward, I recommend reading my previous two blogs on role creation and assigning proper permissions, which are explained through a specific use case. We'll be using the same use case for our purposes here.
We will divide the blog into 2 section.
Creating the Scripts in Script Library
We will create required scripts under script library as shown in below screenshot. Navigate to /sitecore/system/Modules/PowerShell/Script Library and add a new PowerShell Script Module Folder. In our case we have given the name as Test Site Setup Module.
Now add a PowerShell Script Module under above created item. In our case we have given the name as TestHeadless Setup.
Now add a PowerShell Library under above created item. In our case we have given the name as Functions. This will hold our scripts for creating roles and permissions.
Now add two PowerShell Scripts names as Configure Roles and Update Permissions
Roles Scripts
Import-Function -Name Invoke-ConfigureRole
function Invoke-Step {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0 )]
[Sitecore.XA.Foundation.Scaffolding.Models.CreateNewSiteModel]$Model
)
begin {
Write-Verbose "Cmdlet Invoke-Validation - Begin"
}
process {
Write-Verbose "Cmdlet Invoke-Validation - Process"
$siteName =$Model.SiteName
$siteType = "External"
$Organization = "ABC"
write-host "Sitename: " $siteName
Invoke-ConfigureRole $siteName $siteType
}
end {
Write-Verbose "Cmdlet Invoke-Validation - End"
}
}
Assigning Permissions Scripts
Import-Function -Name Invoke-SetRolePermissions
function Invoke-Step {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0 )]
[Sitecore.XA.Foundation.Scaffolding.Models.CreateNewSiteModel]$Model
)
begin {
Write-Verbose "Cmdlet Invoke-Validation - Begin"
}
process {
Write-Verbose "Cmdlet Invoke-Validation - Process"
$siteName = $Model.SiteName
$site = $Model.SiteLocation.Children | ? { $_.Name -eq $siteName } | Select-Object -First 1 | % { Get-Item . -ID $_.ID -Language $Model.Language }
write-host "Item Start Path: " $site.Paths.Path
$sitestartPath = $site.Paths.Path
$sitestart = Get-Item -Path "$sitestartPath"
$siteregionItem = $sitestart.Parent
write-host "Parent Item Start Path: " $siteregionItem.Name
$siteLanguages = $Model.Language
write-host "Language: " $siteLanguages
$siteType = "External"
$Organization = "ABC"
$region = $siteregionItem.Name
$rolePrefix = "$Organization $siteType $siteName"
Invoke-SetRolePermissions $siteLanguages $rolePrefix $region $siteType $siteName
}
end {
Write-Verbose "Cmdlet Invoke-Validation - End"
}
}
Now let's create the Invoke-ConfigureRole and Invoke-SetRolePermissions. Navigate to /sitecore/system/Modules/PowerShell/Script Library/Test Site Setup Module and PowerShell Script Module. In our case we named as Security And Permissions.Under Security and Permissions, create PowerShell Script Library named Functions and then again create a PowerShell Script Library called Cmdlets.under that create the required scripts Invoke-ConfigureRole and Invoke-SetRolePermissions
Invoke-ConfigureRole function
function Invoke-ConfigureRole {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0 )]
[String]$siteName,
[Parameter(Mandatory = $true, Position = 1 )]
[String]$siteType
)
begin {
Write-Verbose "Cmdlet ConfigureRole- Begin"
}
process {
Write-Verbose "Cmdlet ConfigureRole- Process"
write-host "Sitename Inside Configure role main script: " $siteName
write-host "SiteType Inside Configure role main script: " $siteType
$rolePrefix = "ABC $siteType $siteName"
$siteAccessRole = "$rolePrefix Access"
$siteAdminRole = "$rolePrefix Site Admin"
$contentAdminRole = "$rolePrefix Content Admin"
$contentContributorRole = "$rolePrefix Content Contributor"
$contentPublisherRole = "$rolePrefix Content Publisher"
$contentPreviwerRole = "$rolePrefix Content Previewer"
New-Role -Identity $siteAccessRole
Add-RoleMember -Identity "ABC Limiter" -Members $siteAccessRole
New-Role -Identity $contentPreviwerRole
Add-RoleMember -Identity $siteAccessRole -Members $contentPreviwerRole
Add-RoleMember -Identity "Designer" -Members $contentPreviwerRole
New-Role -Identity $contentContributorRole
Add-RoleMember -Identity $contentPreviwerRole -Members $contentContributorRole
Add-RoleMember -Identity "ABC Author" -Members $contentContributorRole
New-Role -Identity $contentPublisherRole
Add-RoleMember -Identity $contentContributorRole -Members $contentPublisherRole
Add-RoleMember -Identity "Sitecore Client Publishing" -Members $contentPublisherRole
New-Role -Identity $contentAdminRole
Add-RoleMember -Identity $contentContributorRole -Members $contentAdminRole
Add-RoleMember -Identity "ABC Approver" -Members $contentAdminRole
Add-RoleMember -Identity "Sitecore Client Publishing" -Members $contentAdminRole
New-Role -Identity $siteAdminRole
Add-RoleMember -Identity $contentAdminRole -Members $siteAdminRole
}
end {
Write-Verbose "Cmdlet ConfigureRole- End"
}
}
Invoke-SetRolePermissions
function Invoke-SetRolePermissions {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0 )]
[String]$siteLanguages,
[Parameter(Mandatory = $true, Position = 1 )]
[String]$rolePrefix,
[Parameter(Mandatory = $true, Position = 2 )]
[String]$region,
[Parameter(Mandatory = $true, Position = 3 )]
[String]$siteType,
[Parameter(Mandatory = $true, Position = 4 )]
[String]$siteName
)
begin {
Write-Verbose "Cmdlet SetRolePermissions - Begin"
}
process {
Write-Verbose "Cmdlet SetRolePermissions - Process"
write-host "the input langauge is :" $siteLanguages
write-host "The rolePrefix: " $rolePrefix
write-host "The region: " $region
write-host "the siteType: " $siteType
write-host "The sitename: " $siteName
$Organization = "ABC"
$siteAccessRole = "$rolePrefix Access"
$siteAdminRole = "$rolePrefix Site Admin"
$contentAdminRole = "$rolePrefix Content Admin"
$contentContributorRole = "$rolePrefix Content Contributor"
$contentPublisherRole = "$rolePrefix Content Publisher"
$contentPreviewerRole = "$rolePrefix Content Previewer"
#Content
$regionPath = "/sitecore/content/$Organization $siteType/$region"
write-host "Region Item: " $regionPath
$sitePath = "$regionPath/$siteName"
write-host "Home Item: " $sitePath
$homePath = "$sitePath/Home"
$mediaPath = "$sitePath/Media"
$dataPath = "$sitePath/Data"
$presentationPath = "$sitePath/Presentation"
$dictionaryPath = "$sitePath/Dictionary"
$SettingsPath = "$sitePath/Settings"
#Media
$mediaTenantPath = "/sitecore/media library/Project/$Organization $siteType"
$mediaRegionPath = "$mediaTenantPath/$region"
$mediaSitePath = "$mediaRegionPath/$siteName"
$mediaSharedPath = "$mediaTenantPath/shared"
$mediaSystemPath = "/sitecore/media library/System"
#System
$publishingTarget = "/sitecore/system/Publishing targets/Edge"
$languages = "/sitecore/system/Languages"
#Access
$allowItemReadSiteAccess = New-ItemAcl -AccessRight item:read -PropagationType Entity -SecurityPermission AllowAccess -Identity $siteAccessRole
$denyInheritanceReadSiteAccess = New-ItemAcl -AccessRight item:read -PropagationType Descendants -SecurityPermission DenyAccess -Identity $siteAccessRole
$allowAnyReadSiteAccess = New-ItemAcl -AccessRight item:read -PropagationType Any -SecurityPermission AllowAccess -Identity $siteAccessRole
$allowLanguageReadSiteAccess = New-ItemAcl -AccessRight language:read -PropagationType Any -SecurityPermission AllowAccess -Identity $siteAccessRole
Get-Item -Path $regionPath | Add-ItemAcl -AccessRules $allowItemReadSiteAccess, $denyInheritanceReadSiteAccess -PassThru
Get-Item -Path $sitePath | Add-ItemAcl -AccessRules $allowAnyReadSiteAccess -PassThru
Get-Item -Path $mediaTenantPath | Add-ItemAcl -AccessRules $allowItemReadSiteAccess, $denyInheritanceReadSiteAccess -PassThru
Get-Item -Path $mediaRegionPath | Add-ItemAcl -AccessRules $allowItemReadSiteAccess, $denyInheritanceReadSiteAccess -PassThru
Get-Item -Path $mediaSitePath | Add-ItemAcl -AccessRules $allowAnyReadSiteAccess -PassThru
Get-Item -Path $mediaSharedPath | Add-ItemAcl -AccessRules $allowAnyReadSiteAccess -PassThru
Get-Item -Path $mediaSystemPath | Add-ItemAcl -AccessRules $allowAnyReadSiteAccess -PassThru
foreach ($language in $siteLanguages) {
Get-Item -Path "$languages/$language" | Add-ItemAcl -AccessRules $allowItemReadSiteAccess, $allowLanguageReadSiteAccess -PassThru
}
#Site Admin
$allowAnyReadSiteAdmin = New-ItemAcl -AccessRight item:read -PropagationType Any -SecurityPermission AllowAccess -Identity $siteAdminRole
$allowAnyWriteSiteAdmin = New-ItemAcl -AccessRight item:write -PropagationType Any -SecurityPermission AllowAccess -Identity $siteAdminRole
$allowAnyRenameSiteAdmin = New-ItemAcl -AccessRight item:rename -PropagationType Any -SecurityPermission AllowAccess -Identity $siteAdminRole
$allowAnyCreateSiteAdmin = New-ItemAcl -AccessRight item:create -PropagationType Any -SecurityPermission AllowAccess -Identity $siteAdminRole
$allowAnyDeleteSiteAdmin = New-ItemAcl -AccessRight item:delete -PropagationType Any -SecurityPermission AllowAccess -Identity $siteAdminRole
Get-Item -Path $sitePath | Add-ItemAcl -AccessRules $allowAnyReadSiteAdmin, $allowAnyWriteSiteAdmin, $allowAnyRenameSiteAdmin, $allowAnyCreateSiteAdmin, $allowAnyDeleteSiteAdmin -PassThru
Get-Item -Path $presentationPath | Add-ItemAcl -AccessRules $allowAnyReadSiteAdmin, $allowAnyWriteSiteAdmin, $allowAnyRenameSiteAdmin, $allowAnyCreateSiteAdmin, $allowAnyDeleteSiteAdmin -PassThru
Get-Item -Path $dictionaryPath | Add-ItemAcl -AccessRules $allowAnyReadSiteAdmin, $allowAnyWriteSiteAdmin, $allowAnyRenameSiteAdmin, $allowAnyCreateSiteAdmin, $allowAnyDeleteSiteAdmin -PassThru
Get-Item -Path $settingsPath | Add-ItemAcl -AccessRules $allowAnyReadSiteAdmin, $allowAnyWriteSiteAdmin, $allowAnyRenameSiteAdmin, $allowAnyCreateSiteAdmin, $allowAnyDeleteSiteAdmin -PassThru
Get-Item -Path $mediaSitePath | Add-ItemAcl -AccessRules $allowAnyReadSiteAdmin, $allowAnyWriteSiteAdmin, $allowAnyRenameSiteAdmin, $allowAnyCreateSiteAdmin, $allowAnyDeleteSiteAdmin -PassThru
Get-Item -Path $mediaSharedPath | Add-ItemAcl -AccessRules $allowAnyReadSiteAdmin, $allowAnyWriteSiteAdmin, $allowAnyRenameSiteAdmin, $allowAnyCreateSiteAdmin, $allowAnyDeleteSiteAdmin -PassThru
#Content Admin
$allowAnyReadSiteAdmin = New-ItemAcl -AccessRight item:read -PropagationType Any -SecurityPermission AllowAccess -Identity $contentAdminRole
$allowDescendantsRenameContentAdmin = New-ItemAcl -AccessRight item:rename -PropagationType Descendants -SecurityPermission AllowAccess -Identity $contentAdminRole
$allowDescendantsDeleteContentAdmin = New-ItemAcl -AccessRight item:delete -PropagationType Descendants -SecurityPermission AllowAccess -Identity $contentAdminRole
Get-Item -Path $homePath | Add-ItemAcl -AccessRules $allowDescendantsRenameContentAdmin, $allowDescendantsDeleteContentAdmin -PassThru
Get-Item -Path $mediaPath | Add-ItemAcl -AccessRules $allowDescendantsRenameContentAdmin, $allowDescendantsDeleteContentAdmin -PassThru
Get-Item -Path $dataPath | Add-ItemAcl -AccessRules $allowDescendantsRenameContentAdmin, $allowDescendantsDeleteContentAdmin -PassThru
Get-Item -Path $mediaSitePath | Add-ItemAcl -AccessRules $allowDescendantsRenameContentAdmin, $allowDescendantsDeleteContentAdmin -PassThru
Get-Item -Path $mediaSharedPath | Add-ItemAcl -AccessRules $allowDescendantsRenameContentAdmin, $allowDescendantsDeleteContentAdmin -PassThru
Get-Item -Path $publishingTarget | Add-ItemAcl -AccessRules $allowAnyReadSiteAdmin -PassThru
#Content Contributor
$allowAnyReadContentContributor = New-ItemAcl -AccessRight item:read -PropagationType Any -SecurityPermission AllowAccess -Identity $contentContributorRole
$allowAnyWriteContentContributor = New-ItemAcl -AccessRight item:write -PropagationType Any -SecurityPermission AllowAccess -Identity $contentContributorRole
$allowAnyCreateContentContributor = New-ItemAcl -AccessRight item:create -PropagationType Any -SecurityPermission AllowAccess -Identity $contentContributorRole
$allowDescendantsCreateContentContributor = New-ItemAcl -AccessRight item:create -PropagationType Descendants -SecurityPermission AllowAccess -Identity $contentContributorRole
$allowLanguageWriteContentContributor = New-ItemAcl -AccessRight language:write -PropagationType Any -SecurityPermission AllowAccess -Identity $contentContributorRole
Get-Item -Path $homePath | Add-ItemAcl -AccessRules $allowAnyWriteContentContributor, $allowAnyCreateContentContributor -PassThru
Get-Item -Path $mediaPath | Add-ItemAcl -AccessRules $allowAnyWriteContentContributor, $allowAnyCreateContentContributor -PassThru
Get-Item -Path $dataPath | Add-ItemAcl -AccessRules $allowAnyWriteContentContributor, $allowDescendantsCreateContentContributor -PassThru
Get-Item -Path "$presentationPath/Partial Designs" | Add-ItemAcl -AccessRules $allowAnyWriteContentContributor, $allowDescendantsCreateContentContributor -PassThru
Get-Item -Path "$settingsPath/Redirects" | Add-ItemAcl -AccessRules $allowAnyReadContentContributor, $allowAnyWriteContentContributor, $allowDescendantsCreateContentContributor -PassThru
Get-Item -Path $mediaSitePath | Add-ItemAcl -AccessRules $allowAnyWriteContentContributor, $allowAnyCreateContentContributor -PassThru
Get-Item -Path $mediaSharedPath | Add-ItemAcl -AccessRules $allowAnyWriteContentContributor, $allowAnyCreateContentContributor -PassThru
foreach ($language in $siteLanguages) {
Get-Item -Path "$languages/$language" | Add-ItemAcl -AccessRules $allowLanguageWriteContentContributor -PassThru
}
#Content Publisher
$allowAnyReadContentPublisher = New-ItemAcl -AccessRight item:read -PropagationType Any -SecurityPermission AllowAccess -Identity $contentPublisherRole
Get-Item -Path $publishingTarget | Add-ItemAcl -AccessRules $allowAnyReadContentPublisher -PassThru
#Content Previewer
$allowAnyReadContentContributor = New-ItemAcl -AccessRight item:read -PropagationType Any -SecurityPermission AllowAccess -Identity $contentPreviewerRole
$denyAnyWriteContentContributor = New-ItemAcl -AccessRight item:write -PropagationType Any -SecurityPermission DenyAccess -Identity $contentPreviewerRole
$denyAnyRenameContentContributor = New-ItemAcl -AccessRight item:rename -PropagationType Any -SecurityPermission DenyAccess -Identity $contentPreviewerRole
$denyAnyCreateContentContributor = New-ItemAcl -AccessRight item:create -PropagationType Any -SecurityPermission DenyAccess -Identity $contentPreviewerRole
$denyAnyDeleteContentContributor = New-ItemAcl -AccessRight item:delete -PropagationType Any -SecurityPermission DenyAccess -Identity $contentPreviewerRole
$denyAnyAdministerContentContributor = New-ItemAcl -AccessRight item:admin -PropagationType Any -SecurityPermission DenyAccess -Identity $contentPreviewerRole
Get-Item -Path $sitePath | Add-ItemAcl -AccessRules $denyAnyWriteContentContributor, $denyAnyRenameContentContributor, $denyAnyCreateContentContributor, $denyAnyDeleteContentContributor, $denyAnyAdministerContentContributor -PassThru
Get-Item -Path $homePath | Add-ItemAcl -AccessRules $allowAnyReadContentContributor -PassThru
}
end {
Write-Verbose "Cmdlet SetRolePermissions - End"
}
}
Creating the functions separately gives use the benefits if reusablity.The scripts are self explanatory. If still you have doubts, then read the above blogs which have detailed explanations. Now our Script part is completed. We will focus on Module creation.
Creating the Module
Navigate to below path /sitecore/system/Settings/Project and a folder called Testing Module. Right Click the folder and add item created from template /sitecore/system/Settings/Project/Testing Module/Test Headless Site Setup. We have named it Test Headless Site Setup.
The item will have field called name Title, give it a suitable name which will be shown during the site creation process under modules tab. There are other fields and what are they used for in reference section link.
Now right click the Test Headless Site Setup and add PostSetupSetp option as shown in below screenshot.
Now add two PostSetup Step ConfigureRole and ConfigurePermission
ConfigureRole Step --> Just Select the configure roles script created under Functions as shown below.
ConfigurePermission Step --> Just Select the Update Permissions script created under Functions as shown below.
Now go to your Site Collection and add a headless site. In module tab you will see our newly created Test Headless Site Setup skeleton. Just check the checkbox and as soon as your new website is created, you will see the newly created roles and permissions in Role Manager.
Thanks for reading and let the learning continue. I have attached an example above like what all can be included in dependencies when you create Test Headless Site Setup. We can add the default module dependencies that will execute before our custom modules.
You can check my other blogs too if interested. Blog Website
References:
Comments
Post a Comment