Skip to content
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

An actor granted a write permission still can't write unless also given read permission #2992

Closed
shahzadlone opened this issue Sep 10, 2024 · 12 comments · Fixed by #3108
Closed
Assignees
Labels
area/acp Related to the acp (access control) system
Milestone

Comments

@shahzadlone
Copy link
Member

shahzadlone commented Sep 10, 2024

An actor granted a write permission still can't write unless also given read permission

Example Policy where reader can strictly only read and writer can strictly only write:

name: Test Policy

description: A Policy

actor:
  name: actor

resources:
  users:
    permissions:
      read:
        expr: owner + reader

      write:
        expr: owner + writer

    relations:
      owner:
        types:
          - actor

      reader:
        types:
          - actor

      writer:
        types:
          - actor

Then the policy above (assume XYZ is resulting policyID) is linked in a schema that is loaded:

type Users @policy(id: XYZ, resource: "users") {
	name: String
	age: Int
}

Now if the owner (index 1) makes a relationship giving write access to the second actor (index 2) in our testing frame work like syntax:

testUtils.AddDocActorRelationship{
	DocID: 0,
	RequestorIdentity: 1,
	TargetIdentity: 2,
	Relation: "writer",
}

The identity 2 still can not mutate due to lack of read permission.

testUtils.UpdateDoc{
	Identity: immutable.Some(2), // This identity can still not update.
	DocID: 0,
	Doc: `
		{
			"name": "Shahzad Lone"
		}
	`,
	ExpectedError: "document not found or not authorized to access",
}

Some existing tests that document this:

  • TestACP_OwnerGivesUpdateWriteAccessToAnotherActorWithoutExplicitReadPerm_OtherActorCantUpdate
  • TestACP_OwnerGivesUpdateWriteAccessToAnotherActorWithoutExplicitReadPerm_OtherActorCantDelete
@shahzadlone shahzadlone added the area/acp Related to the acp (access control) system label Sep 10, 2024
@shahzadlone shahzadlone added this to the DefraDB v0.14 milestone Sep 10, 2024
@shahzadlone shahzadlone self-assigned this Sep 10, 2024
@AndrewSisley
Copy link
Contributor

Be careful with this one, is a chance that the test harness is reading after every write and as a result some failures may be test artifacts

@shahzadlone
Copy link
Member Author

Be careful with this one, is a chance that the test harness is reading after every write and as a result some failures may be test artifacts

What failures are you talking about? What does reading after writes have to do with this issue?

@AndrewSisley
Copy link
Contributor

AndrewSisley commented Sep 10, 2024

What failures are you talking about? What does reading after writes have to do with this issue?

The failures you are seeing in the tests you mentioned in the description, such as TestACP_OwnerGivesUpdateWriteAccessToAnotherActorWithoutExplicitReadPerm_OtherActorCantUpdate.

At the moment I'm pretty sure that even if the prod code was working and handling writes without read permission, the test harness will still log a failure as it will try and read the document just written to.

@shahzadlone
Copy link
Member Author

shahzadlone commented Sep 10, 2024

The failures you are seeing in the tests you mentioned in the description, such as TestACP_OwnerGivesUpdateWriteAccessToAnotherActorWithoutExplicitReadPerm_OtherActorCantUpdate.

How are they failures? That is an expected behavior.

At the moment I'm pretty sure that even if the prod code was working and handling writes without read permission, the test
harness will still log a failure as it will try and read the document just written to.

I think you might be confused as to what this issue is, I don't understand the relevance of the situation you are talking about.

This issue marks the current behavior that will be introduced when the relationship sharing with an other actor PR is merged because unlike before (as owner always had read and write permission) now the new relation might not have a read permission but might have a write permission.

When acp was initially was being implemented the team did decide to assume read access when write access is there, so now we can add that "manipulation" on defra side.

@AndrewSisley
Copy link
Contributor

The issue title An actor granted a write permission still can't write unless also given read permission, and description body suggest that the current behaviour is unwanted and that you want something to change? The tests mentioned document the unwanted behaviour, and will hopefully need to change when the behaviour is changed.

When acp was initially was being implemented the team did decide to assume read access when write access is there, so now we can add that "manipulation" on defra side.

Are you saying Defra will overwrite the policy given by the user to include the read permission when only write is given? The title does not reflect that, and I would have concerns about the impact on replicator nodes that should not have read permission (that do have write).

@shahzadlone
Copy link
Member Author

The issue title An actor granted a write permission still can't write unless also given read permission, and description body suggest that the current behaviour is unwanted and that you want something to change? The tests mentioned document the unwanted behaviour, and will hopefully need to change when the behaviour is changed.

Yes

Are you saying Defra will overwrite the policy given by the user to include the read permission when only write is given? The title does not reflect that, and I would have concerns about the impact on replicator nodes that should not have read permission (that do have write).

Defra won't overwrite the policy but instead let users who have access to write also have access to read.

@AndrewSisley
Copy link
Contributor

AndrewSisley commented Sep 12, 2024

Defra won't overwrite the policy but instead let users who have access to write also have access to read.

Without informing/affecting sourcehub? Have you discussed that with @jsimnz and/or @Lodek? That could be seen as a node ignoring ACP to some extent, and would that work with doc encryption (if ACP/Orbis is managing keys)?

How would a user configure a node where they want read to be prevented, but allow writes? Such as a replicator node, or data-source node (e.g. an edge device such as a wind turbine).

@shahzadlone
Copy link
Member Author

shahzadlone commented Sep 12, 2024

Without informing/affecting sourcehub? Have you discussed that with @jsimnz and/or @Lodek? That could be seen as a node ignoring ACP to some extent, and would that work with doc encryption (if ACP/Orbis is managing keys)?

That depends on the implementation:

  1. One implementation can be to automatically make a read relationship when a write relationship is added, however this can be tedious to always maintain the correct state specially when a user removes a relationship to ensure the extra read permission is also removed (however a user might have already added an explicit read relationship manually in which case we would not want to remove that relationship).

  2. Another approach can be to ignore sourcehub completely and in the check call if requesting a read to see if this identity has write permission and then just the request work.

I raised this point already in a standup with the whole team in March (https://discord.com/channels/427944769851752448/1216831384966922321/1217923732589510779) and the consensus without any pushback was to assume read when write is there. I am happy to bring this up again if there is a pushback or change in consensus, specially as we now have doc encryption and p2p source-hub acp.

How would a user configure a node where they want read to be prevented, but allow writes? Such as a replicator node, or data-source node (e.g. an edge device such as a wind turbine).

A user will have acp on a collection and they want to be able to write without reading? Keep in mind when we talk about write we are only talking about update and delete, both of those AFAIK require the ability to read the data (i.e. ensure existence, before the write op)

@AndrewSisley
Copy link
Contributor

AndrewSisley commented Sep 12, 2024

A user will have acp on a collection and they want to be able to write without reading? Keep in mind when we talk about write we are only talking about update and delete, both of those AFAIK require the ability to read the data (i.e. ensure existence, before the write op)

This depends on the CRDT types in play (LWWR does not need to read) when writing via client paths (such as GQL). Delete never requires read. Read is not required at all when updating the DAG directly via stuff like P2P, where the node receiving docs might not have read permission at all (although depending on how you think about it, that might not be classed as a write).

@shahzadlone
Copy link
Member Author

shahzadlone commented Sep 12, 2024

This depends on the CRDT types in play (LWWR does not need to read) when writing via client paths (such as GQL). Delete never requires read.

I could have sworn that before applying delete there was a check for primary key existing.

Read is not required at all when updating the DAG directly via stuff like P2P, where the node receiving docs might not have read permission at all (although depending on how you think about it, that might not be classed as a write).

As you mentioned, I am not sure that is considered a write permission specific to Document Access Control.

@AndrewSisley
Copy link
Contributor

AndrewSisley commented Sep 12, 2024

I could have sworn that before applying delete there was a check for primary key existing

DocIDs are public I think, so when I talk about delete I assume someone has a docID and is trying to delete it without being able to read it. I can't think of anything relation-wise that would require a read, only thing comes to mind is if a secondary is not-nil, but we dont have not-nil support for relations yet.

@shahzadlone
Copy link
Member Author

shahzadlone commented Sep 12, 2024

DocIDs are public I think, so when I talk about delete I assume someone has a docID and is trying to delete it without being able to read it. I can't think of anything relation-wise that would require a read, only thing comes to mind is if a secondary is not-nil, but we dont have not-nil support for relations yet.

Not all DocIDs are public, only DocIDs of public documents are public. Currently as ACP stands, requesting a list of docIDs in a collection will only show the requesting identity the DocIDs that it can access + the docIDs that are public.

Discussed in standup and the consensus is still to assume read permission is granted when write permission is granted. Small discussion on the implementation, likely to do the write permission check on the defradb level and not bother making a read relation on sourcehub.

shahzadlone added a commit that referenced this issue Oct 2, 2024
## Relevant issue(s)
Resolves #2762

## Description
This PR introduces the ability to make use of the `relation`s defined
within a policy to create relationships between an actor and a document
within a collection. For users sake, I have made the clients (http, and
cli) not consume the `policyID` and `resource` name but instead a
`docID` and `collection name`, since the collection will have the policy
and resource information available we can fetch that and make lives
easier for the users.

This PR also makes use of the `manages` feature we have had in our
policy. The manages essentially defines who can make the relationship
manipulation requests.

There are a lot of tests in this PR due to a lot of edge cases I wanted
to have tested specific to `manger`, and ensuring `write` and `read`
permissions don't leak (i.e. are accidently granted).

## CLI Demo
The following lets the target actor be able to now read the private
document:

```bash
defradb client acp relationship add \
--collection Users \
--docID bae-ff3ceb1c-b5c0-5e86-a024-dd1b16a4261c \
--relation reader \
--actor did:key:z7r8os2G88XXBNBTLj3kFR5rzUJ4VAesbX7PgsA68ak9B5RYcXF5EZEmjRzzinZndPSSwujXb4XKHG6vmKEFG6ZfsfcQn \
--identity e3b722906ee4e56368f581cd8b18ab0f48af1ea53e635e3f7b8acd076676f6ac
```

Result:
```json
{
  "ExistedAlready": false // <-------------- Indicates a new relationship was formed
}
```


### Future (out-of-scope of this PR):
- Most of write tests will split into `delete` and `update` in #2905 
- Ability to revoke or delete relation coming in #2906 
- Decide on the `can't write if no read permission` in #2992 
- Move acp logic to a shared repo:
#2980


## How has this been tested?
- Integration tests

Specify the platform(s) on which this was tested:
- Manjaro WSL2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/acp Related to the acp (access control) system
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants