eclipse-archived / smarthome

Eclipse SmartHome™ project
https://www.eclipse.org/smarthome/
Eclipse Public License 2.0
862 stars 783 forks source link

Add support for conditional access based on user role #579

Open kaikreuzer opened 8 years ago

kaikreuzer commented 8 years ago

migrated from Bugzilla #423548 status NEW severity enhancement in component Core for --- Reported in version unspecified on platform PC Assigned to: Project Inbox

On 2013-12-08 15:16:18 -0500, Kai Kreuzer wrote:

Migrated from https://code.google.com/p/openhab/issues/detail?id=387

On 2015-09-25 03:52:04 -0400, Kai Kreuzer wrote:

Some input from my side what I see should be covered. There are multiple levels of access control that can be addressed:

  1. Global access control as it is done in openHAB 1 (see https://github.com/openhab/openhab/wiki/Security#authentication). I.e. for any access to the runtime, the user needs credentials and is then assigned a role. JAAS is probably a good option here. Note that the solution has to work in general for any OSGi HttpService, it must not be specific to Jetty (while in openHAB 2, we can add a Jetty-specific configuration for JAAS then).
  2. Restrict certain urls and/or http verbs for certain roles. See the example discussed in https://www.eclipse.org/forums/index.php/t/1068387/.
  3. Restrict access on certain data, e.g. return a HTTP 403 when my kids try to access localhost:8080/classicui/app?sitemap=admin. This could be implemented in phases, the most important resource would be sitemaps, then come items, things, rules, etc. But in general this mechanism should be available on all resources. Configuration of such restrictions should not only be by resource name, but possibly also by type/tag, e.g. do not grant access to any item that is tagged as "security".
  4. Filter data within requests, i.e. if I do not have rights for sitemap "admin" (see 3), the REST url /rest/sitemaps should not even list it. Sitemaps that refer to items that I am not allowed to access should filter out these widgets automatically.
  5. Check implications on automation rules. Normally, rules are executed by the system and not the user. But we could imagine that a trigger was caused by some user (e.g. an item state change) and thus the rule could be regarded to be executed on behalf of this user - then again, the permissions should be checked and e.g. sending commands to restricted items must be blocked.

Does anybody has further ideas/requirements?

kaikreuzer commented 6 years ago

Thanks you all for your engagement and motivation to help on this - I am looking forward to our call this afternoon.

To make it effective (as one hour can quickly pass when discussing details), I would suggest to break it down into smaller parts and only start with discussing the technical architecture for fundamental first parts.

I think @jochenhiller has a very valid point about RBAC: If you read the issue title at the top, this was actually the original requirement - and I think it would reduce the complexity immensely if we start looking at that. My goal would be that we manage to sketch out and implement the AUTHENTICATION part, which results in a token being present in the framework that holds at least user/role information and that can later be used for AUTHORISATION. If the first prototype is capable of differentiating between admins and users (as it is already started in the REST API), this would be good start already.

Getting the authentication in place is hugely complex in itself, so I hope we can focus on this and find a decent solution. I'd like to point out again to my comment above that work had already been done in this respect and there are some initial ESH APIs and that I nonetheless failed to get even the simplest login/authentication working so far...

marziman commented 6 years ago

Hello to all,

also thanks from my side! Great stuff came together.

And as always terms and namings have changed. So if you look at the initial ZIP from our side there you will find:

4 Role Management Roles manage permissions. Roles might be defined and permissions might be attached to a Role, e.g. Rolename: Lighting, permission: turn light xy on/off

I think it is clear to all in this topic that we need role based access. It was even mentioned as requirement and I think @jmsjones during the merging it just got lost somehow. We should be careful with naming and details.

@kaikreuzer as much as I agree with many of your points and feel your pain from failing with a basic login/auth, I would stick with: Think Big, Start Small. We have many heads here in this discussion and all will invest energy to take over some implementation work, after we agreed on the big picture and core reuqirements and concepts. I would not risk to quickly implement on part as prototype and put other stuffs into second line. Maybe later people dont have time to support, since we only dig into one part e.g. AUTHENTICATON. At later time, if we come back we might not get all parts smoothly together and end up with chaos and hardly connectable parts. I would like to avoid that, and propose also to focus on the core requirements and concepts.

Everything here in this thread is complex ;-) So it is much more about having the big picture, agreeing on requirements and the concepts and finally spread work between people.

Important: It is not important to clearify every aspect and requirement in detail, rather than focusing on the big enabler concepts, which allow the rest to follow.

BR Mehmet

kaikreuzer commented 6 years ago

Think Big, Start Small.

Right, that's why we have gathered the requirements, so all of those should be the in the back of our heads when talking about a possible architecture. I just want to avoid that we lose time in discussing details on too many ends as this is always the risk, if everything is in scope of a discussion.

What is your expected outcome after the call? Do you have a suggested agenda? I doubt that we will manage to have a final agreement on all required interfaces and data models, so that everybody could go off and start implementing the different parts independently and it would be a pity to just have discussed all the listed requirements without having taken any decisions wrt the architecture in the end.

splatch commented 6 years ago

I think based on gathered requirements we will need to choose most important which needs to be there to start any work - either design and later implementation and discuss what parts needs to be taken into consideration so we leave framework still "open for extension" after initial contribution will be finished.

Once we define base we would like to work on we can focus on supplying a necessary infrastructure for community to continue work on edges interested by different parties.

My proposal is to keep focus on following items today:

These three items are still fairly generic, thus we need to pay attention to not dive too much into implementation details. Lets start small while thinking big. ;-)

kaikreuzer commented 6 years ago

@splatch As you are the author of this API, is it something you think is completely outdated or should it be a seed to build upon and to include in the discussion?

splatch commented 6 years ago

As you are the author of this API, is it something you think is completely outdated or should it be a seed to build upon and to include in the discussion?

It is up to discussion - earlier attempt did not have control over authorization part (this was delegated to jaxr-rs) and few other important drawbacks - ie lack of servlet level security, plus it was unable to be switched on or off - literally it was always on globally for all resources.

If we will manage to define where to put authorization part we could potentially keep it. However, I am not married with it and, we can start from scratch especially that code is already over a year old.

antoniosv commented 6 years ago

Sorry I could not stay until the end of the call! Up to the point I was present though, it seemed to me the focus is going first towards authentication, both local and through external providers (e.g. Google/Facebook). ESH should have the interfaces so the actual implementations of the authorization handlers can be plugged in, is this correct? However, quoting @JochenHiller's earlier post:

I agree entirely with these points, and I feel they could serve as one milestone. Perhaps one of the problems faced in the abstraction is generalizing the interfaces so that many handlers can be used interchangeably. For example, the JWT created by local authentication may contain a field with all the roles that the user has, but perhaps OAuth2 doesn't include this field. But this seems to be more related to authorization, anyway.

I feel what was lacking in the discussion is how much of @splatch's code can be reused and how much needs to be changed according to the current list of requirements. I am also slightly bothered about using the terms "roles" and "user groups" in the document interchangeably, they are conceptually very different! Someone did mention that future efforts could proceed in smaller working groups, and if so, I'd like to take part as well!

marziman commented 6 years ago

Hello @splatch , @JochenHiller , @kaikreuzer , @jmsjones & @HeikoScholtes ,

I ve taken the notes written by Lukasz and added our (Heiko & me) notes and merged it together. Can you please look if this is correct and that we havent missed an important point from the meeting? I ve also extended @splatch notes with a "ToDo" section, where I tought it makes sense to also name people for some topics (even if everybody is free to join the train) to make it more concrete and push the next steps. If you feel uncomfortable or see something as wrong, let us know.

https://docs.google.com/document/d/11vHlUwFbeFOnzE9pJYdpf2cJgnutA2qOVP6Dp8jN4Xw/edit?usp=sharing

Feedback is welcome. We are looking forward to tackle this more detailed with you guys.

BR Heiko & Mehmet

kirantpatil commented 6 years ago

Hi,

Any timeline about test(Beta) release ?

Thanks.

On Thu, Feb 22, 2018 at 2:13 AM, Mehmet Arziman notifications@github.com wrote:

Hello @splatch https://github.com/splatch , @JochenHiller https://github.com/jochenhiller , @kaikreuzer https://github.com/kaikreuzer , @jmsjones https://github.com/jmsjones & @HeikoScholtes https://github.com/heikoscholtes ,

I ve taken the notes written by Lukasz and added our (Heiko & me) notes and merged it together. Can you please look if this is correct and that we havent missed an important point from the meeting? I ve also extended @splatch https://github.com/splatch notes with a "ToDo" section, where I tought it makes sense to also name people for some topics (even if everybody is free to join the train) to make it more concrete and push the next steps. If you feel uncomfortable or see something as wrong, let us know.

https://docs.google.com/document/d/11vHlUwFbeFOnzE9pJYdpf2cJgnutA 2qOVP6Dp8jN4Xw/edit?usp=sharing

Feedback is welcome. We are looking forward to tackle this more detailed with you guys.

BR Heiko & Mehmet

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/eclipse/smarthome/issues/579#issuecomment-367465564, or mute the thread https://github.com/notifications/unsubscribe-auth/ABH5xwfceFS9bFnebNrX_VHBKHFF2Gw0ks5tXH_0gaJpZM4Gt3ya .

kaikreuzer commented 6 years ago

Many thanks @marziman, the notes look good to me. @splatch Will you take the lead on the next steps regarding the embedded API side?

splatch commented 6 years ago

Hey, I been stuck in other project. Im back to life from next week. Looking forward to get back on it.

jmsjones commented 6 years ago

I haven't had much time to commit to this lately, but I have been considering a number of implementation options. I have started adding information to the Google Doc to reflect what I view as a viable design. The leading access control paradigm discussed so far is Role Based Access Control (RBAC). I believe Attribute Based Access Control (ABAC, also referred to as Policy Based Access Control) is a better fit for the requirements that have been established.

marziman commented 6 years ago

Hello @splatch, @kaikreuzer, @HeikoScholtes, @antoniosv & jmsjones,

can we please agree to not let this hang around? We should also avoid to add stuff to multiple documents..Just to avoid we loose good ideas and input.

Lets try to get this into a „doing“ mode instead to stay too long on theory. Simce we might need to switch approaches if we find blockers. We will actively design and implement the ToDos on our side.

@splatch this is a small ping :-)

Hope you can find time to tackle the ESH embedded part of it, while @JochenHiller, @HeikoScholtes and me we will be more or less around cloud side (ohcloud etc.)

Thx & BR Mehmet

splatch commented 6 years ago

Hey Mehmet, Thanks for reminder. I been sniffing around OSGi 4.2 issue lately (let's call it this way), and there are certain trade offs which needs to be paid.

There is no support for filter registrations in this version of specification. This means that the only way to get filters working with current smarthome environment is to register an internal proxy servlet which will dispatch requests and also provide a way to have a filter chain execution. Even if we decide to not go with filters, there is still requirement to secure other servlets (ie. icons servlet). We need to "intercept" request for that and only one repeatable way which I know is via something like a wrapper servlet. It is doable, but I am not sure how many rabbit holes we will get (especially with class loading). This version of specification is already 9 or at least 8 years old (September 2009/March 2010). It would be good to not tie down more modern runtimes to that old spec.

I gonna revisit current approach of servlet registration and see if we can cheat old spec to get more verve. I will do a small PoC aside of ESH to show approach and then we can decide if its applicable for project and all known runtimes.

Cheers, Lukasz

antoniosv commented 6 years ago

I've been looking into how token-based authentication can be used in the OSGi architecture. I've been trying out isolated examples here and there, but due to the complexity of ESH, it's a tough cookie to put it all together. Additionally, the idea of putting in only abstractions to leave open any 3rd party implementations makes it a bit more difficult to swallow. So far as I have observed, this post's answer hits the nail to what it is intended to be accomplished here. I'll keep trying to figure a way on how to put the pieces together to make it work. Meanwhile, I have a couple of questions:

Looking at the current implementation of basic authentication (username:password in http request header), it looks like it could be extended to other types of authentication, but since this approach couldn't be used successfully for OH2, what pitfalls would need to be avoided in an alternative solution?

Thank you for your time, guys. =)

maggu2810 commented 6 years ago

As stated already in another issue I already use JWT in an ESH based product.

For the authorization and authentication I use two separate classes both implementing the ContainerRequestFilter. Both classes are annotated with Provider and use the respective Priority of Priorities.

An SecurityContext is set for the ContainerRequestContext.

I also added some utility methods and interfaces so the code that checks the privileges does not depend on the special implementation. The methods uses the SecurityContext that is injected into the REST resource implementation class for the current handled call using the Context annotation.

So, e.g. if items should be read, I use an "AuthenticationManagerCollector" that is injected by a DS reference that implements the method: boolean canReadItem(SecurityContext securityContext, Item item) The collector itself is a service that collects all AuthenticationManager that provide such methods and checks if at least on allows / forbids the access.

The REST resource implementation for "get all items" can so simple filter the result for only the ones that are readable by the caller:

final Stream<EnrichedItemDTO> itemStream = getItems(type, tags).stream()
    .filter(item -> amc.canReadItem(securityContext, item))
    .map(item -> EnrichedItemDTOMapper.map(bc, item, recursive, uriInfo.getBaseUri(), locale));
antoniosv commented 6 years ago

@maggu2810 Thank you! Could you make a reference to that issue so I can take a deeper look at your approach?

maggu2810 commented 6 years ago

@antoniosv The "another issue" I talk about only contains the information that I used a JWT based implementation, it does not bring any useful information (https://github.com/eclipse/smarthome/issues/3113#issuecomment-331883697)

antoniosv commented 6 years ago

As Issue #2620 got closed, I'll repost this:

I'm having the opposite problem as @maggu2810 . I would like to be denied access to, say, rest/things/items when I use curl without the headers of basic-authentication. However, all requests go through even though the endpoint things/items is annotated by @RolesAllowed({ Role.ADMIN }). I'm guessing that, at some point, basic authentication was disabled, but what was changed?

Edit: After much fiddling on my own, I figured out this happened because the com.eclipsesource.jaxrs.provider.security plugin was not selected from the run configuration in Eclipse.

splatch commented 6 years ago

Hey, Over past couple of weeks I been walking around this topic and looking for a way to remove blocking element which is lack of filter support in OSGi 4.2. Please check below document where I describe simple approach based on whiteboard pattern which will allow to host compatibilty layer for runtime used in commercial products. Such layer will not be necessary for openhab which runs on newer versions of OSGI spec: https://docs.google.com/document/d/1zTk_GKC4QRmeu9saEfaWbvMZJJRB_ExPyOZdd2hA8vQ/edit?usp=sharing

I am aware that its quite difficult to move on with existing runtime which is used. Implementation of solution does not take a lot of code and will work with any http service implementation. All it does is just wrapping of registered servlet. I started doing some prototype implementation which I will be able to publish in coming week (or weeks).

Cheers, Lukasz

splatch commented 6 years ago

Last week I spoke with @antoniosv and we made some progress. Antonio was evaluating possibility to implement basic security checks with http context. We agreed ge will continue with his work and see if it will be possible to implement JWT checks there. It seems to be easiest solution which will be portable between multiple osgi specification versions.

Inspired by his findings I started looking once again in jaxrs connector and found an element which makes possible to inject http context to wrap jersey servlet. I have no idea how I missed such nice extension point. There is no need to add any "compatibility layer" described above, its just sufficient to implement this SPI in order to have place for "preflight" checks.

I also started checking servlet registrations in ESH and, with additional OSGi 4.2 http context injection, it is possible to share authorization logic in there. I got some basic code working but some UIs are registered in quite complicated way (comevisu, paperui, dashboard - they wrap servlet in service). My preliminary assumption was to use base servlet to grab HttpService and HttpContext and close servlet registration in one place, however there are some implications (ie. DS annotations inheritance etc). For now - I managed to port basicui and classicui.

I will submit later PR for review because above improvements is first step in getting this issue resolved.

marziman commented 6 years ago

@antoniosv & @splatch,

lets make a meeting and discuss the new findings and synchronize. We can also share our ideas around this topics, revisit the points from the protocol after our meeting.

Would be great and maybe a good time to check, where we stand and how to proceed to get the „must haves“.

BR Mehmet

splatch commented 6 years ago

Code which allows to use shared http context is in place: https://github.com/Code-House/smarthome/commits/esh-authz2

Now we have to provide HttpContext#handleSecurity(request,response) logic. I attempted to provide support for servlet filters, however without registering own dispatcher servlet at context root(/*) it will not work. Servlet filters are dead end for now.

I will focus now on making authentication switch and some way to bridge request to authneticators.

Cheers, Lukasz

antoniosv commented 6 years ago

I have written some code for the HttpContext#handleSecurity(request,response) logic. I'm making use of the Nimbus JOSE+JWT library to create and verify tokens using a RSA key. For the UI, I'm storing the JWT as a cookie. The logic I have implemented is as follows:

  1. Check if authorization header or cookie is there (if not, return forbidden)
  2. Attempt to do JWT Authentication with auth. header first: parse authorization header to get type of Authorization type. If it's Bearer type, then extract the token and verify it.
  3. If there was no token in the header, but there is a cookie present, take the cookie as token and try to verify it.
  4. If there was no cookie and the auth. header wasn't of type Bearer, fallback to Basic authentication. If successful, allow access and generate a JWT that is stored as a cookie.
  5. Further requests will have the cookie included.

It would be very nice if I could set up a login page instead of relying on Basic authentication for this. I will try to get the code up somewhere ASAP. My code works for simple servlets, I haven't yet attempted to make it work with REST endpoints with the changes that Lukasz has been doing .

splatch commented 6 years ago

Yeah, there is a need to bridge authenticators and http context, I made some scratch around that, but haven't finished it yet. I should get some plumbing done next week.

veotax commented 6 years ago

Personally, I recommend: jCasbin, which is an authorization library that supports models like ACL, RBAC, ABAC.

Related to RBAC, jCasbin has several advantages:

  1. roles can be cascaded, aka roles can have roles.
  2. support resource roles, so users have their roles and resource have their roles too. role = group here.
  3. the permission assignments (or policy in jCasbin's language) can be persisted in files or database.
  4. multiple models like ACL, BLP, RBAC, ABAC, RESTful are supported.

And you can even customize your own access control model, for example, mix RBAC and ABAC together by using roles and attributes at the same time. It's very flexible.

kirantpatil commented 6 years ago

Hi @splatch @marziman, any updates on this issue ?

Thanks.

splatch commented 6 years ago

@veotax I will speak on behalf of myself, but I think ESH policy is quite simple - it does not force any specific security framework. If you would like to provide a jcasbin backed security layer (based on SPI which is in works) - you are free to do that.

@kirantpatil - I submitted for review first PR which covers infrastructure level security.

Bagunda commented 5 years ago

Do we have pass authentication for general page?