locked
Implement UR7 Activity Implementer Workaround For Another Property RRS feed

  • Question

  • Hi

    I have Applied ImplementUR7ActivityImplementerWorkaround.ps1 to fix problem of security scope of Activity Implementer. The provided script lets users of activity implementer profiles change the ActualEndDate property of activity while completing/failing the activity.

    I have modified the same script and changed the ActualEndDate to ActualDownTimeEndDate but getting error

    <#
        .SYNOPSIS
        Modifies SCSM permissions to allow Activity Implementers to edit the ActualEndDate property
    
        .DESCRIPTION
        SCSM 2012 R2 UR7 introduced a fix due to which SCSM will properly set the "ActualEndDate" property on work items at time of resolution.
        
        Unfortunately, Activity Implementers' permissions were not modified to give them permission to set the "ActualEndDate" property, resulting in the Activity Implementers user role being broken after the update was applied - members of the user role could no longer perform the one action their user role was meant to allow, that being the Completion of Manual Activities.
    
        A fix for the bug will be released as part of SCSM 2016. However, until that time and for those who are unable to upgrade, this script provides a workaround.
    
        This script will grant the Activity Implementers user role (and any user role based on it) permissions to update the "ActualEndDate" property of work items, allowing them to properly complete Manual Activities.
    
        A Service Manager administrator only needs to run the script on a Service Manager management server and the permissions will be added.
    
        .NOTES
        Written by Gabriel Taylor and Mihai Sarbulescu, 2016
    #>
    
    #region Parameters
    [CmdletBinding()]
    param ()
    #endregion
    
    #region Variables
    [datetime]$StartTime = Get-Date
    [string]$SMServer = 'localhost'
    [string]$RoleName = 'ActivityImplementer'
    [string]$ClassName = 'System.WorkItem'
    [string]$PropertyName = 'ActualDowntimeEndDate'
    [string]$SMModule = 'System.Center.Service.Manager'
    [string]$SMNamespace = 'Microsoft.EnterpriseManagement.EnterpriseManagementGroup'
    [string]$RelEndPoint = 'Microsoft.EnterpriseManagement.Security.RelationshipEndpoint'
    [string]$OperationImplicitScope = 'Microsoft.EnterpriseManagement.Security.OperationImplicitScope'
    #endregion
    
    #region Start up
    Write-Verbose "ImplementUR7ActivityImplementerWorkaround.ps1" -Verbose
    Write-Verbose "This script will extend the permissions of Activity Implementers to enable them to complete manual activities." -Verbose
    Write-Verbose "This is a workaround for a bug introduced in SCSM 2012 R2 UR7." -Verbose
    Write-Verbose "This script MUST be run on an SCSM management server." -Verbose
    Write-Verbose "This script MUST be run by an SCSM administrator." -Verbose
    Write-Verbose "If errors occur, validate that the above requirements are true and that no other custom permissions have been configured, then try again." -Verbose
    Write-Verbose "Beginning permissions configuration ..." -Verbose
    #endregion
    
    #region Retrieve the SCSM install directory
    Write-Verbose -Message "Retrieving SCSM install path from the registry ..."
    $SCSMRegistryKey = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\System Center\2010\Common\Setup"
    $InstallDirectory = $SCSMRegistryKey.InstallDirectory.TrimEnd('\')
    #endregion
    
    #region Connect to the SCSM Management Group
    ## Add the SCSM DLL in order to interact with the SDK
    Write-Verbose -Message "Loading the SCSM SDK ..."
    $SDKDLLPath = $InstallDirectory + '\SDK Binaries\Microsoft.EnterpriseManagement.Core.dll'
    Add-Type -Path $SDKDLLPath
    
    ## Connect to the Management Group
    Write-Verbose -Message "Connecting to the management group on $SMServer ..."
    $EMGType = $SMNamespace  ##+ '.EnterpriseManagementGroup'
    $EMG = New-Object -TypeName $EMGType -ArgumentList $SMServer
    #endregion
    
    #region Identify the Profile and Class
    ## Get the user profile that should be changed
    Write-Verbose -Message "Retrieving information for user role profile $RoleName ..."
    $Profile = $EMG.Security.GetProfiles() | ?{$_.Name -eq $RoleName}
    
    ## Get class
    Write-Verbose -Message "Retrieving information for class $ClassName ..."
    $Class = $EMG.EntityTypes.GetClasses() | ?{$_.Name -eq $ClassName}
    #endregion
    
    #region Add permissions to update a class property
    ## Retrieve the property information
    Write-Verbose -Message "Retrieving information for property $PropertyName ..."
    $Property = $Class.GetProperties() | ?{$_.Name -eq $PropertyName}
    
    ## Get the Object__Set implicit scope
    Write-Verbose -Message "Configuring custom permissions ..."
    $ObjSet = $Profile.Operations | ?{$_.Name -eq "Object__Set"}
    
    ## Create the new implicit scope object for the class + property combination
    $OIObject = New-Object $OperationImplicitScope -ArgumentList @($Class.Id,$Property.Id)
    
    ## Add the new scope object to the array of scopes, then update the profile
    Write-Verbose -Message "Setting custom permissions ..."
    $ObjSet.ImplicitScopes.Add($OIObject)
    $Profile.Update()
    #endregion 
    
    #region Wrap-up
    Write-Verbose -Message "Permissions configuration complete!" -Verbose
    #Write-Verbose -Message "Total time: $(New-TimeSpan -Start $StartTime -End Get-Date)" -Verbose
    #endregion

    And out put is

    PS C:\> .\ImplementUR7ActivityImplementerWorkaround.ps1 -Verbose
    VERBOSE: ImplementUR7ActivityImplementerWorkaround.ps1
    VERBOSE: This script will extend the permissions of Activity Implementers to enable them to complete manual activities.
    VERBOSE: This is a workaround for a bug introduced in SCSM 2012 R2 UR7.
    VERBOSE: This script MUST be run on an SCSM management server.
    VERBOSE: This script MUST be run by an SCSM administrator.
    VERBOSE: If errors occur, validate that the above requirements are true and that no other custom permissions have been configured, then try again.
    VERBOSE: Beginning permissions configuration ...
    VERBOSE: Retrieving SCSM install path from the registry ...
    VERBOSE: Loading the SCSM SDK ...
    VERBOSE: Connecting to the management group on localhost ...
    VERBOSE: Retrieving information for user role profile ActivityImplementer ...
    VERBOSE: Retrieving information for class System.WorkItem ...
    VERBOSE: Retrieving information for property ActualDowntimeEndDate ...
    VERBOSE: Configuring custom permissions ...
    VERBOSE: Setting custom permissions ...
    Exception calling "Update" with "0" argument(s): "The operation 987525aa-4d63-4e9f-97b0-56ba958f2daa in the profile 0721c457-f7c2-4f2d-b9ac-7111bcceee41 is 
    already restricted to the same type or its base type. Hence there is no need to restrict it to the specified type."
    At C:\ImplementUR7ActivityImplementerWorkaround.ps1:90 char:1
    + $Profile.Update()
    + ~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : ProfileOperationImplicitScopeAlreadyExistsException
     
    VERBOSE: Permissions configuration complete!

    Any help is greatly appreciated.

    Thanks


    YSobhdel

    Wednesday, March 27, 2019 10:59 AM

Answers

  • The SDK will not let you add more than 1 Property restriction per class. You can only do this manually via SQL query (adding the entry in ProfileOperationImplicitScope table). Even though, the setup itself will create more than 1 restriction per class with 2 or more different properties of that class - but it does this via SQL query directly and not via SDK - as said, it's limited to 1 restriction per Class Property ... Here is a query you can use to view all: 

    select
    	p.ProfileName,
    	o.OperationName,
    	mt.TypeName,
    	mtp.ManagedTypePropertyName,
    	rt.RelationshipTypeName,
    	pois.RelationshipEndpoint,
    	pois.IsCustomized
    from ProfileOperationImplicitScope as pois
    join ProfileOperation as po
    	on po.ProfileOperationId = pois.ProfileOperationId
    join Profile as p
    	on p.ProfileId = po.ProfileId
    join Operation as o
    	on o.OperationId = po.OperationId
    left join ManagedType as mt
    	on mt.ManagedTypeId = pois.TypeId
    left join ManagedTypeProperty as mtp
    	on pois.PropertyId = mtp.ManagedTypePropertyId
    left join RelationshipType as rt
    	on rt.RelationshipTypeId = pois.RelationshipTypeId
    where
    	p.ProfileName = 'ActivityImplementer' and
    	mt.TypeName = 'System.WorkItem'

    Here is how to insert the one you need here:

    declare
    	@ClassName nvarchar(255) = N'System.WorkItem',
    	@PropertyName nvarchar(255) = N'ActualDowntimeEndDate',
    	@ProfileName nvarchar(255) = N'ActivityImplementer',
    	@OperationName nvarchar(255) = N'Object__Set'
    insert into ProfileOperationImplicitScope
    (
    	ProfileOperationId,
    	TypeId,
    	PropertyId,
    	RelationshipTypeId,
    	RelationshipEndpoint,
    	IsCustomized
    )
    select
    	(
    		select po.ProfileOperationId
    		from ProfileOperation as po
    		join Profile as p
    			on p.ProfileId = po.ProfileId
    		join Operation as o
    			on o.OperationId = po.OperationId
    		where
    			p.ProfileName = @ProfileName and
    			o.OperationName = @OperationName
    	),
    	mt.ManagedTypeId,
    	mtp.ManagedTypePropertyId,
    	null,
    	2,
    	1
    
    from ManagedType as mt
    join ManagedTypeProperty as mtp
    	on mt.ManagedTypeId = mtp.ManagedTypeId
    where
    	mt.TypeName = @ClassName and
    	mtp.ManagedTypePropertyName = @PropertyName


    Monday, December 2, 2019 11:29 AM

All replies

  • Update:

    I just removed the ActualEndDate Implict Scope using the following sdk code snippet:

    Profile profile = emg.Security.GetProfile(Profile.ActivityImplementerProfileId);
                // Locate the operation in the profile that will be queried
                Operation opObjectSet = profile.Operations.Where(op => op.Name == "Object__Set").FirstOrDefault();
                if (opObjectSet != null)
                {
                    List <OperationImplicitScope> opImplicitScopesCustomized = new List<OperationImplicitScope>();
    
                    //Get scopes which have IsCustomized flag set
                    foreach (OperationImplicitScope opImplicitScope in opObjectSet.ImplicitScopes)
                    {
                        if (opImplicitScope.IsCustomized == true)
                        {
                            opImplicitScopesCustomized.Add(opImplicitScope);
                            if (opImplicitScope.Property.HasValue)
                            {
                                opObjectSet.ImplicitScopes.Remove(opImplicitScope);
                                profile.Update();
                            }
                        }                    
                    }
    
                }

    Then I ran the first script and it successfully executed. Now I can change ActualDownTimeEndDate but cannot add ActualEndDate usign script giving the same error.

    How can I enable activity implementer user to update both of the properties?

    Thanks


    YSobhdel

    Wednesday, March 27, 2019 11:42 AM
  • The SDK will not let you add more than 1 Property restriction per class. You can only do this manually via SQL query (adding the entry in ProfileOperationImplicitScope table). Even though, the setup itself will create more than 1 restriction per class with 2 or more different properties of that class - but it does this via SQL query directly and not via SDK - as said, it's limited to 1 restriction per Class Property ... Here is a query you can use to view all: 

    select
    	p.ProfileName,
    	o.OperationName,
    	mt.TypeName,
    	mtp.ManagedTypePropertyName,
    	rt.RelationshipTypeName,
    	pois.RelationshipEndpoint,
    	pois.IsCustomized
    from ProfileOperationImplicitScope as pois
    join ProfileOperation as po
    	on po.ProfileOperationId = pois.ProfileOperationId
    join Profile as p
    	on p.ProfileId = po.ProfileId
    join Operation as o
    	on o.OperationId = po.OperationId
    left join ManagedType as mt
    	on mt.ManagedTypeId = pois.TypeId
    left join ManagedTypeProperty as mtp
    	on pois.PropertyId = mtp.ManagedTypePropertyId
    left join RelationshipType as rt
    	on rt.RelationshipTypeId = pois.RelationshipTypeId
    where
    	p.ProfileName = 'ActivityImplementer' and
    	mt.TypeName = 'System.WorkItem'

    Here is how to insert the one you need here:

    declare
    	@ClassName nvarchar(255) = N'System.WorkItem',
    	@PropertyName nvarchar(255) = N'ActualDowntimeEndDate',
    	@ProfileName nvarchar(255) = N'ActivityImplementer',
    	@OperationName nvarchar(255) = N'Object__Set'
    insert into ProfileOperationImplicitScope
    (
    	ProfileOperationId,
    	TypeId,
    	PropertyId,
    	RelationshipTypeId,
    	RelationshipEndpoint,
    	IsCustomized
    )
    select
    	(
    		select po.ProfileOperationId
    		from ProfileOperation as po
    		join Profile as p
    			on p.ProfileId = po.ProfileId
    		join Operation as o
    			on o.OperationId = po.OperationId
    		where
    			p.ProfileName = @ProfileName and
    			o.OperationName = @OperationName
    	),
    	mt.ManagedTypeId,
    	mtp.ManagedTypePropertyId,
    	null,
    	2,
    	1
    
    from ManagedType as mt
    join ManagedTypeProperty as mtp
    	on mt.ManagedTypeId = mtp.ManagedTypeId
    where
    	mt.TypeName = @ClassName and
    	mtp.ManagedTypePropertyName = @PropertyName


    Monday, December 2, 2019 11:29 AM
  • Would you please provide the answer for updating relationships as well?

    Thanks


    YSobhdel

    Saturday, April 18, 2020 7:40 AM