0
Won't fix

PowerShell Adapter Transform field unable to be used in DN

Bob Bradley 12 months ago updated by Matthew Davis (Engineering Manager) 11 months ago 3

I am using the following PS Adapter transform to generate a "hrStatus" value for EVERY record:

foreach ($entity in $entities) {
    [string]$hrStatus = "Active"
    if (!($entity["uid"]) -or ($entity["uid"].Value -notlike "A*") -or ($entity["uid"].Value -like "*_*")) {
        $hrStatus = "Inactive"
    }
    $entity["hrStatus"] = $hrStatus
}

I declare the schema for the hrStatus property as follows:

New-Field 'hrStatus' 'string' $false $true $true;

I am then setting the DN to use this property as a next-level OU below OU=Employees.

However when I enable the Adapter I get the error below - does this mean that the REQUIRED property is being ignore?

System.Exception: Swagger Exception could not be parsed. SE response code: 500; SE response text: {"Message":"An error has occurred.","ExceptionMessage":"Error in adapter DotEE Employee distinguished name configuration: The DN component part 'OU=[hrStatus]' could not be executed as the field hrStatus is not required. An empty field would result in a DN of 'OU='.","ExceptionType":"Unify.Framework.UnifyConfigurationException","StackTrace":"   at Unify.Product.IdentityBroker.AdapterEngine.ValidateAdapterForEnabling(IOperationalAdapter adapter)\r\n   at Unify.Product.IdentityBroker.AdapterEngine.<>c__DisplayClass54_0.<EnableAdapter>b__0()\r\n   at Unify.Product.IdentityBroker.AdapterEngine.<>c__DisplayClass145_0.<ConfigurationChange>b__0()\r\n   at Unify.Framework.ExtensionMethods.WaitOnMutex(Mutex mutex, Action work)\r\n   at Unify.Product.IdentityBroker.AdapterEngineAuditingDecorator.EnableAdapter(Guid adapterId)\r\n   at Unify.Product.IdentityBroker.AdapterEngineNotifierDecorator.<>c__DisplayClass19_0.<EnableAdapter>b__0()\r\n   at Unify.Framework.Notification.NotifierDecoratorBase.Notify(ITaskNotificationFactory notificationFactory, Action action)\r\n   at lambda_method(Closure , Object , Object[] )\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClassc.<GetExecutor>b__6(Object instance, Object[] methodParameters)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()","InnerException":{"Message":"An error has occurred.","ExceptionMessage":"The DN component part 'OU=[hrStatus]' could not be executed as the field hrStatus is not required. An empty field would result in a DN of 'OU='.","ExceptionType":"Unify.Framework.UnifyEngineException","StackTrace":"   at Unify.Product.IdentityBroker.FieldTemplateDistinguishedNameComponentExecutor`2.Validate(IEntitySchema schema)\r\n   at Unify.Product.IdentityBroker.TemplateDistinguishedNameExecutor`2.Validate(IEntitySchema schema)\r\n   at Unify.Product.IdentityBroker.AdapterEngine.ValidateAdapterForEnabling(IOperationalAdapter adapter)"}}; ---> Unify.Framework.Client.SwaggerException: The HTTP status code of the response was not expected (500).
at Unify.Connect.Web.Client.AdapterClient.<ToggleAdapterEnabledAsync>d__117.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 Unify.Connect.Web.Client.ProfiledAdapterClient.<ToggleAdapterEnabledAsync>d__124.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 Unify.Framework.Web.UnifyController.<HandleRemoteException>d__42.MoveNext()
--- End of inner exception stack trace ---
at Unify.Framework.Web.UnifyController.InnerHandleSwaggerExceptionForApiCall(SwaggerException se, String messageTemplate, Action`1 handleMessage, Action`1 handleExtended)
at Unify.Framework.Web.UnifyController.HandleSwaggerExceptionForApiCall(SwaggerException se, String messageTemplate)
at Unify.Framework.Web.UnifyController.<HandleRemoteException>d__42.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 Unify.Connect.Web.AdapterController.<ToggleEnableState>d__74.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 Unify.Connect.Web.AdapterController.<EnableAdapter>d__26.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 lambda_method(Closure , Task )
at System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass34.<BeginInvokeAsynchronousActionMethod>b__33(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3c()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass45.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3e()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass1e.<>c__DisplayClass28.<BeginInvokeAction>b__19()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass1e.<BeginInvokeAction>b__1b(IAsyncResult asyncResult)
Affected Versions:
Fixed by Version:
GOOD, I'M SATISFIED

The benefits of using the LDAP filter on the MIM MA are significant/huge - but in my case I was able to achieve this without the need of a PowerShell transform, so ultimately had no need of this feature.  However an improvement would be to throw a meaningful message when attempting to save a DN expression based on an ineligible attribute.

Satisfaction mark by Bob Bradley 11 months ago

Thanks Beau.  I've just tried the suggestion above and it works well - thanks for that.  I have decided not to proceed with the idea, however, for referential integrity challenges - e.g. makes manager DN difficult to calculate on the employee adapter, and group owner even more difficult on a separate connector.  If I come up with another way of segregating active/inactive users by DN I will post here.

An update - I ended up changing my mind and implementing this after all because the benefits were too great, and it was worth the extra pain of additional adapter transforms to construct reference DNs.  Here's the screenshot of the LDAP filter: