diff --git a/acp/README.md b/acp/README.md index 54c479b5ea..4c2c73907a 100644 --- a/acp/README.md +++ b/acp/README.md @@ -427,6 +427,209 @@ Error: ### Execute Explain example (coming soon) +### Sharing Private Documents With Others + +To share a document (or grant a more restricted access) with another actor, we must add a relationship between the +actor and the document. Inorder to make the relationship we require all of the following: + +1) **Target DocID**: The `docID` of the document we want to make a relationship for. +2) **Collection Name**: The name of the collection that has the `Target DocID`. +3) **Relation Name**: The type of relation (name must be defined within the linked policy on collection). +4) **Target Identity**: The identity of the actor the relationship is being made with. +5) **Requesting Identity**: The identity of the actor that is making the request. + +Note: + - ACP must be available (i.e. ACP can not be disabled). + - The collection with the target document must have a valid policy and resource linked. + - The target document must be registered with ACP already (private document). + - The requesting identity MUST either be the owner OR the manager (manages the relation) of the resource. + - If the specified relation was not granted the miminum DPI permissions (read or write) within the policy, + and a relationship is formed, the subject/actor will still not be able to access (read or write) the resource. + - If the relationship already exists, then it will just be a no-op. + +Consider the following policy that we have under `examples/dpi_policy/user_dpi_policy_with_manages.yml`: + +```yaml +name: An Example Policy + +description: A Policy + +actor: + name: actor + +resources: + users: + permissions: + read: + expr: owner + reader + writer + + write: + expr: owner + writer + + nothing: + expr: dummy + + relations: + owner: + types: + - actor + + reader: + types: + - actor + + writer: + types: + - actor + + admin: + manages: + - reader + types: + - actor + + dummy: + types: + - actor +``` + +Add the policy: +```sh +defradb client acp policy add -f examples/dpi_policy/user_dpi_policy_with_manages.yml \ +--identity e3b722906ee4e56368f581cd8b18ab0f48af1ea53e635e3f7b8acd076676f6ac +``` + +Result: +```json +{ + "PolicyID": "ec11b7e29a4e195f95787e2ec9b65af134718d16a2c9cd655b5e04562d1cabf9" +} +``` + +Add schema, linking to the users resource and our policyID: +```sh +defradb client schema add ' +type Users @policy( + id: "ec11b7e29a4e195f95787e2ec9b65af134718d16a2c9cd655b5e04562d1cabf9", + resource: "users" +) { + name: String + age: Int +} +' +``` + +Result: +```json +[ + { + "Name": "Users", + "ID": 1, + "RootID": 1, + "SchemaVersionID": "bafkreihhd6bqrjhl5zidwztgxzeseveplv3cj3fwtn3unjkdx7j2vr2vrq", + "Sources": [], + "Fields": [ + { + "Name": "_docID", + "ID": 0, + "Kind": null, + "RelationName": null, + "DefaultValue": null + }, + { + "Name": "age", + "ID": 1, + "Kind": null, + "RelationName": null, + "DefaultValue": null + }, + { + "Name": "name", + "ID": 2, + "Kind": null, + "RelationName": null, + "DefaultValue": null + } + ], + "Indexes": [], + "Policy": { + "ID": "ec11b7e29a4e195f95787e2ec9b65af134718d16a2c9cd655b5e04562d1cabf9", + "ResourceName": "users" + }, + "IsMaterialized": true + } +] +``` + +Create a private document: +```sh +defradb client collection create --name Users '[{ "name": "SecretShahzadLone" }]' \ +--identity e3b722906ee4e56368f581cd8b18ab0f48af1ea53e635e3f7b8acd076676f6ac +``` + +Only the owner can see it: +```sh +defradb client collection docIDs --identity e3b722906ee4e56368f581cd8b18ab0f48af1ea53e635e3f7b8acd076676f6ac +``` + +Result: +```json +{ + "docID": "bae-ff3ceb1c-b5c0-5e86-a024-dd1b16a4261c", + "error": "" +} +``` + +Another actor can not: +```sh +defradb client collection docIDs --identity 4d092126012ebaf56161716018a71630d99443d9d5217e9d8502bb5c5456f2c5 +``` + +**Result is empty from the above command** + + +Now let's make the other actor a reader of the document by adding a relationship: +```sh +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 +} +``` + +**Note: If the same relationship is created again the `ExistedAlready` would then be true, indicating no-op** + +Now the other actor can read: +```sh +defradb client collection docIDs --identity 4d092126012ebaf56161716018a71630d99443d9d5217e9d8502bb5c5456f2c5 +``` + +Result: +```json +{ + "docID": "bae-ff3ceb1c-b5c0-5e86-a024-dd1b16a4261c", + "error": "" +} +``` + +But, they still can not perform an update as they were only granted a read permission (through `reader` relation): +```sh +defradb client collection update --name Users --docID "bae-ff3ceb1c-b5c0-5e86-a024-dd1b16a4261c" \ +--identity 4d092126012ebaf56161716018a71630d99443d9d5217e9d8502bb5c5456f2c5 '{ "name": "SecretUpdatedShahzad" }' +``` + +Result: +```sh +Error: document not found or not authorized to access +``` ## DAC Usage HTTP: diff --git a/cli/acp_relationship_add.go b/cli/acp_relationship_add.go index 81358f45dd..9733732af8 100644 --- a/cli/acp_relationship_add.go +++ b/cli/acp_relationship_add.go @@ -36,10 +36,18 @@ func MakeACPRelationshipAddCommand() *cobra.Command { ) var cmd = &cobra.Command{ - Use: "add [-i --identity] [policy]", + Use: "add [--docID] [-c --collection] [-r --relation] [-a --actor] [-i --identity]", Short: "Add new relationship", Long: `Add new relationship +To share a document (or grant a more restricted access) with another actor, we must add a relationship between the +actor and the document. Inorder to make the relationship we require all of the following: +1) Target DocID: The docID of the document we want to make a relationship for. +2) Collection Name: The name of the collection that has the Target DocID. +3) Relation Name: The type of relation (name must be defined within the linked policy on collection). +4) Target Identity: The identity of the actor the relationship is being made with. +5) Requesting Identity: The identity of the actor that is making the request. + Notes: - ACP must be available (i.e. ACP can not be disabled). - The target document must be registered with ACP already (policy & resource specified). @@ -48,56 +56,21 @@ Notes: and a relationship is formed, the subject/actor will still not be able to access (read or write) the resource. - Learn more about [ACP & DPI Rules](/acp/README.md) -Consider the following policy: -' -description: A Policy - -actor: - name: actor - -resources: - users: - permissions: - read: - expr: owner + reader + writer - write: - expr: owner + writer - nothing: - expr: dummy - - relations: - owner: - types: - - actor - reader: - types: - - actor - writer: - types: - - actor - admin: - manages: - - reader - types: - - actor - dummy: - types: - - actor -' - -defradb client ... --identity e3b722906ee4e56368f581cd8b18ab0f48af1ea53e635e3f7b8acd076676f6ac - - -Example: Let another actor read my private document: - defradb client acp relationship add --collection User --docID bae-91171025-ed21-50e3-b0dc-e31bccdfa1ab \ - --relation reader --actor did:key:z6MkkHsQbp3tXECqmUJoCJwyuxSKn1BDF1RHzwDGg9tHbXKw \ - --identity 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f - -Example: Create a dummy relation that doesn't do anything (from database prespective): - defradb client acp relationship add -c User --docID bae-91171025-ed21-50e3-b0dc-e31bccdfa1ab -r dummy \ - -a did:key:z6MkkHsQbp3tXECqmUJoCJwyuxSKn1BDF1RHzwDGg9tHbXKw \ - -i 028d53f37a19afb9a0dbc5b4be30c65731479ee8cfa0c9bc8f8bf198cc3c075f - +Example: Let another actor (4d092126012ebaf56161716018a71630d99443d9d5217e9d8502bb5c5456f2c5) read a private document: + defradb client acp relationship add \ + --collection Users \ + --docID bae-ff3ceb1c-b5c0-5e86-a024-dd1b16a4261c \ + --relation reader \ + --actor did:key:z7r8os2G88XXBNBTLj3kFR5rzUJ4VAesbX7PgsA68ak9B5RYcXF5EZEmjRzzinZndPSSwujXb4XKHG6vmKEFG6ZfsfcQn \ + --identity e3b722906ee4e56368f581cd8b18ab0f48af1ea53e635e3f7b8acd076676f6ac + +Example: Creating a dummy relationship does nothing (from database prespective): + defradb client acp relationship add \ + -c Users \ + --docID bae-ff3ceb1c-b5c0-5e86-a024-dd1b16a4261c \ + -r dummy \ + -a did:key:z7r8os2G88XXBNBTLj3kFR5rzUJ4VAesbX7PgsA68ak9B5RYcXF5EZEmjRzzinZndPSSwujXb4XKHG6vmKEFG6ZfsfcQn \ + -i e3b722906ee4e56368f581cd8b18ab0f48af1ea53e635e3f7b8acd076676f6ac `, RunE: func(cmd *cobra.Command, args []string) error { db := mustGetContextDB(cmd) diff --git a/docs/website/references/cli/defradb_client_acp.md b/docs/website/references/cli/defradb_client_acp.md index 5a9c9aef80..d2ffce5036 100644 --- a/docs/website/references/cli/defradb_client_acp.md +++ b/docs/website/references/cli/defradb_client_acp.md @@ -42,4 +42,5 @@ Learn more about [ACP](/acp/README.md) * [defradb client](defradb_client.md) - Interact with a DefraDB node * [defradb client acp policy](defradb_client_acp_policy.md) - Interact with the acp policy features of DefraDB instance +* [defradb client acp relationship](defradb_client_acp_relationship.md) - Interact with the acp relationship features of DefraDB instance diff --git a/docs/website/references/cli/defradb_client_acp_relationship.md b/docs/website/references/cli/defradb_client_acp_relationship.md new file mode 100644 index 0000000000..4c204d0ccd --- /dev/null +++ b/docs/website/references/cli/defradb_client_acp_relationship.md @@ -0,0 +1,41 @@ +## defradb client acp relationship + +Interact with the acp relationship features of DefraDB instance + +### Synopsis + +Interact with the acp relationship features of DefraDB instance + +### Options + +``` + -h, --help help for relationship +``` + +### Options inherited from parent commands + +``` + -i, --identity string Hex formatted private key used to authenticate with ACP + --keyring-backend string Keyring backend to use. Options are file or system (default "file") + --keyring-namespace string Service name to use when using the system backend (default "defradb") + --keyring-path string Path to store encrypted keys when using the file backend (default "keys") + --log-format string Log format to use. Options are text or json (default "text") + --log-level string Log level to use. Options are debug, info, error, fatal (default "info") + --log-output string Log output path. Options are stderr or stdout. (default "stderr") + --log-overrides string Logger config overrides. Format ,=,...;,... + --log-source Include source location in logs + --log-stacktrace Include stacktrace in error and fatal logs + --no-keyring Disable the keyring and generate ephemeral keys + --no-log-color Disable colored log output + --rootdir string Directory for persistent data (default: $HOME/.defradb) + --secret-file string Path to the file containing secrets (default ".env") + --source-hub-address string The SourceHub address authorized by the client to make SourceHub transactions on behalf of the actor + --tx uint Transaction ID + --url string URL of HTTP endpoint to listen on or connect to (default "127.0.0.1:9181") +``` + +### SEE ALSO + +* [defradb client acp](defradb_client_acp.md) - Interact with the access control system of a DefraDB node +* [defradb client acp relationship add](defradb_client_acp_relationship_add.md) - Add new relationship + diff --git a/docs/website/references/cli/defradb_client_acp_relationship_add.md b/docs/website/references/cli/defradb_client_acp_relationship_add.md new file mode 100644 index 0000000000..ba5647c163 --- /dev/null +++ b/docs/website/references/cli/defradb_client_acp_relationship_add.md @@ -0,0 +1,81 @@ +## defradb client acp relationship add + +Add new relationship + +### Synopsis + +Add new relationship + +To share a document (or grant a more restricted access) with another actor, we must add a relationship between the +actor and the document. Inorder to make the relationship we require all of the following: +1) Target DocID: The docID of the document we want to make a relationship for. +2) Collection Name: The name of the collection that has the Target DocID. +3) Relation Name: The type of relation (name must be defined within the linked policy on collection). +4) Target Identity: The identity of the actor the relationship is being made with. +5) Requesting Identity: The identity of the actor that is making the request. + +Notes: + - ACP must be available (i.e. ACP can not be disabled). + - The target document must be registered with ACP already (policy & resource specified). + - The requesting identity MUST either be the owner OR the manager (manages the relation) of the resource. + - If the specified relation was not granted the miminum DPI permissions (read or write) within the policy, + and a relationship is formed, the subject/actor will still not be able to access (read or write) the resource. + - Learn more about [ACP & DPI Rules](/acp/README.md) + +Example: Let another actor (4d092126012ebaf56161716018a71630d99443d9d5217e9d8502bb5c5456f2c5) read a private document: + defradb client acp relationship add \ + --collection Users \ + --docID bae-ff3ceb1c-b5c0-5e86-a024-dd1b16a4261c \ + --relation reader \ + --actor did:key:z7r8os2G88XXBNBTLj3kFR5rzUJ4VAesbX7PgsA68ak9B5RYcXF5EZEmjRzzinZndPSSwujXb4XKHG6vmKEFG6ZfsfcQn \ + --identity e3b722906ee4e56368f581cd8b18ab0f48af1ea53e635e3f7b8acd076676f6ac + +Example: Creating a dummy relationship does nothing (from database prespective): + defradb client acp relationship add \ + -c Users \ + --docID bae-ff3ceb1c-b5c0-5e86-a024-dd1b16a4261c \ + -r dummy \ + -a did:key:z7r8os2G88XXBNBTLj3kFR5rzUJ4VAesbX7PgsA68ak9B5RYcXF5EZEmjRzzinZndPSSwujXb4XKHG6vmKEFG6ZfsfcQn \ + -i e3b722906ee4e56368f581cd8b18ab0f48af1ea53e635e3f7b8acd076676f6ac + + +``` +defradb client acp relationship add [--docID] [-c --collection] [-r --relation] [-a --actor] [-i --identity] [flags] +``` + +### Options + +``` + -a, --actor string Actor to add relationship with + -c, --collection string Collection that has the resource and policy for object + --docID string Document Identifier (ObjectID) to make relationship for + -h, --help help for add + -r, --relation string Relation that needs to be set for the relationship +``` + +### Options inherited from parent commands + +``` + -i, --identity string Hex formatted private key used to authenticate with ACP + --keyring-backend string Keyring backend to use. Options are file or system (default "file") + --keyring-namespace string Service name to use when using the system backend (default "defradb") + --keyring-path string Path to store encrypted keys when using the file backend (default "keys") + --log-format string Log format to use. Options are text or json (default "text") + --log-level string Log level to use. Options are debug, info, error, fatal (default "info") + --log-output string Log output path. Options are stderr or stdout. (default "stderr") + --log-overrides string Logger config overrides. Format ,=,...;,... + --log-source Include source location in logs + --log-stacktrace Include stacktrace in error and fatal logs + --no-keyring Disable the keyring and generate ephemeral keys + --no-log-color Disable colored log output + --rootdir string Directory for persistent data (default: $HOME/.defradb) + --secret-file string Path to the file containing secrets (default ".env") + --source-hub-address string The SourceHub address authorized by the client to make SourceHub transactions on behalf of the actor + --tx uint Transaction ID + --url string URL of HTTP endpoint to listen on or connect to (default "127.0.0.1:9181") +``` + +### SEE ALSO + +* [defradb client acp relationship](defradb_client_acp_relationship.md) - Interact with the acp relationship features of DefraDB instance + diff --git a/docs/website/references/http/openapi.json b/docs/website/references/http/openapi.json index 6b7686c7c1..c0a7898364 100644 --- a/docs/website/references/http/openapi.json +++ b/docs/website/references/http/openapi.json @@ -588,6 +588,36 @@ ] } }, + "/acp/relationship": { + "post": { + "description": "Add an actor relationship using acp system", + "operationId": "add relationship", + "requestBody": { + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + }, + "required": true + }, + "responses": { + "200": { + "$ref": "#/components/responses/success" + }, + "400": { + "$ref": "#/components/responses/error" + }, + "default": { + "description": "" + } + }, + "tags": [ + "acp_relationship" + ] + } + }, "/backup/export": { "post": { "description": "Export a database backup to file", diff --git a/examples/dpi_policy/user_dpi_policy.json b/examples/dpi_policy/user_dpi_policy.json index 74028d8ee6..96c794b490 100644 --- a/examples/dpi_policy/user_dpi_policy.json +++ b/examples/dpi_policy/user_dpi_policy.json @@ -1,4 +1,5 @@ { + "name": "An Example Policy", "description": "A Valid Defra Policy Interface (DPI)", "actor": { "name": "actor" diff --git a/examples/dpi_policy/user_dpi_policy.yml b/examples/dpi_policy/user_dpi_policy.yml index fafae06957..1b1df1e0b9 100644 --- a/examples/dpi_policy/user_dpi_policy.yml +++ b/examples/dpi_policy/user_dpi_policy.yml @@ -7,6 +7,8 @@ # # Learn more about the DefraDB Policy Interface [DPI](/acp/README.md) +name: An Example Policy + description: A Valid DefraDB Policy Interface (DPI) actor: diff --git a/examples/dpi_policy/user_dpi_policy_with_manages.yml b/examples/dpi_policy/user_dpi_policy_with_manages.yml new file mode 100644 index 0000000000..4667660136 --- /dev/null +++ b/examples/dpi_policy/user_dpi_policy_with_manages.yml @@ -0,0 +1,49 @@ +# The below policy contains an example with valid DPI compliant resource that can be linked to a collection +# object during the schema add command to have access control enabled for documents of that collection. +# +# This policy specifically has the manages attribute defined under admin relation which gives admin +# of a resource, the ability to add/remove relationships with `reader` relation name. +# +# Learn more about the DefraDB Policy Interface [DPI](/acp/README.md) + +name: An Example Policy + +description: A Policy + +actor: + name: actor + +resources: + users: + permissions: + read: + expr: owner + reader + writer + + write: + expr: owner + writer + + nothing: + expr: dummy + + relations: + owner: + types: + - actor + + reader: + types: + - actor + + writer: + types: + - actor + + admin: + manages: + - reader + types: + - actor + + dummy: + types: + - actor