From 68f15bd11c525b0c1c464508ce690cc26a683dc0 Mon Sep 17 00:00:00 2001 From: philipwright <95368282+phil198@users.noreply.github.com> Date: Thu, 10 Apr 2025 11:26:29 +0100 Subject: [PATCH 1/7] WIP relationship examples --- .../property-based-access-control.adoc | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc b/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc index 73bc04891..d08507931 100644 --- a/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc +++ b/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc @@ -12,7 +12,7 @@ CREATE ROLE regularUsers; [[property-based-access-control]] = Property-based access control -Property-based access control grants permissions to users to read node properties based on property/value conditions. +Property-based access control grants permissions to users to read element properties based on property/value conditions. Each property-based privilege can only be restricted by a single property. For information about read privileges and their syntax, see xref:authentication-authorization/privileges-reads.adoc[Read privileges]. @@ -40,7 +40,9 @@ To specify the property/value conditions of the read privilege, you can use the | FOR { ([var][:label["|" ...]] "{" property: value "}") - | (var[:label["|" ...]]) + | (var[:label["|" ...]]) + | ()[<]-"["[var][:type["|" ...]] "{" property: value "}" "]"-[>]() + | ()[<]-"["var[:type["|" ...]]"]"-[>]() WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } } | (var[:label["|" ...]] WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } } ) @@ -57,7 +59,7 @@ See xref:authentication-authorization/limitations.adoc#property-based-access-con When having property rules, the following factors can worsen the impact on performance: -* The number of properties on the nodes concerned (more properties = greater performance impact). +* The number of properties on the elements concerned (more properties = greater performance impact). * The number of property-based privileges (more property-based privileges = greater performance impact). * The type of the privilege: `TRAVERSE` property-based privileges have greater performance impact than `READ` property-based privileges. * The type of storage medium in operation. The impact of the property-based privileges on performance is considerably amplified by accessing disc storage. @@ -81,7 +83,7 @@ GRANT privilege-name ON GRAPH graph-name FOR pattern TO role-name The user role does not need to have `READ` privilege for the property used by the property-based privilege. ==== -=== Grant a property-based privilege on a specific property using its value +=== Grant a property-based privilege on a specific property using the value of another property The following example shows how to grant permission to `READ` the `address` property on `Email` or `Website` nodes with domain `exampledomain.com` to role `regularUsers`: @@ -97,6 +99,14 @@ Alternatively, you can use the following syntax: GRANT READ { address } ON GRAPH * FOR (:Email|Website {domain: 'exampledomain.com'}) TO regularUsers ---- +=== Grant a property-based privilege on a specific property using the value of that same property + +The following example shows how to grant permission to `READ` the `since` property on `OWNS` relationships having `since` equal to `2025-01-01` to role `regularUsers`: + +[source, syntax, role="noheader"] +---- +GRANT READ { since } ON GRAPH * FOR ()-[o:OWNS]-() WHERE o.since = date("2025-01-01") TO regularUsers +---- === Grant a property-based privilege using `NULL` From 1ad904b88a35809af84c133783c24b222cd7b5fd Mon Sep 17 00:00:00 2001 From: Hannes Sandberg Date: Thu, 10 Apr 2025 13:43:52 +0200 Subject: [PATCH 2/7] added relationship as well for the examples covering all nodes --- .../authentication-authorization/limitations.adoc | 2 +- .../property-based-access-control.adoc | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/modules/ROOT/pages/authentication-authorization/limitations.adoc b/modules/ROOT/pages/authentication-authorization/limitations.adoc index d7d2d2daf..1f09ca6ab 100644 --- a/modules/ROOT/pages/authentication-authorization/limitations.adoc +++ b/modules/ROOT/pages/authentication-authorization/limitations.adoc @@ -390,7 +390,7 @@ So due to the additional data access required by the security checks, this opera [[property-based-access-control-limitations]] === Property-based access control limitations -Extra node-level security checks are necessary when adding security rules based on property rules, and these can have a significant performance impact. +Extra element-level security checks are necessary when adding security rules based on property rules, and these can have a significant performance impact. The following example shows how the database behaves when adding security rules to roles `restricted` and `unrestricted`: [source, cypher] diff --git a/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc b/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc index d08507931..022c584c8 100644 --- a/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc +++ b/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc @@ -119,20 +119,22 @@ GRANT TRAVERSE ON GRAPH * FOR (n:Email) WHERE n.classification IS NULL TO regula === Deny a property-based privilege using a comparison operator -The following example shows how to deny permission to `READ` and `TRAVERSE` nodes where the property `classification` is different from `UNCLASSIFIED` to role `regularUsers`: +The following example shows how to deny permission to `READ` and `TRAVERSE` nodes and relationships where the property `classification` is different from `UNCLASSIFIED` to role `regularUsers`: [source, syntax, role="noheader"] ---- DENY MATCH {*} ON GRAPH * FOR (n) WHERE n.classification <> 'UNCLASSIFIED' TO regularUsers +DENY MATCH {*} ON GRAPH * FOR ()-[r]-() WHERE r.classification <> 'UNCLASSIFIED' TO regularUsers ---- === Grant a property-based privilege on all properties using a property value -The following example shows how to grant permission to `READ` all properties on nodes where the property `securityLevel` is higher than `3` to role `regularUsers`: +The following example shows how to grant permission to `READ` all properties on nodes and relationships where the property `securityLevel` is higher than `3` to role `regularUsers`: [source, syntax, role="noheader"] ---- GRANT READ {*} ON GRAPH * FOR (n) WHERE n.securityLevel > 3 TO regularUsers +GRANT READ {*} ON GRAPH * FOR ()-[r]-() WHERE r.securityLevel > 3 TO regularUsers ---- [NOTE] @@ -142,22 +144,24 @@ The role `regularUsers` does not need to have `READ` privilege for the property === Deny a property-based privilege using a list of values -The following example shows how to deny permission to `READ` all properties on nodes where the property `classification` is not included in the list of `[UNCLASSIFIED, PUBLIC]`: +The following example shows how to deny permission to `READ` all properties on nodes and relationships where the property `classification` is not included in the list of `[UNCLASSIFIED, PUBLIC]`: [source, syntax, role="noheader"] ---- DENY READ {*} ON GRAPH * FOR (n) WHERE NOT n.classification IN ['UNCLASSIFIED', 'PUBLIC'] TO regularUsers +DENY READ {*} ON GRAPH * FOR ()-[r]-() WHERE NOT r.classification IN ['UNCLASSIFIED', 'PUBLIC'] TO regularUsers ---- // The last two examples were added in 5.26. === Grant a property-based privilege using temporal value -The following example shows how to grant permission to `READ` all properties on nodes where the property `createdAt` is later than the current date: +The following example shows how to grant permission to `READ` all properties on nodes and relationships where the property `createdAt` is later than the current date: [source, syntax, role="noheader"] ---- GRANT READ {*} ON GRAPH * FOR (n) WHERE n.createdAt > date() TO regularUsers +GRANT READ {*} ON GRAPH * FOR ()-[r]-() WHERE r.createdAt > date() TO regularUsers ---- [NOTE] @@ -184,6 +188,7 @@ SHOW ROLE regularUsers PRIVILEGES AS REVOKE COMMANDS |=== |command |"REVOKE GRANT READ {*} ON GRAPH * FOR (n) WHERE n.createdAt > date('2024-10-25') FROM `regularUsers`" -a|Rows: 1 +|"REVOKE GRANT READ {*} ON GRAPH * FOR ()-[r]-() WHERE r.createdAt > date('2024-10-25') FROM `regularUsers`" +a|Rows: 2 |=== From 604eaff99d2ef6569e4ad80d5dc79f0c8acf88b0 Mon Sep 17 00:00:00 2001 From: Hannes Sandberg Date: Thu, 10 Apr 2025 15:00:51 +0200 Subject: [PATCH 3/7] minor changes --- .../authentication-authorization/limitations.adoc | 3 ++- .../property-based-access-control.adoc | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/ROOT/pages/authentication-authorization/limitations.adoc b/modules/ROOT/pages/authentication-authorization/limitations.adoc index 1f09ca6ab..7c654056b 100644 --- a/modules/ROOT/pages/authentication-authorization/limitations.adoc +++ b/modules/ROOT/pages/authentication-authorization/limitations.adoc @@ -391,7 +391,8 @@ So due to the additional data access required by the security checks, this opera [[property-based-access-control-limitations]] === Property-based access control limitations Extra element-level security checks are necessary when adding security rules based on property rules, and these can have a significant performance impact. -The following example shows how the database behaves when adding security rules to roles `restricted` and `unrestricted`: + +The following example shows how the database behaves when adding security rules for nodes to roles `restricted` and `unrestricted`, the same limitations apply to relationships as well: [source, cypher] ---- diff --git a/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc b/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc index 022c584c8..40d587073 100644 --- a/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc +++ b/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc @@ -12,9 +12,9 @@ CREATE ROLE regularUsers; [[property-based-access-control]] = Property-based access control -Property-based access control grants permissions to users to read element properties based on property/value conditions. +Property-based access control grants/denies permission to read or traverse elements based on property/value conditions. Each property-based privilege can only be restricted by a single property. -For information about read privileges and their syntax, see xref:authentication-authorization/privileges-reads.adoc[Read privileges]. +For information and syntax for these privileges, see xref:authentication-authorization/privileges-reads.adoc[Read privileges]. [IMPORTANT] ==== @@ -25,7 +25,7 @@ Users who can change this property can affect the granted property-based privile == Syntax -To specify the property/value conditions of the read privilege, you can use the following syntax: +To specify the property/value conditions of the privilege, you can use the following syntax: [source, syntax, role="noheader"] ---- @@ -99,13 +99,13 @@ Alternatively, you can use the following syntax: GRANT READ { address } ON GRAPH * FOR (:Email|Website {domain: 'exampledomain.com'}) TO regularUsers ---- -=== Grant a property-based privilege on a specific property using the value of that same property +=== Grant a property-based privilege on a specific property using the value of another property -The following example shows how to grant permission to `READ` the `since` property on `OWNS` relationships having `since` equal to `2025-01-01` to role `regularUsers`: +The following example shows how to grant permission to `READ` the `since` property on `OWNS` relationships having `classification` equal to `UNCLASSIFIED` to role `regularUsers`: [source, syntax, role="noheader"] ---- -GRANT READ { since } ON GRAPH * FOR ()-[o:OWNS]-() WHERE o.since = date("2025-01-01") TO regularUsers +GRANT READ { since } ON GRAPH * FOR ()-[o:OWNS]-() WHERE o.classification = 'UNCLASSIFIED' TO regularUsers ---- === Grant a property-based privilege using `NULL` From 64b3eab747d7d254c93dda1270a5795f79cf6c42 Mon Sep 17 00:00:00 2001 From: Phil Wright <95368282+phil198@users.noreply.github.com> Date: Fri, 11 Apr 2025 14:34:49 +0100 Subject: [PATCH 4/7] Apply suggestions from code review Co-authored-by: Therese Magnusson --- .../property-based-access-control.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc b/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc index 40d587073..0cfd0c20e 100644 --- a/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc +++ b/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc @@ -12,9 +12,9 @@ CREATE ROLE regularUsers; [[property-based-access-control]] = Property-based access control -Property-based access control grants/denies permission to read or traverse elements based on property/value conditions. +Property-based access control grants or denies permission to read or traverse nodes or relationships based on property/value conditions. Each property-based privilege can only be restricted by a single property. -For information and syntax for these privileges, see xref:authentication-authorization/privileges-reads.adoc[Read privileges]. +For information about and syntax for these privileges, see xref:authentication-authorization/privileges-reads.adoc[Read privileges]. [IMPORTANT] ==== From e4ba5bc8c31254df7d1882b2d55ead5923e20878 Mon Sep 17 00:00:00 2001 From: philipwright <95368282+phil198@users.noreply.github.com> Date: Fri, 11 Apr 2025 14:48:36 +0100 Subject: [PATCH 5/7] pr review comments --- .../limitations.adoc | 2 +- .../property-based-access-control.adoc | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/modules/ROOT/pages/authentication-authorization/limitations.adoc b/modules/ROOT/pages/authentication-authorization/limitations.adoc index 7c654056b..4ef143076 100644 --- a/modules/ROOT/pages/authentication-authorization/limitations.adoc +++ b/modules/ROOT/pages/authentication-authorization/limitations.adoc @@ -390,7 +390,7 @@ So due to the additional data access required by the security checks, this opera [[property-based-access-control-limitations]] === Property-based access control limitations -Extra element-level security checks are necessary when adding security rules based on property rules, and these can have a significant performance impact. +Extra node or relationship-level security checks are necessary when adding security rules based on property rules, and these can have a significant performance impact. The following example shows how the database behaves when adding security rules for nodes to roles `restricted` and `unrestricted`, the same limitations apply to relationships as well: diff --git a/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc b/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc index 0cfd0c20e..828da58f1 100644 --- a/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc +++ b/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc @@ -38,16 +38,18 @@ To specify the property/value conditions of the privilege, you can use the follo | NODE[S] { * | label[, ...] } | RELATIONSHIP[S] { * | rel-type[, ...] } | FOR { - -([var][:label["|" ...]] "{" property: value "}") - | (var[:label["|" ...]]) - | ()[<]-"["[var][:type["|" ...]] "{" property: value "}" "]"-[>]() - | ()[<]-"["var[:type["|" ...]]"]"-[>]() - WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } } - | (var[:label["|" ...]] -WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } } ) -} - + ([var][:label["|" ...]] "{" property: value "}") + | (var[:label["|" ...]]) + WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } } + | (var[:label["|" ...]] + WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } } ) + | ()[<]-"["[var][:type["|" ...]] "{" property: value "}" "]"-[>]() + | ()[<]-"["var[:type["|" ...]]"]"-[>]() + WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } } + | ()[<]-"["var[:type["|" ...]] + WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } } "]"-[>]() + } + ] {TO | FROM} role[, ...] ---- @@ -59,7 +61,7 @@ See xref:authentication-authorization/limitations.adoc#property-based-access-con When having property rules, the following factors can worsen the impact on performance: -* The number of properties on the elements concerned (more properties = greater performance impact). +* The number of properties on the nodes and relationships concerned (more properties = greater performance impact). * The number of property-based privileges (more property-based privileges = greater performance impact). * The type of the privilege: `TRAVERSE` property-based privileges have greater performance impact than `READ` property-based privileges. * The type of storage medium in operation. The impact of the property-based privileges on performance is considerably amplified by accessing disc storage. @@ -99,8 +101,6 @@ Alternatively, you can use the following syntax: GRANT READ { address } ON GRAPH * FOR (:Email|Website {domain: 'exampledomain.com'}) TO regularUsers ---- -=== Grant a property-based privilege on a specific property using the value of another property - The following example shows how to grant permission to `READ` the `since` property on `OWNS` relationships having `classification` equal to `UNCLASSIFIED` to role `regularUsers`: [source, syntax, role="noheader"] From c6f16143676492486d15172ee2114c39bf8ff2c0 Mon Sep 17 00:00:00 2001 From: Hannes Sandberg Date: Tue, 15 Apr 2025 11:49:53 +0200 Subject: [PATCH 6/7] Update modules/ROOT/pages/authentication-authorization/limitations.adoc Co-authored-by: Reneta Popova --- .../ROOT/pages/authentication-authorization/limitations.adoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/authentication-authorization/limitations.adoc b/modules/ROOT/pages/authentication-authorization/limitations.adoc index 4ef143076..d6d42a190 100644 --- a/modules/ROOT/pages/authentication-authorization/limitations.adoc +++ b/modules/ROOT/pages/authentication-authorization/limitations.adoc @@ -392,7 +392,8 @@ So due to the additional data access required by the security checks, this opera === Property-based access control limitations Extra node or relationship-level security checks are necessary when adding security rules based on property rules, and these can have a significant performance impact. -The following example shows how the database behaves when adding security rules for nodes to roles `restricted` and `unrestricted`, the same limitations apply to relationships as well: +The following example shows how the database behaves when adding security rules for nodes to roles `restricted` and `unrestricted`. +The same limitations apply to relationships: [source, cypher] ---- From 108884c50489a99a56e21cd691b78f0f452d59f1 Mon Sep 17 00:00:00 2001 From: Hannes Sandberg Date: Tue, 15 Apr 2025 12:27:47 +0200 Subject: [PATCH 7/7] Update modules/ROOT/pages/authentication-authorization/limitations.adoc Co-authored-by: Therese Magnusson --- .../ROOT/pages/authentication-authorization/limitations.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ROOT/pages/authentication-authorization/limitations.adoc b/modules/ROOT/pages/authentication-authorization/limitations.adoc index d6d42a190..9879bd63b 100644 --- a/modules/ROOT/pages/authentication-authorization/limitations.adoc +++ b/modules/ROOT/pages/authentication-authorization/limitations.adoc @@ -393,7 +393,7 @@ So due to the additional data access required by the security checks, this opera Extra node or relationship-level security checks are necessary when adding security rules based on property rules, and these can have a significant performance impact. The following example shows how the database behaves when adding security rules for nodes to roles `restricted` and `unrestricted`. -The same limitations apply to relationships: +The same limitations apply to relationships. [source, cypher] ----