Services unauthorized to register with custom service registry

Hello leaf-team,

When creating a new Service Registry, the leaf documentation says this

        // At the beginning of the WebServer setup, add the ServiceRegistryRestResource setup
        /*
         * ATTENTION: Carefully select the value for this boolean. See ServiceRegistryRestResource JavaDoc for details.
         */
        boolean requireUserHeaders = <TRUE_OR_FALSE>;
        IRestContextProvider contextProvider = RestContextProvider.newBuilder().build();
        ServiceRegistryRestResource registryResource = new ServiceRegistryRestResource(registry, contextProvider,
                requireUserHeaders);

And the documentation for the ServiceRegistryRestResource says

    /**
     * When set to true, requests will be expected to provide a {@link User}. When set to false, requests without a
     * User will be promoted to use {@link User#SYSTEM}.
     */
    private final boolean requireUserHeaders;

We are extending the metadata for services to include a classification field, to prevent users from seeing a service that they do not have high enough clearance for.

So with that, I would think we want this boolean as true, so any calls to the service registry from the front end to load in services will be authenticated, that way a user with classification: 1 cant see a class 4 service.

The part I’m confused on, is that the websocket and dashboard service are showing as unauthorized in the logs of the service registry

19:05:15.920 [qtp2066950947-49] [1;31mERROR[m c.l.l.p.s.ServiceRegistry - message: Registration failed, serviceId: WebsocketService
com.leidos.leaf.beans.exception.authorization.UnauthorizedException: No User was provided, and is therefore unauthorized.
	at com.leidos.leaf.internal.dataobject.service.authorization.policy.DataObjectAuthorizationHelper.lambda$evaluateAuthorization$13(DataObjectAuthorizationHelper.java:225) ~[framework-services-core-3.6.1.jar:?]
	at java.util.Optional.ifPresentOrElse(Optional.java:203) ~[?:?]
	at com.leidos.leaf.internal.dataobject.service.authorization.policy.DataObjectAuthorizationHelper.evaluateAuthorization(DataObjectAuthorizationHelper.java:223) ~[framework-services-core-3.6.1.jar:?]

But, other services are registering with the system user, and that boolean is set to true. This property is attached to all the service data objects in mongodb
createdByUsername: "AnonymousSystemUser"

So then, if I set that boolean to false, the websocket and dashboard service can register, but also using
createdByUsername: "AnonymousSystemUser"

So any ideas why some services can register with the system user but these two cant?

and this 500 error repeating in the logs of both services that can not register

14:49:16.115 [pool-2-thread-1] e[1;31mERRORe[m c.l.l.p.s.ServiceDiscoveryEmitter - Error encountered registering the service object
java.lang.RuntimeException: Response indicates failure, but unable to parse exception message. Status: 500 Entity: null
	at com.leidos.leaf.rest.util.exception.RestExceptionUtils.checkResponseForException(RestExceptionUtils.java:58) ~[framework-services-rest-3.5.5.jar:?]
	at com.leidos.leaf.platform.servicediscovery.ServiceDiscoveryEmitter.registerService(ServiceDiscoveryEmitter.java:136) ~[platform-services-service-discovery-3.3.0.jar:3.3.0]
	at com.leidos.leaf.platform.servicediscovery.ServiceDiscoveryEmitter.lambda$initialize$0(ServiceDiscoveryEmitter.java:96) ~[platform-services-service-discovery-3.3.0.jar:3.3.0]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) [?:?]
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) [?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
	at java.lang.Thread.run(Thread.java:829) [?:?]

Hello, Jacob. I’ve spent some time walking through the 3.6 LKB guides on newly generated 3.5 Data Services and here’s what I’ve found.

Setup

I generated a 3.5 Data Service and updated it to 3.6, then walked through the guide to convert it into a Service Registry. When choosing a value for requireUserHeaders, I chose true.

I generated two additional 3.5 Data Services and upgraded them to 3.6. I updated one of the Data Services to use the non-deprecated classes for service discovery (ServiceRegistryRestClient and ServiceRegistryScheduler) while the other continued to use the deprecated ServiceDiscoveryEmitter.

Result

Both the scheduler-based and emitter-based Data Services were able to register with my custom-built Service Registry. The ServiceDiscoveryEmitter is not friendly for changing the IContext which is sounds like you need to do, so regardless I recommend updating to the newer non-deprecated classes for service discovery. See the 3.6 LKB Discoverable Service Registration guide for more info.

I know this doesn’t necessarily address your issue, but here are some comments/questions:

  • I’m curious to know what differences there are between the services that are successfully registering and those that aren’t.
  • What is the error you’re seeing for registration in the Service Registry for the services failing to register? Is that the AuthorizationException you posted above, and if so can you post more of the stack trace so we can see where it’s being thrown from?
  • For the services that are successfully registering, AnonymousSystemUser means the registration process is still not having Authorization applied to it. The System User bypasses any LEAF Auth Policy.

Interesting that it worked for you. I believe all the services we use are on

leaf {
    version = '3.5.5'

Here is the full error

19:49:42.044 [qtp183371252-39] e[1;31mERRORe[m c.l.l.p.s.ServiceRegistry - message: Registration failed, serviceId: WebsocketService
com.leidos.leaf.beans.exception.authorization.UnauthorizedException: No User was provided, and is therefore unauthorized.
	at com.leidos.leaf.internal.dataobject.service.authorization.policy.DataObjectAuthorizationHelper.lambda$evaluateAuthorization$13(DataObjectAuthorizationHelper.java:225) ~[framework-services-core-3.6.1.jar:?]
	at java.util.Optional.ifPresentOrElse(Optional.java:203) ~[?:?]
	at com.leidos.leaf.internal.dataobject.service.authorization.policy.DataObjectAuthorizationHelper.evaluateAuthorization(DataObjectAuthorizationHelper.java:223) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.internal.dataobject.service.authorization.policy.DataObjectAuthorizationHelper.applyAuthorizationOnLoad(DataObjectAuthorizationHelper.java:80) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.dataobject.service.load.helper.DataObjectServiceLoadHelper.lambda$processQuery$23(DataObjectServiceLoadHelper.java:401) ~[framework-services-core-3.6.1.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleFlatMap$SingleFlatMapCallback.onSuccess(SingleFlatMap.java:77) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleFlatMap$SingleFlatMapCallback$FlatMapSingleObserver.onSuccess(SingleFlatMap.java:112) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.observers.ResumeSingleObserver.onSuccess(ResumeSingleObserver.java:46) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleJust.subscribeActual(SingleJust.java:30) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleDelayWithCompletable$OtherObserver.onComplete(SingleDelayWithCompletable.java:69) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.disposables.EmptyDisposable.complete(EmptyDisposable.java:68) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.completable.CompletableEmpty.subscribeActual(CompletableEmpty.java:27) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Completable.subscribe(Completable.java:2859) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleDelayWithCompletable.subscribeActual(SingleDelayWithCompletable.java:36) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleFlatMap$SingleFlatMapCallback.onSuccess(SingleFlatMap.java:85) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleMap$MapSingleObserver.onSuccess(SingleMap.java:65) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleMap$MapSingleObserver.onSuccess(SingleMap.java:65) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleMap$MapSingleObserver.onSuccess(SingleMap.java:65) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleMap$MapSingleObserver.onSuccess(SingleMap.java:65) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleMap$MapSingleObserver.onSuccess(SingleMap.java:65) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleJust.subscribeActual(SingleJust.java:30) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleMap.subscribeActual(SingleMap.java:35) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleMap.subscribeActual(SingleMap.java:35) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleMap.subscribeActual(SingleMap.java:35) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleMap.subscribeActual(SingleMap.java:35) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleMap.subscribeActual(SingleMap.java:35) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleFlatMap.subscribeActual(SingleFlatMap.java:37) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleFlatMap.subscribeActual(SingleFlatMap.java:37) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleFlatMap.subscribeActual(SingleFlatMap.java:37) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleFlatMap.subscribeActual(SingleFlatMap.java:37) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleFlatMap.subscribeActual(SingleFlatMap.java:37) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.single.SingleFlatMapPublisher.subscribeActual(SingleFlatMapPublisher.java:59) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:15917) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.flowable.FlowableToListSingle.subscribeActual(FlowableToListSingle.java:56) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4855) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Single.blockingGet(Single.java:3644) ~[rxjava-3.1.3.jar:?]
	at com.leidos.leaf.internal.publisher.RxJavaUtils.toList(RxJavaUtils.java:43) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.internal.dataobject.service.IDataObjectServiceRx.load(IDataObjectServiceRx.java:513) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.dataobject.service.DataObjectServiceExtensible.lambda$new$26(DataObjectServiceExtensible.java:725) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.hooked.IMethod.invoke(IMethod.java:125) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.hooked.default_.hooks.CacheHook.doCacheCheck(CacheHook.java:271) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.hooked.default_.hooks.CacheHook.lambda$hookInvoker$8(CacheHook.java:224) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.hooked.IMethod.invoke(IMethod.java:125) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.hooked.default_.hooks.metrics.TimerHook.lambda$hookInvoker$1(TimerHook.java:99) ~[framework-services-metrics-3.6.1.jar:?]
	at com.leidos.leaf.hooked.IMethod.invoke(IMethod.java:125) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.hooked.default_.hooks.metrics.MeterHook.lambda$hookInvoker$1(MeterHook.java:103) ~[framework-services-metrics-3.6.1.jar:?]
	at com.leidos.leaf.hooked.IMethod.invoke(IMethod.java:125) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.hooked.default_.hooks.LogHook.lambda$hookInvoker$2(LogHook.java:145) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.hooked.IMethod.invoke(IMethod.java:125) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.hooked.default_.hooks.TimeLimiterHook.lambda$hookInvoker$1(TimeLimiterHook.java:95) ~[framework-services-core-3.6.1.jar:?]
	at io.reactivex.rxjava3.internal.operators.maybe.MaybeFromCallable.subscribeActual(MaybeFromCallable.java:47) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Maybe.subscribe(Maybe.java:5375) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.internal.operators.maybe.MaybeTimeoutMaybe.subscribeActual(MaybeTimeoutMaybe.java:50) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Maybe.subscribe(Maybe.java:5375) ~[rxjava-3.1.3.jar:?]
	at io.reactivex.rxjava3.core.Maybe.blockingGet(Maybe.java:2859) ~[rxjava-3.1.3.jar:?]
	at com.leidos.leaf.hooked.default_.hooks.TimeLimiterHook.lambda$hookInvoker$2(TimeLimiterHook.java:97) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.hooked.BaseExtensibleService.invoke(BaseExtensibleService.java:129) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.dataobject.service.DataObjectServiceExtensible.load(DataObjectServiceExtensible.java:888) ~[framework-services-core-3.6.1.jar:?]
	at com.leidos.leaf.platform.servicediscovery.ServiceRegistry.loadRegisteredService(ServiceRegistry.java:132) ~[platform-services-service-discovery-3.6.0.jar:3.6.0]
	at com.leidos.leaf.platform.servicediscovery.ServiceRegistry.registerService(ServiceRegistry.java:56) ~[platform-services-service-discovery-3.6.0.jar:3.6.0]
	at com.leidos.leaf.platform.servicediscovery.rest.ServiceRegistryRestResource.registerService(ServiceRegistryRestResource.java:92) ~[platform-services-service-discovery-3.6.0.jar:3.6.0]
	at jdk.internal.reflect.GeneratedMethodAccessor6.invoke(Unknown Source) ~[?:?]
	at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
	at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
	at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:408) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:69) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:249) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:60) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:55) ~[resteasy-core-5.0.2.Final.jar:5.0.2.Final]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) ~[javax.servlet-api-3.1.0.jar:3.1.0]
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:799) ~[jetty-servlet-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:550) ~[jetty-servlet-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) ~[jetty-server-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1434) ~[jetty-server-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188) ~[jetty-server-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:501) ~[jetty-servlet-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) ~[jetty-server-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1349) ~[jetty-server-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[jetty-server-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:763) ~[jetty-server-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:59) ~[jetty-server-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) ~[jetty-server-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.server.Server.handle(Server.java:516) ~[jetty-server-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:400) ~[jetty-server-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:645) ~[jetty-server-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:392) ~[jetty-server-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277) ~[jetty-server-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) ~[jetty-io-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105) ~[jetty-io-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104) ~[jetty-io-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338) ~[jetty-util-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315) ~[jetty-util-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173) ~[jetty-util-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131) ~[jetty-util-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409) ~[jetty-util-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883) ~[jetty-util-9.4.44.v20210927.jar:9.4.44.v20210927]
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034) ~[jetty-util-9.4.44.v20210927.jar:9.4.44.v20210927]
	at java.lang.Thread.run(Thread.java:829) ~[?:?]

I did fix the dashboard service, and it is now registering. I hadn’t updated my master branch in a while, so I did and redeployed. It is now registering. I don’t know what changed, so I’m going to compare the commit I was on and the latest. Did the same to the websocket service but I’m not that lucky.

I’m not familiar with IContext, so what makes you say that I will most likely have to change it?

The IContext

The IContext is important as it passes around the User and more for each operation LEAF performs. Learn more about Contexts and Users from the LKB.

The error we are seeing above seems to indicated that a User object is not being passed along with the Context across the REST calls being made for Service Registration. This is unexpected behavior as both the deprecated ServiceDiscoveryEmitter and ServiceRegistryScheduler classes will default to creating the System Context, or in other words a System.USER should be present on the registration requests.

The deprecated ServiceDiscoveryEmitter does not allow domains to change which User is used for scheduled requests, at least not cleanly, without extending the class which I don’t recommend. The newer library offerings, introduced in 3.6, for Service Discovery will allow you to pass the IContext you wish to have used.

Your Objective

“So with that, I would think we want this boolean as true, so any calls to the service registry from the front end to load in services will be authenticated, that way a user with classification: 1 cant see a class 4 service.”

The boolean called requireUserHeaders that we pass to the ServiceRegistryRestResource will only affect the REST endpoints that it exposes. The only endpoints exposed by the ServiceRegistryRestResource are /service/register and /service/deregister/{id}. While you may wish to lock them down further, the description you’ve included above seems to be more about what front end application users can load, and that’s going to go through a different set of endpoints (the DataObjectRestService endpoints exposed by the RestService in the Service Registry to be precise). In other words, this boolean will not apply to front end applications and their users unless those front end applications are trying to register and deregister services, which they should not be doing.

LEAF Service Registration is a backend service communicating with another backend service operation, and so no authenticated users are usually involved. Instead, this internal, system operation can be secured by restricting access to those endpoints so that only Discoverable Services within the cluster can make requests of the registration and deregistration endpoints. To learn more about locking down endpoints, see this RedOak Knowledge Base guidance about how Istio AuthorizationPolicies can be used to restrict endpoint access on a Service Registry. (Disclaimer: This is documentation for a dev release of RedOak and is therefore subject to change.)

To learn more about adding authorization to your custom-built Service Registry, or any Data Service for that matter, check out the following guidance on security and DataObject Authorization in the LKB. If I understand your objective, you’ll need to create a new IDataObjectAuthorizationPolicy for the Service Registry and ensure that it applies security to Users based upon their classification when they try to query for registered services.

Ah I see. Thanks for the explaination.

Since that is the case, yes we want that boolean set to false. The service is registering now.

Thank you!