-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validate Role records #188
Labels
post-mvp
de-scoped to after MVP
Comments
This was referenced Aug 18, 2023
Closed
EvanHahn
added a commit
that referenced
this issue
Nov 12, 2024
This adds a new option to `DataType.prototype.getByDocId()`, `mustBeFound`. If set to `false` and the document doesn't exist, it will resolve with `null` instead of throwing. If the option is missing or set to `true`, the current behavior is maintained (throwing if the document is missing). I think this is a useful feature on its own but will also hopefully make at least one [upcoming change][0] a little easier. [0]: #188
EvanHahn
added a commit
that referenced
this issue
Nov 12, 2024
This adds a new option to `DataType.prototype.getByDocId()`, `mustBeFound`. If set to `false` and the document doesn't exist, it will resolve with `null` instead of throwing. If the option is missing or set to `true`, the current behavior is maintained (throwing if the document is missing). I think this is a useful feature on its own but will also hopefully make at least one [upcoming change][0] a little easier. [0]: #188
EvanHahn
added a commit
that referenced
this issue
Nov 12, 2024
(This diff looks large, but it's just one line of source code and a bunch of tests.) We have some code like this: ``` if (isAssigningProjectCreatorRole && !this.#isProjectCreator()) { ``` The intent: only allow the project creator to change their own role. However, `this.#isProjectCreator` returned a `Promise`, which meant that the second part of the condition *always* evaluated to `false`, which meant that the whole condition always evaluated to false, which meant that non-creators could change the creator's role. This fixes that by making `#isProjectCreator` return a `boolean`, not `Promise<boolean>`. Found this while working on [#188]. [#188]: #188
EvanHahn
added a commit
that referenced
this issue
Nov 12, 2024
This adds a new option to `DataType.prototype.getByDocId()`, `mustBeFound`. If set to `false` and the document doesn't exist, it will resolve with `null` instead of throwing. If the option is missing or set to `true`, the current behavior is maintained (throwing if the document is missing). I think this is a useful feature on its own but will also hopefully make at least one [upcoming change][0] a little easier. [0]: #188
EvanHahn
added a commit
that referenced
this issue
Nov 14, 2024
This change should have no impact on functionality, and is a minor change. In [an upcoming change][0], I plan to make several references to the blocked role. This defines the `BLOCKED_ROLE` constant for this purpose. [0]: #188
EvanHahn
added a commit
that referenced
this issue
Nov 14, 2024
This change should have no impact on functionality, and is a minor change. In [an upcoming change][0], I plan to make several references to the blocked role. This defines the `BLOCKED_ROLE` constant for this purpose. [0]: #188
EvanHahn
added a commit
that referenced
this issue
Nov 18, 2024
(This diff looks large, but it's just one line of source code and a bunch of tests.) We have some code like this: ``` if (isAssigningProjectCreatorRole && !this.#isProjectCreator()) { ``` The intent: only allow the project creator to change their own role. However, `this.#isProjectCreator` returned a `Promise`, which meant that the second part of the condition *always* evaluated to `false`, which meant that the whole condition always evaluated to false, which meant that non-creators could change the creator's role. This fixes that by making `#isProjectCreator` return a `boolean`, not `Promise<boolean>`. Found this while working on [#188]. [#188]: #188
EvanHahn
added a commit
that referenced
this issue
Nov 18, 2024
This makes the following kind of change in a bunch of places: ```diff -throw new Error('Not found') +throw new NotFoundError() ``` I think this is a useful improvement on its own, but the changes to DataStore will also make [an upcoming change easier][0]. [0]: #188
EvanHahn
added a commit
that referenced
this issue
Nov 18, 2024
This adds a new option to `DataType.prototype.getByDocId()`, `mustBeFound`. If set to `false` and the document doesn't exist, it will resolve with `null` instead of throwing. If the option is missing or set to `true`, the current behavior is maintained (throwing if the document is missing). I think this is a useful feature on its own but will also hopefully make at least one [upcoming change][0] a little easier. [0]: #188
EvanHahn
added a commit
that referenced
this issue
Nov 18, 2024
This makes the following kind of change in a bunch of places: ```diff -throw new Error('Not found') +throw new NotFoundError() ``` I think this is a useful improvement on its own, but the changes to DataStore will also make [an upcoming change easier][0]. [0]: #188
This was referenced Nov 18, 2024
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Description
Validating a role record requires tracing a "role chain" back to the project creator auth core (the core whose key is the project key), and checking in each case that the role defined has the capability to assign the role given.
Because roles can change over time (e.g. a device might start as a "member", then be changed to "coordinator", then be changed to "removed"), each role record has a
fromIndex
property, that defines the index from which the role applies in the auth core of the person to whom the role applies.An example:
Validating device B's role requires the following steps:
What is a "Role chain"
A "Role chain" is the chain of role assignments that can be traced back to the project creator. E.g. project creator assigns device A a role, then device A assigns a role to device B, and device B assigns a role to device C. This "chain" of role assignments from creator -> A -> B -> C we call a "role chain" (suggestions for a better name are welcome!). Using the core key of the auth core as the
docId
for each role document, combined with the key of the auth core where the role document is written, can be used to validate this role chain.Validation flowchart
This flowchart summarises all the steps to take to validate any role:
Validating
fromIndex
There is currently no way to validate that
fromIndex
was actually the length of the auth core of the device assigned the role at the time the role document was written. This could be used to "back-date" a role assignment.However this is also a feature, for example "device X" is in a coordinator role, and turns "bad". Device X invites other bad actors to the project. Another device that has a role with the capability to assign the "blocked" role (the prevents sync) can assign that role with a
fromIndex
of0
. That would mean that any device with a role that came from X would be considered an invalid role, and be blocked. If any of these devices were considered OK (e.g. not bad actors) then another device could assign them a role, again with a "back-dated"fromIndex
, which would give them a valid role chain back to when they first joined the project.The one way that
fromIndex
could be exploited is when two bad actors manage to coordinate - e.g. one device with more capabilities could backdate capabilities to another device. However a bad actor with a role with a lot of capabilities like this could do lots of other bad things without backdating (inviting other bad actors), so there needs to be some implicit trust in members of a project. If a bad actor is discovered, then they can be removed (along with anyone they have assigned a role to) as described above.If we want some extra security about backdating, we could, in the future, add a method to analyze the auth cores, and see where it has happened. To do this will will need to add an extra property to every record written to the auth store that includes a "vector clock", e.g. a map of auth core keys to their current length. This would give a way to check whether
fromIndex
was written with a value other than the length of the core at the time. It remains to be seen however if this is a valuable feature and whether manipulating this is actually a threat.Tasks
capabilities.getRole(deviceId)
.The text was updated successfully, but these errors were encountered: