diff --git a/documentation/IDTA-01004/modules/ROOT/nav.adoc b/documentation/IDTA-01004/modules/ROOT/nav.adoc index efc4042..d59ce8b 100644 --- a/documentation/IDTA-01004/modules/ROOT/nav.adoc +++ b/documentation/IDTA-01004/modules/ROOT/nav.adoc @@ -31,6 +31,8 @@ SPDX-License-Identifier: CC-BY-4.0 ** xref:./annex/json-access-rule-examples.adoc[Examples of Access Rules in JSON serialization] +** xref:./annex/route-examples.adoc[Examples of ROUTEs and HTTP requests] + * xref:changelog.adoc[Change Log] diff --git a/documentation/IDTA-01004/modules/ROOT/pages/access-rule-model.adoc b/documentation/IDTA-01004/modules/ROOT/pages/access-rule-model.adoc index 5a7b92e..82e4493 100644 --- a/documentation/IDTA-01004/modules/ROOT/pages/access-rule-model.adoc +++ b/documentation/IDTA-01004/modules/ROOT/pages/access-rule-model.adoc @@ -69,6 +69,8 @@ The Security Model is explained step by step in the following Chapter <> is intended to improve interoperability when ROUTE objects are used for authorization decisions. +Concrete informative examples for RIGHTS, ROUTEs and HTTP requests are given in xref:annex/route-examples.adoc[]. + +[[table-rights-to-verbs]] +.Indicative mapping of RIGHTS to AAS operation verbs and HTTP methods +[cols="1,2,2,4",options="header"] +|=== +|Right +|Operation verb +|HTTP method +|Meaning + +|CREATE +|Post +|POST +|Permission to create a new resource at a collection or factory-style endpoint. + +|CREATE +|Put +|PUT +|Permission to create a new resource at a client-addressable resource endpoint if the addressed resource does not yet exist. + +|READ +|Get, GetAll +|GET +|Permission to read resource content. + +|UPDATE +|Patch +|PATCH +|Permission to partially update an existing resource. + +|UPDATE +|Put +|PUT +|Permission to replace an existing resource at a client-addressable resource endpoint. + +|DELETE +|Delete +|DELETE +|Permission to delete an existing resource. + +|EXECUTE +|Invoke +|POST +|Permission to invoke an operation. + +|VIEW +|GetAll +|GET +|Permission to see that a resource exists, typically as identifiers, references, idShort values, or descriptor entries without access to the full resource value. + +|ALL +|n/a +|n/a +|Abbreviation for all eligible rights. +|=== + +The mapping is not intended to redefine AAS Part 2 operations. +It clarifies how the abstract RIGHT values are typically applied when an authorization decision is made for a concrete HTTP route. +The same HTTP method can therefore be used for different rights depending on the targeted interface operation and the representation that is returned. +For example, GET may correspond to READ for full content access or VIEW for reference-only or existence-only access. +Search-style read operations may also use POST in specific interfaces. +For endpoints with create-or-replace or upsert semantics, the required right depends on whether the addressed resource already exists. +For example, `PUT /api/v3/submodels/{submodelIdentifier}` requires CREATE if the addressed submodel does not yet exist and UPDATE if it already exists. +The same principle applies to endpoint-specific POST operations such as `POST /api/v3/lookup/shells/{aasIdentifier}` if the endpoint creates the addressed resource when absent and updates it when present. + + ==== Attributes [source,bnf,linenums] @@ -182,7 +255,21 @@ include::partial$bnf/objects.bnf[] Objects to be protected are either API Routes, Identifiables (e.g. AAS or Submodel), Referables (e.g. SubmodelElements), Descriptors or Fragments of those (e.g. AssetId, SemanticId, SpecificAssetId). -Routes may use * or end with a *, which means that all routes with a given prefix are valid. +ROUTE defines the endpoint address of an interface operation. +This allows access control to be defined for single interface operations, groups of interface operations, or complete interfaces. + +For AAS HTTP/REST APIs, a ROUTE literal shall use the URL path part only, i.e. the part of the endpoint address starting with "/". +The scheme, authority, query part and fragment identifier are not part of ROUTE matching. +The deployment-specific server base URL is therefore handled separately from the ROUTE literal. + +ROUTE matching uses the following rules: + +* A ROUTE literal starting with "/" and not ending with "*" matches one concrete path. +* The literal "*" matches all routes. +* A ROUTE literal ending with "*" matches all routes with the given prefix. + +Examples are "/shells", "/shells/*" and "*". +For HTTP/REST APIs the examples in xref:annex/route-examples.adoc[] show how ROUTE literals can be combined with RIGHTS and concrete request examples from AAS Part 2. An Object Group defines a list of single objects and/or a list of names of other object groups. diff --git a/documentation/IDTA-01004/modules/ROOT/pages/annex/route-examples.adoc b/documentation/IDTA-01004/modules/ROOT/pages/annex/route-examples.adoc new file mode 100644 index 0000000..89726a0 --- /dev/null +++ b/documentation/IDTA-01004/modules/ROOT/pages/annex/route-examples.adoc @@ -0,0 +1,234 @@ +//// +Copyright (c) 2025 Industrial Digital Twin Association + +This work is licensed under a [Creative Commons Attribution 4.0 International License]( +https://creativecommons.org/licenses/by/4.0/). + +SPDX-License-Identifier: CC-BY-4.0 + +//// + += Examples of ROUTEs and HTTP requests + +This annex is informative. +It gives concrete examples for RIGHTS and ROUTE objects using AAS Part 2 HTTP/REST path templates. + +Unless stated otherwise, the examples use the server base URL `https://admin-shell.io/api/v3/` as published in the AAS Part 2 OpenAPI descriptions. +Only the URL path is relevant for ROUTE matching. + +== Rights, operation verbs and HTTP methods + +The following diagram illustrates one possible relation between abstract rights, operation verbs and HTTP methods. +It is an example to support the interpretation of the normative mapping in xref:access-rule-model.adoc#table-rights-to-verbs[]. + +[plantuml,annex-rights-verbs-http-methods,svg] +.... +include::partial$diagrams/rights-verbs-http-methods.puml[] +.... + +== Example requests by right + +The following requests use real path templates from the published AAS Part 2 OpenAPI descriptions. +They are representative examples for access control decisions on ROUTE objects. +For client-addressable routes with create-or-replace or upsert semantics, the required right depends on whether the addressed resource already exists. +In the examples below, `PUT /api/v3/submodels/{id}` and `POST /api/v3/lookup/shells/{someencodedid}` therefore appear under both CREATE and UPDATE with different preconditions. + +=== CREATE + +Here are endpoints that can need CREATE rights to create new resources or entries in the repository or registry. PUT endpoints with create-or-replace semantics can require UPDATE instead of CREATE rights if the addressed resource already exists. + +Example 1: create a new AAS in the repository by POST. + +[source,http] +---- +POST /api/v3/shells +---- + +Example 2: create a new submodel at a route by PUT if the addressed submodel does not yet exist. + +[source,http] +---- +PUT /api/v3/submodels/aHR0cHM6Ly9leGFtcGxlLmNvbS9zbS9uYW1lcGxhdGU +---- + +Example 3: create a new submodel element in a collection by POST. + +[source,http] +---- +POST /api/v3/submodels/aHR0cHM6Ly9leGFtcGxlLmNvbS9zbS9uYW1lcGxhdGU/submodel-elements +---- + +Example 4: create a lookup entry by POST if the addressed entry does not yet exist. + +[source,http] +---- +POST /api/v3/lookup/shells/someencodedid +---- + +=== READ + +Here are endpoints that can need READ rights to access existing resources or entries in the repository or registry. VIEW right can be used as an alternative for GetAll endpointsif only existence information, references, identifiers, or descriptor entries shall be accessible. + +Example 1: read all AAS objects. + +[source,http] +---- +GET /api/v3/shells?limit=50 +---- + +Example 2: read one submodel. + +[source,http] +---- +GET /api/v3/submodels/aHR0cHM6Ly9leGFtcGxlLmNvbS9zbS9uYW1lcGxhdGU +---- + +Example 3: read one submodel element by path. + +[source,http] +---- +GET /api/v3/submodel/aHR0cHM6Ly9leGFtcGxlLmNvbS9hYXMvMTIzNA/submodel-elements/Identification/ManufacturerName +---- + +Example 4: read all shell descriptors from the registry. + +[source,http] +---- +GET /api/v3/shell-descriptors +---- + +Example 5: resolve AAS IDs through discovery. + +This is an example of a read-like search operation implemented as POST. + +[source,http] +---- +POST /api/v3/lookup/shellsByAssetLink +---- + +=== UPDATE + +Here are endpoints that can need UPDATE rights to modify existing resources or entries in the repository or registry. For client-addressable routes with create-or-replace semantics, CREATE rights can be sufficient if the addressed resource does not yet exist. + +Example 1: replace an existing AAS resource by PUT. + +[source,http] +---- +PUT /api/v3/shells/aHR0cHM6Ly9leGFtcGxlLmNvbS9hYXMvMTIzNA +---- + +Example 2: replace an existing submodel at a client-addressable route by PUT if the addressed submodel already exists. + +[source,http] +---- +PUT /api/v3/submodels/aHR0cHM6Ly9leGFtcGxlLmNvbS9zbS9uYW1lcGxhdGU +---- + +Example 3: partially update a submodel by PATCH. + +[source,http] +---- +PATCH /api/v3/submodels/aHR0cHM6Ly9leGFtcGxlLmNvbS9zbS9uYW1lcGxhdGU +---- + +Example 4: update the value-only representation of a submodel element. + +[source,http] +---- +PATCH /api/v3/submodel/submodel-elements/Identification/ManufacturerName/$value +---- + +Example 5: update an AAS descriptor in the registry. + +[source,http] +---- +PUT /api/v3/shell-descriptors/aHR0cHM6Ly9leGFtcGxlLmNvbS9hYXMvMTIzNA +---- + +Example 6: update a lookup entry by POST if the addressed entry already exists. + +[source,http] +---- +POST /api/v3/lookup/shells/someencodedid +---- + +=== DELETE + +Here are endpoints that can need DELETE rights to delete existing resources or entries in the repository or registry. + +Example 1: delete a submodel from the repository. + +[source,http] +---- +DELETE /api/v3/submodels/aHR0cHM6Ly9leGFtcGxlLmNvbS9hYXMvMTIzNA +---- + +Example 2: delete a submodel element by path. + +[source,http] +---- +DELETE /api/v3/submodels/aHR0cHM6Ly9leGFtcGxlLmNvbS9hYXMvMTIzNA/submodel-elements/Identification/ManufacturerName +---- + +Example 3: delete a shell descriptor from the registry. + +[source,http] +---- +DELETE /api/v3/shell-descriptors/aHR0cHM6Ly9leGFtcGxlLmNvbS9hYXMvMTIzNA +---- + +=== EXECUTE + +Here are endpoints that can need EXECUTE rights to invoke operations on the repository or registry. + +Example 1: synchronously invoke an Operation. + +[source,http] +---- +POST /api/v3/submodel/submodel-elements/Reset/invoke +---- + +Example 2: asynchronously invoke an Operation. + +[source,http] +---- +POST /api/v3/submodels/aHR0cHM6Ly9leGFtcGxlLmNvbS9zbS9tYWludGVuYW5jZQ/submodel-elements/Reset/invoke-async +---- + +Example 3: retrieve the status of an asynchronous invocation. + +[source,http] +---- +GET /api/v3/submodel/submodel-elements/Reset/operation-status/4a2a7aaf-6f44-4f88-bba2-0b0d2d3e7a10 +---- + +=== VIEW + +VIEW is not bound to a dedicated HTTP method. +In HTTP/REST APIs it is usually enforced on GET operations that only expose existence information, references, identifiers, or descriptor entries. + +Example 1: retrieve references instead of full resource content. + +[source,http] +---- +GET /api/v3/submodels/aHR0cHM6Ly9leGFtcGxlLmNvbS9zbS9uYW1lcGxhdGU/$reference +---- + +Example 2: retrieve submodel references of an AAS. + +[source,http] +---- +GET /api/v3/shells/aHR0cHM6Ly9leGFtcGxlLmNvbS9hYXMvMTIzNA/submodel-refs +---- + +Example 3: retrieve descriptor entries without accessing the hosted AAS content itself. + +[source,http] +---- +GET /api/v3/shell-descriptors +---- + +== Notes for access rule authors + +* ROUTE literals should be defined against stable path families such as `/shells/*`, `/submodels/*`, `/shell-descriptors/*` or `/lookup/*` if authorization is intended for complete interfaces. +* Exact ROUTE literals such as `/submodel/submodel-elements/Reset/invoke` are useful for single sensitive operations. diff --git a/documentation/IDTA-01004/modules/ROOT/pages/changelog.adoc b/documentation/IDTA-01004/modules/ROOT/pages/changelog.adoc index f6a1370..81aed6a 100644 --- a/documentation/IDTA-01004/modules/ROOT/pages/changelog.adoc +++ b/documentation/IDTA-01004/modules/ROOT/pages/changelog.adoc @@ -22,6 +22,8 @@ Minor Changes: * update: Revised description text to replace 'may include signing' / 'will be' with 'is signed' / 'be signed' for clarity and consistency. * added: Access control examples for REFERENCE & along with rules for creating only specific models, defined using BNF and JSON. +* added: Clarified ROUTE semantics for AAS HTTP/REST path matching and added informative ROUTE and request examples [#58](https://github.com/admin-shell-io/aas-specs-security/issues/58) +* added: Expanded the explanation of RIGHTS with a mapping to operation verbs and HTTP methods, including an illustrative table and diagram [#56](https://github.com/admin-shell-io/aas-specs-security/issues/56) Bugfixes: diff --git a/documentation/IDTA-01004/modules/ROOT/partials/diagrams/rights-verbs-http-methods.puml b/documentation/IDTA-01004/modules/ROOT/partials/diagrams/rights-verbs-http-methods.puml new file mode 100644 index 0000000..6499b2e --- /dev/null +++ b/documentation/IDTA-01004/modules/ROOT/partials/diagrams/rights-verbs-http-methods.puml @@ -0,0 +1,57 @@ +@startuml +left to right direction + +rectangle "RIGHT" as RIGHTS { + together { + rectangle "UPDATE" as R_UPDATE + rectangle "CREATE" as R_CREATE + rectangle "READ" as R_READ + rectangle "VIEW" as R_VIEW + rectangle "EXECUTE" as R_EXECUTE + rectangle "DELETE" as R_DELETE + } +} + +rectangle "Operation Verb" as VERBS { + together { + rectangle "Patch" as V_PATCH + rectangle "Put" as V_PUT + rectangle "Post" as V_POST + rectangle "GetAll" as V_GETALL + rectangle "Get" as V_GET + rectangle "Invoke" as V_INVOKE + rectangle "Delete" as V_DELETE + } +} + +rectangle "HTTP REST Method" as HTTP { + together { + rectangle "PATCH" as H_PATCH + rectangle "PUT" as H_PUT + rectangle "POST" as H_POST + rectangle "GET" as H_GET + rectangle "DELETE" as H_DELETE + } +} + +R_UPDATE --> V_PATCH +R_UPDATE --> V_PUT +R_CREATE --> V_PUT +R_CREATE --> V_POST +R_READ --> V_GETALL +R_READ --> V_GET +R_VIEW --> V_GETALL +R_EXECUTE --> V_INVOKE +R_DELETE --> V_DELETE + +V_PATCH --> H_PATCH +V_PATCH --> H_PUT +V_PUT --> H_PUT +V_POST --> H_POST +V_GETALL --> H_GET +V_GETALL --> H_POST +V_GET --> H_GET +V_INVOKE --> H_POST +V_DELETE --> H_DELETE + +@enduml \ No newline at end of file