[B10025] UNSAccountB: Write permission denied for value “UID_UNSContainerB”

We have a customer with a number of custom target systems.  These are kept in sync each with its own Synchronization Project.  A few days ago, one of the CSV projects learned a new trick.  For every new record it detects in the CSV, it produces the following error in the synchronization log… 

[B10025] UNSAccountB: Write permission denied for value “UID_UNSContainerB”

If we delete a number of records from UNSAccountB, all these records are added to the list of errors on the next sync.

It’s possible that someone has edited UNSAccountB template code recently, but aside from this, absolutely nothing has changed on the system.

Anyone have any idea of what can be causing this? 

 

We found the exact same error for version 7.0.1 with a message that it was a bug that was fixed by a hotfix.  Our customer is on 8.0.2017.1104, is it possible that an old bug has returned?

---

The UID_UNSContainerB is set by the Sync-Project Mapping via a “Key resolution by reference” which is passed the Canonical-name of the container…

 

Here is the template code for UID_UNSContainerB…   data-sync is not checked in the workflow so this code should get skipped entirely.  As far as we are aware this is the only code that has been modified recently.

'$FK(UID_Person).UID_Department$

'$FK(UID_Person).UID_Locality$

'$FK(UID_Person).UID_ProfitCenter$

'#If ORG Then

'$FK(UID_Person).UID_Org$

'#End If

'If CBool(Connection.Variables.Get("FULLSYNC")) = False Then

If Not CBool(Variables("FULLSYNC")) Then

      Select Case ($FK(UID_TSBBehavior).ITDataUsage:Int$)

            Case 0:'do not get data from employee

            Case -1:'fill property initially from the ITData of the employee

                  If Not $[IsLoaded]:Bool$ Then

                        Value = TSB_ITDataFromOrg($UID_Person$, $UID_TSBAccountDef$, Base.TableDef.Columns("UID_UNSContainerB"))

                        If $FK(UID_UNSRootB).Ident_UNSRoot$ = "TOPdesk" Then

                              If $AccountDisabled:Bool$ Then

                                   Dim UID As String = CCC_getDataFromAnyTable("UNSContainerB", "CanonicalName", "TOPdesk/Operators/Archived", "UID_UNSContainerB")

                                   If Not String.IsNullOrEmpty(UID) Then

                                         Value = UID

                                   End If

                              End If

                        End If

                  End If

            Case 1:'update property depending on ITData of the employee

                  Value = TSB_ITDataFromOrg($UID_Person$, $UID_TSBAccountDef$, Base.TableDef.Columns("UID_UNSContainerB"))

                  If $FK(UID_UNSRootB).Ident_UNSRoot$ = "TOPdesk" Then

                        If $AccountDisabled:Bool$ Then

                              Dim UID As String = CCC_getDataFromAnyTable("UNSContainerB", "CanonicalName", "TOPdesk/Operators/Archived", "UID_UNSContainerB")

                              If Not String.IsNullOrEmpty(UID) Then

                                   Value = UID

                              End If

                        End If

                  End If

      End Select

End If

 

 

And here is the template code for “cn” which is triggered by a change to UID_UNSContainerB…   $Ident_UNSRoot$ = "TOPdesk" for the system with the problem.

If $UID_UNSRootB$ <> "" Then

 

      Dim cnFix, cnNew, DNold, DNnew, wherePart As String

      Dim f As ISqlFormatter = Connection.SqlFormatter

      'Dim p as IDnParser = VI_GetDnParser("LDAP")

 

      Dim attributeName as String = "CN"

 

      ' If targetsystem is configured without containers

      If Not $FK(UID_UNSRootB).UsesContainer:Bool$ Then

            attributeName = "user"

      End If

     

      cnFix = $cn$

     

      If $FK(UID_UNSRootB).Ident_UNSRoot$ = "TOPdesk" Then

            If Entity.Columns.Item("Lastname").IsChanged _

                        OrElse Entity.Columns.Item("Firstname").IsChanged _

                        OrElse Entity.Columns.Item("AccountName").IsChanged _

                        OrElse (Not cnFix.EndsWith(")") And Not String.IsNullOrWhiteSpace($AccountName$)) Then

                 

                  Dim cn = {$Firstname$, $Lastname$}

                  cnFix = String.Join(" ", cn.Where(Function(o) Not String.IsNullOrWhiteSpace(o)))

                 

                  If Not String.IsNullOrWhiteSpace($AccountName$) Then

                        cnFix = String.Format("{0} ({1})", cnFix, $AccountName$)

                  End If

            Else

                  cnFix = $cn$

            End If

      Else

            If Entity.Columns.Item("Lastname").IsChanged _

                        OrElse Entity.Columns.Item("Firstname").IsChanged Then

                 

                  Dim cn = {$Firstname$, $Lastname$}

                  cnFix = String.Join(" ", cn.Where(Function(o) Not String.IsNullOrWhiteSpace(o)))

 

            Else

                  cnFix = $cn$

            End If

      End If

 

      Dim cnLen as Integer = Entity.Columns.Item("cn").MaxLen

 

      cnFix = VID_Left(cnFix, cnLen)

 

      If $cn[o]$<>cnFix OrElse Entity.Columns.Item("UID_UNSContainerB").IsChanged Then

            Dim i As Integer = 1

            cnNew = cnFix

           

            'to avoid triggering template on change DistinguishedName of parent object no objectwalker used

            If $UID_UNSContainerB[o]$ <> "" Then

                  DNold = VI_GetValueOfObject ("UNSContainerB", "UID_UNSContainerB", $UID_UNSContainerB[o]$, "DistinguishedName")

            Else

                  DNold = VI_GetValueOfObject ("UNSRootB", "UID_UNSRootB", $UID_UNSRootB[o]$, "DistinguishedName")

            End If

            If $UID_UNSContainerB$ <> "" Then

                  DNnew = VI_GetValueOfObject ("UNSContainerB", "UID_UNSContainerB", $UID_UNSContainerB$, "DistinguishedName")

            Else

                  DNnew = VI_GetValueOfObject ("UNSRootB", "UID_UNSRootB", $UID_UNSRootB$, "DistinguishedName")

            End If

 

            wherePart = f.AndRelation( _

                                   f.UidComparison("UID_UNSAccountB", $UID_UNSAccountB$, CompareOperator.NotEqual), _

                                   f.UidComparison("UID_UNSRootB", $UID_UNSRootB$))

 

            Do While Connection.Exists(   "UNSAccountB", _

                                         f.OrRelation( _

                                               f.AndRelation( _

                                                     f.Comparison("DistinguishedName", TSB_CreateDN(attributeName, cnNew, DNnew), ValType.String), _

                                                     wherePart _

                                               ), _

                                               f.AndRelation( _

                                                     f.Comparison("DistinguishedName",TSB_CreateDN(attributeName, cnNew, DNOld), ValType.String), _

                                                     wherePart _

                                               ) _

                                         ))

 

                  cnNew = VID_Left(cnFix, cnLen - (1 + CStr(i).Length)) & "_" & i

                  i=i+1

            Loop

           

            Value = cnNew

           

      End If

End If

 

 

This is the custom function called by the template code..

 

Public Function CCC_getDataFromAnyTable(ByVal TableName As String, ByVal CompareAttribute As String, ByVal CompareValue As String, ByVal ReturnAttributeName As String) As String

      Dim f As ISqlFormatter = connection.SqlFormatter

      Dim ccc_objects As IColDbObject = Connection.CreateCol(TableName) 'Maak een collectie van objecten uit deze tabel

            ccc_objects.prototype.whereclause = f.Comparison(CompareAttribute,CompareValue,Valtype.string,CompareOperator.Equal)

            'Select ... from <table> where <Compareattribute> = '<comparevalue'>

            ccc_objects.prototype.Columns(Returnattributename).isDisplayItem = True

            'Select ... is translated to a return column here

            ccc_objects.Load() 'Load all objects

           

                  If ccc_objects.Count > 0 Then

                        Dim ccc_object As IColElem = ccc_objects(0)

                        Return ccc_object.GetValue(ReturnAttributeName).String

                  End If

                 

      Return ""

End Function

  • We do the same for UID_UNSRootB as for UID_UNSContainerB... we pass Ident_UNSRoot to 'Key resolution by reference', and let it populate UID_UNSRootB.

  • That wasn't what I meant.
    Does your synchronization project also have a workflow step for UNSRootB? How is that workflow step configured?

  • A workflow step for UNSRoot?  I never heard of such a thing.  We have a Scope filter on all One Identity objects to select objects from this target system, and we use the 'Key resolution by reference' to set UID_UNSRootB in each mapping.  But a specific step in the workflow for UNSRootB ? What is this?

  • Standard synchronization projects like an active directory synchronization project usually also have a property mapping and workflow step for there domain object, to keep it up to date (in database). Whether it is a active directory domain, a LDAP domain, a exchange organisation, or some other root object of synchronization is up to the specific target system type. There for it appears be reasonable to assume a custom made synchronization project might also contain such a property mapping and workflow.
    The provided information gave no clue if your synchronization project might contain such configuration the target systems root object of synchronization, which is a UNSRootB object in your case.

  • Hi Haaf,
    I have the same issue, Did you find any solution, Thanks 

  • Do you have exactly the same use-case as above or just the same error?

    If it is just the same error then please check the UNSRootB is configured to use containers or not.

    And, you can not change the container if the account is markedfordeletion. Is this the case eventually?

  • I believe the same case, 
    The case simply when modifying the default value calculation script for UID_UNSContainerB in UNSAccountB Table and resolve the UID_UNSContainerB during the sync, I got the error "Write permission denied for value "UID_UNSContainerB".

    once I revert back to the original value calculation script, the sync is working fine and the accounts are mapped to the correct container, Also the custom value calculation script is working fine during the provisioning, and also by reapplying the templates.

    The issue occurs only when modifying the default value calculation for UID_UNSContainerB and resolve the UID_UNSContainerB during the sync

  • The first question, are you using the data import flag at the workflow step that imports your data?

    Second question, are you using automatic dependency resolution in your sync project?

    Third question, can you post the code of the template?

  • That discussion is already quite old.
    However, it has never been resolved.

    At the moment there is a Service Request for exactly the same problem.
    And we discovered the root cause.

    It's bug #34750.

    Explanation:

    The UID_UNSContainerB is changeable only if the UNSRootB has the option "UsesContainer".
    BUT: If the UNSAccountB doesn't have an UNSRootB assigned, the UID_UNSContainerB is also not changeable.
    For an existing object the UNSRootB cannot be empty, because it's mandatory.
    However, in the case of a newly created object, it depends on the order in which the individual properties are written to the object.
    If the UID_UNSContainerB is set BEFORE the UID_UNSRootB, you get the error.
    It works only, if the UID_UNSContainerB is set AFTER the UID_UNSRootB.

    The right order is calculated automatically based on different sources.
    One source are the implemented rules in the Customizer.
    Another source are dependencies implemented in TEMPLATES.
    And that explains why the change of the template code obviously has an influence.
    The template itself will not be executed, but the code is used by the algorithm to calculate the sort order.
    By adding another reference in the template (in the above case it's "$FK(UID_UNSRootB).Ident_UNSRoot$") the "sort order algorithm" calculates another (wrong) sort order.