[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

Parents
  • Ok.  We've gotten a bit further, but I definitely don’t understand what is going wrong.  The problem is caused by the Template code for setting UID_UNSContainerB on UNSAccountB.  If we restore the default OOTB code, the CSV sync inserts UNSAccountB records just fine.  With our altered code, it gives “[B10025] UNSAccountB: Write permission denied for value “UID_UNSContainerB”” for each new record.

    How is this possible?  The entire template is surrounded by…

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

    And the data-import flag in the workflow is not checked.

    We’ve tried to narrow down the problem, and have found if we remove one line from the template, the Sync works ok.  Add the line, and we get the error.

    This is our minimalized pre-compiled code…

    Public Sub Tmpl_UNSAccountB_UID_UNSContainerB ()
    'GetTriggerValue("FK(UID_Person).UID_Department").String
    'GetTriggerValue("FK(UID_Person).UID_Locality").String
    'GetTriggerValue("FK(UID_Person).UID_ProfitCenter").String
    #If ORG Then
    'GetTriggerValue("FK(UID_Person).UID_Org").String
    #End If
    If CBool(Connection.Variables.Get("FULLSYNC")) = False Then
            Select Case (GetTriggerValue("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 GetTriggerValue("[IsLoaded]").Bool Then
                                    Value = TSB_ITDataFromOrg(GetTriggerValue("UID_Person").String, GetTriggerValue("UID_TSBAccountDef").String, Base.TableDef.Columns("UID_UNSContainerB")) 
                   If GetTriggerValue("FK(UID_UNSRootB).Ident_UNSRoot").String = "TOPdesk" Then
                                                    Value = "fc223716-22f2-4afd-a174-8c0a06db80a7"
                                    End If
                            End If
                    Case 1:'update property depending on ITData of the employee
                            Value = TSB_ITDataFromOrg(GetTriggerValue("UID_Person").String, GetTriggerValue("UID_TSBAccountDef").String, Base.TableDef.Columns("UID_UNSContainerB")) 
               If GetTriggerValue("FK(UID_UNSRootB).Ident_UNSRoot").String = "TOPdesk" Then
                                            Value = "fc223716-22f2-4afd-a174-8c0a06db80a7"
                            End If
            End Select
    End If
    End Sub
    

    If we remove the lines [ If GetTriggerValue("FK(UID_UNSRootB).Ident_UNSRoot").String = "TOPdesk" Then ] all works fine.  

    Add the lines, and the SYNC fails.

    What. The. Heck ?

  • The error code [B10025] looks wrong. It should consist of digits only.
    It looks like your UnsRootB is configured to deny the usage of containers. But somehow your template tries to set a value.
    In addition I suspect you see a different sync project state then the one used for the import.
    To be save, reload the synchronization project, check that the proper workflow is used, review the data import flag at all workflow steps, save the project.
    Open the project properties, toggle the shadow copy flag, save, restore the initial setting and save again.

  • I'm thinking something very different is happening.  During a Sync, when the match pattern does not find an existing record, the engine creates a new UNSAccountB entity.  Then the “Key resolution by reference” component uses the Canonical Name for the Container to determine the UID.  It updates the UID_UNSContainerB in the entity it just created, and this trigger template code.  However at this time, the global variable "FULLSYNC" is not True, even though data-import has not been checked.  This is the only explanation I can think of for why changing code inside a   If FULLSYNC = False Then / End If   can be causing the sync to fail or succeed.

    What makes me think that this is correct is that i my experience any problem the object-layer encounters is often reported as "write permission denied" instead of something more specific.

    I think this is a bug that needs to be reported to Support.

    You are right about the error code.  I was reading it wrong.  The first letter is an eight not a b.  It is:  810025

    You mentioned toggling the shadow copy flag, but as far as I know, this is an 8.1 feature, and our customer is still running 8.0

    Thanks for your suggestions.

  • In regards to the suggestion with the shadow copy flag, this happens if you do not specify the version in your thread. Just saying.

    In regards to your code, did you copy this code containing the .GetTriggerValue calls from the system debugger or from the Designer? If it is the latter case, you do have an issue as the $-Notation would be missing that is used by the Database Compiler and the object layer to determine the data flow execution.

    Did you contact support? If not I suggest doing so.

  • I didn't realize the customer was on an old release of OneIdentity until I tried to check the shadow copy setting.  When I saw there was none, I checked the version, and found that they were still on 8.0.3 (I believe).

    The code I posted was from the System Debugger.  I wanted to make sure the pre-compiler wasn't generating something strange.  I still think the Sync Engine is causing this problem by invoking the Object-Layer without setting FULLSYNC to true.

    I'll have to see if I can get the customer to open a support case.  As a OneIdentty Partner, the support site won't let me open a case because I'm not the owner of the customer's support contract, I'm afraid.

    Thanks for your suggestions.

  • Do you have a mapping in your sync project that is setting the UID_UNSContainerB? The template is of no concern if the sync is mapping the data into the UNSAccountB table directly.

  • We are feeding the "Key resolution by reference" component the Canonical-name of the UNSContainerB that the account needs to be created in.

    This works just fine, unless we add code to the Template for UID_UNSContainerB between [ If CBool(Connection.Variables.Get("FULLSYNC")) = False Then ] and [ End If ]   If this code tries to change the UID_UNSContainerB, then the SYNC fails with a 810025 error.  If I remove the code from the Template, the error goes away and the SYNC succeeds.  This means that I can't determine the container when someone creates the UNSAccountB in Manager.

    Data-import is off, so I would expect code between a [ if not FULLSYNC ] and [ end if ] to have no effect what so ever on the SYNC.

  • Does your Import also update UnsRootB.Ident_UNSRoot without Fullsync being activated?

    Updating UnsRootB.Ident_UNSRoot with Data import activated would trigger the remote template on UNSAccountB.UID_UNSContainerB. In this case it would run without fullsync active.

  • 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.

Reply Children
  • 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.