Understanding the Passbolt rights model

I’d like to start a discussion around the permissions in Passbolt, as I have several requirements in a small company environment which are currently hard to meet.


PART ONE: I’d like to start by ensuring I understand the existing rights model.

As far as I can see, the only documentation for Passbolt is the FAQ, and it doesn’t cover this in any detail.

Here’s what I’ve managed to gather so far.

(1) Firstly: there are the system roles. In the database there are four roles defined:

mysql> select name,description from roles;
+-------+----------------------------+
| name  | description                |
+-------+----------------------------+
| admin | Organization administrator |
| guest | Non logged in user         |
| root  | Super Administrator        |
| user  | Logged in user             |
+-------+----------------------------+

However in my installation, I don’t see the “root” (Super Administrator) role in use at all:

mysql> select r.name,count(*) from users u join roles r on u.role_id=r.id group by r.name;
+-------+----------+
| name  | count(*) |
+-------+----------+
| admin |        7 |
| guest |        1 |
| user  |       21 |
+-------+----------+
3 rows in set (0.00 sec)

Nor can I see how to promote anyone to the root role. When I’m logged in as administrator and look at other users, the GUI just has a check box (“This user is an administrator”).

I believe that the purpose of “admin” is to create and delete users and groups, and that admins can see all users and groups on the system (can normal users??)

I’m not sure if there’s anything else that Admins can do. In particular, being an admin doesn’t let you add users to groups (only Group Managers can do that). And being an Admin does not let you even see the existence of passwords which are not shared with you.

I don’t have any idea of the purpose of the “root” role, nor the “guest” role. I see there is one guest user, with username anonymous@passbolt.com.

(2) Next, there are the rights on passwords (or “resources” as they’re known in the database).

I see three types of permission: “can read” (1), “can update” (7), and “is owner” (15).

mysql> select type,count(*) from permissions group by type;
+------+----------+
| type | count(*) |
+------+----------+
|    1 |       29 |
|    7 |       25 |
|   15 |      109 |
+------+----------+
3 rows in set (0.00 sec)

“can read” and “can update” are obvious. As far as I understand it, “is owner” can also modify which Users and/or Groups it is shared with, and what levels of access those Users and Groups have.

Each permission row refers to one resource (aco), and adds a permission either for one User or Group (aro).

mysql> select aro, aco, count(*) from permissions group by aro, aco;
+-------+----------+----------+
| aro   | aco      | count(*) |
+-------+----------+----------+
| Group | Resource |       64 |
| User  | Resource |       99 |
+-------+----------+----------+
2 rows in set (0.00 sec)

You can get a full list of permissions for each resource like this:

mysql> select r.id,r.name,p.type,p.aro,IFNULL(u.username,g.name) as name
from resources r
left join permissions p on p.aco='Resource' and p.aco_foreign_key=r.id
left join users u on p.aro='User' and p.aro_foreign_key=u.id
left join groups g on p.aro='Group' and p.aro_foreign_key=g.id
order by r.id;

There is a view called “users_resources_permissions” which does something similar, but it is quite a complex query (I think it flattens out groups).

(3) There are permissions for Groups.

Groups can contain Users (but not other groups, i.e. no nesting).

A user can either be “Member” or “Group Manager” in a group. I presume this is the “is_admin” flag in the groups_users table.

As far as I can tell, only a Group Manager can add/remove users into a group.

So if I understand all this correctly, there are three ways that a user can gain access to a password:

  1. The password Owner can add sharing access directly to that User
  2. The password Owner can add sharing access to some Group that the User is already a member of
  3. If the password is already shared with a group, then the Group Manager can add the User to that group

Am I right so far? This means that the “Admin” role doesn’t come into play at all, for controlling access to passwords.


PART TWO: The problems

I have deployed passbolt in a small company. It’s becoming extremely useful, but there are number of issues which have come to light.

(1) Whenever a new password is created, it has by default only a single owner. If that person leaves the company, then:

  • there’s no way to delete the user (since PB refuses to delete a user who is the sole owner on one or more resources)
  • there’s no longer any way to change the sharing settings on that password

And if the owner is away temporarily (e.g. on holiday) it’s not possible to modify the sharing on that password.

WORKAROUND: if the password is shared with some other user or group, they can be promoted to owner by a SQL update on their permission, to set type=15.

(2) Audit: we need to be able to list all passwords which are in the system, and who they are shared with. Currently, if you are logged in as Admin role you can see all Users and Groups, but you cannot see any passwords which are not shared with you (not even the fact that they exist).

WORKAROUND: direct SQL query, like the one I showed above.

(3) Password recovery: all stored passwords in our server are (by definition) the property of the company. However if they are not shared, then they cannot be recovered in emergency, when the user(s) it is shared with are not available.

(4) Group recovery: if only a single individual is a group manager, but we need to add/remove users from a group when that person is not available, we cannot do so.

I am thinking about working around these problems as follows.

  • We already have a “System Operations” group which the key trusted sysadmins are members of (i.e. the same people who have root access to the passbolt server itself)

  • We make a new company policy that every password in Passbolt must be shared with the “System Operations” group with “Owner” privileges. We use a SQL report to identify violations

  • Ideally we would also say that every group must have the “System Operations” group as Group Manager, but unfortunately there are no nested groups; the best we can do is to add all members of the System Operations group individually as Managers of every group.

  • Passwords which are shared ad-hoc with individuals, rather than groups, are frowned upon; but as long as they are shared with the System Operations group as Owner, we can fix this when required.

I think this approach will work, but it would be nice if Passbolt itself could help enforce this - in particular that every password has a specific recovery group as Owner which cannot be removed, in addition to the creator.

In addition, it seems to me that there is some scope for increasing the capabilities of the “Admin” role without breaking the security model. This would include:

  • Any Admin should be able to see the existence of all passwords and their metadata, even if they don’t have rights to decrypt them. Possibly also be able to delete them.

  • If an Admin already has read or modify access to a password, then let them change or add user and group rights to that password.

Note that anyone who has read or modify rights can already view the password, and therefore at worst could simply create a new password containing the same data and share it with whichever users or groups they like. So, letting admins update the sharing rights for passwords they can already see doesn’t add any security risk that I can see.

Sorry for the long post, but this is actually quite an involved topic!

Regards,

Brian.


Aside 1: as far as I can see there is no database unique constraint on resources.name, so reports need to show resources.id to distinguish them.

Aside 2: when I checked permissions on resource objects in my database, I found a few resources which are completely orphaned with no permissions at all - not even an owner. I thought they might be deleted, but not all of them are:

mysql> select r.id,r.expiry_date,r.deleted from resources r left join permissions p on p.aco_foreign_key=r.id where p.id is null;
+--------------------------------------+-------------+---------+
| id                                   | expiry_date | deleted |
+--------------------------------------+-------------+---------+
| 59bf8f34-9870-4ad8-a436-486cb92d621e | NULL        |       1 |
| 59c92c45-fb5c-4a57-a905-029cb92d621e | NULL        |       1 |
| 5a0436f0-4428-4275-afbb-7625b92d621e | NULL        |       0 |
| 5a13ff70-1dc0-4765-8a61-5b31b92d621e | NULL        |       0 |
+--------------------------------------+-------------+---------+
4 rows in set (0.00 sec)

This seems like it could be a bug: perhaps the resource and its initial owner were not added in the same DB transaction?

Conversely, there are some deleted resources which do still have permissions attached, although that’s not unreasonable:

mysql> select distinct r.id from resources r join permissions p on p.aco_foreign_key=r.id where r.deleted=1;
+--------------------------------------+
| id                                   |
+--------------------------------------+
| 59b2bdd0-2084-4d60-a6b5-4307b92d621e |
| 59b2c114-66c4-4a33-b160-450bb92d621e |
| 59b69d49-9224-466d-896b-5691b92d621e |
| 59b7ae63-29b4-4baa-98b0-0ca1b92d621e |
+--------------------------------------+
4 rows in set (0.00 sec)
1 Like

@candlerb thanks for digging into it and for the write up. I really appreciate your effort to have an informed conversation about this topic as it’s quite complex.
We do have some internal documentation / specs for the permission system. We’ll tidy it up and write a blog about it.

Some comments:

However in my installation, I don’t see the “root” (Super Administrator) role in use at all

Yes it is a role that is not used at the moment. Initially we envisioned that it will be used in the future for orgs that want an account to have access to all passwords and/or to create organizational units (e.g organizations inside the organization).

I believe that the purpose of “admin” is to create and delete users and groups

Correct. Regular users can also see all the active users (not the inactive ones)

I don’t have any idea of the purpose of the “guest” role.

The guest role is used to provide some logic for people that are not logged in.
The anonymous user was envisioned to provide default settings for guest role user (like locale and stuffs) but it will be gone in v2.

As far as I can tell, only a Group Manager can add/remove users into a group.

Correct.

So if I understand all this correctly, there are three ways that a user can gain access to a password […]. Am I right so far?

Yes

(1) Whenever a new password is created, it has by default only a single owner. If that person leaves the company…

Yes that’s correct. We envision to do something @kevin described in the other thread: give admin users the right to transfer group and passwords ownership in the delete users/groups scenarios. We already have some specs for this.

(2) Audit: Admin need to be able to list all passwords which are in the system, and who they are shared with.

Yes that make sense. We were planning to provide something like that as part of the audit trail module, where admin can also see who accessed what when.

(3) Password recovery: all stored passwords in our server are (by definition) the property of the company. However if they are not shared, then they cannot be recovered in emergency, when the user(s) it is shared with are not available.

We have a different take on this. In Europe for example everyone has a constitutional right for privacy and the respect for their private and family life, home, and communications. So in this context we believe people should have the right to store personal secret in passbolt disregard if it’s their instance is owned by their employer. I personally would like to keep this the default setting, as this improves security of people that have currently no password manager, but I understand your needs as well. I would say that it should be the responsibility of the user to share non personal password with their backup buddy (e.g. via policy like you describe), but I understand you need a way to enforce that as admin, as people will make mistake and forget to share non personal passwords.

So yes we could add some org settings that forces certain group to be added by default as owner when creating a resource ( and maybe another optional setting to allow removing them if the org allows personal passwords).

(4) Group recovery: if only a single individual is a group manager, but we need to add/remove users from a group when that person is not available, we cannot do so.

Same solution than 1 on the long term, except that one cannot add/remove people (unless we are in this new admin owns everything scenario), just promote them (as the admin cannot create the encrypted version of the secret since it can’t read it).
There should be a policy that you need at least 2 people per group. We don’t enforce that at creation as we appreciate the fact that sometimes their might be need to have a one man orchestra, like when forming the groups.

Aside 2: when I checked permissions on resource objects in my database, I found a few resources which are completely orphaned

Yes these are bugs, this is something we’ll be fixing with v2. (I actually worked on solving this exact problem this week).

1 Like

You’re right: people do also have their own individual (user-specific) passwords. I don’t object in principle to them being stored in Passbolt; it would be helpful, in that users wouldn’t need to run a separate password manager for their individual passwords.

So that means passwords fall into two categories:

  • Personal (i.e. user-specific) passwords. Existing company policy already says these should never be shared. Hence if they are stored in Passbolt, they should have only a single Owner, and not be shared with any other user or group.
  • Shared, corporate/non-personal passwords. These should at least have the Systems Operations group as Owner, and may have other owners / modifiers / readers.

For now, I can document that as policy, and I can also write a SQL report which finds any passwords which don’t meet one or other criterion.

From a process point of view, it would be great if when a password was created the user was offered a choice:

What type of password is this?
(*) Individual
( ) Shared

and then depending on the choice, the system could enforce one policy or the other. There could even be multiple types of policy, if there were some way to define them.

Such policies might be things like: “must be shared with at least 2 other users”, “must be shared with user/group X”, or “must not be shared with any users or groups”

There should be a policy that you need at least 2 people per group. We don’t enforce that at creation as we appreciate the fact that sometimes their might be need to have a one man orchestra, like when forming the groups.

If a group has only one member, then in effect it’s just the same as sharing with an individual (or indeed not sharing it at all, if the only member of the group is yourself).

Leaving aside the policy enforcement of who a password is or is not shared with, I think most other sticking cases would be covered by:

  1. An Admin can promote an existing group Member to Manager
  2. An Admin can promote an existing password Reader/Modifier to Owner

(1) means that as long as one of the existing group members is available, they can perform the group update. But even if none of the group members are available, (2) means that the passwords can be shared with a new group.

If the password has only one person who can access it, and it was only shared with one group, and that group only had one member who is also the password owner, then the password was never shared in the first place!

One another thought. To make group management easier, I was also thinking of making it policy that every group has System Operations as Manager (remember that I already decided that all passwords would be shared with System Operations). However, because groups don’t nest, it means that every time we create a group, we’d have to add all the System Operations staff as individual members. I think that’s manageable, as long as the number of groups doesn’t get too large - nested groups are probably an unnecessary complication.

Regards, Brian.

Here are some base queries in case they are useful to anyone else.

Which passwords a user has direct access to or ownership of

This can’t be done via the GUI, even as an Admin.

mysql> select r.id as resource_id,r.name,p.type from users u
       join permissions p on p.aro='User' and p.aro_foreign_key=u.id
       join resources r on p.aco='Resource' and p.aco_foreign_key=r.id
       where u.username='XXXX@XXXXX';
+--------------------------------------+------------------+------+
| resource_id                          | name             | type |
+--------------------------------------+------------------+------+
| 59c3bc73-c2c8-4314-8906-7d9ab92d621e | XXXXXXXXXXXXXXXX |    1 |
+--------------------------------------+------------------+------+
1 row in set (0.00 sec)

Type 1 = can read, 7 = can update, 15 = owner.

If they are owner, then the GUI will not let you delete that user unless all the resources that they are owner of have at least one other owner.

Access can be promoted by means of a SQL update to the ‘type’ column.

Which users or groups a given password is shared with

Can only be done from the GUI if you have access to that password yourself.

mysql> select id from resources where name='XXXXX';
+--------------------------------------+
| id                                   |
+--------------------------------------+
| 59c3bc73-c2c8-4314-8906-7d9ab92d621e |
+--------------------------------------+
1 row in set (0.00 sec)

mysql> select p.aro as entity,ifnull(u.username, g.name) as name, type
       from permissions p
       left join users u on p.aro='User' and p.aro_foreign_key=u.id
       left join groups g on p.aro='Group' and p.aro_foreign_key=g.id
       where p.aco='Resource' and p.aco_foreign_key='59c3bc73-c2c8-4314-8906-7d9ab92d621e';
+--------+----------------------+------+
| entity | name                 | type |
+--------+----------------------+------+
| User   | XXXX@XXXXX           |   15 |
| User   | XXXX@XXXXX           |    1 |
+--------+----------------------+------+
2 rows in set (0.00 sec)

What groups a user is member of

This can be done in the GUI, by clicking on “users” and clicking on the user. However it can also be done through SQL:

mysql> select g.id,g.name,gu.is_admin from users u
       join groups_users gu on gu.user_id=u.id
       join groups g on gu.group_id=g.id
       where u.username='XXXX@XXXXX';
+--------------------------------------+------------------------+----------+
| id                                   | name                   | is_admin |
+--------------------------------------+------------------------+----------+
| 59b69018-d968-4a58-8484-420bb92d621e | XXXXXXXXXXXXXXXXXXXXXX |        0 |
| 59b69ceb-ba44-4d48-8d1e-2e42b92d621e | XXXXXXXXXXXXXXXXXXXXXX |        1 |
+--------------------------------------+------------------------+----------+
2 rows in set (0.00 sec)

is_admin means they are group Manager. For each group they are a manager of, you may want to check the group membership, in particular that there is at least one other group manager, before deleting the user.

Which users are members of a group

This can also be done through the GUI: under “users” and “All groups”, click on the group. Through SQL:

mysql> select u.username,is_admin from groups_users gu
       join users u on gu.user_id=u.id
       where gu.group_id='59b69ceb-ba44-4d48-8d1e-2e42b92d621e';
+----------------------+----------+
| username             | is_admin |
+----------------------+----------+
| XXXX@XXXXX           |        1 |
| XXXX@XXXXX           |        1 |
| XXXX@XXXXX           |        0 |
| XXXX@XXXXX           |        1 |
| XXXX@XXXXX           |        0 |
| XXXX@XXXXX           |        0 |
| XXXX@XXXXX           |        1 |
+----------------------+----------+
7 rows in set (0.00 sec)

A user can be promoted to group manager by setting is_admin to 1.

Which passwords are shared with a group

You can’t do this in the GUI unless you are a member of that group yourself.

mysql> select r.id,r.name,p.type from permissions p
       join resources r on p.aco='Resource' and p.aco_foreign_key=r.id
       where p.aro='Group' and p.aro_foreign_key='59b69ceb-ba44-4d48-8d1e-2e42b92d621e';
+--------------------------------------+---------+------+
| id                                   | name    | type |
+--------------------------------------+---------+------+
| 59b69d86-9720-4d8e-99e1-420db92d621e | Test 8  |   15 |
| 59b69f7a-f254-49f1-9795-2e44b92d621e | Test 0  |   15 |
...
1 Like