Custom roles and permissions

Hi,

I’m with openHAB 5.1.3 on OpenBSD amd64.

as far as I researched, it’s not possible to manage custom roles for users in karaf console, as it’s still an open enhancement request: Add/remove user roles via karaf console · Issue #2453 · openhab/openhab-core · GitHub

but I found I can edit:
vi /var/db/openhab/jsondb/users.json

and just add multiple roles to the array alike:
`“roles”: [“administrator”,“parent”],`
And then in karaf console they are shown:

openhab> openhab:users list
sebastia (administrator, parent)
test1 (child, user)
test2 (parent, user)

I found that at least user or administrator role are necessary, but then can add more roles to each user. So I have to combine my custom “parent” and “child” with “user” role.

So far so good. In the Pages, I can use:

visibleTo:
- role:parent

to hide elements from children. that’s nice.

The default Overview page renders my locations with equipment semantically, and as far as I figured up to now, I can only hide the complete overview page.
I haven’t found a way to for example hide some of the equipments, or make them read-only.

Can I do this in the overview page, or at the item or in the model?

When I create a custom page, and I have controls, which for parents I want to have usable, but for children, I’d like to have them read-only, because they may show a current state.
Is that something I could achieve?

cheers,
Sebastian

You can hide them at the Item/Widget level. To hide them in the tabs of the Overview page you go to the Item you don’t want to appear, click “Add metadata to Item” and select “default list item widget”. There you can change the widget that will be shown in the cards on the Overview page. At the bottom you’ll find the “visible” and “visible to” fields.

However, I don’t know if the list for the “visible to” field will pick up your custom roles or not. If not you can just select “admin” and then opn the code tab and manually add your parent role or what ever.

Note that the “visible” field will take an expression so, for example, you can hide a widgetbased on the state of Items or such.

For custom pages, one good approach is to add a “default stand alone widget” to the Equipment Group. Then you can just add the Equipment to the page and that is the widget that will be used.

Having widgets visible but read only for users of certain roles will probably require quite a bit of complicated expressions. But the user role is avaialble to the widget expressions so that should be doable. It might be sufficient to change the action usign an expression and ahve it set a variable for teh kids role and do the real action for the parent’s role.

But if you want to actually change the widget entirely it might be easier to create two widgets for your custom page, one read only and one interactive and use the visible to fields to hide one or the other based on the logged in role.

Or just create two separate pages and hide the pages based on the roles.

Hi Rich,

the hint with the “Add Metadata” → “Default List Item Widget” was the missing piece.

In the visible: I tried alike:

visible: =device.clientInfo.roles.includes(‘parent’)

but that didn’t work out. “Visible only to” only allowed me to select between “Administrator” and “User”. It doesn’t seem to be aware of my custom roles or groups.

But switching from “Config” to “Code” Tab, I was able to:

value: " "
config:
visibleTo:
- role: parent

and that worked like a charm.

There are a few devices I definitely don’t want kinds to tinker with, and being able to hide them this way is exctly what I was looking for.

Now also found this: User Interface Design Overview | Documentation Preview

For my kids at home, totally fine, but wouldn’t use this in something more public then :wink:

thanks,

Sebastian

According to the docs the expression would be

visible: '=user.roles.includes("parent")'

Note the quotes around the expression are required. And I think using user over device is more flexible and will work no matter what client is used to access MainUI.

Indeed. Visiblity is merely cosmetic. All the Items are avaiable through the REST API. Someone who knows OH or is even a little bit determined can access and command any Item.

I’m not suggesting that this makes it somehow “secure”, but almost all the REST endpoints require admin privileges. You specify the level required when you declare the endpoint, and it seems to me that this is mostly just copied without more reflection, so that I’ve only seen a very few that doesn’t require admin privileges.

yes, just confirming above snippet also works.

Items do not.

Those endpoints required for sitemaps and MainUI to provide the user facing stuff are available to the “user” role.

The point is that access is to all Items. Any user logged in with the “user” role can access and send command to any and all Items. If the implicit user role is enabled, anyone who can access openHAB on the network whether they are logged in or not can access and send command to any and all Items.

Setting the visibility of an Item’s widget so only the admin role can see it does not prevent someone with a user role accessing the Item. It just hides the UI widget from the Page or sitemap.

I know there have been attempts at RBAC but I haven’t been following it very closely.

Just reading this discussion here made me think of an idea:

Each item can have a special metadata, e.g. users and/or groups + access (read, or read/write). Those without this metadata are accessible by all. Then the rest endpoints can simply apply filtering in core.

Would that work?

As far as I can remember, there have been at least three attempts at RBAC. The first two were academic papers and they followed exactly that approach, with some changes to core to control whether or not to access them. Unfortunately, once they wrote their papers they lost insterest and never even attempted a PR.

The third attemp is still an open PR but I admit I’ve not followed the overall approach that closely. I can’t seem to find the PR now, maybe it became closed as abandonded? :person_shrugging:

As for whether that would work, I imagine it could meet at least some use cases. It gets complicated if you really want to lock it down though. For example, let’s say you have a widget that has as it’s action a direct invocation of a rule. That rule gets the states of Items and commands some Items. Should that be filtered?

The event stream would need to be filtered too I imagine.

What’s the impact on sitemaps?

None of this is impossible or particularly hard but something seems to keep getting in the way of a complete PR.

Yeah, just to confirm, I just stumbled upon this “Implicit User Role” issue as well. That when logged on anonymously, my otherwise hidden equipment for a “child” account was suddenly visible.

Disabling the “Implicit User Role” helped, and works for me.

Sebastian

Yes thanks for pointing that out. For backwards compat, allow all. Add extra rule properties similar to the item metadata (or invent rule metadata?). Then filter the rule execution at the REST boundary similar to item command user/group filtering.

Are there any other points that need to be restricted?

The oh-repeater card will need a look to make sure it handles not being able to access Items. Probably the map page and layout pages too. I don’t think most of these will like being asked to do something with an Item that it can’t access/doesn’t exist.

I’m sure there are others I’m not thinking of.

Though I am assuming that an admin role user can see everything no matter what the metadata says it should. If we are going to restric the admin role though that opens up a whole can of worms. Everywhere one might interact with or see an Item needs to be touched, including the logger panes.

What happens when a user requests an item to which they don’t have read access? Is this like listing files in a directory where I can see that the file exists but I don’t have access to it or does the API return an error? Is that a 404 just like a request to an item that doesn’t exist or is it a 403 to indicate the item does exist but is not available to the user? If something is actually returned, is there some new special DENIED item state or does the item just register as UNDEF?

Groups produce a series of cases that would need to be addressed specifically I suspect. Do groups have their own permissions or do they inherit the permissions of their member items? If they have their own permissions, which takes precedence the group permissions or the item permissions? Presumably the item permissions should override the groups permissions, but then you can get some strange cases with groups that have member items with a mixture of permissions. This gets even more tangled of course with the semantic model and multiple tiers of nested groups.

Displaying a group membership list filtered for only items that a user has read access to is not too bad, or does it make more sense to list every item in the group but mark the ones with access restrictions? Can a user send a command to a group that has member items which that user does not have write access to? If so, does that override the item’s permission or does the group only propagate the command to user writable items?

What if the group has an aggregation function? Does the function result take all the group members into account or only the ones the user has read access to? Presumably you can’t have a group that has a different aggregation state for different users. At best this becomes confusing when a user sees a group with an aggregation state that doesn’t follow from the member items that are listed, and at worst this is technically a “security hole” as the state of an item a user does not even have read access to could be possibly be inferred by its group’s aggregation state.

My two cents is that this is a complicated topic that shouldn’t be “hacked into” the existing metadata structure. It should rather have its own data structure that is well-defined and thought through. ACL can be complicated, and I think that rules for inheritance should be defined upfront. Permissions without inheritance is more or less a failed concept IMO, as can be seen from the Linux file permission system (without the ACL extension).

Windows has a much better model here, but it’s also not without its problems. I think existing ACL “constructs” should be studied and some conclusions drawn from the failure of other solutions before one is chosen here. A permission system where you have to micromanage every single detail will never actually be used.

I’m new to openHAB, and don’t have a real idea about the code, java is not my favourite :wink:

but anyways, I can see at least two ways of:

  • administrator user/role that always has all access to everything
    • if adminrole → allow, otherwise check roles and grant permissions accordingly
  • paired with varying user roles
    • may or may not allow permissions assigned to users directly
    • or always assign permissions to roles

Or

  • no special distinction between administrator and other roles
  • administrator role is just a role with all permissions assignes
  • regardless of roles assigned to user, check them and grant permissions accordingly
    • no if admin → else check, just always plain check
  • admin could lock out himself, but then karaf console to the rescue

And definitely would suggest to not re-use existing features like Metadata, but rather use something designed for permissions.

Then may also think if read-only vs. read-write is enough.

Maybe

  • “manage”: allowed to change config of an item
  • “use”: allowed to toggle a switch
  • “view”: allowed to see an items

Inheritance:

  • block access by default, and then allow to enable access
  • or allow access by default, and then allow to block
  • can inherited permissions be overridden? i.e. allow kids to see every equipment in each room, but only in their own room, they are allowed to toggle switches at some specific items.

I’haven’t yet got my hands dirty in automation with scripts etc. But probably scripts etc. should run with their own identity and own permissions (a.k.a. service account with its own role(s) assigned), regardless of the user permissions just poking at the API or looking around in the UI, so that results of automations will always have the same results and outcomes.

just only a few things that came to my mind quickly, there’s probably more :wink:

cheers,

Sebastian