From fc251c3e21726ac6d8a39a07abd1b2fe71a1a22b Mon Sep 17 00:00:00 2001 From: Athman Gude Date: Tue, 25 Apr 2023 11:52:18 +0300 Subject: [PATCH 01/10] Update permissions.md Moved properties to correct objects --- specs/permissions.md | 53 +++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/specs/permissions.md b/specs/permissions.md index bc4689435..625d914aa 100644 --- a/specs/permissions.md +++ b/specs/permissions.md @@ -51,20 +51,12 @@ The permissions object contains the details about a permission that can be used ### note The "note" member is a freeform string that provides additional details about the permission that cannot be determined from the other members of the permission object. -### implicit -The "implicit" member is a boolean value that indicates that the current permission object is implied. The default value is "false". This member is usually set to "true" in combination with a "alsoRequires" expression. - -> Note: This member enables support for legacy paths that have been created that do not require any permission. Also, when used in combination with the "alsoRequires" member it enables support for the Microsoft Graph "create subscription" endpoint and the "Search query" endpoint. - ### schemes The "schemes" member is a REQUIRED JSON object whose members are [Scheme objects](#schemeObject) supported by the permission. The key of each member is an identifier of the scheme and the value is a [Scheme object](#schemeObject) that contains descriptions of the permission within the scheme. ### pathSets The "pathSets" member is a REQUIRED JSON Array. Each element of the array is a [pathSet object](#pathSetObject). -### privilegeLevel -The "privilegeLevel" member value provides a hint as to the risks of consenting this permissions. Valid values include: low, medium and high. - ## Provisioning Info Object The provisioning info object contains information related to the deployment of the permission into its environment. This object should only contain information that is not required by a consumer of the API and can safely be removed in any public projection of the permissions information. @@ -113,9 +105,6 @@ The "methods" member is a REQUIRED array of strings that represent the HTTP meth ### paths The "paths" member is a REQUIRED object whose keys contain a simplified URI template to identify the resources protected by this permission object. -### alsoRequires -The "alsoRequires" member is logical expression of permissions that must be presented as claims alongside the current permission. - ``` (User.Read | User.Read.All) & Group.Read ``` @@ -137,15 +126,18 @@ The scheme object has members that describe the permission within the context of "adminDescription": "Allows the app to read and report the signed-in user's activity in the app.", "userConsentDisplayName": "Read and write app activity to users'activity feed", "userConsentDescription": "Allows the app to read and report the signed-in user's activity in the app.", - "requiresAdminConsent": true + "requiresAdminConsent": true, + "privilegeLevel": 3 }, "DelegatedPersonal": { "userConsentDisplayName": "Read and write app activity to users'activity feed", - "userConsentDescription": "Allows the app to read and report the signed-in user's activity in the app." + "userConsentDescription": "Allows the app to read and report the signed-in user's activity in the app.", + "privilegeLevel": 2 }, "Application": { "adminDisplayName": "Read and write app activity to users' activity feed", "adminDescription": "Allows the app to read and report the signed-in user's activity in the app.", + "privilegeLevel": 5 } ``` @@ -164,17 +156,32 @@ The "userConsentDescription" member is a REQUIRED string that describes the perm ### requiresAdminConsent The "requiresAdminConsent" member is a boolean value with a default value of false. When true, this permission can only be consented by an adminstrator. +### privilegeLevel +The "privilegeLevel" member is an integer value that provides a hint as to the risks of consenting to the permissions. Valid values range from 1 (least privileged) to 5 (most privileged). The value is arrived at by considering the breadth of access that a permission will give access to and the sensitivity of the operations allowed by the permission. + ## Path Object The path object contains properties that affect how the permission object controls access to resource identified by the key of the path object. ```json "paths": { - "/me/activities/{id}": { - "leastPrivilegePermission": ["DelegatedWork", "DelegatedPersonal"] - } + "/me/activities/{id}": "least=DelegatedWork,DelegatedPersonal" +``` + ``` +"paths": { + "/search/query": "implicit=true;alsoRequires=Bookmark.Read.All;least=Delegated" +} +``` + +### alsoRequires +The "alsoRequires" member is logical expression of permissions that must be presented as claims alongside the current permission. + +### implicit +The "implicit" member is a boolean value that indicates that the current permission object is implied. The default value is "false". This member is usually set to "true" in combination with a "alsoRequires" expression. -### leastPrivilegePermission +> Note: This member enables support for legacy paths that have been created that do not require any permission. Also, when used in combination with the "alsoRequires" member it enables support for the Microsoft Graph "create subscription" endpoint and the "Search query" endpoint. + +### least (least privilege permission) The "leastPrivilegePermission" member is an array of strings that identify the schemes for which the current permission is the least privilege permission for accessing the path. Each string value in the array MUST match one of the schemes defined in the [pathSet Object](#pathsetObject) ## Appendix A. Model Diagram @@ -243,7 +250,6 @@ classDiagram "additionalProperties": false, "properties": { "note": {"type": "string"}, - "implicit": {"type": "boolean"}, "isHidden": {"type": "boolean"}, "ownerEmail": {"type": "string"}, "privilegeLevel": { @@ -256,10 +262,6 @@ classDiagram "type": "string" } }, - "alsoRequires": { - "type": "string", - "pattern": "[\\w]+\\.[\\w]+[\\.[\\w]+]?" - }, "schemes": { "type": "object", "patternProperties": { @@ -320,10 +322,15 @@ classDiagram "path": { "type": "object", "properties": { + "alsoRequires": { + "type": "string", + "pattern": "[\\w]+\\.[\\w]+[\\.[\\w]+]?" + }, + "implicit": {"type": "boolean"}, "leastPrivilegePermission": { "type": "array", "items": { "type":"string"} - } + }, }, "scheme": { "type": "object", From 09acc05c76d9d463fbf5fc03fefb4c1501ff84c2 Mon Sep 17 00:00:00 2001 From: Athman Gude Date: Tue, 25 Apr 2023 12:15:30 +0300 Subject: [PATCH 02/10] updated model schema object properties and definitions --- specs/permissions.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/specs/permissions.md b/specs/permissions.md index 625d914aa..81f3fb3ba 100644 --- a/specs/permissions.md +++ b/specs/permissions.md @@ -30,7 +30,7 @@ The canonical model for a permissions document is a JSON [JSON] object. When ser "schemes": ["DelegatedWork"], "methods": ["GET"], "paths": { - "/print/settings": {} + "/print/settings": "" } }] } @@ -90,7 +90,7 @@ A pathSet object identifies a set of paths that are accessible and have a common "schemeKeys": ["Application"], "methods": ["GET,POST"], "paths": { - "/print/settings": {} + "/print/settings": "" } } ] @@ -157,7 +157,7 @@ The "userConsentDescription" member is a REQUIRED string that describes the perm The "requiresAdminConsent" member is a boolean value with a default value of false. When true, this permission can only be consented by an adminstrator. ### privilegeLevel -The "privilegeLevel" member is an integer value that provides a hint as to the risks of consenting to the permissions. Valid values range from 1 (least privileged) to 5 (most privileged). The value is arrived at by considering the breadth of access that a permission will give access to and the sensitivity of the operations allowed by the permission. +The "privilegeLevel" member is an integer value that provides a hint as to the risks of consenting to the permissions. Valid values range from 1 (least privileged) to 5 (most privileged). The value is arrived at by considering the breadth of access that a permission will give access to and the sensitivity of the operations allowed by the permission. The same permission can have different privilege levels when used with different schemes. ## Path Object The path object contains properties that affect how the permission object controls access to resource identified by the key of the path object. @@ -167,7 +167,7 @@ The path object contains properties that affect how the permission object contro "/me/activities/{id}": "least=DelegatedWork,DelegatedPersonal" ``` -``` +```json "paths": { "/search/query": "implicit=true;alsoRequires=Bookmark.Read.All;least=Delegated" } @@ -191,7 +191,6 @@ classDiagram class Permission{ note: string - implicit: bool requiredEnvironments: string[] ownerEmail:string isHidden: bool @@ -203,13 +202,14 @@ classDiagram class PathSet{ schemeKeys: string[] methods: string[] - alsoRequires: stringExpression includedProperties: string[] excludedProperties: string[] } PathSet "1" --> "*" Path:paths class Path{ + alsoRequires: stringExpression + implicit: bool leastPrivilegePermission: string } @@ -219,6 +219,7 @@ classDiagram userDisplayName: string userDescription: string requiresAdminConsent: string + privilegeLevel: int } ``` From 8489c09a0f2643b7667f8d0bbcf3c2901f3b8b48 Mon Sep 17 00:00:00 2001 From: Athman Gude Date: Tue, 25 Apr 2023 12:25:33 +0300 Subject: [PATCH 03/10] updated JSON schema in appendix --- specs/permissions.md | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/specs/permissions.md b/specs/permissions.md index 81f3fb3ba..9c771ed68 100644 --- a/specs/permissions.md +++ b/specs/permissions.md @@ -160,7 +160,7 @@ The "requiresAdminConsent" member is a boolean value with a default value of fal The "privilegeLevel" member is an integer value that provides a hint as to the risks of consenting to the permissions. Valid values range from 1 (least privileged) to 5 (most privileged). The value is arrived at by considering the breadth of access that a permission will give access to and the sensitivity of the operations allowed by the permission. The same permission can have different privilege levels when used with different schemes. ## Path Object -The path object contains properties that affect how the permission object controls access to resource identified by the key of the path object. +The path object contains stringified properties and value pairs that affect how the permission object controls access to resource identified by the key of the path object. ```json "paths": { @@ -321,18 +321,7 @@ classDiagram } }, "path": { - "type": "object", - "properties": { - "alsoRequires": { - "type": "string", - "pattern": "[\\w]+\\.[\\w]+[\\.[\\w]+]?" - }, - "implicit": {"type": "boolean"}, - "leastPrivilegePermission": { - "type": "array", - "items": { "type":"string"} - }, - }, + "type": "string", "scheme": { "type": "object", "properties": { From 8ed0e256fc0b5064b7637a2bcce395b494f026b7 Mon Sep 17 00:00:00 2001 From: Athman Gude Date: Wed, 26 Apr 2023 13:02:36 +0300 Subject: [PATCH 04/10] removed provisioningInfo from permissions schema --- specs/permissions.md | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/specs/permissions.md b/specs/permissions.md index 9c771ed68..3dd1ffcef 100644 --- a/specs/permissions.md +++ b/specs/permissions.md @@ -57,19 +57,9 @@ The "schemes" member is a REQUIRED JSON object whose members are [Scheme objects ### pathSets The "pathSets" member is a REQUIRED JSON Array. Each element of the array is a [pathSet object](#pathSetObject). -## Provisioning Info Object - -The provisioning info object contains information related to the deployment of the permission into its environment. This object should only contain information that is not required by a consumer of the API and can safely be removed in any public projection of the permissions information. - -### isHidden -The "isHidden" member is a boolean value that indicates if a permission should be publicly usable in the API. - -### requiredEnvironments -The "requiredEnvironments" member is an array of strings that identifies the deployment environments in which the permission SHOULD be supported. When this member is not present, support for all environments is implied. - -### resourceAppId -The "resourceAppId" member value provides an identifier of the resource server that is used to enforce Conditional Access checks for this permission. +## Owner Info Object +The owner info object contains information related to the ownership of the permission. This object should only contain information that is not required by a consumer of the API and can safely be removed in any public projection of the permissions information. ### ownerSecurityGroup The "ownerSecurityGroup" member is a REQUIRED string that provides a contact mechanism for communicating with the owners of the permission. It is important that owners of permissions are aware when new paths are added to an existing permission. @@ -115,7 +105,6 @@ The "includedProperties" member is an array of strings that identify properties ### excludedProperties The "excludedProperties" member is an array of strings that identify properties of the resource representation returned by the path, that are not accessible with the permission. - ## Scheme Object The scheme object has members that describe the permission within the context of the scheme. Additional members provide behavioral constraints of the permission when used with the scheme. @@ -252,11 +241,6 @@ classDiagram "properties": { "note": {"type": "string"}, "isHidden": {"type": "boolean"}, - "ownerEmail": {"type": "string"}, - "privilegeLevel": { - "type":"string", - "enum":["low","medium","high"] - } "requiredEnvironments": { "type": "array", "items": { @@ -322,6 +306,7 @@ classDiagram }, "path": { "type": "string", + }, "scheme": { "type": "object", "properties": { @@ -339,6 +324,10 @@ classDiagram }, "userConsentDescription": { "type": "string" + }, + "privilegeLevel": { + "type": "int", + "enum": [1, 2, 3, 4, 5] } } } From 475b4f3e394c2e6a0276bb4948415e3e3c34c7b6 Mon Sep 17 00:00:00 2001 From: Athman Gude Date: Wed, 26 Apr 2023 13:02:58 +0300 Subject: [PATCH 05/10] added provisioningInfo file --- specs/provisioningInfo.md | 56 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 specs/provisioningInfo.md diff --git a/specs/provisioningInfo.md b/specs/provisioningInfo.md new file mode 100644 index 000000000..f97607101 --- /dev/null +++ b/specs/provisioningInfo.md @@ -0,0 +1,56 @@ +# Provisioning Info for Permissions in Graph + +## Abstract +The provisioning info file is a JSON file that contains a list of permissions and the cloud environments in which they are available. + +## Introduction +The JSON permissions model seeks to be the authoritative source of truth for for data on permissions to API mapping. We have restricted the contents of the JSON permission files to modeling data that has to be reviewed for every change. This does not include data about the cloud environments in which API workloads intend to publish permissions to. Some of that data is only known after the permission has been published to the environment and would have to either be automatically or manually updated by the publishing team back to the permissions model file after the change review. This should not require a review of the change to the permission file. The provisioning info file is complementary to the JSON permissions model files and allows us to keep the permissions model file as the authoritative source of truth for permissions modeling data while allowing us to maintain a separate source of truth for cloud availability data. + +## The Provisioning Info file +The provisioning info file is a single file for all permissions. Permissions are still the primary concept with a many to many relationship between permissions and cloud environments. Permission claim values are the top level members to enable quick lookup for provisioning for a permission. Not all implemented schemes of a permission are published consistently across all environments and even when published they would happen to have different unique identifiers. The provisioning info file allows us to model the cloud availability of each scheme of a permission. + +```json +"provisioningInfo": { + “Foo.Read.All”: { + "requiredEnvironments": [ + { + "mooncake": { + "schemes": [ + { + "DelegatedWork": { + "isPresent": true, + "isHidden": false, + "isDisabled": false, + "id": "bed71653-0fa8-42a0-b33c-a1aab02ecda6" + } + } + ] + }, + "global": { + "schemes": [ + { + "DelegatedWork": { + "isPresent": true, + "isHidden": false, + "isDisabled": false, + "id": "bed71653-0fa8-42a0-b33c-a1aab02ecda6" + } + } + ] + } + } + ] + } +} +``` + +### isHidden +The "isHidden" member is a boolean value that indicates if a permission should be publicly usable in the API. + +### requiredEnvironments +The "requiredEnvironments" member is an array of strings that identifies the deployment environments in which the permission SHOULD be supported. When this member is not present, support for all environments is implied. + +### resourceAppId +The "resourceAppId" member value provides an identifier of the resource server that is used to enforce Conditional Access checks for this permission. + + From 54dad8c3559ecdd98373b3f47c28de6247ece2a8 Mon Sep 17 00:00:00 2001 From: Athman Gude Date: Tue, 9 May 2023 11:38:23 +0300 Subject: [PATCH 06/10] removed proposal for provisioning info --- specs/provisioningInfo.md | 56 --------------------------------------- 1 file changed, 56 deletions(-) delete mode 100644 specs/provisioningInfo.md diff --git a/specs/provisioningInfo.md b/specs/provisioningInfo.md deleted file mode 100644 index f97607101..000000000 --- a/specs/provisioningInfo.md +++ /dev/null @@ -1,56 +0,0 @@ -# Provisioning Info for Permissions in Graph - -## Abstract -The provisioning info file is a JSON file that contains a list of permissions and the cloud environments in which they are available. - -## Introduction -The JSON permissions model seeks to be the authoritative source of truth for for data on permissions to API mapping. We have restricted the contents of the JSON permission files to modeling data that has to be reviewed for every change. This does not include data about the cloud environments in which API workloads intend to publish permissions to. Some of that data is only known after the permission has been published to the environment and would have to either be automatically or manually updated by the publishing team back to the permissions model file after the change review. This should not require a review of the change to the permission file. The provisioning info file is complementary to the JSON permissions model files and allows us to keep the permissions model file as the authoritative source of truth for permissions modeling data while allowing us to maintain a separate source of truth for cloud availability data. - -## The Provisioning Info file -The provisioning info file is a single file for all permissions. Permissions are still the primary concept with a many to many relationship between permissions and cloud environments. Permission claim values are the top level members to enable quick lookup for provisioning for a permission. Not all implemented schemes of a permission are published consistently across all environments and even when published they would happen to have different unique identifiers. The provisioning info file allows us to model the cloud availability of each scheme of a permission. - -```json -"provisioningInfo": { - “Foo.Read.All”: { - "requiredEnvironments": [ - { - "mooncake": { - "schemes": [ - { - "DelegatedWork": { - "isPresent": true, - "isHidden": false, - "isDisabled": false, - "id": "bed71653-0fa8-42a0-b33c-a1aab02ecda6" - } - } - ] - }, - "global": { - "schemes": [ - { - "DelegatedWork": { - "isPresent": true, - "isHidden": false, - "isDisabled": false, - "id": "bed71653-0fa8-42a0-b33c-a1aab02ecda6" - } - } - ] - } - } - ] - } -} -``` - -### isHidden -The "isHidden" member is a boolean value that indicates if a permission should be publicly usable in the API. - -### requiredEnvironments -The "requiredEnvironments" member is an array of strings that identifies the deployment environments in which the permission SHOULD be supported. When this member is not present, support for all environments is implied. - -### resourceAppId -The "resourceAppId" member value provides an identifier of the resource server that is used to enforce Conditional Access checks for this permission. - - From 50fcdb060be0f5738bea34ff95cbdd29bd2a0fbc Mon Sep 17 00:00:00 2001 From: Athman Gude Date: Tue, 9 May 2023 11:42:16 +0300 Subject: [PATCH 07/10] schema updates --- specs/permissions.md | 1 - 1 file changed, 1 deletion(-) diff --git a/specs/permissions.md b/specs/permissions.md index 3dd1ffcef..cdf0f58a4 100644 --- a/specs/permissions.md +++ b/specs/permissions.md @@ -183,7 +183,6 @@ classDiagram requiredEnvironments: string[] ownerEmail:string isHidden: bool - privilegeLevel: string } Permission "1" --> "*" PathSet:pathSets Permission "1" --> "*" Scheme:schemes From bdbbfaab87e8bd2248fbf9499d5716ea449b03b0 Mon Sep 17 00:00:00 2001 From: Athman Gude Date: Tue, 9 May 2023 13:34:14 +0300 Subject: [PATCH 08/10] added boolean expressions for additional permissions --- specs/permissions.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/specs/permissions.md b/specs/permissions.md index cdf0f58a4..8de5d37fd 100644 --- a/specs/permissions.md +++ b/specs/permissions.md @@ -165,6 +165,24 @@ The path object contains stringified properties and value pairs that affect how ### alsoRequires The "alsoRequires" member is logical expression of permissions that must be presented as claims alongside the current permission. +The value `alsoRequires` member can express complex logical expressions using boolean operators. + +```json +"paths": { + "/search/query": "implicit=true;alsoRequires=Bookmark.Read.All||ChatMessages.Read;least=Delegated" +} +``` +The example above shows that any one of a list of additional permissions are required. + +We can also express more complex scenarios using parenthesis. + +```json +"paths": { + "/foo/bar": "implicit=true;alsoRequires=(PermissionA.Read.All||PermissionB.Read)&&(PermissionC.Read.All&&PermissionD.Read.All);least=Delegated", + "/foo/barz": "implicit=true;alsoRequires=(PermissionA.Read.All&&PermissionB.Read)||(PermissionC.Read.All&&PermissionD.Read.All);least=Delegated" +} +``` + ### implicit The "implicit" member is a boolean value that indicates that the current permission object is implied. The default value is "false". This member is usually set to "true" in combination with a "alsoRequires" expression. From 965ddb2d7b445fe41b872ba88871f6047105726c Mon Sep 17 00:00:00 2001 From: Athman Gude Date: Wed, 17 May 2023 17:23:53 +0300 Subject: [PATCH 09/10] updated spec definition --- specs/permissions.md | 35 ++++++----------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/specs/permissions.md b/specs/permissions.md index 8de5d37fd..9fea174a3 100644 --- a/specs/permissions.md +++ b/specs/permissions.md @@ -57,11 +57,11 @@ The "schemes" member is a REQUIRED JSON object whose members are [Scheme objects ### pathSets The "pathSets" member is a REQUIRED JSON Array. Each element of the array is a [pathSet object](#pathSetObject). -## Owner Info Object +## OwnerInfo Object The owner info object contains information related to the ownership of the permission. This object should only contain information that is not required by a consumer of the API and can safely be removed in any public projection of the permissions information. ### ownerSecurityGroup -The "ownerSecurityGroup" member is a REQUIRED string that provides a contact mechanism for communicating with the owners of the permission. It is important that owners of permissions are aware when new paths are added to an existing permission. +The "ownerSecurityGroup" member is a string that provides a contact mechanism for communicating with the owners of the permission. It is important that owners of permissions are aware when new paths are added to an existing permission. This member is only required when `ownerInfo` is present. ## PathSet Object A pathSet object identifies a set of paths that are accessible and have a common set of security characteristics, such as HTTP methods and schemes. Ideally, a permission object contains a single pathSet object. This indicates that all paths protected by the permission support the same characteristics. In practice there are cases where support is not uniform. Distinct pathSet objects can be created to separate the paths with varying characteristics. @@ -95,7 +95,10 @@ The "methods" member is a REQUIRED array of strings that represent the HTTP meth ### paths The "paths" member is a REQUIRED object whose keys contain a simplified URI template to identify the resources protected by this permission object. -``` +### alsoRequires +The "alsoRequires" member is logical expression of permissions that must be presented as claims alongside the current permission. + +```json (User.Read | User.Read.All) & Group.Read ``` @@ -162,32 +165,6 @@ The path object contains stringified properties and value pairs that affect how } ``` -### alsoRequires -The "alsoRequires" member is logical expression of permissions that must be presented as claims alongside the current permission. - -The value `alsoRequires` member can express complex logical expressions using boolean operators. - -```json -"paths": { - "/search/query": "implicit=true;alsoRequires=Bookmark.Read.All||ChatMessages.Read;least=Delegated" -} -``` -The example above shows that any one of a list of additional permissions are required. - -We can also express more complex scenarios using parenthesis. - -```json -"paths": { - "/foo/bar": "implicit=true;alsoRequires=(PermissionA.Read.All||PermissionB.Read)&&(PermissionC.Read.All&&PermissionD.Read.All);least=Delegated", - "/foo/barz": "implicit=true;alsoRequires=(PermissionA.Read.All&&PermissionB.Read)||(PermissionC.Read.All&&PermissionD.Read.All);least=Delegated" -} -``` - -### implicit -The "implicit" member is a boolean value that indicates that the current permission object is implied. The default value is "false". This member is usually set to "true" in combination with a "alsoRequires" expression. - -> Note: This member enables support for legacy paths that have been created that do not require any permission. Also, when used in combination with the "alsoRequires" member it enables support for the Microsoft Graph "create subscription" endpoint and the "Search query" endpoint. - ### least (least privilege permission) The "leastPrivilegePermission" member is an array of strings that identify the schemes for which the current permission is the least privilege permission for accessing the path. Each string value in the array MUST match one of the schemes defined in the [pathSet Object](#pathsetObject) From 3cd1bf19d55c49031166dd819c7b6cd99e989b6c Mon Sep 17 00:00:00 2001 From: Athman Gude Date: Wed, 17 May 2023 17:26:28 +0300 Subject: [PATCH 10/10] toned down stress on requirement of ownerSecurityGroup --- specs/permissions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/permissions.md b/specs/permissions.md index 9fea174a3..74d53f934 100644 --- a/specs/permissions.md +++ b/specs/permissions.md @@ -61,7 +61,7 @@ The "pathSets" member is a REQUIRED JSON Array. Each element of the array is a [ The owner info object contains information related to the ownership of the permission. This object should only contain information that is not required by a consumer of the API and can safely be removed in any public projection of the permissions information. ### ownerSecurityGroup -The "ownerSecurityGroup" member is a string that provides a contact mechanism for communicating with the owners of the permission. It is important that owners of permissions are aware when new paths are added to an existing permission. This member is only required when `ownerInfo` is present. +The "ownerSecurityGroup" member is a string that provides a contact mechanism for communicating with the owners of the permission. It is important that owners of permissions are aware when new paths are added to an existing permission. This member is REQUIRED when `ownerInfo` is present. ## PathSet Object A pathSet object identifies a set of paths that are accessible and have a common set of security characteristics, such as HTTP methods and schemes. Ideally, a permission object contains a single pathSet object. This indicates that all paths protected by the permission support the same characteristics. In practice there are cases where support is not uniform. Distinct pathSet objects can be created to separate the paths with varying characteristics.