You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@sling.apache.org by Carsten Ziegeler <cz...@apache.org> on 2017/05/09 05:31:53 UTC

Revisiting ServiceUserMapped

While working on the "configurationless" Sling, I noticed that the
ServiceUserMapped concept does not only create problems with zero
configurations but is also not working as expected. Right now, it
creates a false sense of safety.

It is a good idea to express the requirement of a component to use a
specific service user as a dependency to a service registered in the
service registry. Therefore we created the ServiceUserMapped. However as
the name already applies, the existence of this service only means that
a *mapping* is available. It does not express whether the underlying
*service user* is available. Therefore the whole mechanism is creating
this false sense of safety and in reality does not provide the wanted value.

There is the assumption that if such a mapping is available the
underlying service user is available as well - which unfortunately is
wrong. In this sense we could also remove the whole concept again and
simply assume that if the JCR resource provider is available, the
service user is created. It's the same shaky assumption but just simpler :)

Or we could try to make this work as expected. Now, a component using a
service user does not know which service user it will use as this is
configured in the mapping. I think this decoupling is a good idea.
Therefore the current dependency to a ServiceUserMapped is a good thing.
(Although the current use of @Reference in many places could be improved
to what we have now in the code - but that's OT for this thread).

However, the automatic registration of the ServiceUserMapped service
just due to the existence of a mapping configuration is the part which
is wrong. In addition, we have to keep in mind that we might have many
resource providers not just one which is using service users.
Fortunately there are resource providers not requiring authentication
and these can be used without the existence of a service user. Taking
this into account, a resource provider using authentication should
announce which service users it knows, our implementation of the service
user mapper compares the mapping configuration with the existence of
service users in *all* resource providers requiring authentication and
if each of them provides such a service user, it will register the
ServiceUserMapped. Similar of no resource provider requires
authentication, the ServiceUserMapped can be registered as well.

This will bring us a working and reliable solution and in addition
solves the configurationless part as well - for example if you only have
the file resource provider, the ServiceUserMapped can be registered and
no additional configuration is required.

There is one neglectable "problem" with this approach. It assumes that
potentially the requested service user will access all (authenticated)
resource providers while in practice it might be the case that only one
is hit.

So, to keep the long story short: either we remove the ServiceUserMapped
concept or we do it right. The way it is today is not really solving the
problems it should.

Regards
Carsten
-- 
Carsten Ziegeler
Adobe Research Switzerland
cziegeler@apache.org

Re: Revisiting ServiceUserMapped

Posted by Carsten Ziegeler <cz...@apache.org>.
Marius Petria wrote
> Hi,
> 
> Do we need an additional interface to check for user existence, or could we just treat it as a special case of validity by using the ServiceUserValidator?
> 

I think it's easier :) We can just try to login to the resource resolver
factory. If it fails, there is something wrong. If it works, the service
user exists (in all providers)

Carsten

> Marius
> 
> On 5/12/17, 7:14 PM, "Carsten Ziegeler" <cz...@apache.org> wrote:
> 
>     Julian Sedding wrote
>     
>     > 
>     > Interesting aspect that "all" need to have the service user. I had
>     > assumed "at least one" resource provider needs to have the service
>     > user.
>     > 
>     > Both "all" and "at least one" are heuristics, because we don't know
>     > what the service-user will access.
>     
>     Not exactly :) At least all providers which require authentication and
>     are not lazy need to provide this service user. Otherwise the login
>     already fails.
>     
>     > 
>     > In some cases "all" may be too strict: you need to provide matching
>     > users in all RRPs to allow a service user access to one of them.
>     > In other cases "at least one" may be to lax: the service user actually
>     > needs to access multiple RRPs.
>     > 
>     > Not sure where the sweet spot is... Maybe we should allow indicating
>     > the desired RRP(s) in the ServiceUserMapped's target filter (which can
>     > be set via configuration, i.e. during deployment).
>     
>     I think we should not break the abstraction by doing so. If we go with
>     the requirement that all non lazy providers must have this, then I think
>     we are pretty close to what is usually needed. As mentioned of a non
>     lazy provider does not have the service user, the login will fail
>     anyways. So the only option we have is whether to check the existence
>     with lazy providers as well. I think we should not check for this is
>     exactly what the difference between lazy and non lazy resource providers
>     is intended for.
>     
>     Regards
>     
>      Carsten
>     
>     -- 
>     Carsten Ziegeler
>     Adobe Research Switzerland
>     cziegeler@apache.org
>     
> 


 

-- 
Carsten Ziegeler
Adobe Research Switzerland
cziegeler@apache.org

Re: Revisiting ServiceUserMapped

Posted by Marius Petria <mp...@adobe.com.INVALID>.
Hi,

Do we need an additional interface to check for user existence, or could we just treat it as a special case of validity by using the ServiceUserValidator?

Marius

On 5/12/17, 7:14 PM, "Carsten Ziegeler" <cz...@apache.org> wrote:

    Julian Sedding wrote
    
    > 
    > Interesting aspect that "all" need to have the service user. I had
    > assumed "at least one" resource provider needs to have the service
    > user.
    > 
    > Both "all" and "at least one" are heuristics, because we don't know
    > what the service-user will access.
    
    Not exactly :) At least all providers which require authentication and
    are not lazy need to provide this service user. Otherwise the login
    already fails.
    
    > 
    > In some cases "all" may be too strict: you need to provide matching
    > users in all RRPs to allow a service user access to one of them.
    > In other cases "at least one" may be to lax: the service user actually
    > needs to access multiple RRPs.
    > 
    > Not sure where the sweet spot is... Maybe we should allow indicating
    > the desired RRP(s) in the ServiceUserMapped's target filter (which can
    > be set via configuration, i.e. during deployment).
    
    I think we should not break the abstraction by doing so. If we go with
    the requirement that all non lazy providers must have this, then I think
    we are pretty close to what is usually needed. As mentioned of a non
    lazy provider does not have the service user, the login will fail
    anyways. So the only option we have is whether to check the existence
    with lazy providers as well. I think we should not check for this is
    exactly what the difference between lazy and non lazy resource providers
    is intended for.
    
    Regards
    
     Carsten
    
    -- 
    Carsten Ziegeler
    Adobe Research Switzerland
    cziegeler@apache.org
    


Re: Revisiting ServiceUserMapped

Posted by Carsten Ziegeler <cz...@apache.org>.
Julian Sedding wrote

> 
> Interesting aspect that "all" need to have the service user. I had
> assumed "at least one" resource provider needs to have the service
> user.
> 
> Both "all" and "at least one" are heuristics, because we don't know
> what the service-user will access.

Not exactly :) At least all providers which require authentication and
are not lazy need to provide this service user. Otherwise the login
already fails.

> 
> In some cases "all" may be too strict: you need to provide matching
> users in all RRPs to allow a service user access to one of them.
> In other cases "at least one" may be to lax: the service user actually
> needs to access multiple RRPs.
> 
> Not sure where the sweet spot is... Maybe we should allow indicating
> the desired RRP(s) in the ServiceUserMapped's target filter (which can
> be set via configuration, i.e. during deployment).

I think we should not break the abstraction by doing so. If we go with
the requirement that all non lazy providers must have this, then I think
we are pretty close to what is usually needed. As mentioned of a non
lazy provider does not have the service user, the login will fail
anyways. So the only option we have is whether to check the existence
with lazy providers as well. I think we should not check for this is
exactly what the difference between lazy and non lazy resource providers
is intended for.

Regards

 Carsten

-- 
Carsten Ziegeler
Adobe Research Switzerland
cziegeler@apache.org

Re: Revisiting ServiceUserMapped

Posted by Julian Sedding <js...@gmail.com>.
On Fri, May 12, 2017 at 9:56 AM, Carsten Ziegeler <cz...@apache.org> wrote:
> Julian Sedding wrote
>> Definitely +1 on doing this right.
>>
>> Regardless of the above, the goals I read in this thread are the following:
>> - only register a service if the required service-user is available
>> (ServiceUserMapped)
>> - announce service-users lazily
>>
>> An implementation could consist of a component, let's call it
>> ServiceUserRegistry. The ServiceUserRegistry looks for
>> ServiceUserProvider services (e.g. a SlingRepository implementation
>> could also implement this interface). Furthermore, the
>> ServiceUserRegistry implements FindHook (in theory I think a
>> ListenerHook would be better, but this does not work with the current
>> Felix SCR implementation) looking for requests for ServiceUserMapped
>> services and their (optional) sub-service name. If a service is
>> requested that is not yet available, the ServiceUserRegistry asks all
>> ServiceUserProviders if they can provide a suitable service user. If
>> that is the case it registers an appropriately configured service
>> (this could be achieved by means of a ComponentFactory).
>>
>> Unregistering of service users that go away could be handled on two
>> levels: 1. if a ServiceUserProvider is unregistered, all service-users
>> it provided need to be unregistered as well. 2. A ServiceUserProvider
>> needs to be able to signal the ServiceUserRegistry that a user has
>> disappeared.
>>
>> With the introduction of a default service-user mapping, at least the
>> name ServiceUserMapped seems no longer appropriate. We could rename it
>> to ServiceUser or ServiceUserAvailable. And/or I could imagine going a
>> step further and provide a ServiceResourceResolverFactory (an
>> interface with a single method "createResourceResolver(Map authInfo)"
>> or maybe a second one with no args for convenience). A consumer would
>> inject the ServiceResourceResolverFactory instead of a
>> ResourceResolverFactory. The @Reference target filter could optionally
>> indicate a subservice name.
>>
>> Please feel free to rip this apart or improve on it! ;)
>
> :) Thanks, yes we could do something along these lines. But it gets more
> complicated with having N resource providers as potentially each
> resource provider (which uses authentication) has to have this service
> user. Still doable.
>
> Let's assume for the sake of the discussion that we keep the name
> ServiceUserMapped.
>
> We could register service hooks: if a ServiceUserMapped is requested
> which doesn't exist, the hook could:
> - get "all" resource providers requiring authentication (let's talk
> about "all" below)
> - ask each of them through some interface whether they have the
> requested service user

Agreed. I called "some interface" ServiceUserProvider.

> - if all of them respond with "yes" or if there is no resource provider
> requiring authentication, the ServiceUserMapped service is registered
>
> If a ServiceUserMapped is registered and a resource provider requiring
> authentication is added, the above check needs to be done for the new
> provider and potentially the ServiceUserMapped gets unregistered.
>
> I mentioned above that "all" resource providers need to be asked, we
> could also argue that only resource providers which require
> authentication and are not lazy need to provide the service user. Lazy
> resource providers are optional anyway.
>

Interesting aspect that "all" need to have the service user. I had
assumed "at least one" resource provider needs to have the service
user.

Both "all" and "at least one" are heuristics, because we don't know
what the service-user will access.

In some cases "all" may be too strict: you need to provide matching
users in all RRPs to allow a service user access to one of them.
In other cases "at least one" may be to lax: the service user actually
needs to access multiple RRPs.

Not sure where the sweet spot is... Maybe we should allow indicating
the desired RRP(s) in the ServiceUserMapped's target filter (which can
be set via configuration, i.e. during deployment).

Regards
Julian

> If we can go with that assumption, the check whether a service user
> exists becomes pretty easy: simply try to get a resource resolver with
> that service user - if a login exception occurs, it's not available ->
> no ServiceUserMapped. Otherwise register the ServiceUserMapped.
>
> I think with the above simplification it becomes fairly easy to
> implement. It neither exposes service users to the world nor does it
> require API changes
>
>
> Regards
>
>  Carsten
>
> --
> Carsten Ziegeler
> Adobe Research Switzerland
> cziegeler@apache.org

Re: Revisiting ServiceUserMapped

Posted by Karl Pauls <ka...@gmail.com>.
On Fri, May 12, 2017 at 9:56 AM, Carsten Ziegeler <cz...@apache.org> wrote:
> Julian Sedding wrote
>> Definitely +1 on doing this right.
>>
>> Regardless of the above, the goals I read in this thread are the following:
>> - only register a service if the required service-user is available
>> (ServiceUserMapped)
>> - announce service-users lazily
>>
>> An implementation could consist of a component, let's call it
>> ServiceUserRegistry. The ServiceUserRegistry looks for
>> ServiceUserProvider services (e.g. a SlingRepository implementation
>> could also implement this interface). Furthermore, the
>> ServiceUserRegistry implements FindHook (in theory I think a
>> ListenerHook would be better, but this does not work with the current
>> Felix SCR implementation) looking for requests for ServiceUserMapped
>> services and their (optional) sub-service name. If a service is
>> requested that is not yet available, the ServiceUserRegistry asks all
>> ServiceUserProviders if they can provide a suitable service user. If
>> that is the case it registers an appropriately configured service
>> (this could be achieved by means of a ComponentFactory).
>>
>> Unregistering of service users that go away could be handled on two
>> levels: 1. if a ServiceUserProvider is unregistered, all service-users
>> it provided need to be unregistered as well. 2. A ServiceUserProvider
>> needs to be able to signal the ServiceUserRegistry that a user has
>> disappeared.
>>
>> With the introduction of a default service-user mapping, at least the
>> name ServiceUserMapped seems no longer appropriate. We could rename it
>> to ServiceUser or ServiceUserAvailable. And/or I could imagine going a
>> step further and provide a ServiceResourceResolverFactory (an
>> interface with a single method "createResourceResolver(Map authInfo)"
>> or maybe a second one with no args for convenience). A consumer would
>> inject the ServiceResourceResolverFactory instead of a
>> ResourceResolverFactory. The @Reference target filter could optionally
>> indicate a subservice name.
>>
>> Please feel free to rip this apart or improve on it! ;)
>
> :) Thanks, yes we could do something along these lines. But it gets more
> complicated with having N resource providers as potentially each
> resource provider (which uses authentication) has to have this service
> user. Still doable.
>
> Let's assume for the sake of the discussion that we keep the name
> ServiceUserMapped.
>
> We could register service hooks: if a ServiceUserMapped is requested
> which doesn't exist, the hook could:
> - get "all" resource providers requiring authentication (let's talk
> about "all" below)
> - ask each of them through some interface whether they have the
> requested service user
> - if all of them respond with "yes" or if there is no resource provider
> requiring authentication, the ServiceUserMapped service is registered
>
> If a ServiceUserMapped is registered and a resource provider requiring
> authentication is added, the above check needs to be done for the new
> provider and potentially the ServiceUserMapped gets unregistered.
>
> I mentioned above that "all" resource providers need to be asked, we
> could also argue that only resource providers which require
> authentication and are not lazy need to provide the service user. Lazy
> resource providers are optional anyway.
>
> If we can go with that assumption, the check whether a service user
> exists becomes pretty easy: simply try to get a resource resolver with
> that service user - if a login exception occurs, it's not available ->
> no ServiceUserMapped. Otherwise register the ServiceUserMapped.
>
> I think with the above simplification it becomes fairly easy to
> implement. It neither exposes service users to the world nor does it
> require API changes

I think that sounds reasonable. I guess the only thing we are missing
is that service users could get created (i.e., become available) or
deleted (unavailable) at the discretion of a given resource provider.
If we wanted to support that we would need to add some eventing for
that case but that could be a second step.

regards,

Karl

> Regards
>
>  Carsten
>
> --
> Carsten Ziegeler
> Adobe Research Switzerland
> cziegeler@apache.org



-- 
Karl Pauls
karlpauls@gmail.com

Re: Revisiting ServiceUserMapped

Posted by Carsten Ziegeler <cz...@apache.org>.
Julian Sedding wrote
> Definitely +1 on doing this right.
> 
> Regardless of the above, the goals I read in this thread are the following:
> - only register a service if the required service-user is available
> (ServiceUserMapped)
> - announce service-users lazily
> 
> An implementation could consist of a component, let's call it
> ServiceUserRegistry. The ServiceUserRegistry looks for
> ServiceUserProvider services (e.g. a SlingRepository implementation
> could also implement this interface). Furthermore, the
> ServiceUserRegistry implements FindHook (in theory I think a
> ListenerHook would be better, but this does not work with the current
> Felix SCR implementation) looking for requests for ServiceUserMapped
> services and their (optional) sub-service name. If a service is
> requested that is not yet available, the ServiceUserRegistry asks all
> ServiceUserProviders if they can provide a suitable service user. If
> that is the case it registers an appropriately configured service
> (this could be achieved by means of a ComponentFactory).
> 
> Unregistering of service users that go away could be handled on two
> levels: 1. if a ServiceUserProvider is unregistered, all service-users
> it provided need to be unregistered as well. 2. A ServiceUserProvider
> needs to be able to signal the ServiceUserRegistry that a user has
> disappeared.
> 
> With the introduction of a default service-user mapping, at least the
> name ServiceUserMapped seems no longer appropriate. We could rename it
> to ServiceUser or ServiceUserAvailable. And/or I could imagine going a
> step further and provide a ServiceResourceResolverFactory (an
> interface with a single method "createResourceResolver(Map authInfo)"
> or maybe a second one with no args for convenience). A consumer would
> inject the ServiceResourceResolverFactory instead of a
> ResourceResolverFactory. The @Reference target filter could optionally
> indicate a subservice name.
> 
> Please feel free to rip this apart or improve on it! ;)

:) Thanks, yes we could do something along these lines. But it gets more
complicated with having N resource providers as potentially each
resource provider (which uses authentication) has to have this service
user. Still doable.

Let's assume for the sake of the discussion that we keep the name
ServiceUserMapped.

We could register service hooks: if a ServiceUserMapped is requested
which doesn't exist, the hook could:
- get "all" resource providers requiring authentication (let's talk
about "all" below)
- ask each of them through some interface whether they have the
requested service user
- if all of them respond with "yes" or if there is no resource provider
requiring authentication, the ServiceUserMapped service is registered

If a ServiceUserMapped is registered and a resource provider requiring
authentication is added, the above check needs to be done for the new
provider and potentially the ServiceUserMapped gets unregistered.

I mentioned above that "all" resource providers need to be asked, we
could also argue that only resource providers which require
authentication and are not lazy need to provide the service user. Lazy
resource providers are optional anyway.

If we can go with that assumption, the check whether a service user
exists becomes pretty easy: simply try to get a resource resolver with
that service user - if a login exception occurs, it's not available ->
no ServiceUserMapped. Otherwise register the ServiceUserMapped.

I think with the above simplification it becomes fairly easy to
implement. It neither exposes service users to the world nor does it
require API changes


Regards

 Carsten

-- 
Carsten Ziegeler
Adobe Research Switzerland
cziegeler@apache.org

Re: Revisiting ServiceUserMapped

Posted by Julian Sedding <js...@gmail.com>.
Definitely +1 on doing this right.

Regardless of the above, the goals I read in this thread are the following:
- only register a service if the required service-user is available
(ServiceUserMapped)
- announce service-users lazily

An implementation could consist of a component, let's call it
ServiceUserRegistry. The ServiceUserRegistry looks for
ServiceUserProvider services (e.g. a SlingRepository implementation
could also implement this interface). Furthermore, the
ServiceUserRegistry implements FindHook (in theory I think a
ListenerHook would be better, but this does not work with the current
Felix SCR implementation) looking for requests for ServiceUserMapped
services and their (optional) sub-service name. If a service is
requested that is not yet available, the ServiceUserRegistry asks all
ServiceUserProviders if they can provide a suitable service user. If
that is the case it registers an appropriately configured service
(this could be achieved by means of a ComponentFactory).

Unregistering of service users that go away could be handled on two
levels: 1. if a ServiceUserProvider is unregistered, all service-users
it provided need to be unregistered as well. 2. A ServiceUserProvider
needs to be able to signal the ServiceUserRegistry that a user has
disappeared.

With the introduction of a default service-user mapping, at least the
name ServiceUserMapped seems no longer appropriate. We could rename it
to ServiceUser or ServiceUserAvailable. And/or I could imagine going a
step further and provide a ServiceResourceResolverFactory (an
interface with a single method "createResourceResolver(Map authInfo)"
or maybe a second one with no args for convenience). A consumer would
inject the ServiceResourceResolverFactory instead of a
ResourceResolverFactory. The @Reference target filter could optionally
indicate a subservice name.

Please feel free to rip this apart or improve on it! ;)

Regards
Julian


On Thu, May 11, 2017 at 10:49 AM, Bertrand Delacretaz
<bd...@apache.org> wrote:
> Hi,
>
> On Thu, May 11, 2017 at 9:39 AM, Carsten Ziegeler <cz...@apache.org> wrote:
>> ...Service users are a very low level
>> configuration of the data store and we could assume that this is
>> correctly configured - as well as the mapping...
>
> I think the main goal of ServiceUserMapped is to have components wait
> at startup until the mappings (+ service users but that doesn't work)
> are available.
>
> So "configuration is correct" is just part of the deal.
>
> How about having the code that registers the ServiceUserMapped markers
> wait for the SlingRepository service?
>
> If service users are registered via repoinit, waiting for
> SlingRepository waits for all of them, assuming the configuration is
> correct. And if not those services will generally fail loudly.
>
> -Bertrand

Re: Revisiting ServiceUserMapped

Posted by Carsten Ziegeler <cz...@apache.org>.
Bertrand Delacretaz wrote
> Hi,
> 
> On Thu, May 11, 2017 at 9:39 AM, Carsten Ziegeler <cz...@apache.org> wrote:
>> ...Service users are a very low level
>> configuration of the data store and we could assume that this is
>> correctly configured - as well as the mapping...
> 
> I think the main goal of ServiceUserMapped is to have components wait
> at startup until the mappings (+ service users but that doesn't work)
> are available.
> 
> So "configuration is correct" is just part of the deal.
> 
> How about having the code that registers the ServiceUserMapped markers
> wait for the SlingRepository service?

I don't think this is necessary as the code using a service user either
depends on the resource resolver factory or the sling repository
service. Otherwise it can't use the service user anyway.

Carsten

> 
> If service users are registered via repoinit, waiting for
> SlingRepository waits for all of them, assuming the configuration is
> correct. And if not those services will generally fail loudly.
> 
> -Bertrand
> 


 

-- 
Carsten Ziegeler
Adobe Research Switzerland
cziegeler@apache.org

Re: Revisiting ServiceUserMapped

Posted by Bertrand Delacretaz <bd...@apache.org>.
Hi,

On Thu, May 11, 2017 at 9:39 AM, Carsten Ziegeler <cz...@apache.org> wrote:
> ...Service users are a very low level
> configuration of the data store and we could assume that this is
> correctly configured - as well as the mapping...

I think the main goal of ServiceUserMapped is to have components wait
at startup until the mappings (+ service users but that doesn't work)
are available.

So "configuration is correct" is just part of the deal.

How about having the code that registers the ServiceUserMapped markers
wait for the SlingRepository service?

If service users are registered via repoinit, waiting for
SlingRepository waits for all of them, assuming the configuration is
correct. And if not those services will generally fail loudly.

-Bertrand

Re: Revisiting ServiceUserMapped

Posted by Timothee Maret <tm...@apache.org>.
Hi Carsten,

2017-05-11 9:39 GMT+02:00 Carsten Ziegeler <cz...@apache.org>:

> From the few responses in this thread I have the feeling that the
> preference is on implementing this correctly.
>
> However, we're still lacking a good idea on how exactly to implement this.
>
> Now, I think it is not a good idea to expose each and every service user
> as a service in the service registry. I don't want to make that
> information generally available. But then the question is how can the
> service user mapper implementation find out about this?
>
> The other option we have is to accept that this is not worth the effort
> and we simply remove the ServiceUserMapped support (deprecate it and
> remove the usage in Sling). Service users are a very low level
> configuration of the data store and we could assume that this is
> correctly configured - as well as the mapping.
>

I think deprecating makes sense, indeed service users seem rather like
configurations than resources to be managed during the app runtime.

Also, if a component still needs to detect this miss configuration upon
activation, it could still do it by explicitly invoking
ServiceUserMapper#getServiceUserID.

Regards,

Timothee


>
> Thoughts?
>
> Regards
> Carsten
> --
> Carsten Ziegeler
> Adobe Research Switzerland
> cziegeler@apache.org
>

Re: Revisiting ServiceUserMapped

Posted by Carsten Ziegeler <cz...@apache.org>.
Konrad Windszus wrote
> There is indeed a very valid use case for ServiceUserMapped and that is using the service resolver in the activate() method.
> If the configuration or system user is not available at that point, the activate() fails with an exception and the component is never being restarted (even if at a later point in time both configuration and the bound system user is there).

That's true - but even if ServiceUserMapped is available it gives you
zero guarantee that the service user is really registered in the
repository. So your component can still fail and never gets activated.

Right now this works under the assumption that all service users are
there when the repository starts. But thats a faulty assumption. Or if
people think it's a valid one, I can argue that the assumption of
configurations being there holds true as well. In which case the
ServiceUserMapped service is not needed.

> This functionality is IMHO crucial, because at least during development it could be that the configuration mapping is not yet provided when the service would be first started. Just failing once and never retry again, is IMHO against all OSGi services practice. So having an explicit dependency against that feels right.

Ok, so I could argue that we make production difficult to make
development easy :)

> If it is too complicated to check for the existence of the service user we could at least keep the current dependency, which enforces that the service is not started until at least the configuration is available. This is very helpful and should not be removed.

This is were I don't agree as it provides a wrong perception.

 Regards

Carsten

-- 
Carsten Ziegeler
Adobe Research Switzerland
cziegeler@apache.org

Re: Revisiting ServiceUserMapped

Posted by Konrad Windszus <ko...@gmx.de>.
There is indeed a very valid use case for ServiceUserMapped and that is using the service resolver in the activate() method.
If the configuration or system user is not available at that point, the activate() fails with an exception and the component is never being restarted (even if at a later point in time both configuration and the bound system user is there).
This functionality is IMHO crucial, because at least during development it could be that the configuration mapping is not yet provided when the service would be first started. Just failing once and never retry again, is IMHO against all OSGi services practice. So having an explicit dependency against that feels right.
If it is too complicated to check for the existence of the service user we could at least keep the current dependency, which enforces that the service is not started until at least the configuration is available. This is very helpful and should not be removed.
Konrad


> On 11. May 2017, at 09:39, Carsten Ziegeler <cz...@apache.org> wrote:
> 
> From the few responses in this thread I have the feeling that the
> preference is on implementing this correctly.
> 
> However, we're still lacking a good idea on how exactly to implement this.
> 
> Now, I think it is not a good idea to expose each and every service user
> as a service in the service registry. I don't want to make that
> information generally available. But then the question is how can the
> service user mapper implementation find out about this?
> 
> The other option we have is to accept that this is not worth the effort
> and we simply remove the ServiceUserMapped support (deprecate it and
> remove the usage in Sling). Service users are a very low level
> configuration of the data store and we could assume that this is
> correctly configured - as well as the mapping.
> 
> Thoughts?
> 
> Regards
> Carsten
> -- 
> Carsten Ziegeler
> Adobe Research Switzerland
> cziegeler@apache.org


Re: Revisiting ServiceUserMapped

Posted by Carsten Ziegeler <cz...@apache.org>.
From the few responses in this thread I have the feeling that the
preference is on implementing this correctly.

However, we're still lacking a good idea on how exactly to implement this.

Now, I think it is not a good idea to expose each and every service user
as a service in the service registry. I don't want to make that
information generally available. But then the question is how can the
service user mapper implementation find out about this?

The other option we have is to accept that this is not worth the effort
and we simply remove the ServiceUserMapped support (deprecate it and
remove the usage in Sling). Service users are a very low level
configuration of the data store and we could assume that this is
correctly configured - as well as the mapping.

Thoughts?

Regards
Carsten
-- 
Carsten Ziegeler
Adobe Research Switzerland
cziegeler@apache.org

Re: Revisiting ServiceUserMapped

Posted by Carsten Ziegeler <cz...@apache.org>.
Robert Munteanu wrote
> On Tue, 2017-05-09 at 09:41 +0200, Oliver Lietz wrote:
>>> There is the assumption that if such a mapping is available the
>>> underlying service user is available as well - which unfortunately
>>> is
>>> wrong. In this sense we could also remove the whole concept again
>>> and
>>> simply assume that if the JCR resource provider is available, the
>>> service user is created. It's the same shaky assumption but just
>>> simpler :)
>>
>> AFAIR (I'm on holidays and have no time to check) the mapping is
>> registered 
>> only when the service/system user is present. I had problems in
>> integration 
>> tests where system users materialized after service user mapping
>> config was 
>> processed and they failed.
> 
> Looking at the code I don't see this happening.
> 

I don't think so either - if you wait for the mapping configuration by
having a dependency your component might be activated later which by
chance solves the problem. But there is no guarantee atm

Regards
Carsten

> I agree that we should make it work properly.
> 
> Robert
> 


 

-- 
Carsten Ziegeler
Adobe Research Switzerland
cziegeler@apache.org

Re: Revisiting ServiceUserMapped

Posted by Carsten Ziegeler <cz...@apache.org>.
Carsten Ziegeler wrote
> Robert Munteanu wrote
>> On Tue, 2017-05-09 at 09:41 +0200, Oliver Lietz wrote:
>>>> There is the assumption that if such a mapping is available the
>>>> underlying service user is available as well - which unfortunately
>>>> is
>>>> wrong. In this sense we could also remove the whole concept again
>>>> and
>>>> simply assume that if the JCR resource provider is available, the
>>>> service user is created. It's the same shaky assumption but just
>>>> simpler :)
>>>
>>> AFAIR (I'm on holidays and have no time to check) the mapping is
>>> registered 
>>> only when the service/system user is present. I had problems in
>>> integration 
>>> tests where system users materialized after service user mapping
>>> config was 
>>> processed and they failed.
>>
>> Looking at the code I don't see this happening.
>>
>> I agree that we should make it work properly.
>>
> 
> I think most of what I suggested can easily be implemented, the
> main question is how can the service user implementation find out
> which service users exist?
> A provider could announce this by registering services but then
> these services need to be associated with the given resource provider.
> (Which of course is doable). Or we could add new API with something
> like a boolean method asking for existence of a service user.
> 

One way of doing it is lazy registration of a "service user service".
The jcr resource provider implementation could register service hooks.
If now the service user mapper bundle is looking for a "service user
service" for the jcr resource provider with a given name, the hook can
query the user manager for the existence of such a user and if so
dynamically register it.
Or the jcr resource provider keeps track of all available service users
and register such a service.
Other resource providers requiring authentication would do something
similar.

Carsten

 

-- 
Carsten Ziegeler
Adobe Research Switzerland
cziegeler@apache.org

Re: Revisiting ServiceUserMapped

Posted by Carsten Ziegeler <cz...@apache.org>.
Robert Munteanu wrote
> On Tue, 2017-05-09 at 09:41 +0200, Oliver Lietz wrote:
>>> There is the assumption that if such a mapping is available the
>>> underlying service user is available as well - which unfortunately
>>> is
>>> wrong. In this sense we could also remove the whole concept again
>>> and
>>> simply assume that if the JCR resource provider is available, the
>>> service user is created. It's the same shaky assumption but just
>>> simpler :)
>>
>> AFAIR (I'm on holidays and have no time to check) the mapping is
>> registered 
>> only when the service/system user is present. I had problems in
>> integration 
>> tests where system users materialized after service user mapping
>> config was 
>> processed and they failed.
> 
> Looking at the code I don't see this happening.
> 
> I agree that we should make it work properly.
> 

I think most of what I suggested can easily be implemented, the
main question is how can the service user implementation find out
which service users exist?
A provider could announce this by registering services but then
these services need to be associated with the given resource provider.
(Which of course is doable). Or we could add new API with something
like a boolean method asking for existence of a service user.

Carsten

 

-- 
Carsten Ziegeler
Adobe Research Switzerland
cziegeler@apache.org

Re: Revisiting ServiceUserMapped

Posted by Robert Munteanu <ro...@apache.org>.
On Tue, 2017-05-09 at 09:41 +0200, Oliver Lietz wrote:
> > There is the assumption that if such a mapping is available the
> > underlying service user is available as well - which unfortunately
> > is
> > wrong. In this sense we could also remove the whole concept again
> > and
> > simply assume that if the JCR resource provider is available, the
> > service user is created. It's the same shaky assumption but just
> > simpler :)
> 
> AFAIR (I'm on holidays and have no time to check) the mapping is
> registered 
> only when the service/system user is present. I had problems in
> integration 
> tests where system users materialized after service user mapping
> config was 
> processed and they failed.

Looking at the code I don't see this happening.

I agree that we should make it work properly.

Robert

Re: Revisiting ServiceUserMapped

Posted by Oliver Lietz <ap...@oliverlietz.de>.
On Tuesday 09 May 2017 07:31:53 Carsten Ziegeler wrote:
> While working on the "configurationless" Sling, I noticed that the
> ServiceUserMapped concept does not only create problems with zero
> configurations but is also not working as expected. Right now, it
> creates a false sense of safety.
> 
> It is a good idea to express the requirement of a component to use a
> specific service user as a dependency to a service registered in the
> service registry. Therefore we created the ServiceUserMapped. However as
> the name already applies, the existence of this service only means that
> a *mapping* is available. It does not express whether the underlying
> *service user* is available. Therefore the whole mechanism is creating
> this false sense of safety and in reality does not provide the wanted value.
> 
> There is the assumption that if such a mapping is available the
> underlying service user is available as well - which unfortunately is
> wrong. In this sense we could also remove the whole concept again and
> simply assume that if the JCR resource provider is available, the
> service user is created. It's the same shaky assumption but just simpler :)

AFAIR (I'm on holidays and have no time to check) the mapping is registered 
only when the service/system user is present. I had problems in integration 
tests where system users materialized after service user mapping config was 
processed and they failed.

> Or we could try to make this work as expected. Now, a component using a
> service user does not know which service user it will use as this is
> configured in the mapping. I think this decoupling is a good idea.
> Therefore the current dependency to a ServiceUserMapped is a good thing.
> (Although the current use of @Reference in many places could be improved
> to what we have now in the code - but that's OT for this thread).
> 
> However, the automatic registration of the ServiceUserMapped service
> just due to the existence of a mapping configuration is the part which
> is wrong. In addition, we have to keep in mind that we might have many
> resource providers not just one which is using service users.
> Fortunately there are resource providers not requiring authentication
> and these can be used without the existence of a service user. Taking
> this into account, a resource provider using authentication should
> announce which service users it knows, our implementation of the service
> user mapper compares the mapping configuration with the existence of
> service users in *all* resource providers requiring authentication and
> if each of them provides such a service user, it will register the
> ServiceUserMapped. Similar of no resource provider requires
> authentication, the ServiceUserMapped can be registered as well.
> 
> This will bring us a working and reliable solution and in addition
> solves the configurationless part as well - for example if you only have
> the file resource provider, the ServiceUserMapped can be registered and
> no additional configuration is required.
> 
> There is one neglectable "problem" with this approach. It assumes that
> potentially the requested service user will access all (authenticated)
> resource providers while in practice it might be the case that only one
> is hit.
> 
> So, to keep the long story short: either we remove the ServiceUserMapped
> concept or we do it right. The way it is today is not really solving the
> problems it should.

+1 for doing it right

Regards,
O.

> Regards
> Carsten