diff --git a/base/service/src/main/java/org/eclipse/ditto/base/service/signaltransformer/placeholdersubstitution/AbstractTypedSubstitutionStrategy.java b/base/service/src/main/java/org/eclipse/ditto/base/service/signaltransformer/placeholdersubstitution/AbstractTypedSubstitutionStrategy.java index d0bb0eec155..b4911a235f5 100644 --- a/base/service/src/main/java/org/eclipse/ditto/base/service/signaltransformer/placeholdersubstitution/AbstractTypedSubstitutionStrategy.java +++ b/base/service/src/main/java/org/eclipse/ditto/base/service/signaltransformer/placeholdersubstitution/AbstractTypedSubstitutionStrategy.java @@ -72,8 +72,9 @@ protected static PolicyEntry substitutePolicyEntry(final PolicyEntry existingPol if (existingSubjects.equals(substitutedSubjects)) { resultEntry = existingPolicyEntry; } else { - resultEntry = PolicyEntry.newInstance(existingPolicyEntry.getLabel(), substitutedSubjects, - existingPolicyEntry.getResources()); + resultEntry = PoliciesModelFactory.newPolicyEntry(existingPolicyEntry.getLabel(), substitutedSubjects, + existingPolicyEntry.getResources(), existingPolicyEntry.getImportableType(), + existingPolicyEntry.getAllowedImportAdditions()); } return resultEntry; diff --git a/documentation/src/main/resources/openapi/ditto-api-2.yml b/documentation/src/main/resources/openapi/ditto-api-2.yml index 42e66448e41..89aac466fb3 100644 --- a/documentation/src/main/resources/openapi/ditto-api-2.yml +++ b/documentation/src/main/resources/openapi/ditto-api-2.yml @@ -6273,6 +6273,279 @@ paths: $ref: '#/components/schemas/AdvancedError' '412': $ref: '#/components/responses/PreconditionFailed' + '/api/2/policies/{policyId}/entries/{label}/allowedImportAdditions': + get: + summary: Retrieve the allowed import additions for a specific policy entry + description: |- + Returns the allowed import additions of the policy entry identified by the + `policyId` path parameter and the `label` path parameter. + + Allowed import additions control which types of additions (subjects, resources) are permitted + when this entry is imported by other policies via `entriesAdditions`. + tags: + - Policies + parameters: + - $ref: '#/components/parameters/PolicyIdPathParam' + - $ref: '#/components/parameters/LabelPathParam' + - $ref: '#/components/parameters/IfMatchHeaderParamHash' + - $ref: '#/components/parameters/IfNoneMatchHeaderParam' + - $ref: '#/components/parameters/TimeoutParam' + responses: + '200': + description: The request successfully returned. The allowed import additions are returned. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/AllowedImportAdditions' + '304': + $ref: '#/components/responses/NotModified' + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '404': + description: |- + The request could not be completed. The policy with the given ID or + the policy entry was not found in the context of the authenticated + user. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '412': + $ref: '#/components/responses/PreconditionFailed' + put: + summary: Modify the allowed import additions for a specific policy entry + description: |- + Modify the allowed import additions of the policy entry identified by the + `policyId` path parameter and the `label` path parameter. + + Allowed import additions control which types of additions (subjects, resources) are permitted + when this entry is imported by other policies via `entriesAdditions`. Setting an empty array + disables all additions for this entry. + tags: + - Policies + parameters: + - $ref: '#/components/parameters/PolicyIdPathParam' + - $ref: '#/components/parameters/LabelPathParam' + - $ref: '#/components/parameters/IfMatchHeaderParamHash' + - $ref: '#/components/parameters/IfNoneMatchHeaderParam' + - $ref: '#/components/parameters/IfEqualHeaderParam' + - $ref: '#/components/parameters/TimeoutParam' + - $ref: '#/components/parameters/ResponseRequiredParam' + responses: + '204': + description: The allowed import additions were successfully updated. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + * the JSON body of the allowed import additions is invalid + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '403': + description: |- + The request could not be completed. Possible reasons: + * the caller has insufficient permissions. + You need `WRITE` permission on the `policy:/entries/{label}/allowedImportAdditions` resource, + without any revoke in a deeper path of the policy resource. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '404': + description: |- + The request could not be completed. The policy with the given ID was + not found in the context of the authenticated user. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '412': + $ref: '#/components/responses/PreconditionFailed' + '413': + $ref: '#/components/responses/EntityTooLarge' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AllowedImportAdditions' + example: + - subjects + - resources + description: JSON array of allowed import addition types. + required: true + '/api/2/policies/{policyId}/entries/{label}/importable': + get: + summary: Retrieve the importable type for a specific policy entry + description: |- + Returns the importable type of the policy entry identified by the + `policyId` path parameter and the `label` path parameter. + + The importable type controls whether and how a policy entry can be imported by other policies: + * `implicit` (default): the entry is imported without being listed individually + * `explicit`: the entry is only imported if it is listed in the importing policy + * `never`: the entry is not imported, regardless of being listed + tags: + - Policies + parameters: + - $ref: '#/components/parameters/PolicyIdPathParam' + - $ref: '#/components/parameters/LabelPathParam' + - $ref: '#/components/parameters/IfMatchHeaderParamHash' + - $ref: '#/components/parameters/IfNoneMatchHeaderParam' + - $ref: '#/components/parameters/TimeoutParam' + responses: + '200': + description: The request successfully returned. The importable type is returned. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/Importable' + '304': + $ref: '#/components/responses/NotModified' + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '404': + description: |- + The request could not be completed. The policy with the given ID or + the policy entry was not found in the context of the authenticated + user. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '412': + $ref: '#/components/responses/PreconditionFailed' + put: + summary: Modify the importable type for a specific policy entry + description: |- + Modify the importable type of the policy entry identified by the + `policyId` path parameter and the `label` path parameter. + + The importable type controls whether and how a policy entry can be imported by other policies: + * `implicit` (default): the entry is imported without being listed individually + * `explicit`: the entry is only imported if it is listed in the importing policy + * `never`: the entry is not imported, regardless of being listed + tags: + - Policies + parameters: + - $ref: '#/components/parameters/PolicyIdPathParam' + - $ref: '#/components/parameters/LabelPathParam' + - $ref: '#/components/parameters/IfMatchHeaderParamHash' + - $ref: '#/components/parameters/IfNoneMatchHeaderParam' + - $ref: '#/components/parameters/IfEqualHeaderParam' + - $ref: '#/components/parameters/TimeoutParam' + - $ref: '#/components/parameters/ResponseRequiredParam' + responses: + '204': + description: The importable type was successfully updated. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + * the JSON body of the importable type is invalid + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '403': + description: |- + The request could not be completed. Possible reasons: + * the caller has insufficient permissions. + You need `WRITE` permission on the `policy:/entries/{label}/importable` resource, + without any revoke in a deeper path of the policy resource. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '404': + description: |- + The request could not be completed. The policy with the given ID was + not found in the context of the authenticated user. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '412': + $ref: '#/components/responses/PreconditionFailed' + '413': + $ref: '#/components/responses/EntityTooLarge' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Importable' + example: explicit + description: 'The importable type value. Must be one of: "implicit", "explicit", "never".' + required: true '/api/2/policies/{policyId}/imports': get: summary: Retrieve the imports of a specific policy @@ -6287,8 +6560,453 @@ paths: - $ref: '#/components/parameters/IfNoneMatchHeaderParam' - $ref: '#/components/parameters/TimeoutParam' responses: - '200': - description: The request successfully returned completed and returned are the policy imports. + '200': + description: The request successfully returned completed and returned are the policy imports. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/PolicyImports' + '304': + $ref: '#/components/responses/NotModified' + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '402': + description: The request could not be completed due to exceeded data volume or exceeded transaction count. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '403': + description: The request could not be completed due to a missing or invalid API Token. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '404': + description: |- + The request could not be completed. The policy with the given ID was + not found in the context of the authenticated user. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '412': + $ref: '#/components/responses/PreconditionFailed' + put: + summary: Modify the imports of a specific policy + description: Modify the policy imports of the policy identified by the `policyId` path parameter. + tags: + - Policies + parameters: + - $ref: '#/components/parameters/PolicyIdPathParam' + - $ref: '#/components/parameters/IfMatchHeaderParamHash' + - $ref: '#/components/parameters/IfNoneMatchHeaderParam' + - $ref: '#/components/parameters/IfEqualHeaderParam' + - $ref: '#/components/parameters/TimeoutParam' + - $ref: '#/components/parameters/ResponseRequiredParam' + responses: + '204': + description: The policy imports were successfully updated. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + * the JSON body of the policy imports to be created/modified is invalid + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '402': + description: The request could not be completed due to exceeded data volume or exceeded transaction count. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '403': + description: |- + The request could not be completed. Possible reasons: + * the caller has insufficient permissions. + You need `WRITE` permission on the `policy:/imports` resource, + without any revoke in a deeper path of the policy resource. + * the caller has insufficient permissions. + You need `READ` permission on the policy entries of the imported policies. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '404': + description: |- + The request could not be completed. The policy (or an imported policy) with the given ID was + not found in the context of the authenticated user. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '412': + $ref: '#/components/responses/PreconditionFailed' + '413': + $ref: '#/components/responses/EntityTooLarge' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PolicyImports' + example: + 'com.acme:imported1': + entries: + - IMPORTED_ENTRY + 'com.acme:imported2': {} + description: JSON representation of the policy imports. + required: true + '/api/2/policies/{policyId}/imports/{importedPolicyId}': + get: + summary: Retrieve a specific policy import. + description: |- + Returns the policy import of the policy identified by the `policyId` path + parameter and imported policy identified by the `importedPolicyId` path parameter. + tags: + - Policies + parameters: + - $ref: '#/components/parameters/PolicyIdPathParam' + - $ref: '#/components/parameters/ImportedPolicyIdPathParam' + - $ref: '#/components/parameters/IfMatchHeaderParamHash' + - $ref: '#/components/parameters/IfNoneMatchHeaderParam' + - $ref: '#/components/parameters/IfEqualHeaderParam' + - $ref: '#/components/parameters/TimeoutParam' + responses: + '200': + description: The request successfully returned completed and returned is the policy import. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/PolicyImport' + '304': + $ref: '#/components/responses/NotModified' + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` or the `importedPolicyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '402': + description: The request could not be completed due to exceeded data volume or exceeded transaction count. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '403': + description: The request could not be completed due to a missing or invalid API Token. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '404': + description: |- + The request could not be completed. The policy with the given ID or + the policy import was not found in the context of the authenticated + user. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '412': + $ref: '#/components/responses/PreconditionFailed' + put: + summary: Create or modify a specific policy import of a policy. + description: |- + Create or modify the policy import of a specific policy identified by the `policyId` path parameter + and the imported policy identified by the `importedPolicyId` path parameter. + + * If you specify a new policy import, the respective policy import will be created + * If you specify an existing policy import, the respective policy import will be updated + tags: + - Policies + parameters: + - $ref: '#/components/parameters/PolicyIdPathParam' + - $ref: '#/components/parameters/ImportedPolicyIdPathParam' + - $ref: '#/components/parameters/IfMatchHeaderParamHash' + - $ref: '#/components/parameters/IfNoneMatchHeaderParam' + - $ref: '#/components/parameters/IfEqualHeaderParam' + - $ref: '#/components/parameters/TimeoutParam' + - $ref: '#/components/parameters/ResponseRequiredParam' + responses: + '201': + description: The policy import was successfully created. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + Location: + description: The location of the created policy import + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/PolicyImport' + '204': + description: The policy import was successfully updated. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` or the `importedPolicyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + * the JSON body of the policy import to be created/modified is invalid + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '402': + description: The request could not be completed due to exceeded data volume or exceeded transaction count. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '403': + description: |- + The request could not be completed. Possible reasons: + * the caller has insufficient permissions. + You need `WRITE` permission on the `policy:/imports/{importedPolicyId}` resource, + without any revoke in a deeper path of the policy resource. + * the caller has insufficient permissions. + You need `READ` permission on the `policy:/entries/{label}` resource of the *imported* policy, + without any revoke in a deeper path of the policy resource. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '404': + description: |- + The request could not be completed. The policy with the given ID was + not found in the context of the authenticated user. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '412': + $ref: '#/components/responses/PreconditionFailed' + '413': + $ref: '#/components/responses/EntityTooLarge' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PolicyImport' + example: + entries: + - IMPORTED + description: JSON representation of the policy import. + required: true + delete: + summary: Delete a specific policy import. + description: |- + Deletes a specific policy import identified by the `policyId` path parameter + and the `importedPolicyId` path parameter. + tags: + - Policies + parameters: + - $ref: '#/components/parameters/PolicyIdPathParam' + - $ref: '#/components/parameters/ImportedPolicyIdPathParam' + - $ref: '#/components/parameters/IfMatchHeaderParamHash' + - $ref: '#/components/parameters/IfNoneMatchHeaderParam' + - $ref: '#/components/parameters/TimeoutParam' + - $ref: '#/components/parameters/ResponseRequiredParam' + responses: + '204': + description: The policy import was successfully deleted. + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` or the `importedPolicyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '402': + description: The request could not be completed due to exceeded data volume or exceeded transaction count. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '403': + description: |- + The request could not be completed. Possible reasons: + * the caller has insufficient permissions. + You need `WRITE` permission on the `policy:/imported/{importedPolicyId}` resource, + without any revoke in a deeper path of the policy resource. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '404': + description: |- + The request could not be completed. The policy with the given ID was + not found in the context of the authenticated user. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '412': + $ref: '#/components/responses/PreconditionFailed' + '/api/2/policies/{policyId}/imports/{importedPolicyId}/entries': + get: + summary: Retrieve the entries of a specific policy import + description: |- + Returns the entries (imported labels) of the policy import identified by the `policyId` path + parameter and the `importedPolicyId` path parameter. + + The entries define which policy entries from the imported policy should be imported, + identified by their labels. An empty array means all implicit entries are imported. + tags: + - Policies + parameters: + - $ref: '#/components/parameters/PolicyIdPathParam' + - $ref: '#/components/parameters/ImportedPolicyIdPathParam' + - $ref: '#/components/parameters/IfMatchHeaderParamHash' + - $ref: '#/components/parameters/IfNoneMatchHeaderParam' + - $ref: '#/components/parameters/TimeoutParam' + responses: + '200': + description: The request successfully returned. The entries are returned as a JSON array of label strings. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + content: + application/json: + schema: + type: array + items: + type: string + description: Label of a policy entry to import from the referenced policy. + example: + - default + - import + '304': + $ref: '#/components/responses/NotModified' + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` or the `importedPolicyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '404': + description: |- + The request could not be completed. The policy with the given ID or + the policy import was not found in the context of the authenticated + user. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '412': + $ref: '#/components/responses/PreconditionFailed' + put: + summary: Modify the entries of a specific policy import + description: |- + Modify the entries (imported labels) of the policy import identified by the `policyId` path + parameter and the `importedPolicyId` path parameter. + + The entries define which policy entries from the imported policy should be imported, + identified by their labels. Provide an empty array to import all implicit entries. + tags: + - Policies + parameters: + - $ref: '#/components/parameters/PolicyIdPathParam' + - $ref: '#/components/parameters/ImportedPolicyIdPathParam' + - $ref: '#/components/parameters/IfMatchHeaderParamHash' + - $ref: '#/components/parameters/IfNoneMatchHeaderParam' + - $ref: '#/components/parameters/IfEqualHeaderParam' + - $ref: '#/components/parameters/TimeoutParam' + - $ref: '#/components/parameters/ResponseRequiredParam' + responses: + '204': + description: The entries were successfully updated. headers: ETag: description: |- @@ -6296,17 +7014,12 @@ paths: "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". schema: type: string - content: - application/json: - schema: - $ref: '#/components/schemas/PolicyImports' - '304': - $ref: '#/components/responses/NotModified' '400': description: |- The request could not be completed. Possible reasons: - * the `policyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + * the `policyId` or the `importedPolicyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + * the JSON body of the entries is invalid content: application/json: schema: @@ -6317,22 +7030,95 @@ paths: application/json: schema: $ref: '#/components/schemas/AdvancedError' - '402': - description: The request could not be completed due to exceeded data volume or exceeded transaction count. + '403': + description: |- + The request could not be completed. Possible reasons: + * the caller has insufficient permissions. + You need `WRITE` permission on the `policy:/imports/{importedPolicyId}` resource, + without any revoke in a deeper path of the policy resource. content: application/json: schema: $ref: '#/components/schemas/AdvancedError' - '403': - description: The request could not be completed due to a missing or invalid API Token. + '404': + description: |- + The request could not be completed. The policy with the given ID or + the policy import was not found in the context of the authenticated + user. + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '412': + $ref: '#/components/responses/PreconditionFailed' + '413': + $ref: '#/components/responses/EntityTooLarge' + requestBody: + content: + application/json: + schema: + type: array + items: + type: string + description: Label of a policy entry to import from the referenced policy. + example: + - default + - import + description: JSON array of policy entry labels to import. + required: true + '/api/2/policies/{policyId}/imports/{importedPolicyId}/entriesAdditions': + get: + summary: Retrieve all entries additions of a specific policy import + description: |- + Returns the entries additions of the policy import identified by the `policyId` path + parameter and the `importedPolicyId` path parameter. + + Entries additions define additional subjects and/or resources to be additively merged + into imported policy entries. + tags: + - Policies + parameters: + - $ref: '#/components/parameters/PolicyIdPathParam' + - $ref: '#/components/parameters/ImportedPolicyIdPathParam' + - $ref: '#/components/parameters/IfMatchHeaderParamHash' + - $ref: '#/components/parameters/IfNoneMatchHeaderParam' + - $ref: '#/components/parameters/TimeoutParam' + responses: + '200': + description: The request successfully returned. The entries additions are returned. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/EntriesAdditions' + '304': + $ref: '#/components/responses/NotModified' + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` or the `importedPolicyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + content: + application/json: + schema: + $ref: '#/components/schemas/AdvancedError' + '401': + description: The request could not be completed due to missing authentication. content: application/json: schema: $ref: '#/components/schemas/AdvancedError' '404': description: |- - The request could not be completed. The policy with the given ID was - not found in the context of the authenticated user. + The request could not be completed. The policy with the given ID or + the policy import was not found in the context of the authenticated + user. content: application/json: schema: @@ -6340,12 +7126,19 @@ paths: '412': $ref: '#/components/responses/PreconditionFailed' put: - summary: Modify the imports of a specific policy - description: Modify the policy imports of the policy identified by the `policyId` path parameter. + summary: Modify all entries additions of a specific policy import + description: |- + Modify the entries additions of the policy import identified by the `policyId` path + parameter and the `importedPolicyId` path parameter. + + Entries additions define additional subjects and/or resources to be additively merged + into imported policy entries. The imported policy entries must explicitly allow these + additions via their "allowedImportAdditions" field. tags: - Policies parameters: - $ref: '#/components/parameters/PolicyIdPathParam' + - $ref: '#/components/parameters/ImportedPolicyIdPathParam' - $ref: '#/components/parameters/IfMatchHeaderParamHash' - $ref: '#/components/parameters/IfNoneMatchHeaderParam' - $ref: '#/components/parameters/IfEqualHeaderParam' @@ -6353,7 +7146,7 @@ paths: - $ref: '#/components/parameters/ResponseRequiredParam' responses: '204': - description: The policy imports were successfully updated. + description: The entries additions were successfully updated. headers: ETag: description: |- @@ -6365,8 +7158,8 @@ paths: description: |- The request could not be completed. Possible reasons: - * the `policyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) - * the JSON body of the policy imports to be created/modified is invalid + * the `policyId` or the `importedPolicyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + * the JSON body of the entries additions is invalid content: application/json: schema: @@ -6377,28 +7170,23 @@ paths: application/json: schema: $ref: '#/components/schemas/AdvancedError' - '402': - description: The request could not be completed due to exceeded data volume or exceeded transaction count. - content: - application/json: - schema: - $ref: '#/components/schemas/AdvancedError' '403': description: |- The request could not be completed. Possible reasons: * the caller has insufficient permissions. - You need `WRITE` permission on the `policy:/imports` resource, + You need `WRITE` permission on the `policy:/imports/{importedPolicyId}` resource, without any revoke in a deeper path of the policy resource. - * the caller has insufficient permissions. - You need `READ` permission on the policy entries of the imported policies. + * the imported policy entries do not allow the specified additions via their + "allowedImportAdditions" field. content: application/json: schema: $ref: '#/components/schemas/AdvancedError' '404': description: |- - The request could not be completed. The policy (or an imported policy) with the given ID was - not found in the context of the authenticated user. + The request could not be completed. The policy with the given ID or + the policy import was not found in the context of the authenticated + user. content: application/json: schema: @@ -6411,32 +7199,40 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/PolicyImports' + $ref: '#/components/schemas/EntriesAdditions' example: - 'com.acme:imported1': - entries: - - IMPORTED_ENTRY - 'com.acme:imported2': {} - description: JSON representation of the policy imports. + default: + subjects: + 'integration:my-connection': + type: generated + resources: + 'thing:/features': + grant: + - READ + revoke: [] + description: JSON representation of the entries additions. required: true - '/api/2/policies/{policyId}/imports/{importedPolicyId}': + '/api/2/policies/{policyId}/imports/{importedPolicyId}/entriesAdditions/{label}': get: - summary: Retrieve a specific policy import. + summary: Retrieve a specific entry addition of a policy import description: |- - Returns the policy import of the policy identified by the `policyId` path - parameter and imported policy identified by the `importedPolicyId` path parameter. + Returns the entry addition for the specified label of the policy import identified by the + `policyId` path parameter and the `importedPolicyId` path parameter. + + An entry addition defines additional subjects and/or resources to be additively merged + into the imported policy entry identified by the label. tags: - Policies parameters: - $ref: '#/components/parameters/PolicyIdPathParam' - $ref: '#/components/parameters/ImportedPolicyIdPathParam' + - $ref: '#/components/parameters/LabelPathParam' - $ref: '#/components/parameters/IfMatchHeaderParamHash' - $ref: '#/components/parameters/IfNoneMatchHeaderParam' - - $ref: '#/components/parameters/IfEqualHeaderParam' - $ref: '#/components/parameters/TimeoutParam' responses: '200': - description: The request successfully returned completed and returned is the policy import. + description: The request successfully returned. The entry addition is returned. headers: ETag: description: |- @@ -6447,7 +7243,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/PolicyImport' + $ref: '#/components/schemas/EntryAddition' '304': $ref: '#/components/responses/NotModified' '400': @@ -6465,23 +7261,11 @@ paths: application/json: schema: $ref: '#/components/schemas/AdvancedError' - '402': - description: The request could not be completed due to exceeded data volume or exceeded transaction count. - content: - application/json: - schema: - $ref: '#/components/schemas/AdvancedError' - '403': - description: The request could not be completed due to a missing or invalid API Token. - content: - application/json: - schema: - $ref: '#/components/schemas/AdvancedError' '404': description: |- - The request could not be completed. The policy with the given ID or - the policy import was not found in the context of the authenticated - user. + The request could not be completed. The policy with the given ID, + the policy import, or the entry addition was not found in the context + of the authenticated user. content: application/json: schema: @@ -6489,18 +7273,22 @@ paths: '412': $ref: '#/components/responses/PreconditionFailed' put: - summary: Create or modify a specific policy import of a policy. + summary: Create or modify a specific entry addition of a policy import description: |- - Create or modify the policy import of a specific policy identified by the `policyId` path parameter - and the imported policy identified by the `importedPolicyId` path parameter. + Create or modify the entry addition for the specified label of the policy import identified + by the `policyId` path parameter and the `importedPolicyId` path parameter. - * If you specify a new policy import, the respective policy import will be created - * If you specify an existing policy import, the respective policy import will be updated + * If the entry addition does not yet exist, it will be created. + * If the entry addition already exists, it will be updated. + + The imported policy entry must explicitly allow these additions via its "allowedImportAdditions" + field, otherwise the additions are rejected. tags: - Policies parameters: - $ref: '#/components/parameters/PolicyIdPathParam' - $ref: '#/components/parameters/ImportedPolicyIdPathParam' + - $ref: '#/components/parameters/LabelPathParam' - $ref: '#/components/parameters/IfMatchHeaderParamHash' - $ref: '#/components/parameters/IfNoneMatchHeaderParam' - $ref: '#/components/parameters/IfEqualHeaderParam' @@ -6508,7 +7296,7 @@ paths: - $ref: '#/components/parameters/ResponseRequiredParam' responses: '201': - description: The policy import was successfully created. + description: The entry addition was successfully created. headers: ETag: description: |- @@ -6517,15 +7305,15 @@ paths: schema: type: string Location: - description: The location of the created policy import + description: The location of the created entry addition schema: type: string content: application/json: schema: - $ref: '#/components/schemas/PolicyImport' + $ref: '#/components/schemas/EntryAddition' '204': - description: The policy import was successfully updated. + description: The entry addition was successfully updated. headers: ETag: description: |- @@ -6538,7 +7326,7 @@ paths: The request could not be completed. Possible reasons: * the `policyId` or the `importedPolicyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) - * the JSON body of the policy import to be created/modified is invalid + * the JSON body of the entry addition is invalid content: application/json: schema: @@ -6549,29 +7337,23 @@ paths: application/json: schema: $ref: '#/components/schemas/AdvancedError' - '402': - description: The request could not be completed due to exceeded data volume or exceeded transaction count. - content: - application/json: - schema: - $ref: '#/components/schemas/AdvancedError' '403': description: |- The request could not be completed. Possible reasons: - * the caller has insufficient permissions. - You need `WRITE` permission on the `policy:/imports/{importedPolicyId}` resource, - without any revoke in a deeper path of the policy resource. - * the caller has insufficient permissions. - You need `READ` permission on the `policy:/entries/{label}` resource of the *imported* policy, - without any revoke in a deeper path of the policy resource. + * the caller has insufficient permissions. + You need `WRITE` permission on the `policy:/imports/{importedPolicyId}` resource, + without any revoke in a deeper path of the policy resource. + * the imported policy entry does not allow the specified additions via its + "allowedImportAdditions" field. content: application/json: schema: $ref: '#/components/schemas/AdvancedError' '404': description: |- - The request could not be completed. The policy with the given ID was - not found in the context of the authenticated user. + The request could not be completed. The policy with the given ID or + the policy import was not found in the context of the authenticated + user. content: application/json: schema: @@ -6584,29 +7366,36 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/PolicyImport' + $ref: '#/components/schemas/EntryAddition' example: - entries: - - IMPORTED - description: JSON representation of the policy import. + subjects: + 'integration:my-connection': + type: generated + resources: + 'thing:/features': + grant: + - READ + revoke: [] + description: JSON representation of the entry addition. required: true delete: - summary: Delete a specific policy import. + summary: Delete a specific entry addition of a policy import description: |- - Deletes a specific policy import identified by the `policyId` path parameter - and the `importedPolicyId` path parameter. + Deletes the entry addition for the specified label of the policy import identified by the + `policyId` path parameter and the `importedPolicyId` path parameter. tags: - Policies parameters: - $ref: '#/components/parameters/PolicyIdPathParam' - $ref: '#/components/parameters/ImportedPolicyIdPathParam' + - $ref: '#/components/parameters/LabelPathParam' - $ref: '#/components/parameters/IfMatchHeaderParamHash' - $ref: '#/components/parameters/IfNoneMatchHeaderParam' - $ref: '#/components/parameters/TimeoutParam' - $ref: '#/components/parameters/ResponseRequiredParam' responses: '204': - description: The policy import was successfully deleted. + description: The entry addition was successfully deleted. '400': description: |- The request could not be completed. Possible reasons: @@ -6622,17 +7411,11 @@ paths: application/json: schema: $ref: '#/components/schemas/AdvancedError' - '402': - description: The request could not be completed due to exceeded data volume or exceeded transaction count. - content: - application/json: - schema: - $ref: '#/components/schemas/AdvancedError' '403': description: |- The request could not be completed. Possible reasons: * the caller has insufficient permissions. - You need `WRITE` permission on the `policy:/imported/{importedPolicyId}` resource, + You need `WRITE` permission on the `policy:/imports/{importedPolicyId}` resource, without any revoke in a deeper path of the policy resource. content: application/json: @@ -6640,8 +7423,9 @@ paths: $ref: '#/components/schemas/AdvancedError' '404': description: |- - The request could not be completed. The policy with the given ID was - not found in the context of the authenticated user. + The request could not be completed. The policy with the given ID, + the policy import, or the entry addition was not found in the context + of the authenticated user. content: application/json: schema: @@ -8532,26 +9316,31 @@ components: required: - thingDefinitionUrl PermissionCheckRequest: - type: object - description: Request to check permissions for various entities and resources. - additionalProperties: - type: object - description: Details for a specific permission check request. - properties: - resource: - type: string - description: Resource path the permission check applies to. - entityId: - type: string - description: thingId of the entity performing the action. - hasPermissions: - type: array - items: - type: string - enum: - - READ - - WRITE - description: Required permissions on the resource. + content: + application/json: + schema: + type: object + description: Request to check permissions for various entities and resources. + additionalProperties: + type: object + description: Details for a specific permission check request. + properties: + resource: + type: string + description: Resource path the permission check applies to. + entityId: + type: string + description: thingId of the entity performing the action. + hasPermissions: + type: array + items: + type: string + enum: + - READ + - WRITE + description: Required permissions on the resource. + description: 'JSON object containing permission check requests, keyed by an arbitrary identifier.' + required: true DynamicValidationConfigRequest: content: application/json: @@ -8686,21 +9475,28 @@ components: - patch - mergeStatus PermissionCheckResponse: - type: object description: Response with permission check results for each entity. - additionalProperties: - type: boolean + content: + application/json: + schema: + type: object + description: Response with permission check results for each entity. + additionalProperties: + type: boolean WotValidationConfigResponse: + description: The WoT validation configuration. content: application/json: schema: $ref: '#/components/schemas/WotValidationConfig' DynamicValidationConfigResponse: + description: The dynamic WoT validation configuration. content: application/json: schema: $ref: '#/components/schemas/DynamicValidationConfig' ConfigOverridesResponse: + description: The WoT validation configuration overrides. content: application/json: schema: @@ -9725,16 +10521,28 @@ components: type: array default: [] description: |- - The policy entries to import from the referenced policy identified by their labels. - In case the field is omitted or an empty array is provided, + The policy entries to import from the referenced policy identified by their labels. + In case the field is omitted or an empty array is provided, all policy entries defined as implicit ("importable": "implicit") are imported. items: type: string description: Label of a policy entry to import from the referenced policy. + entriesAdditions: + $ref: '#/components/schemas/EntriesAdditions' example: entries: - default - import + entriesAdditions: + default: + subjects: + 'integration:my-connection': + type: generated + resources: + 'thing:/features': + grant: + - READ + revoke: [] Importable: type: string description: |- @@ -9768,6 +10576,8 @@ components: $ref: '#/components/schemas/Resources' importable: $ref: '#/components/schemas/Importable' + allowedImportAdditions: + $ref: '#/components/schemas/AllowedImportAdditions' required: - subjects - resources @@ -9847,6 +10657,65 @@ components: enum: - READ - WRITE + AllowedImportAdditions: + type: array + description: |- + Defines which types of additions are allowed when this entry is imported by other policies + via `entriesAdditions`. If omitted or empty, no additions are allowed. This default ensures + that existing policies cannot be extended with additional subjects or resources unless the + policy author explicitly opts in. + * `subjects` — allows importing policies to add additional subjects to this entry + * `resources` — allows importing policies to add additional resources to this entry + items: + type: string + enum: + - subjects + - resources + example: + - subjects + EntriesAdditions: + type: object + description: |- + Additional subjects and/or resources to additively merge into imported policy entries. + Each key is a label of an imported policy entry. The value is an object with optional "subjects" + and/or "resources" fields that will be merged into the corresponding imported entry. + Subjects are added (existing subjects from the template are preserved). + For resources, new paths are added and overlapping paths get their permissions merged (union of + grants and revokes; template revokes are always preserved). + The imported policy entry must explicitly allow these additions via its "allowedImportAdditions" + field, otherwise the additions are rejected. + additionalProperties: + $ref: '#/components/schemas/EntryAddition' + example: + default: + subjects: + 'integration:my-connection': + type: generated + resources: + 'thing:/features': + grant: + - READ + revoke: [] + EntryAddition: + type: object + description: |- + Defines additional subjects and/or resources to be merged into a single imported policy entry. + The imported policy entry must explicitly allow these additions via its "allowedImportAdditions" + field, otherwise the additions are rejected. + properties: + subjects: + $ref: '#/components/schemas/Subjects' + resources: + $ref: '#/components/schemas/Resources' + example: + subjects: + 'integration:my-connection': + type: generated + resources: + 'thing:/features': + grant: + - READ + revoke: [] SubjectAnnouncement: type: object description: Settings for announcements to be made about the subject. @@ -11303,7 +12172,7 @@ components: OpenIDConnect: type: openIdConnect description: OpenID Connect Discovery URL. The placeholder is replaced by Swagger UI when configured. - openIdConnectUrl: "__OIDC_DISCOVERY_URL__" + openIdConnectUrl: __OIDC_DISCOVERY_URL__ DevOpsBasic: type: http description: Eclipse Ditto devops user (devops) + password (foobar) diff --git a/documentation/src/main/resources/openapi/sources/api-2-index.yml b/documentation/src/main/resources/openapi/sources/api-2-index.yml index 7f73e89f46d..307401ae592 100644 --- a/documentation/src/main/resources/openapi/sources/api-2-index.yml +++ b/documentation/src/main/resources/openapi/sources/api-2-index.yml @@ -129,10 +129,20 @@ paths: $ref: "./paths/policies/resources.yml" '/api/2/policies/{policyId}/entries/{label}/resources/{resourcePath}': $ref: "./paths/policies/resource.yml" + '/api/2/policies/{policyId}/entries/{label}/allowedImportAdditions': + $ref: "./paths/policies/allowedImportAdditions.yml" + '/api/2/policies/{policyId}/entries/{label}/importable': + $ref: "./paths/policies/importable.yml" '/api/2/policies/{policyId}/imports': $ref: "./paths/policies/imports.yml" '/api/2/policies/{policyId}/imports/{importedPolicyId}': $ref: "./paths/policies/import.yml" + '/api/2/policies/{policyId}/imports/{importedPolicyId}/entries': + $ref: "./paths/policies/importEntries.yml" + '/api/2/policies/{policyId}/imports/{importedPolicyId}/entriesAdditions': + $ref: "./paths/policies/entriesAdditions.yml" + '/api/2/policies/{policyId}/imports/{importedPolicyId}/entriesAdditions/{label}': + $ref: "./paths/policies/entryAddition.yml" ### ### Who Am I @@ -424,6 +434,12 @@ components: $ref: "./schemas/policies/resourceEntry.yml" Permission: $ref: "./schemas/policies/permission.yml" + AllowedImportAdditions: + $ref: "./schemas/policies/allowedImportAdditions.yml" + EntriesAdditions: + $ref: "./schemas/policies/entriesAdditions.yml" + EntryAddition: + $ref: "./schemas/policies/entryAddition.yml" SubjectAnnouncement: $ref: "./schemas/policies/subjectAnnouncement.yml" Features: diff --git a/documentation/src/main/resources/openapi/sources/paths/policies/allowedImportAdditions.yml b/documentation/src/main/resources/openapi/sources/paths/policies/allowedImportAdditions.yml new file mode 100644 index 00000000000..ffcce950d46 --- /dev/null +++ b/documentation/src/main/resources/openapi/sources/paths/policies/allowedImportAdditions.yml @@ -0,0 +1,144 @@ +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0 +# +# SPDX-License-Identifier: EPL-2.0 +get: + summary: Retrieve the allowed import additions for a specific policy entry + description: |- + Returns the allowed import additions of the policy entry identified by the + `policyId` path parameter and the `label` path parameter. + + Allowed import additions control which types of additions (subjects, resources) are permitted + when this entry is imported by other policies via `entriesAdditions`. + tags: + - Policies + parameters: + - $ref: '../../parameters/policyIdPathParam.yml' + - $ref: '../../parameters/labelPathParam.yml' + - $ref: '../../parameters/ifMatchHeaderParamHash.yml' + - $ref: '../../parameters/ifNoneMatchHeaderParam.yml' + - $ref: '../../parameters/timeoutParam.yml' + responses: + '200': + description: The request successfully returned. The allowed import additions are returned. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + content: + application/json: + schema: + $ref: '../../schemas/policies/allowedImportAdditions.yml' + '304': + $ref: '../../responses/notModified.yml' + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '404': + description: |- + The request could not be completed. The policy with the given ID or + the policy entry was not found in the context of the authenticated + user. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '412': + $ref: '../../responses/preconditionFailed.yml' +put: + summary: Modify the allowed import additions for a specific policy entry + description: |- + Modify the allowed import additions of the policy entry identified by the + `policyId` path parameter and the `label` path parameter. + + Allowed import additions control which types of additions (subjects, resources) are permitted + when this entry is imported by other policies via `entriesAdditions`. Setting an empty array + disables all additions for this entry. + tags: + - Policies + parameters: + - $ref: '../../parameters/policyIdPathParam.yml' + - $ref: '../../parameters/labelPathParam.yml' + - $ref: '../../parameters/ifMatchHeaderParamHash.yml' + - $ref: '../../parameters/ifNoneMatchHeaderParam.yml' + - $ref: '../../parameters/ifEqualHeaderParam.yml' + - $ref: '../../parameters/timeoutParam.yml' + - $ref: '../../parameters/responseRequiredParam.yml' + responses: + '204': + description: The allowed import additions were successfully updated. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + * the JSON body of the allowed import additions is invalid + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '403': + description: |- + The request could not be completed. Possible reasons: + * the caller has insufficient permissions. + You need `WRITE` permission on the `policy:/entries/{label}/allowedImportAdditions` resource, + without any revoke in a deeper path of the policy resource. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '404': + description: |- + The request could not be completed. The policy with the given ID was + not found in the context of the authenticated user. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '412': + $ref: '../../responses/preconditionFailed.yml' + '413': + $ref: '../../responses/entityTooLarge.yml' + requestBody: + content: + application/json: + schema: + $ref: '../../schemas/policies/allowedImportAdditions.yml' + example: [ "subjects", "resources" ] + description: |- + JSON array of allowed import addition types. + required: true diff --git a/documentation/src/main/resources/openapi/sources/paths/policies/entriesAdditions.yml b/documentation/src/main/resources/openapi/sources/paths/policies/entriesAdditions.yml new file mode 100644 index 00000000000..20eb618fbfb --- /dev/null +++ b/documentation/src/main/resources/openapi/sources/paths/policies/entriesAdditions.yml @@ -0,0 +1,155 @@ +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0 +# +# SPDX-License-Identifier: EPL-2.0 +get: + summary: Retrieve all entries additions of a specific policy import + description: |- + Returns the entries additions of the policy import identified by the `policyId` path + parameter and the `importedPolicyId` path parameter. + + Entries additions define additional subjects and/or resources to be additively merged + into imported policy entries. + tags: + - Policies + parameters: + - $ref: '../../parameters/policyIdPathParam.yml' + - $ref: '../../parameters/importedPolicyIdPathParam.yml' + - $ref: '../../parameters/ifMatchHeaderParamHash.yml' + - $ref: '../../parameters/ifNoneMatchHeaderParam.yml' + - $ref: '../../parameters/timeoutParam.yml' + responses: + '200': + description: The request successfully returned. The entries additions are returned. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + content: + application/json: + schema: + $ref: '../../schemas/policies/entriesAdditions.yml' + '304': + $ref: '../../responses/notModified.yml' + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` or the `importedPolicyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '404': + description: |- + The request could not be completed. The policy with the given ID or + the policy import was not found in the context of the authenticated + user. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '412': + $ref: '../../responses/preconditionFailed.yml' +put: + summary: Modify all entries additions of a specific policy import + description: |- + Modify the entries additions of the policy import identified by the `policyId` path + parameter and the `importedPolicyId` path parameter. + + Entries additions define additional subjects and/or resources to be additively merged + into imported policy entries. The imported policy entries must explicitly allow these + additions via their "allowedImportAdditions" field. + tags: + - Policies + parameters: + - $ref: '../../parameters/policyIdPathParam.yml' + - $ref: '../../parameters/importedPolicyIdPathParam.yml' + - $ref: '../../parameters/ifMatchHeaderParamHash.yml' + - $ref: '../../parameters/ifNoneMatchHeaderParam.yml' + - $ref: '../../parameters/ifEqualHeaderParam.yml' + - $ref: '../../parameters/timeoutParam.yml' + - $ref: '../../parameters/responseRequiredParam.yml' + responses: + '204': + description: The entries additions were successfully updated. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` or the `importedPolicyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + * the JSON body of the entries additions is invalid + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '403': + description: |- + The request could not be completed. Possible reasons: + * the caller has insufficient permissions. + You need `WRITE` permission on the `policy:/imports/{importedPolicyId}` resource, + without any revoke in a deeper path of the policy resource. + * the imported policy entries do not allow the specified additions via their + "allowedImportAdditions" field. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '404': + description: |- + The request could not be completed. The policy with the given ID or + the policy import was not found in the context of the authenticated + user. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '412': + $ref: '../../responses/preconditionFailed.yml' + '413': + $ref: '../../responses/entityTooLarge.yml' + requestBody: + content: + application/json: + schema: + $ref: '../../schemas/policies/entriesAdditions.yml' + example: + default: + subjects: + "integration:my-connection": + type: "generated" + resources: + "thing:/features": + grant: [ "READ" ] + revoke: [] + description: |- + JSON representation of the entries additions. + required: true diff --git a/documentation/src/main/resources/openapi/sources/paths/policies/entryAddition.yml b/documentation/src/main/resources/openapi/sources/paths/policies/entryAddition.yml new file mode 100644 index 00000000000..481ea887e6e --- /dev/null +++ b/documentation/src/main/resources/openapi/sources/paths/policies/entryAddition.yml @@ -0,0 +1,229 @@ +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0 +# +# SPDX-License-Identifier: EPL-2.0 +get: + summary: Retrieve a specific entry addition of a policy import + description: |- + Returns the entry addition for the specified label of the policy import identified by the + `policyId` path parameter and the `importedPolicyId` path parameter. + + An entry addition defines additional subjects and/or resources to be additively merged + into the imported policy entry identified by the label. + tags: + - Policies + parameters: + - $ref: '../../parameters/policyIdPathParam.yml' + - $ref: '../../parameters/importedPolicyIdPathParam.yml' + - $ref: '../../parameters/labelPathParam.yml' + - $ref: '../../parameters/ifMatchHeaderParamHash.yml' + - $ref: '../../parameters/ifNoneMatchHeaderParam.yml' + - $ref: '../../parameters/timeoutParam.yml' + responses: + '200': + description: The request successfully returned. The entry addition is returned. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + content: + application/json: + schema: + $ref: '../../schemas/policies/entryAddition.yml' + '304': + $ref: '../../responses/notModified.yml' + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` or the `importedPolicyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '404': + description: |- + The request could not be completed. The policy with the given ID, + the policy import, or the entry addition was not found in the context + of the authenticated user. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '412': + $ref: '../../responses/preconditionFailed.yml' +put: + summary: Create or modify a specific entry addition of a policy import + description: |- + Create or modify the entry addition for the specified label of the policy import identified + by the `policyId` path parameter and the `importedPolicyId` path parameter. + + * If the entry addition does not yet exist, it will be created. + * If the entry addition already exists, it will be updated. + + The imported policy entry must explicitly allow these additions via its "allowedImportAdditions" + field, otherwise the additions are rejected. + tags: + - Policies + parameters: + - $ref: '../../parameters/policyIdPathParam.yml' + - $ref: '../../parameters/importedPolicyIdPathParam.yml' + - $ref: '../../parameters/labelPathParam.yml' + - $ref: '../../parameters/ifMatchHeaderParamHash.yml' + - $ref: '../../parameters/ifNoneMatchHeaderParam.yml' + - $ref: '../../parameters/ifEqualHeaderParam.yml' + - $ref: '../../parameters/timeoutParam.yml' + - $ref: '../../parameters/responseRequiredParam.yml' + responses: + '201': + description: The entry addition was successfully created. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + Location: + description: The location of the created entry addition + schema: + type: string + content: + application/json: + schema: + $ref: '../../schemas/policies/entryAddition.yml' + '204': + description: The entry addition was successfully updated. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` or the `importedPolicyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + * the JSON body of the entry addition is invalid + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '403': + description: |- + The request could not be completed. Possible reasons: + * the caller has insufficient permissions. + You need `WRITE` permission on the `policy:/imports/{importedPolicyId}` resource, + without any revoke in a deeper path of the policy resource. + * the imported policy entry does not allow the specified additions via its + "allowedImportAdditions" field. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '404': + description: |- + The request could not be completed. The policy with the given ID or + the policy import was not found in the context of the authenticated + user. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '412': + $ref: '../../responses/preconditionFailed.yml' + '413': + $ref: '../../responses/entityTooLarge.yml' + requestBody: + content: + application/json: + schema: + $ref: '../../schemas/policies/entryAddition.yml' + example: + subjects: + "integration:my-connection": + type: "generated" + resources: + "thing:/features": + grant: [ "READ" ] + revoke: [] + description: |- + JSON representation of the entry addition. + required: true +delete: + summary: Delete a specific entry addition of a policy import + description: |- + Deletes the entry addition for the specified label of the policy import identified by the + `policyId` path parameter and the `importedPolicyId` path parameter. + tags: + - Policies + parameters: + - $ref: '../../parameters/policyIdPathParam.yml' + - $ref: '../../parameters/importedPolicyIdPathParam.yml' + - $ref: '../../parameters/labelPathParam.yml' + - $ref: '../../parameters/ifMatchHeaderParamHash.yml' + - $ref: '../../parameters/ifNoneMatchHeaderParam.yml' + - $ref: '../../parameters/timeoutParam.yml' + - $ref: '../../parameters/responseRequiredParam.yml' + responses: + '204': + description: The entry addition was successfully deleted. + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` or the `importedPolicyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '403': + description: |- + The request could not be completed. Possible reasons: + * the caller has insufficient permissions. + You need `WRITE` permission on the `policy:/imports/{importedPolicyId}` resource, + without any revoke in a deeper path of the policy resource. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '404': + description: |- + The request could not be completed. The policy with the given ID, + the policy import, or the entry addition was not found in the context + of the authenticated user. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '412': + $ref: '../../responses/preconditionFailed.yml' diff --git a/documentation/src/main/resources/openapi/sources/paths/policies/importEntries.yml b/documentation/src/main/resources/openapi/sources/paths/policies/importEntries.yml new file mode 100644 index 00000000000..601bbff645b --- /dev/null +++ b/documentation/src/main/resources/openapi/sources/paths/policies/importEntries.yml @@ -0,0 +1,151 @@ +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0 +# +# SPDX-License-Identifier: EPL-2.0 +get: + summary: Retrieve the entries of a specific policy import + description: |- + Returns the entries (imported labels) of the policy import identified by the `policyId` path + parameter and the `importedPolicyId` path parameter. + + The entries define which policy entries from the imported policy should be imported, + identified by their labels. An empty array means all implicit entries are imported. + tags: + - Policies + parameters: + - $ref: '../../parameters/policyIdPathParam.yml' + - $ref: '../../parameters/importedPolicyIdPathParam.yml' + - $ref: '../../parameters/ifMatchHeaderParamHash.yml' + - $ref: '../../parameters/ifNoneMatchHeaderParam.yml' + - $ref: '../../parameters/timeoutParam.yml' + responses: + '200': + description: The request successfully returned. The entries are returned as a JSON array of label strings. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + content: + application/json: + schema: + type: array + items: + type: string + description: Label of a policy entry to import from the referenced policy. + example: [ "default", "import" ] + '304': + $ref: '../../responses/notModified.yml' + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` or the `importedPolicyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '404': + description: |- + The request could not be completed. The policy with the given ID or + the policy import was not found in the context of the authenticated + user. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '412': + $ref: '../../responses/preconditionFailed.yml' +put: + summary: Modify the entries of a specific policy import + description: |- + Modify the entries (imported labels) of the policy import identified by the `policyId` path + parameter and the `importedPolicyId` path parameter. + + The entries define which policy entries from the imported policy should be imported, + identified by their labels. Provide an empty array to import all implicit entries. + tags: + - Policies + parameters: + - $ref: '../../parameters/policyIdPathParam.yml' + - $ref: '../../parameters/importedPolicyIdPathParam.yml' + - $ref: '../../parameters/ifMatchHeaderParamHash.yml' + - $ref: '../../parameters/ifNoneMatchHeaderParam.yml' + - $ref: '../../parameters/ifEqualHeaderParam.yml' + - $ref: '../../parameters/timeoutParam.yml' + - $ref: '../../parameters/responseRequiredParam.yml' + responses: + '204': + description: The entries were successfully updated. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` or the `importedPolicyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + * the JSON body of the entries is invalid + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '403': + description: |- + The request could not be completed. Possible reasons: + * the caller has insufficient permissions. + You need `WRITE` permission on the `policy:/imports/{importedPolicyId}` resource, + without any revoke in a deeper path of the policy resource. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '404': + description: |- + The request could not be completed. The policy with the given ID or + the policy import was not found in the context of the authenticated + user. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '412': + $ref: '../../responses/preconditionFailed.yml' + '413': + $ref: '../../responses/entityTooLarge.yml' + requestBody: + content: + application/json: + schema: + type: array + items: + type: string + description: Label of a policy entry to import from the referenced policy. + example: [ "default", "import" ] + description: |- + JSON array of policy entry labels to import. + required: true diff --git a/documentation/src/main/resources/openapi/sources/paths/policies/importable.yml b/documentation/src/main/resources/openapi/sources/paths/policies/importable.yml new file mode 100644 index 00000000000..6e251d18bec --- /dev/null +++ b/documentation/src/main/resources/openapi/sources/paths/policies/importable.yml @@ -0,0 +1,147 @@ +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0 +# +# SPDX-License-Identifier: EPL-2.0 +get: + summary: Retrieve the importable type for a specific policy entry + description: |- + Returns the importable type of the policy entry identified by the + `policyId` path parameter and the `label` path parameter. + + The importable type controls whether and how a policy entry can be imported by other policies: + * `implicit` (default): the entry is imported without being listed individually + * `explicit`: the entry is only imported if it is listed in the importing policy + * `never`: the entry is not imported, regardless of being listed + tags: + - Policies + parameters: + - $ref: '../../parameters/policyIdPathParam.yml' + - $ref: '../../parameters/labelPathParam.yml' + - $ref: '../../parameters/ifMatchHeaderParamHash.yml' + - $ref: '../../parameters/ifNoneMatchHeaderParam.yml' + - $ref: '../../parameters/timeoutParam.yml' + responses: + '200': + description: The request successfully returned. The importable type is returned. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + content: + application/json: + schema: + $ref: '../../schemas/policies/importable.yml' + '304': + $ref: '../../responses/notModified.yml' + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '404': + description: |- + The request could not be completed. The policy with the given ID or + the policy entry was not found in the context of the authenticated + user. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '412': + $ref: '../../responses/preconditionFailed.yml' +put: + summary: Modify the importable type for a specific policy entry + description: |- + Modify the importable type of the policy entry identified by the + `policyId` path parameter and the `label` path parameter. + + The importable type controls whether and how a policy entry can be imported by other policies: + * `implicit` (default): the entry is imported without being listed individually + * `explicit`: the entry is only imported if it is listed in the importing policy + * `never`: the entry is not imported, regardless of being listed + tags: + - Policies + parameters: + - $ref: '../../parameters/policyIdPathParam.yml' + - $ref: '../../parameters/labelPathParam.yml' + - $ref: '../../parameters/ifMatchHeaderParamHash.yml' + - $ref: '../../parameters/ifNoneMatchHeaderParam.yml' + - $ref: '../../parameters/ifEqualHeaderParam.yml' + - $ref: '../../parameters/timeoutParam.yml' + - $ref: '../../parameters/responseRequiredParam.yml' + responses: + '204': + description: The importable type was successfully updated. + headers: + ETag: + description: |- + The (current server-side) ETag for this (sub-)resource. For top-level resources it is in the format + "rev:[revision]", for sub-resources it has the format "hash:[calculated-hash]". + schema: + type: string + '400': + description: |- + The request could not be completed. Possible reasons: + + * the `policyId` does not conform to the namespaced entity ID notation (see [Ditto documentation on namespaced entity IDs](https://www.eclipse.dev/ditto/basic-namespaces-and-names.html#namespaced-id)) + * the JSON body of the importable type is invalid + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '401': + description: The request could not be completed due to missing authentication. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '403': + description: |- + The request could not be completed. Possible reasons: + * the caller has insufficient permissions. + You need `WRITE` permission on the `policy:/entries/{label}/importable` resource, + without any revoke in a deeper path of the policy resource. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '404': + description: |- + The request could not be completed. The policy with the given ID was + not found in the context of the authenticated user. + content: + application/json: + schema: + $ref: '../../schemas/errors/advancedError.yml' + '412': + $ref: '../../responses/preconditionFailed.yml' + '413': + $ref: '../../responses/entityTooLarge.yml' + requestBody: + content: + application/json: + schema: + $ref: '../../schemas/policies/importable.yml' + example: "explicit" + description: |- + The importable type value. Must be one of: "implicit", "explicit", "never". + required: true diff --git a/documentation/src/main/resources/openapi/sources/requests/permissionCheckRequest.yml b/documentation/src/main/resources/openapi/sources/requests/permissionCheckRequest.yml index 3ff25f1b568..d6e0a89b426 100644 --- a/documentation/src/main/resources/openapi/sources/requests/permissionCheckRequest.yml +++ b/documentation/src/main/resources/openapi/sources/requests/permissionCheckRequest.yml @@ -8,8 +8,14 @@ # http://www.eclipse.org/legal/epl-2.0 # # SPDX-License-Identifier: EPL-2.0 -type: object +content: + application/json: + schema: + type: object + description: |- + Request to check permissions for various entities and resources. + additionalProperties: + $ref: '../schemas/checkPermissions/permissionEntityCheck.yml' description: |- - Request to check permissions for various entities and resources. -additionalProperties: - $ref: '../schemas/checkPermissions/permissionEntityCheck.yml' \ No newline at end of file + JSON object containing permission check requests, keyed by an arbitrary identifier. +required: true diff --git a/documentation/src/main/resources/openapi/sources/responses/permissionCheckResponse.yml b/documentation/src/main/resources/openapi/sources/responses/permissionCheckResponse.yml index 6c86166c4d7..548ba970ed9 100644 --- a/documentation/src/main/resources/openapi/sources/responses/permissionCheckResponse.yml +++ b/documentation/src/main/resources/openapi/sources/responses/permissionCheckResponse.yml @@ -8,7 +8,11 @@ # http://www.eclipse.org/legal/epl-2.0 # # SPDX-License-Identifier: EPL-2.0 -type: object -description: "Response with permission check results for each entity." -additionalProperties: - type: boolean \ No newline at end of file +description: Response with permission check results for each entity. +content: + application/json: + schema: + type: object + description: "Response with permission check results for each entity." + additionalProperties: + type: boolean \ No newline at end of file diff --git a/documentation/src/main/resources/openapi/sources/responses/wotValidationConfig/configOverridesResponse.yml b/documentation/src/main/resources/openapi/sources/responses/wotValidationConfig/configOverridesResponse.yml index a86c1fb2899..4838afb046e 100644 --- a/documentation/src/main/resources/openapi/sources/responses/wotValidationConfig/configOverridesResponse.yml +++ b/documentation/src/main/resources/openapi/sources/responses/wotValidationConfig/configOverridesResponse.yml @@ -8,6 +8,7 @@ # http://www.eclipse.org/legal/epl-2.0 # # SPDX-License-Identifier: EPL-2.0 +description: The WoT validation configuration overrides. content: application/json: schema: diff --git a/documentation/src/main/resources/openapi/sources/responses/wotValidationConfig/dynamicValidationConfigResponse.yml b/documentation/src/main/resources/openapi/sources/responses/wotValidationConfig/dynamicValidationConfigResponse.yml index 4d6078f30e8..054747b6777 100644 --- a/documentation/src/main/resources/openapi/sources/responses/wotValidationConfig/dynamicValidationConfigResponse.yml +++ b/documentation/src/main/resources/openapi/sources/responses/wotValidationConfig/dynamicValidationConfigResponse.yml @@ -8,6 +8,7 @@ # http://www.eclipse.org/legal/epl-2.0 # # SPDX-License-Identifier: EPL-2.0 +description: The dynamic WoT validation configuration. content: application/json: schema: diff --git a/documentation/src/main/resources/openapi/sources/responses/wotValidationConfig/wotValidationConfigResponse.yml b/documentation/src/main/resources/openapi/sources/responses/wotValidationConfig/wotValidationConfigResponse.yml index 1dd9360ff96..6477d92b13a 100644 --- a/documentation/src/main/resources/openapi/sources/responses/wotValidationConfig/wotValidationConfigResponse.yml +++ b/documentation/src/main/resources/openapi/sources/responses/wotValidationConfig/wotValidationConfigResponse.yml @@ -8,6 +8,7 @@ # http://www.eclipse.org/legal/epl-2.0 # # SPDX-License-Identifier: EPL-2.0 +description: The WoT validation configuration. content: application/json: schema: diff --git a/documentation/src/main/resources/openapi/sources/schemas/policies/allowedImportAdditions.yml b/documentation/src/main/resources/openapi/sources/schemas/policies/allowedImportAdditions.yml new file mode 100644 index 00000000000..437694d2945 --- /dev/null +++ b/documentation/src/main/resources/openapi/sources/schemas/policies/allowedImportAdditions.yml @@ -0,0 +1,24 @@ +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0 +# +# SPDX-License-Identifier: EPL-2.0 +type: array +description: |- + Defines which types of additions are allowed when this entry is imported by other policies + via `entriesAdditions`. If omitted or empty, no additions are allowed. This default ensures + that existing policies cannot be extended with additional subjects or resources unless the + policy author explicitly opts in. + * `subjects` — allows importing policies to add additional subjects to this entry + * `resources` — allows importing policies to add additional resources to this entry +items: + type: string + enum: + - subjects + - resources +example: [ "subjects" ] diff --git a/documentation/src/main/resources/openapi/sources/schemas/policies/entriesAdditions.yml b/documentation/src/main/resources/openapi/sources/schemas/policies/entriesAdditions.yml new file mode 100644 index 00000000000..4a4479e49b0 --- /dev/null +++ b/documentation/src/main/resources/openapi/sources/schemas/policies/entriesAdditions.yml @@ -0,0 +1,31 @@ +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0 +# +# SPDX-License-Identifier: EPL-2.0 +type: object +description: |- + Additional subjects and/or resources to additively merge into imported policy entries. + Each key is a label of an imported policy entry. The value is an object with optional "subjects" + and/or "resources" fields that will be merged into the corresponding imported entry. + Subjects are added (existing subjects from the template are preserved). + For resources, new paths are added and overlapping paths get their permissions merged (union of + grants and revokes; template revokes are always preserved). + The imported policy entry must explicitly allow these additions via its "allowedImportAdditions" + field, otherwise the additions are rejected. +additionalProperties: + $ref: 'entryAddition.yml' +example: + default: + subjects: + "integration:my-connection": + type: "generated" + resources: + "thing:/features": + grant: [ "READ" ] + revoke: [] diff --git a/documentation/src/main/resources/openapi/sources/schemas/policies/entryAddition.yml b/documentation/src/main/resources/openapi/sources/schemas/policies/entryAddition.yml new file mode 100644 index 00000000000..e91c5723308 --- /dev/null +++ b/documentation/src/main/resources/openapi/sources/schemas/policies/entryAddition.yml @@ -0,0 +1,28 @@ +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0 +# +# SPDX-License-Identifier: EPL-2.0 +type: object +description: |- + Defines additional subjects and/or resources to be merged into a single imported policy entry. + The imported policy entry must explicitly allow these additions via its "allowedImportAdditions" + field, otherwise the additions are rejected. +properties: + subjects: + $ref: 'subjects.yml' + resources: + $ref: 'resources.yml' +example: + subjects: + "integration:my-connection": + type: "generated" + resources: + "thing:/features": + grant: [ "READ" ] + revoke: [] diff --git a/documentation/src/main/resources/openapi/sources/schemas/policies/policyEntry.yml b/documentation/src/main/resources/openapi/sources/schemas/policies/policyEntry.yml index a112b125214..5bb71f11a15 100644 --- a/documentation/src/main/resources/openapi/sources/schemas/policies/policyEntry.yml +++ b/documentation/src/main/resources/openapi/sources/schemas/policies/policyEntry.yml @@ -17,6 +17,8 @@ properties: $ref: 'resources.yml' importable: $ref: 'importable.yml' + allowedImportAdditions: + $ref: 'allowedImportAdditions.yml' required: - subjects - resources \ No newline at end of file diff --git a/documentation/src/main/resources/openapi/sources/schemas/policies/policyImport.yml b/documentation/src/main/resources/openapi/sources/schemas/policies/policyImport.yml index d50f736bcda..b7836d945fe 100644 --- a/documentation/src/main/resources/openapi/sources/schemas/policies/policyImport.yml +++ b/documentation/src/main/resources/openapi/sources/schemas/policies/policyImport.yml @@ -15,11 +15,22 @@ properties: type: array default: [] description: |- - The policy entries to import from the referenced policy identified by their labels. - In case the field is omitted or an empty array is provided, + The policy entries to import from the referenced policy identified by their labels. + In case the field is omitted or an empty array is provided, all policy entries defined as implicit ("importable": "implicit") are imported. items: type: string description: Label of a policy entry to import from the referenced policy. + entriesAdditions: + $ref: 'entriesAdditions.yml' example: - entries: [ "default", "import" ] \ No newline at end of file + entries: [ "default", "import" ] + entriesAdditions: + default: + subjects: + "integration:my-connection": + type: "generated" + resources: + "thing:/features": + grant: [ "READ" ] + revoke: [] diff --git a/documentation/src/main/resources/pages/ditto/basic-policy.md b/documentation/src/main/resources/pages/ditto/basic-policy.md index 0d5dc347db7..01de9121422 100644 --- a/documentation/src/main/resources/pages/ditto/basic-policy.md +++ b/documentation/src/main/resources/pages/ditto/basic-policy.md @@ -322,7 +322,13 @@ The field can have one of the following three values: If the field is not specified, the default value is `implicit`. -Example of a policy specifying different types of `importable` entries: +Additionally, each entry can specify `allowedImportAdditions` to control what kinds of additions importing +policies are permitted to merge into this entry via `entriesAdditions`. Valid values are `"subjects"` and +`"resources"`. If the field is omitted or empty, no additions are allowed. This default is intentional: existing +policies that were created before this feature cannot be extended with additional subjects or resources through +`entriesAdditions` unless the policy author explicitly opts in by setting `allowedImportAdditions`. + +Example of a policy specifying different types of `importable` entries and allowed additions: ```json { "entries": { @@ -333,12 +339,14 @@ Example of a policy specifying different types of `importable` entries: "IMPLICIT": { "subjects": { ... }, "resources": { ... }, - "importable": "implicit" + "importable": "implicit", + "allowedImportAdditions": [ "subjects" ] }, "EXPLICIT": { "subjects": { ... }, "resources": { ... }, - "importable": "explicit" + "importable": "explicit", + "allowedImportAdditions": [ "subjects", "resources" ] }, "NEVER": { "subjects": { ... }, @@ -358,13 +366,101 @@ Example of a policy importing two other policies: "entries": { ... }, "imports": { "ditto:imported-policy" : { - // import the "EXPLICIT" entry and entries that are of importable type implicit - "entries": [ "EXPLICIT" ] + // import the "EXPLICIT" entry and entries that are of importable type implicit + "entries": [ "EXPLICIT" ] }, "ditto:another-imported-policy" : { } // import only entries that are of importable type implicit } } -``` +``` + +### Entries additions + +Optionally, the importing policy can define `entriesAdditions` to additively merge additional subjects and/or +resources into imported policy entries. This enables template-based policy reuse: the imported (template) policy +defines resources (the "what"), and the importing policy adds subjects (the "who") and optionally extends resources. + +Each key in `entriesAdditions` is the label of an imported entry. The value is an object with optional `subjects` +and/or `resources` fields: +* **Subjects** are merged additively — all subjects from the template are preserved, and the additional subjects + are added. +* **Resources** at new paths are added directly. For overlapping resource paths, permissions are merged as a union + of grants and revokes. Template revokes are always preserved and cannot be removed by additions. + +The imported policy entry must explicitly allow these additions via its `allowedImportAdditions` field. +If the entry does not allow subject additions, any `subjects` in `entriesAdditions` for that entry will be rejected. +Likewise for `resources`. This gives the template policy author full control over what importing policies can extend. + +#### Example: role-based access template for a power plant + +A central template policy defines the roles and permissions that apply to all power plants in an organization. +Each entry specifies `allowedImportAdditions: ["subjects"]` so that the individual power plant policies can add +their own employees while the centrally defined permissions remain unchanged and under central control. + +Template policy (`energy-corp:power-plant-roles`): +```json +{ + "policyId": "energy-corp:power-plant-roles", + "entries": { + "operator": { + "subjects": {}, + "resources": { + "thing:/features/reactor": { "grant": ["READ", "WRITE"], "revoke": [] }, + "thing:/features/turbine": { "grant": ["READ", "WRITE"], "revoke": [] }, + "thing:/features/cooling": { "grant": ["READ", "WRITE"], "revoke": [] } + }, + "importable": "implicit", + "allowedImportAdditions": [ "subjects" ] + }, + "safetyInspector": { + "subjects": {}, + "resources": { + "thing:/features/reactor": { "grant": ["READ"], "revoke": [] }, + "thing:/features/cooling": { "grant": ["READ"], "revoke": [] }, + "thing:/features/safetyLogs": { "grant": ["READ"], "revoke": [] } + }, + "importable": "implicit", + "allowedImportAdditions": [ "subjects" ] + } + } +} +``` + +A specific power plant imports this template and assigns its employees to the predefined roles via +`entriesAdditions`: +```json +{ + "policyId": "energy-corp:plant-springfield", + "entries": { + "admin": { + "subjects": { "oauth2:plant-springfield-admin@energy-corp.com": { "type": "employee" } }, + "resources": { "policy:/": { "grant": ["READ", "WRITE"], "revoke": [] } } + } + }, + "imports": { + "energy-corp:power-plant-roles": { + "entriesAdditions": { + "operator": { + "subjects": { + "oauth2:homer.simpson@energy-corp.com": { "type": "employee" }, + "oauth2:lenny.leonard@energy-corp.com": { "type": "employee" } + } + }, + "safetyInspector": { + "subjects": { + "oauth2:frank.grimes@energy-corp.com": { "type": "employee" } + } + } + } + } + } +} +``` + +With this setup the operator subjects (`homer.simpson`, `lenny.leonard`) receive READ and WRITE access to the +reactor, turbine, and cooling features, while the safety inspector (`frank.grimes`) receives READ-only access to +reactor, cooling, and safety logs — all defined centrally. If the organization later adds a new resource to the +`operator` role in the template, every power plant that imports it automatically inherits the change. A subject creating or modifying a policy with policy imports must have the following permissions: * permission on the _importing policy_ to `WRITE` the modified policy import or policy imports diff --git a/documentation/src/main/resources/pages/ditto/protocol/examples/policies/generated/commands/modify/modifyimport.md b/documentation/src/main/resources/pages/ditto/protocol/examples/policies/generated/commands/modify/modifyimport.md index 6a6616d843d..57f6ff6111d 100644 --- a/documentation/src/main/resources/pages/ditto/protocol/examples/policies/generated/commands/modify/modifyimport.md +++ b/documentation/src/main/resources/pages/ditto/protocol/examples/policies/generated/commands/modify/modifyimport.md @@ -12,3 +12,25 @@ } } ``` + +### With entries additions + +```json +{ + "topic": "org.eclipse.ditto/the_policy_id/policies/commands/modify", + "headers": { + "correlation-id": "" + }, + "path": "/imports/org.eclipse.ditto:imported-policy", + "value": { + "entries" : [ "IMPORTED_ENTRY" ], + "entriesAdditions": { + "IMPORTED_ENTRY": { + "subjects": { + "integration:my-connection": { "type": "generated" } + } + } + } + } +} +``` diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/policies/PolicyEntriesRoute.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/policies/PolicyEntriesRoute.java index 3857d52cc78..b29e0bd5fc5 100755 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/policies/PolicyEntriesRoute.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/policies/PolicyEntriesRoute.java @@ -14,8 +14,10 @@ import static org.eclipse.ditto.base.model.exceptions.DittoJsonException.wrapJsonRuntimeException; -import java.util.Optional; +import java.util.Arrays; +import java.util.LinkedHashSet; import java.util.Set; +import java.util.stream.Collectors; import javax.annotation.Nullable; @@ -24,12 +26,16 @@ import org.eclipse.ditto.gateway.service.endpoints.routes.AbstractRoute; import org.eclipse.ditto.gateway.service.endpoints.routes.RouteBaseProperties; import org.eclipse.ditto.gateway.service.security.authentication.AuthenticationResult; +import org.eclipse.ditto.json.JsonArray; import org.eclipse.ditto.json.JsonFactory; import org.eclipse.ditto.json.JsonObject; +import org.eclipse.ditto.json.JsonValue; import org.eclipse.ditto.jwt.model.JsonWebToken; import org.eclipse.ditto.placeholders.UnresolvedPlaceholderException; +import org.eclipse.ditto.policies.model.AllowedImportAddition; import org.eclipse.ditto.policies.model.ImportableType; import org.eclipse.ditto.policies.model.Label; +import org.eclipse.ditto.policies.model.PolicyEntryInvalidException; import org.eclipse.ditto.policies.model.PoliciesModelFactory; import org.eclipse.ditto.policies.model.PolicyEntry; import org.eclipse.ditto.policies.model.PolicyId; @@ -49,12 +55,16 @@ import org.eclipse.ditto.policies.model.signals.commands.modify.DeleteSubject; import org.eclipse.ditto.policies.model.signals.commands.modify.ModifyPolicyEntries; import org.eclipse.ditto.policies.model.signals.commands.modify.ModifyPolicyEntry; +import org.eclipse.ditto.policies.model.signals.commands.modify.ModifyPolicyEntryAllowedImportAdditions; +import org.eclipse.ditto.policies.model.signals.commands.modify.ModifyPolicyEntryImportable; import org.eclipse.ditto.policies.model.signals.commands.modify.ModifyResource; import org.eclipse.ditto.policies.model.signals.commands.modify.ModifyResources; import org.eclipse.ditto.policies.model.signals.commands.modify.ModifySubject; import org.eclipse.ditto.policies.model.signals.commands.modify.ModifySubjects; import org.eclipse.ditto.policies.model.signals.commands.query.RetrievePolicyEntries; import org.eclipse.ditto.policies.model.signals.commands.query.RetrievePolicyEntry; +import org.eclipse.ditto.policies.model.signals.commands.query.RetrievePolicyEntryAllowedImportAdditions; +import org.eclipse.ditto.policies.model.signals.commands.query.RetrievePolicyEntryImportable; import org.eclipse.ditto.policies.model.signals.commands.query.RetrieveResource; import org.eclipse.ditto.policies.model.signals.commands.query.RetrieveResources; import org.eclipse.ditto.policies.model.signals.commands.query.RetrieveSubject; @@ -71,6 +81,8 @@ final class PolicyEntriesRoute extends AbstractRoute { private static final String PATH_SUFFIX_SUBJECTS = "subjects"; private static final String PATH_SUFFIX_RESOURCES = "resources"; + private static final String PATH_SUFFIX_ALLOWED_IMPORT_ADDITIONS = "allowedImportAdditions"; + private static final String PATH_SUFFIX_IMPORTABLE = "importable"; private static final String PATH_ACTIONS = "actions"; @@ -107,6 +119,8 @@ Route buildPolicyEntriesRoute(final RequestContext ctx, policyEntrySubjectsEntry(ctx, dittoHeaders, policyId), policyEntryResources(ctx, dittoHeaders, policyId), policyEntryResourcesEntry(ctx, dittoHeaders, policyId), + policyEntryAllowedImportAdditions(ctx, dittoHeaders, policyId), + policyEntryImportable(ctx, dittoHeaders, policyId), policyEntryActions(ctx, dittoHeaders, policyId, authResult) ); } @@ -178,17 +192,7 @@ private Route policyEntry(final RequestContext ctx, final DittoHeaders dittoHead private static PolicyEntry createPolicyEntryForPut(final String jsonString, final CharSequence labelString) { final JsonObject jsonObject = wrapJsonRuntimeException(() -> JsonFactory.newObject(jsonString)); - final Subjects subjects = - PoliciesModelFactory.newSubjects(jsonObject.getValueOrThrow(PolicyEntry.JsonFields.SUBJECTS)); - final Resources resources = - PoliciesModelFactory.newResources(jsonObject.getValueOrThrow(PolicyEntry.JsonFields.RESOURCES)); - - final Optional importableOpt = jsonObject.getValue(PolicyEntry.JsonFields.IMPORTABLE_TYPE) - .flatMap(ImportableType::forName); - return importableOpt - .map(importableType -> PoliciesModelFactory.newPolicyEntry(Label.of(labelString), subjects, resources, - importableType)) - .orElseGet(() -> PoliciesModelFactory.newPolicyEntry(Label.of(labelString), subjects, resources)); + return PoliciesModelFactory.newPolicyEntry(labelString, jsonObject); } /* @@ -357,6 +361,102 @@ private Route policyEntryResourcesEntry(final RequestContext ctx, final DittoHea ); } + /* + * Describes {@code /entries/