0
Fixed

SCIM gateway doesn't appear to support update with multiple changing attributes

Adrian Corston 2 years ago in UNIFYBroker Service updated by Beau Harrison (Senior Product Software Engineer) 2 years ago 6

I put through an update from Azure via SCIM which had two attributes changing at the same time, and the following error appeared in the UNIFYBroker log:

20220422,05:36:27,UNIFYBroker,SCIMGateway,Error,"Error during SCIM operation: System.InvalidOperationException: Sequence contains more than one element
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at Unify.Product.IdentityBroker.SCIMProvider.Patch(IAdapterEntity adapterEntity, PatchRequest2 patch, ISCIMGatewayMapping mappings, IValueAdapter`2 valueAdapter, IEntitySchema schema)
at Unify.Product.IdentityBroker.SCIMProvider.d__20.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.SystemForCrossDomainIdentityManagement.ProviderBase.d__45.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.SystemForCrossDomainIdentityManagement.ProviderAdapterTemplate`1.d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.SystemForCrossDomainIdentityManagement.ControllerTemplate`1.d__5.MoveNext()",Normal


Here is the corresponding update from the Azure side:

Image 6280

As a possible complication for this ticket, the user involved previously didn't have a value for their employeeNumber field (which is a required/key field of the underlying connector) and that caused this error:

20220422,05:34:08,UNIFYBroker,An exception has occured in the AdapterEntityChangeDetectorCollator. Please see the exception for details,Error,"Npgsql:
System.InvalidOperationException: Parameter 'key1value0' must have its value set
at Npgsql.NpgsqlParameter.ResolveHandler(ConnectorTypeMapper typeMapper)
at Npgsql.NpgsqlParameter.Bind(ConnectorTypeMapper typeMapper)
at Npgsql.NpgsqlCommand.ValidateParameters()
at Npgsql.NpgsqlCommand.d__100.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Npgsql.NpgsqlCommand.d__92.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Npgsql.NpgsqlCommand.ExecuteNonQuery()
at Unify.Product.IdentityBroker.MultiKeyValueQueryExecutor`2.PopulateTempTable(NpgsqlConnection connection, NpgsqlTransaction transaction, IDictionary`2 tempKeyLookup, ValueToObjectAdapter adapter, IEnumerable`1 multiKeyValues, String tempTableName)
at Unify.Product.IdentityBroker.MultiKeyValueQueryExecutor`2.Execute(NpgsqlConnection connection, ValueToObjectAdapter adapter, Guid partitionId, IEnumerable`1 multiKeyValues, String tempTableName, String entityValueFieldName, String entityTableName, String partitionIdName, Func`2 readData)
at Unify.Product.IdentityBroker.KnownEntityPartitionPostgreSqlUpdatableContextBase`3.GetEntities(Guid partitionId, IEnumerable`1 keys)
at Unify.Product.IdentityBroker.EntityRepositoryExtensions.<>c__DisplayClass1_0.b__0(MultiKeyValue`1[] multiKeyValues)
at Unify.Product.IdentityBroker.EntityRepositoryExtensions.ConvertConnectorEntities(IEnumerable`1 connectorEntities, IMultiKey`1 schemaKey, Func`2 retrieveEntities, Guid connectorId, IEnumerable`1 wellKnownEntities)
at Unify.Product.IdentityBroker.EntityRepositoryExtensions.ConvertConnectorEntities(IEnumerable`1 connectorEntities, IMultiKey`1 schemaKey, IKnownEntityContextBase`3 context, Guid connectorId, IEnumerable`1 wellKnownEntities)
at Unify.Product.IdentityBroker.EntityChangeDetector.ProcessConnectorChangedEntities(Guid connectorId, IEnumerable`1 connectorEntities, IEnumerable`1 wellKnownItems)
at Unify.Product.IdentityBroker.AdapterEntityChangeDetectorCollator.DetectChanges(KeyValuePair`2 connectorEntities)
at Unify.Framework.Visitor.<>c__DisplayClass0_0`1.b__0(T item, Int32 index)
at Unify.Framework.Visitor.Visit[T](IEnumerable`1 visitCollection, Action`2 visitor)
at Unify.Product.IdentityBroker.AdapterEntityChangeDetectorCollator.Run()
at Unify.Framework.AsynchronousJobExecutor.PerformJobCallback(Object state)",Normal

Could you please investigate and fix the update error, and also consider improving the behaviour when a connector's required field is missing in a SCIM update?

For the purposes of my demo next week I can make sure this 'bad data' doesn't occur, and so the only dependency for this is SIT/UAT meaning that it's a medium priority.

Under review

Hi Adrian,

It might be Friday Afternoon Brain, but I'm not quite understanding what you mean by your second point in the ticket. Are you able to provide some more background to the scenario you had, what you performed, and what the outcome was (error in this case) vs what you expect? I'm not sure what you're hoping for when you say "improving the behaviour when a required field is missing" 

No problem.

First, I attempted to provision a new user via SCIM, but that user had a blank/missing employeeNumber attribute which meant the connector entity couldn't be created (since it's a required/key field).  So I added the employeeNumber value in Azure and re-ran the user.  This resulted in the error shown at the start of this ticket, where Azure says it found the user but the attempt to update it failed.

Ideally, if a required/key field is missing then it would be nice if the SCIM gateway rejected the request to create that user, with a message that indicated what the problem was (e.g. "Could not save user because the 'employeeNumber' required attribute value is missing or blank").  But I realise it's a long way between the SCIM gateway and the AD connector code so that may just be too difficult to arrange.

But regardless of that, when the second request comes in it should not have responded in a way that Azure intereted as meaning there is an existing record that it can update.

The SCIM gateway responding with the error message "Sequence contains more than one element" seems to suggest that it can't process the attempt by Azure to update what it believes to be an existing user record - presumably because the update contains changes to "more than one element" (attribute?)  It's very confusing.

Also worth keeping in mind that the 'title' attribute - which is sourced from the 'appRoleAssignments' attribute on the Azure side - appears to be a huge XML document (example provided on https://voice.unifysolutions.net/en/communities/6/topics/4312-scim-user-update-not-working-in-unifyconnect).  It could be that the parsing of the SCIM request has gone askew and that attribute's value isn't being extracted as it should be.  But that's just conjecture on my behalf.

If you'd like to look at the configuration in a shared session please let me know and I'll be happy to work through it (and explain the background and outcomes that I'm configuring it for).

The issue resulting in the first error has been fixed and a patch provided to David.

Hi Adrian

Preparing to roll these changes into the next release of Broker. Has this issue been resolved?

I haven't had problems like this for a while, so it looks like it has.