Firebase's Security Rules and SAFE

Hey folks,

It has been months since my last comment here, hope the project is still going on. :grin:

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);

Example - An edit war on Wikipedia:

  1. 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;
  1. 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]
  1. 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;
  1. An edit war starts between User#1 and User#2;

  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;
  3. 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;
  1. 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;

  2. Revs complain to a Mod;

  3. 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.

14 Likes

This is a very interesting idea and proposal, thank you!

The current access control implementation is very low-level at this point in time and it is not very suited for websites and apps with large amounts of users – but it is not set in stone, of course. Personally I feel that apps should have more freedom in defining their own rules in permissions handling but most likely that will require support for computation and custom logic for vaults.

But we have such thing as type tags in Mutable Data which can have special meaning and processing rules in Vaults – perhaps role-based permissions can work for certain type tags only, so a user will have a choice whether they want to have this network overhead or not?

10 Likes

A quick reaction is that this seems sensible, though I can’t comment in depth, not having looked much at permissions in general.

I’m commenting mainly to add that we should also consider Solid Access Control Lists to see how well any proposal covers that case too.

Another point is that I’d like to see the NFS API support permissions /access control lists, at the file level, not just per MD, and if we do that, also some extra metadata, particularly Content Type.

With @anon71598723’s suggestions and these I think we would be converging on a powerful and easy to use feature set. :slight_smile:

PS @anon71598723, please, please, please come back to us and play! We miss you :slight_smile: I would even promise not to mention SAFE VFS again :wink:

6 Likes

As an alternative to Access Control Lists, there is also Capability lists.

With an access control list, the MD would for each user have a list of what that user can do read, write etc. The MD itself contains the list of users and their permitted actions.

With a capability list on on the other hand, the MD wouldn’t have a list of users, instead a user (or app) would have a list of capabilities. A user could have a list like MD1:read access, MD2, read and write access, etc. A capability would typically be a (revokable) token that can be used to access the data. User1 might have a read access token for MD1. User2 might have a read and write token for MD1 and can further pass along restricted access like a read only access token for another user or app.

6 Likes

Thank you for the ideas! WebAccessControl and capability lists definitely need to be researched and considered as options in addition to the role-based security proposal.

Agreed, this opens up interesting use cases such as making certain files in a directory immutable or protected. And on the surface it can be implemented simply by adding the permissions field to the Mutable Data Value struct. As for metadata, I believe this should be already supported – there is a metadata field in the File structure and its interpretation is up to a user or an app.

5 Likes

Us poor cousins using the DOM API can read file metadata but are not allowed to write it AFAIK :wink:

Also, I think the NFS API should define a standard for metadata, such as serialised JSON - or better a provide map/iterator API to get/set/iterate properties, otherwise app devs will implement it in incompatible ways.

1 Like

These interpretations are only conventions implemented by apps and are not enforced by vaults. This is a problem because it is possible to develop apps that bypass these conventions (for example modifying a read-only file).

This would be much better because access control would be enforced by vaults.

5 Likes

I created a task to allow setting user metadata when a file is created with NFS emulation: [MAID-2603] - JIRA
This wouldn’t allow to enforce restrictions as already mentioned though.

3 Likes

Would that metadata be stored in a way that would allow it to be accessed without going via an MD entry?

For example, say I just have the xor address of an Immutable Data - could I access its metadata to return a suitable Content Type header to a RESTful client (cf. a Web browser, LDP client etc)?

No, that’s just user metadata and it’s part of the data stored in the file’s entry in the parent/container MD. Although, I was also thinking along the same lines to be able to embed some metadata in the ID itself for some use cases similar to the one you are mentioning, but I personally still need to research a bit more to understand how feasible and desirable such a thing would be in the lower layers to work on a proposal.

2 Likes

As expected, asking because I’m thinking about support for file sharing again :slight_smile:

2 Likes

The ERights wiki has some interesting info on capabilities and links to further reading

http://wiki.erights.org/wiki/Capability

1 Like