Hey folks,
It has been months since my last comment here, hope the project is still going on.
The last time I was playing with SAFE app development (9 months ago) I found particularly challenging the way SAFE controls permissions. It was so difficult for me that I stop playing with SAFE at all, waiting for this to be improved first.
So, in order to help, I proposed a change to the whitelists/ownership properties (the base of SAFEâs permission mechanism). Itâs a simple but powerful change, with a very low footprint to the network.
I posted the proposal on the dev forum, but Iâm re-posting here to reach a wider audience (in a hope that this SAFE mechanism can be improved).
I would love to hear what do you guys respectfully think about it, especially from web devs.
PS: This proposal is based on the Firebaseâs Security Rules, hence the title.
Proposal: Role-based security (Wikipedia example)
Letâs say an app needs different kinds of roles: admin, managers, sales, etc. Each role has different permissions. This is actually a very basic functionality in apps. We can use Wikipedia and all its roles (admin, mods, revs) as example.
So, how to implement this in SAFE?
Current SAFE API has 2 access control mechanisms: multi-signed ownership, and black/white lists. This unfortunately (imo), is not enough to implement the multi-roles and require some complex workarounds (as far as I can see).
The proposal:
Change âwhitelistâ and âownersâ properties to not be a list of users anymore. Instead they will be a list of a list of users, or a list of ârolesâ. Here, each entry/role is a pointer to an MD that contains a list of users. Ex.: âowner: [admins, managers, sales]â, then we will have 3 MDs (named âadminsâ, âmanagersâ, âsalesâ) containing a list of users each.
With this indirect reference I believe we can easily implement multi-role / hierarchical access.
In practical terms:
- Add 2 properties to MutableData: âowner_groupsâ, âwhitelist_groupsâ (or replace the current âownerâ/âwhitelistâ);
- Both properties are lists of mutable references;
- These mutables have a list of userIDs;
- Anyone in any âowner_groupsâ can do anything with the MD, except to remove an owner at its left side in the list.
- Ex.: owner_groups: [admins, mods, revs].
A âmodâ user can do anything with the MD except to remove the âadminsâ entry from the âowner_groupsâ property (because itâs on its left side);
- Ex.: owner_groups: [admins, mods, revs].
Example - An edit war on Wikipedia:
- User#1 creates a âcarâ article;
- App creates a MD:
- name: âwiki_carâ;
- owners: [admins, mods, revs];
- whitelist: ;
- App creates an Immutable that contains the articleâs contents and adds it in the MD;
- Definitions:
- âRevsâ MD:
- ownership: [admins, mods]
- whitelist: [mods]
- data: Rev#1, Rev#2, Rev#3
- âModsâ MD:
- ownership: [admins]
- whitelist: [admins]
- data: Mod#1, Mod#2
- âAdminsâ MD:
- ownership: [god]
- whitelist: [god]
- User#2 edits the article:
- New immutable is created and added into the âwiki_carâ MD;
- As the âwhitelist_groupâ is empty, network doesnât need to do any additional checking;
-
An edit war starts between User#1 and User#2;
-
Rev#1 protects the article, allowing only other revs to change it:
- Update âwiki_carâ MD:
- whitelist: [revs]
- The network fetches all âownersâ MDs of âwiki_carâ and verifies that Rev#1 is there, allowing the operation;
- Update âwiki_carâ MD:
-
User#2 tries to edit (add an immutable ref into the MD):
- The network fetch the ârevsâ MD that is in the âwiki_carâ whitelist and forbids the update;
-
User#2 complains to another rev. He says it is unfair. Other revs accept the complain and decide to undo Rev#1 changes, but Rev#1 disagree and starts a edit war with others revs, which is against the rules;
-
Revs complain to a Mod;
-
Mod#1 âfiresâ Rev#1:
- Remove Rev#1 from âRevsâ MD;
- Change âcarâ articleâs whitelist to empty again, un-protecting it;
With this approach, is fairly easy to manage an hierarchy of roles, even if the app has thousands of users. Add an admin doesnât require to update millions of articles, for example.
Considerations:
Network overhead: For each MD update, the network will need to fetch extra MDs (the ones in âwhitelist_groupsâ). This means that the more whitelist_groups entries we have, slower the app will be for updates. Same thing applies when changing MD properties like ownership or the whitelist list: in this case, the network needs to fetch MDs listed in the ownership_group property. This can be a problem for the network, but consider the following:
- This only happens on UPDATEs, which cost money - possibly eliminating it as an attack vector;
- If still a problem, a solution could be to the network charge more (according to the amount of entries) or limit the number of entries (e.g. 5);
- By slowing down the app (due to the extra GETs on UPDATEs) will serve as a pressure to developers keep lists lean;
- Most cases will need only 1 entry in the whitelist. Even in a Wikipedia, with thousands of super-users, only needs to have 1 entry in the whitelist (the immediate superior);
- Itâs not recursive: this method allows an hierarchy of permissions and power delegation, and only does a few predictable amount of requests (in most cases, only 1, and only when adding new items to the MD);
- Without an embedded ârole controlâ mechanism, workarounds will be necessary, costing much more GETs to the network;
- The âRoleâ MD can have a special type, that the network can use to optimize this mechanism;
Decentralized apps: I used a current-internet-app example, but I do think this approach can be very useful when managing permissions in decentralized apps. For example, on a SafeTube protocol you can follow a âcuratorâ group of people that works on a hierarchy of roles. Or you can decentralize permissions of your protocol based on a chain of trust.